Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
de78f06b66
commit
c0e21fd75e
|
|
@ -13,7 +13,6 @@ Gitlab/Rails/SafeFormat:
|
|||
- 'app/helpers/merge_requests_helper.rb'
|
||||
- 'app/helpers/profiles_helper.rb'
|
||||
- 'app/helpers/projects_helper.rb'
|
||||
- 'app/helpers/reminder_emails_helper.rb'
|
||||
- 'app/helpers/search_helper.rb'
|
||||
- 'app/helpers/sourcegraph_helper.rb'
|
||||
- 'app/helpers/whats_new_helper.rb'
|
||||
|
|
|
|||
|
|
@ -218,7 +218,6 @@ Layout/LineLength:
|
|||
- 'app/helpers/projects/security/configuration_helper.rb'
|
||||
- 'app/helpers/projects_helper.rb'
|
||||
- 'app/helpers/registrations_helper.rb'
|
||||
- 'app/helpers/reminder_emails_helper.rb'
|
||||
- 'app/helpers/repository_languages_helper.rb'
|
||||
- 'app/helpers/routing/pseudonymization_helper.rb'
|
||||
- 'app/helpers/search_helper.rb'
|
||||
|
|
|
|||
|
|
@ -31,7 +31,6 @@ Rails/OutputSafety:
|
|||
- 'app/helpers/page_layout_helper.rb'
|
||||
- 'app/helpers/profiles_helper.rb'
|
||||
- 'app/helpers/projects_helper.rb'
|
||||
- 'app/helpers/reminder_emails_helper.rb'
|
||||
- 'app/helpers/safe_format_helper.rb'
|
||||
- 'app/helpers/search_helper.rb'
|
||||
- 'app/helpers/sidebars_helper.rb'
|
||||
|
|
|
|||
|
|
@ -44,7 +44,6 @@ Style/FormatString:
|
|||
- 'app/helpers/projects/project_members_helper.rb'
|
||||
- 'app/helpers/projects_helper.rb'
|
||||
- 'app/helpers/registrations_helper.rb'
|
||||
- 'app/helpers/reminder_emails_helper.rb'
|
||||
- 'app/helpers/search_helper.rb'
|
||||
- 'app/helpers/ssh_keys_helper.rb'
|
||||
- 'app/helpers/tags_helper.rb'
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ Style/IfUnlessModifier:
|
|||
- 'app/helpers/preferences_helper.rb'
|
||||
- 'app/helpers/projects_helper.rb'
|
||||
- 'app/helpers/releases_helper.rb'
|
||||
- 'app/helpers/reminder_emails_helper.rb'
|
||||
- 'app/helpers/routing/artifacts_helper.rb'
|
||||
- 'app/helpers/search_helper.rb'
|
||||
- 'app/helpers/snippets_helper.rb'
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ export default {
|
|||
isCanceling: false,
|
||||
isRetrying: false,
|
||||
showConfirmationModal: false,
|
||||
pipelineToCancel: this.pipeline,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -55,10 +56,11 @@ export default {
|
|||
this.isCanceling = true;
|
||||
this.showConfirmationModal = false;
|
||||
|
||||
this.$emit('cancel-pipeline', this.pipeline);
|
||||
this.$emit('cancel-pipeline', this.pipelineToCancel);
|
||||
},
|
||||
handleCancelClick() {
|
||||
this.showConfirmationModal = true;
|
||||
this.pipelineToCancel = this.pipeline;
|
||||
|
||||
this.trackClick('click_cancel_button');
|
||||
},
|
||||
|
|
@ -79,7 +81,7 @@ export default {
|
|||
<template>
|
||||
<div class="gl-text-right">
|
||||
<pipeline-stop-modal
|
||||
:pipeline="pipeline"
|
||||
:pipeline="pipelineToCancel"
|
||||
:show-confirmation-modal="showConfirmationModal"
|
||||
@submit="onConfirmCancelPipeline"
|
||||
@close-modal="onCloseModal"
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ export default {
|
|||
:title="modalTitle"
|
||||
:action-primary="primaryProps"
|
||||
:action-cancel="$options.cancelProps"
|
||||
data-testid="pipeline-stop-modal"
|
||||
@primary="emitSubmit($event)"
|
||||
>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
import { __ } from '~/locale';
|
||||
|
||||
export const START_RULE = {
|
||||
regex: /^[a-zA-Z0-9\u{00A9}-\u{1f9ff}_]/u,
|
||||
message: __('Group name must start with a letter, digit, emoji, or underscore.'),
|
||||
};
|
||||
|
||||
export const CONTAINS_RULE = {
|
||||
regex: /^[a-zA-Z0-9\p{Pd}\u{00A9}-\u{1f9ff}_. ()]+$/u,
|
||||
message: __(
|
||||
'Group name can contain only letters, digits, dashes, spaces, dots, underscores, parenthesis, and emojis.',
|
||||
),
|
||||
};
|
||||
|
|
@ -14,7 +14,7 @@ export default {
|
|||
GlSprintf,
|
||||
},
|
||||
i18n: {
|
||||
topicsTitle: s__('ProjectSettings|Topics'),
|
||||
topicsTitle: s__('ProjectSettings|Project topics'),
|
||||
topicsHelpText: s__(
|
||||
'ProjectSettings|Topics are publicly visible even on private projects. Do not include sensitive information in topic names. %{linkStart}Learn more%{linkEnd}.',
|
||||
),
|
||||
|
|
|
|||
|
|
@ -55,15 +55,13 @@ const getTrialStatusWidgetData = (sidebarData) => {
|
|||
trialDaysUsed,
|
||||
trialDuration,
|
||||
percentageComplete,
|
||||
widgetUrl,
|
||||
groupId,
|
||||
featureId,
|
||||
dismissEndpoint,
|
||||
} = convertObjectPropsToCamelCase(sidebarData.duo_pro_trial_status_widget_data_attrs);
|
||||
|
||||
const { daysRemaining, trialEndDate, purchaseNowUrl } = convertObjectPropsToCamelCase(
|
||||
sidebarData.duo_pro_trial_status_popover_data_attrs,
|
||||
);
|
||||
const { daysRemaining, trialEndDate, purchaseNowUrl, learnAboutButtonUrl } =
|
||||
convertObjectPropsToCamelCase(sidebarData.duo_pro_trial_status_popover_data_attrs);
|
||||
|
||||
return {
|
||||
showDuoProTrialStatusWidget: true,
|
||||
|
|
@ -71,14 +69,13 @@ const getTrialStatusWidgetData = (sidebarData) => {
|
|||
trialDaysUsed: Number(trialDaysUsed),
|
||||
trialDuration: Number(trialDuration),
|
||||
percentageComplete: Number(percentageComplete),
|
||||
widgetUrl,
|
||||
groupId,
|
||||
featureId,
|
||||
dismissEndpoint,
|
||||
daysRemaining,
|
||||
trialEndDate: new Date(trialEndDate),
|
||||
purchaseNowUrl,
|
||||
learnAboutButtonUrl: widgetUrl,
|
||||
learnAboutButtonUrl,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -351,7 +351,7 @@ export default {
|
|||
}
|
||||
|
||||
this.markdownPreviewLoading = false;
|
||||
this.markdownPreview = data.body || __('Nothing to preview.');
|
||||
this.markdownPreview = data.body || data.html || __('Nothing to preview.');
|
||||
|
||||
this.$nextTick()
|
||||
.then(() => {
|
||||
|
|
|
|||
|
|
@ -1,77 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ReminderEmailsHelper
|
||||
def invitation_reminder_salutation(reminder_index, format: nil)
|
||||
case reminder_index
|
||||
when 0
|
||||
s_('InviteReminderEmail|Invitation pending')
|
||||
when 1
|
||||
if format == :html
|
||||
wave_emoji_tag = Gitlab::Emoji.gl_emoji_tag(TanukiEmoji.find_by_alpha_code('wave'))
|
||||
s_('InviteReminderEmail|Hey there %{wave_emoji}').html_safe % { wave_emoji: wave_emoji_tag }
|
||||
else
|
||||
s_('InviteReminderEmail|Hey there!')
|
||||
end
|
||||
when 2
|
||||
s_('InviteReminderEmail|In case you missed it...')
|
||||
end
|
||||
end
|
||||
|
||||
def invitation_reminder_body(member, reminder_index, format: nil)
|
||||
options = {
|
||||
inviter: sanitize_name(member.created_by.name),
|
||||
strong_start: '',
|
||||
strong_end: '',
|
||||
project_or_group_name: member_source.human_name,
|
||||
project_or_group: member_source.model_name.singular,
|
||||
role: member.human_access.downcase
|
||||
}
|
||||
|
||||
if format == :html
|
||||
options.merge!(
|
||||
inviter: (link_to member.created_by.name, user_url(member.created_by)).html_safe,
|
||||
strong_start: '<strong>'.html_safe,
|
||||
strong_end: '</strong>'.html_safe
|
||||
)
|
||||
end
|
||||
|
||||
if reminder_index == 2
|
||||
options[:invitation_age] = (Date.current - member.created_at.to_date).to_i
|
||||
end
|
||||
|
||||
body = invitation_reminder_body_text(reminder_index)
|
||||
|
||||
(format == :html ? ERB::Util.html_escape(body) : body) % options
|
||||
end
|
||||
|
||||
def invitation_reminder_accept_link(token, format: nil)
|
||||
case format
|
||||
when :html
|
||||
link_to s_('InviteReminderEmail|Accept invitation'), invite_url(token), class: 'invite-btn-join'
|
||||
else
|
||||
s_('InviteReminderEmail|Accept invitation: %{invite_url}') % { invite_url: invite_url(token) }
|
||||
end
|
||||
end
|
||||
|
||||
def invitation_reminder_decline_link(token, format: nil)
|
||||
case format
|
||||
when :html
|
||||
link_to s_('InviteReminderEmail|Decline invitation'), decline_invite_url(token), class: 'invite-btn-decline'
|
||||
else
|
||||
s_('InviteReminderEmail|Decline invitation: %{decline_url}') % { decline_url: decline_invite_url(token) }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def invitation_reminder_body_text(reminder_index)
|
||||
case reminder_index
|
||||
when 0
|
||||
s_('InviteReminderEmail|%{inviter} is waiting for you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}.')
|
||||
when 1
|
||||
s_('InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}.')
|
||||
when 2
|
||||
s_("InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the %{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. What would you like to do?")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -50,29 +50,6 @@ module Emails
|
|||
subject: subject("Access to the #{human_name} #{member_source.model_name.singular} was denied"))
|
||||
end
|
||||
|
||||
def member_invited_reminder_email(member_source_type, member_id, token, reminder_index)
|
||||
@member_source_type = member_source_type
|
||||
@member_id = member_id
|
||||
@token = token
|
||||
@reminder_index = reminder_index
|
||||
|
||||
return unless member_exists? && member.created_by && member.invite_to_unknown_user?
|
||||
|
||||
subjects = {
|
||||
0 => s_("InviteReminderEmail|%{inviter}'s invitation to GitLab is pending"),
|
||||
1 => s_('InviteReminderEmail|%{inviter} is waiting for you to join GitLab'),
|
||||
2 => s_('InviteReminderEmail|%{inviter} is still waiting for you to join GitLab')
|
||||
}
|
||||
|
||||
subject_line = subjects[reminder_index] % { inviter: member.created_by.name }
|
||||
|
||||
email_with_layout(
|
||||
layout: 'unknown_user_mailer',
|
||||
to: member.invite_email,
|
||||
subject: subject(subject_line)
|
||||
)
|
||||
end
|
||||
|
||||
def member_invite_accepted_email(member_source_type, member_id)
|
||||
@member_source_type = member_source_type
|
||||
@member_id = member_id
|
||||
|
|
|
|||
|
|
@ -0,0 +1,132 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Members
|
||||
class InviteReminderMailer < ApplicationMailer
|
||||
include SafeFormatHelper
|
||||
|
||||
helper EmailsHelper
|
||||
|
||||
helper_method :reminder_common_body_options
|
||||
|
||||
layout 'unknown_user_mailer'
|
||||
|
||||
def email(member, token, reminder_index)
|
||||
@member = member
|
||||
@token = token
|
||||
@reminder_index = reminder_index
|
||||
|
||||
return unless valid_to_email?
|
||||
|
||||
@email_instance = email_klass[reminder_index].new
|
||||
|
||||
subject_line = format(email_instance.subject, inviter: member.created_by.name)
|
||||
|
||||
mail_with_locale(to: member.invite_email, subject: EmailsHelper.subject_with_suffix([subject_line]))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :token, :member, :reminder_index, :email_instance
|
||||
|
||||
def email_klass
|
||||
{
|
||||
0 => FirstEmail,
|
||||
1 => SecondEmail,
|
||||
2 => LastEmail
|
||||
}
|
||||
end
|
||||
|
||||
def valid_to_email?
|
||||
return true if member.present? && member.created_by && member.invite_to_unknown_user?
|
||||
|
||||
Gitlab::AppLogger.info('Tried to send an email invitation for an invalid member.') if member.blank?
|
||||
|
||||
false
|
||||
end
|
||||
|
||||
def reminder_common_body_options(member)
|
||||
{
|
||||
project_or_group_name: member.source.human_name,
|
||||
project_or_group: member.source.model_name.singular,
|
||||
role: member.human_access.downcase
|
||||
}
|
||||
end
|
||||
|
||||
class FirstEmail
|
||||
def subject
|
||||
s_("InviteReminderEmail|%{inviter}'s invitation to GitLab is pending")
|
||||
end
|
||||
|
||||
def salutation
|
||||
s_('InviteReminderEmail|Invitation pending')
|
||||
end
|
||||
|
||||
alias_method :salutation_html, :salutation
|
||||
|
||||
def body_text
|
||||
s_(
|
||||
'InviteReminderEmail|%{inviter} is waiting for you to join the ' \
|
||||
'%{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}.'
|
||||
)
|
||||
end
|
||||
|
||||
def extra_body_options(_)
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
class SecondEmail
|
||||
include SafeFormatHelper
|
||||
|
||||
def subject
|
||||
s_('InviteReminderEmail|%{inviter} is waiting for you to join GitLab')
|
||||
end
|
||||
|
||||
def salutation
|
||||
s_('InviteReminderEmail|Hey there!')
|
||||
end
|
||||
|
||||
def salutation_html
|
||||
wave_emoji_tag = Gitlab::Emoji.gl_emoji_tag(TanukiEmoji.find_by_alpha_code('wave'))
|
||||
safe_format(s_('InviteReminderEmail|Hey there %{wave_emoji}'), wave_emoji: wave_emoji_tag)
|
||||
end
|
||||
|
||||
def body_text
|
||||
s_(
|
||||
'InviteReminderEmail|This is a friendly reminder that %{inviter} invited you to join the ' \
|
||||
'%{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}.'
|
||||
)
|
||||
end
|
||||
|
||||
def extra_body_options(_)
|
||||
{}
|
||||
end
|
||||
end
|
||||
|
||||
class LastEmail
|
||||
def subject
|
||||
s_('InviteReminderEmail|%{inviter} is still waiting for you to join GitLab')
|
||||
end
|
||||
|
||||
def salutation
|
||||
s_('InviteReminderEmail|In case you missed it...')
|
||||
end
|
||||
|
||||
alias_method :salutation_html, :salutation
|
||||
|
||||
def body_text
|
||||
s_(
|
||||
"InviteReminderEmail|It's been %{invitation_age} days since %{inviter} invited you to join the " \
|
||||
"%{strong_start}%{project_or_group_name}%{strong_end} %{project_or_group} as a %{role}. " \
|
||||
"What would you like to do?"
|
||||
)
|
||||
end
|
||||
|
||||
def extra_body_options(created_at_date)
|
||||
{
|
||||
invitation_age: (Date.current - created_at_date).to_i
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,7 +4,6 @@ class Notify < ApplicationMailer
|
|||
include ActionDispatch::Routing::PolymorphicRoutes
|
||||
include GitlabRoutingHelper
|
||||
include EmailsHelper
|
||||
include ReminderEmailsHelper
|
||||
include IssuablesHelper
|
||||
|
||||
mattr_accessor :override_layout_lookup_table, default: {}
|
||||
|
|
@ -34,7 +33,6 @@ class Notify < ApplicationMailer
|
|||
helper DiffHelper
|
||||
helper BlobHelper
|
||||
helper EmailsHelper
|
||||
helper ReminderEmailsHelper
|
||||
helper MembersHelper
|
||||
helper AvatarsHelper
|
||||
helper GitlabRoutingHelper
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Members
|
||||
class InviteReminderMailerPreview < ActionMailer::Preview
|
||||
def first_reminder_email
|
||||
Members::InviteReminderMailer.email(member, '1234', 0).message
|
||||
end
|
||||
|
||||
def second_reminder_email
|
||||
Members::InviteReminderMailer.email(member, '1234', 1).message
|
||||
end
|
||||
|
||||
def last_reminder_email
|
||||
Members::InviteReminderMailer.email(member, '1234', 2).message
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def member
|
||||
Member.not_accepted_invitations.with_created_by.last
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -461,7 +461,7 @@ class NotifyPreview < ActionMailer::Preview
|
|||
end
|
||||
|
||||
def member
|
||||
@member ||= Member.last
|
||||
@member ||= Member.non_invite.last
|
||||
end
|
||||
|
||||
def key
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ class Member < ApplicationRecord
|
|||
scope :not_accepted_invitations_by_user, ->(user) { not_accepted_invitations.where(created_by: user) }
|
||||
scope :not_expired, ->(today = Date.current) { where(arel_table[:expires_at].gt(today).or(arel_table[:expires_at].eq(nil))) }
|
||||
scope :expiring_and_not_notified, ->(date) { where("expiry_notified_at is null AND expires_at >= ? AND expires_at <= ?", Date.current, date) }
|
||||
scope :with_created_by, -> { where.associated(:created_by) }
|
||||
|
||||
scope :created_today, -> do
|
||||
now = Date.current
|
||||
|
|
@ -526,7 +527,9 @@ class Member < ApplicationRecord
|
|||
|
||||
generate_invite_token! unless @raw_invite_token
|
||||
|
||||
run_after_commit_or_now { notification_service.invite_member_reminder(self, @raw_invite_token, reminder_index) }
|
||||
run_after_commit_or_now do
|
||||
Members::InviteReminderMailer.email(self, @raw_invite_token, reminder_index).deliver_later
|
||||
end
|
||||
end
|
||||
|
||||
def create_notification_setting
|
||||
|
|
|
|||
|
|
@ -315,14 +315,6 @@ class Repository
|
|||
false
|
||||
end
|
||||
|
||||
def branch_or_tag?(ref)
|
||||
return false unless exists?
|
||||
|
||||
ref = Gitlab::Git.ref_name(ref, types: 'heads|tags')
|
||||
|
||||
branch_exists?(ref) || tag_exists?(ref)
|
||||
end
|
||||
|
||||
def search_branch_names(pattern)
|
||||
redis_set_cache.search('branch_names', pattern) { branch_names }
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,28 +18,25 @@ module Ci
|
|||
end
|
||||
|
||||
def execute(ref)
|
||||
# "ref" is not a enough for a cache key because the name is static but that branch can be changed any time.
|
||||
sha = project.commit(ref).try(:sha)
|
||||
with_reactive_cache(ref, sha) { |result| result }
|
||||
|
||||
with_reactive_cache(sha) { |result| result }
|
||||
end
|
||||
|
||||
def calculate_reactive_cache(ref, sha)
|
||||
def calculate_reactive_cache(sha)
|
||||
config = ::Gitlab::Ci::ProjectConfig.new(project: project, sha: sha)
|
||||
|
||||
return {} unless config.exists?
|
||||
|
||||
# The `ref` parameter should be branch or tag name. However, the API also accepts a commit SHA and we can't
|
||||
# change it to not introduce breaking changes. Instead, here we're checking if a commit SHA is passed
|
||||
# as `ref`. If so, we should verify the sha whether it belongs to the project in YamlProcessor.
|
||||
sha_passed_as_ref_parameter = !project.repository.branch_or_tag?(ref)
|
||||
ref_name = Gitlab::Ci::RefFinder.new(project).find_by_sha(sha)
|
||||
|
||||
result = Gitlab::Ci::YamlProcessor.new(
|
||||
config.content,
|
||||
project: project,
|
||||
user: current_user,
|
||||
sha: sha,
|
||||
ref: ref,
|
||||
verify_project_sha: sha_passed_as_ref_parameter
|
||||
ref: ref_name,
|
||||
verify_project_sha: true
|
||||
).execute
|
||||
|
||||
result.valid? ? result.root_variables_with_prefill_data : {}
|
||||
|
|
|
|||
|
|
@ -568,10 +568,6 @@ class NotificationService
|
|||
mailer.member_about_to_expire_email(member.real_source_type, member.id).deliver_later
|
||||
end
|
||||
|
||||
def invite_member_reminder(group_member, token, reminder_index)
|
||||
mailer.member_invited_reminder_email(group_member.real_source_type, group_member.id, token, reminder_index).deliver_later
|
||||
end
|
||||
|
||||
def project_was_moved(project, old_path_with_namespace)
|
||||
recipients = project_moved_recipients(project)
|
||||
recipients = notifiable_users(recipients, :custom, custom_action: :moved_project, project: project)
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
%h1.gl-sr-only= @breadcrumb_title
|
||||
|
||||
- if can?(current_user, :admin_group, @group)
|
||||
= render ::Layouts::SettingsBlockComponent.new(_('Naming, visibility'),
|
||||
= render ::Layouts::SettingsBlockComponent.new(_('Naming, description, visibility'),
|
||||
id: 'js-general-settings',
|
||||
testid: 'general-settings',
|
||||
expanded: true) do |c|
|
||||
|
|
|
|||
|
|
@ -7,33 +7,34 @@
|
|||
.form-group.col-md-5
|
||||
= f.label :name, s_('Groups|Group name'), class: 'label-bold'
|
||||
= f.text_field :name, class: 'form-control', data: { testid: 'group-name-field' }
|
||||
.text-muted
|
||||
%span.form-text.text-muted
|
||||
= s_('Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.')
|
||||
|
||||
.form-group.col-md-7
|
||||
.form-group.col-md-4
|
||||
= f.label :id, s_('Groups|Group ID'), class: 'label-bold'
|
||||
= f.text_field :id, class: 'form-control w-auto', readonly: true
|
||||
= f.text_field :id, class: 'form-control gl-form-input', readonly: true
|
||||
|
||||
.row.gl-mt-3
|
||||
.form-group.gl-mt-4.gl-mb-9
|
||||
= render Pajamas::AvatarComponent.new(@group, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
|
||||
= f.label :avatar, s_('Groups|Group avatar'), class: 'label-bold gl-block'
|
||||
= render 'shared/choose_avatar_button', f: f
|
||||
- if @group.avatar?
|
||||
%hr
|
||||
= link_button_to s_('Groups|Remove avatar'), group_avatar_path(@group.to_param), aria: { label: s_('Groups|Remove avatar') }, data: { confirm: s_('Groups|Avatar will be removed. Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :delete, variant: :danger, category: :secondary
|
||||
|
||||
.row
|
||||
.form-group.col-md-9
|
||||
= f.label :description, s_('Groups|Group description (optional)'), class: 'label-bold'
|
||||
= f.text_area :description, class: 'form-control', rows: 3, maxlength: 500
|
||||
= f.text_area :description, class: 'form-control', rows: 4, maxlength: 500
|
||||
|
||||
.row.gl-mt-3
|
||||
= render 'shared/repository_size_limit_setting_registration_features_cta', form: f
|
||||
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
|
||||
|
||||
.row
|
||||
.form-group.col-md-5
|
||||
= f.label :description, s_('Groups|Group README'), class: 'label-bold'
|
||||
#js-group-settings-readme{ data: group_settings_readme_app_data(@group) }
|
||||
|
||||
= render 'shared/repository_size_limit_setting_registration_features_cta', form: f
|
||||
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :group
|
||||
|
||||
.form-group.gl-mt-3.gl-mb-6
|
||||
= render Pajamas::AvatarComponent.new(@group, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
|
||||
= f.label :avatar, s_('Groups|Group avatar'), class: 'label-bold gl-block'
|
||||
= render 'shared/choose_avatar_button', f: f
|
||||
- if @group.avatar?
|
||||
%hr
|
||||
= link_button_to s_('Groups|Remove avatar'), group_avatar_path(@group.to_param), aria: { label: s_('Groups|Remove avatar') }, data: { confirm: s_('Groups|Avatar will be removed. Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :delete, variant: :danger, category: :secondary
|
||||
.form-group.gl-form-group
|
||||
= render 'shared/visibility_level', f: f, visibility_level: @group.visibility_level, can_change_visibility_level: can_change_group_visibility_level?(@group), form_model: @group
|
||||
= f.submit s_('Groups|Save changes'), pajamas_button: true, class: 'js-dirty-submit', data: { testid: 'save-name-visibility-settings-button' }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
%tr
|
||||
%td.text-content
|
||||
%h2.invite-header
|
||||
= @email_instance.salutation_html
|
||||
%p.invite-body
|
||||
- options = { inviter: link_to(@member.created_by.name, user_url(@member.created_by)) }.merge(reminder_common_body_options(@member))
|
||||
= safe_format(@email_instance.body_text,
|
||||
options.merge(tag_pair(tag.strong,
|
||||
:strong_start, :strong_end)).merge(@email_instance.extra_body_options(@member.created_at.to_date)))
|
||||
%p.invite-actions
|
||||
= link_to s_('InviteReminderEmail|Accept invitation'), invite_url(@token), class: 'invite-btn-join'
|
||||
= link_to s_('InviteReminderEmail|Decline invitation'), decline_invite_url(@token), class: 'invite-btn-decline'
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<%= @email_instance.salutation %>
|
||||
|
||||
<% options = {
|
||||
inviter: sanitize_name(@member.created_by.name),
|
||||
strong_start: '',
|
||||
strong_end: ''
|
||||
}.merge(reminder_common_body_options(@member))
|
||||
%>
|
||||
|
||||
<%= format(@email_instance.body_text, options.merge(@email_instance.extra_body_options(@member.created_at.to_date))) %>
|
||||
|
||||
<%= s_('InviteReminderEmail|Accept invitation: %{invite_url}') % { invite_url: invite_url(@token) } %>
|
||||
<%= s_('InviteReminderEmail|Decline invitation: %{decline_url}') % { decline_url: decline_invite_url(@token) } %>
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
%tr
|
||||
%td.text-content
|
||||
%h2.invite-header
|
||||
= invitation_reminder_salutation(@reminder_index, format: :html)
|
||||
%p.invite-body
|
||||
= invitation_reminder_body(member, @reminder_index, format: :html)
|
||||
%p.invite-actions
|
||||
= invitation_reminder_accept_link(@token, format: :html)
|
||||
= invitation_reminder_decline_link(@token, format: :html)
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
<%= invitation_reminder_salutation(@reminder_index) %>
|
||||
|
||||
<%= invitation_reminder_body(member, @reminder_index) %>
|
||||
|
||||
<%= invitation_reminder_accept_link(@token) %>
|
||||
<%= invitation_reminder_decline_link(@token) %>
|
||||
|
|
@ -3,16 +3,18 @@
|
|||
- add_page_specific_style 'page_bundles/projects_edit'
|
||||
- reduce_visibility_form_id = 'reduce-visibility-form'
|
||||
- @force_desktop_expanded_sidebar = true
|
||||
- project_docs_path = help_page_path('user/project/working_with_projects')
|
||||
- project_docs_link_start = '<a href="%{url}" target="_blank">'.html_safe % { url: project_docs_path }
|
||||
|
||||
%h1.gl-sr-only= @breadcrumb_title
|
||||
|
||||
- if can?(current_user, :admin_project, @project)
|
||||
= render ::Layouts::SettingsBlockComponent.new(_('Naming, topics, avatar'),
|
||||
= render ::Layouts::SettingsBlockComponent.new(_('Naming, description, topics'),
|
||||
id: 'js-general-settings',
|
||||
testid: 'general-settings-content',
|
||||
expanded: true) do |c|
|
||||
- c.with_description do
|
||||
= _('Update your project name, topics, description, and avatar.')
|
||||
= html_escape(_('Update your project name, description, avatar, and topics. %{link_start}Learn more about projects%{link_end}.')) % { link_start: project_docs_link_start, link_end: '</a>'.html_safe }
|
||||
- c.with_body do
|
||||
= render 'projects/settings/general'
|
||||
|
||||
|
|
|
|||
|
|
@ -8,33 +8,35 @@
|
|||
= f.label :name, class: 'label-bold', for: 'project_name_edit' do
|
||||
= _('Project name')
|
||||
= f.text_field :name, class: 'form-control gl-form-input', id: "project_name_edit", data: { testid: 'project-name-field' }
|
||||
%span.form-text.text-muted
|
||||
= _('Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.')
|
||||
|
||||
.form-group.col-md-7
|
||||
.form-group.col-md-4
|
||||
= f.label :id, class: 'label-bold' do
|
||||
= _('Project ID')
|
||||
= f.text_field :id, class: 'form-control gl-form-input w-auto', readonly: true
|
||||
= f.text_field :id, class: 'form-control gl-form-input', readonly: true
|
||||
|
||||
.form-group.gl-mt-2.gl-mb-8
|
||||
= render Pajamas::AvatarComponent.new(@project, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
|
||||
= f.label :avatar, _('Project avatar'), class: 'label-bold gl-block'
|
||||
= render 'shared/choose_avatar_button', f: f
|
||||
- if @project.avatar?
|
||||
%hr
|
||||
= link_button_to _('Remove avatar'), project_avatar_path(@project), aria: { label: _('Remove avatar') }, data: { confirm: _('Avatar will be removed. Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :delete, variant: :danger, category: :secondary
|
||||
|
||||
.row
|
||||
.form-group.col-md-9
|
||||
= f.label :description, _('Project description (optional)'), class: 'label-bold'
|
||||
= f.text_area :description, class: 'form-control gl-form-input', rows: 4
|
||||
|
||||
.row= render_if_exists 'projects/classification_policy_settings', f: f
|
||||
|
||||
= render 'shared/repository_size_limit_setting_registration_features_cta', form: f
|
||||
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
|
||||
|
||||
.row
|
||||
.form-group.col-md-9
|
||||
.js-topics-selector{ data: { hidden_input_id: hidden_topics_field_id } }
|
||||
= f.hidden_field :topics, value: @project.topic_list.join(', '), id: hidden_topics_field_id
|
||||
|
||||
.row
|
||||
.form-group.col-md-9
|
||||
= f.label :description, _('Project description (optional)'), class: 'label-bold'
|
||||
= f.text_area :description, class: 'form-control gl-form-input', rows: 3
|
||||
|
||||
.row= render_if_exists 'projects/classification_policy_settings', f: f
|
||||
|
||||
= render 'shared/repository_size_limit_setting_registration_features_cta', form: f
|
||||
= render_if_exists 'shared/repository_size_limit_setting', form: f, type: :project
|
||||
|
||||
.form-group.gl-mt-3.gl-mb-3
|
||||
= render Pajamas::AvatarComponent.new(@project, size: 96, alt: '', class: 'gl-float-left gl-mr-5')
|
||||
= f.label :avatar, _('Project avatar'), class: 'label-bold gl-block'
|
||||
= render 'shared/choose_avatar_button', f: f
|
||||
- if @project.avatar?
|
||||
%hr
|
||||
= link_button_to _('Remove avatar'), project_avatar_path(@project), aria: { label: _('Remove avatar') }, data: { confirm: _('Avatar will be removed. Are you sure?'), 'confirm-btn-variant': 'danger' }, method: :delete, variant: :danger, category: :secondary
|
||||
|
||||
= f.submit _('Save changes'), pajamas_button: true, class: "gl-mt-6", data: { testid: 'save-naming-topics-avatar-button' }
|
||||
= f.submit _('Save changes'), pajamas_button: true, data: { testid: 'save-naming-topics-avatar-button' }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%div{ class: [container_class, @content_class, 'gl-pt-5!'] }
|
||||
%div{ class: [container_class, @content_class, '!gl-pt-5'] }
|
||||
= render Pajamas::BannerComponent.new(button_text: s_('AutoDevOps|Enable in settings'),
|
||||
button_link: project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'),
|
||||
svg_path: 'illustrations/devops-sm.svg',
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
- script = local_assigns.fetch(:script, true)
|
||||
- method = params[:action] == 'create' ? :post : :put
|
||||
|
||||
%h1.page-title.gl-font-size-h-display
|
||||
%h1.page-title.gl-text-size-h-display
|
||||
= _('Anti-spam verification')
|
||||
%hr
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
.gl-display-flex.gl-align-items-center.gl-gap-5{ data: { testid: 'divider' } }
|
||||
%hr.gl-flex-grow-1.gl-border-gray-100
|
||||
.gl-flex.gl-items-center.gl-gap-5{ data: { testid: 'divider' } }
|
||||
%hr.gl-grow.gl-border-gray-100
|
||||
= local_assigns[:text]
|
||||
%hr.gl-flex-grow-1.gl-border-gray-100
|
||||
%hr.gl-grow.gl-border-gray-100
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- show_group_events = local_assigns.fetch(:show_group_events, false)
|
||||
|
||||
.scrolling-tabs-container.inner-page-scroll-tabs.gl-flex-grow-1.gl-min-w-0.gl-w-full
|
||||
.scrolling-tabs-container.inner-page-scroll-tabs.gl-grow.gl-min-w-0.gl-w-full
|
||||
%button.fade-left{ type: 'button', title: _('Scroll left'), 'aria-label': _('Scroll left') }
|
||||
= sprite_icon('chevron-lg-left', size: 12)
|
||||
%button.fade-right{ type: 'button', title: _('Scroll right'), 'aria-label': _('Scroll right') }
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@
|
|||
|
||||
#blob-content.file-content.code.js-syntax-highlight
|
||||
.blob-content{ data: { blob_id: blob.id, path: blob.path, highlight_line: highlight } }
|
||||
%pre{ class: "code highlight gl-border-none!" }
|
||||
%pre{ class: "code highlight !gl-border-none" }
|
||||
%code.gl-border-none
|
||||
= highlighted_blob
|
||||
|
|
|
|||
|
|
@ -5,6 +5,6 @@
|
|||
-# 100vh because of the presence of the bottom bar
|
||||
|
||||
#ide.gl-h-full{ data: data }
|
||||
.web-ide-loader.gl-display-flex.gl-justify-content-center.gl-align-items-center.gl-flex-direction-column.gl-h-full.gl-mx-auto
|
||||
.web-ide-loader.gl-flex.gl-justify-center.gl-items-center.gl-flex-col.gl-h-full.gl-mx-auto
|
||||
= brand_header_logo
|
||||
%h3.clblack.gl-mt-6= loading_text
|
||||
|
|
|
|||
|
|
@ -5,22 +5,22 @@
|
|||
- issuable_mr = @issuable_meta_data[issuable.id].merge_requests_count
|
||||
|
||||
- if issuable_mr > 0
|
||||
%li.gl-block.has-tooltip{ title: _('Related merge requests'), data: { testid: 'merge-requests' }, class: 'gl-mr-0!' }
|
||||
%li.gl-block.has-tooltip{ title: _('Related merge requests'), data: { testid: 'merge-requests' }, class: '!gl-mr-0' }
|
||||
= sprite_icon('merge-request', css_class: "gl-align-middle")
|
||||
= issuable_mr
|
||||
|
||||
- if note_count > 0
|
||||
%li.gl-block.has-tooltip{ title: _('Comments'), data: { testid: 'issuable-comments' }, class: 'gl-mr-0!' }
|
||||
%li.gl-block.has-tooltip{ title: _('Comments'), data: { testid: 'issuable-comments' }, class: '!gl-mr-0' }
|
||||
= sprite_icon('comments', css_class: "gl-align-middle")
|
||||
= note_count
|
||||
|
||||
- if upvotes > 0
|
||||
%li.gl-block.has-tooltip{ title: _('Upvotes'), data: { testid: 'issuable-upvotes' }, class: 'gl-mr-0!' }
|
||||
%li.gl-block.has-tooltip{ title: _('Upvotes'), data: { testid: 'issuable-upvotes' }, class: '!gl-mr-0' }
|
||||
= sprite_icon('thumb-up', css_class: "gl-align-middle")
|
||||
= upvotes
|
||||
|
||||
- if downvotes > 0
|
||||
%li.gl-block.has-tooltip{ title: _('Downvotes'), data: { testid: 'issuable-downvotes' }, class: 'gl-mr-0!' }
|
||||
%li.gl-block.has-tooltip{ title: _('Downvotes'), data: { testid: 'issuable-downvotes' }, class: '!gl-mr-0' }
|
||||
= sprite_icon('thumb-down', css_class: "gl-align-middle")
|
||||
= downvotes
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
= render "shared/label_row", label: label, force_priority: force_priority
|
||||
%ul.label-actions-list
|
||||
- if can?(current_user, :admin_label, @project)
|
||||
%li.gl-display-inline-block.js-toggle-priority.gl-ml-3{ data: { url: remove_priority_project_label_path(@project, label),
|
||||
%li.gl-inline-block.js-toggle-priority.gl-ml-3{ data: { url: remove_priority_project_label_path(@project, label),
|
||||
dom_id: dom_id(label), type: label.type } }
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary,
|
||||
size: :small,
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
icon: 'star-o',
|
||||
button_options: { class: 'add-priority has-tooltip', title: _('Prioritize'), aria_label: _('Prioritize label'), data: { placement: 'bottom' } })
|
||||
- if current_user
|
||||
%li.gl-display-inline-block.label-subscription.js-label-subscription.gl-ml-3.gl-mt-1
|
||||
%li.gl-inline-block.label-subscription.js-label-subscription.gl-ml-3.gl-mt-1
|
||||
- if label.can_subscribe_to_label_in_different_levels?
|
||||
= render Pajamas::ButtonComponent.new(size: :small, button_options: { class: "js-unsubscribe-button gl-w-full #{'hidden' if status.unsubscribed?}", data: { url: toggle_subscription_path, toggle: 'tooltip', container: 'body' }, title: tooltip_title }) do
|
||||
= _('Unsubscribe')
|
||||
|
|
@ -42,7 +42,7 @@
|
|||
= render Pajamas::ButtonComponent.new(size: :small, button_options: { class: 'js-subscribe-button gl-w-full', data: { status: status, url: toggle_subscription_path, toggle: 'tooltip', container: 'body' }, title: tooltip_title }) do
|
||||
= label_subscription_toggle_button_text(label, @project)
|
||||
- if can?(current_user, :admin_label, label)
|
||||
%li.gl-display-inline-block
|
||||
%li.gl-inline-block
|
||||
- can_promote = label.project_label? && label.project.group && can?(current_user, :admin_label, label.project.group)
|
||||
.js-vue-label-actions{ data: {
|
||||
label_id: label.id,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- full_path = label.subject_full_name
|
||||
|
||||
.gl-font-sm.gl-font-semibold.gl-text-secondary
|
||||
.gl-text-sm.gl-font-semibold.gl-text-secondary
|
||||
- if label.project_label?
|
||||
= sprite_icon('project', size: 12, css_class: 'gl-text-gray-600')
|
||||
- else
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
- show_label_issues_link = subject_or_group_defined && show_label_issuables_link?(label, :issues)
|
||||
- show_label_merge_requests_link = subject_or_group_defined && show_label_issuables_link?(label, :merge_requests)
|
||||
|
||||
.label-name.gl-flex-shrink-0.gl-mr-5
|
||||
.label-name.gl-shrink-0.gl-mr-5
|
||||
= render_label(label, link: '#', tooltip: true, tooltip_shows_title: true)
|
||||
- if show_labels_full_path?(@project, @group)
|
||||
.gl-mt-2
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@
|
|||
= _('Only project members can comment.')
|
||||
|
||||
.md-area.position-relative
|
||||
.md-header.gl-px-3.gl-rounded-top-base.gl-border-b.gl-border-gray-100
|
||||
.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-justify-content-space-between
|
||||
.md-header-toolbar.gl-display-flex.gl-py-3.gl-flex-wrap.gl-gap-y-3
|
||||
.md-header.gl-px-3.gl-rounded-t-base.gl-border-b.gl-border-gray-100
|
||||
.gl-flex.gl-items-center.gl-flex-wrap.gl-justify-between
|
||||
.md-header-toolbar.gl-flex.gl-py-3.gl-flex-wrap.gl-gap-y-3
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, size: :small, button_options: { class: 'js-md-preview-button', value: 'preview' }) do
|
||||
= _('Preview')
|
||||
= render 'shared/blob/markdown_buttons', supports_quick_actions: supports_quick_actions
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
- if can?(current_user, :read_pipeline, merge_request.head_pipeline)
|
||||
%li.issuable-pipeline-status.gl-display-flex
|
||||
= render 'ci/status/icon', status: merge_request.head_pipeline.detailed_status(current_user), option_css_classes: 'gl-display-flex'
|
||||
%li.issuable-pipeline-status.gl-flex
|
||||
= render 'ci/status/icon', status: merge_request.head_pipeline.detailed_status(current_user), option_css_classes: 'gl-flex'
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- count_badge_classes = 'gl-hidden sm:gl-inline-flex'
|
||||
|
||||
= gl_tabs_nav({class: 'gl-border-b-0 gl-flex-grow-1', data: { testid: 'milestones-filter' } }) do
|
||||
= gl_tabs_nav({class: 'gl-border-b-0 gl-grow', data: { testid: 'milestones-filter' } }) do
|
||||
= gl_tab_link_to milestones_filter_path(state: 'opened'), { item_active: params[:state].blank? || params[:state] == 'opened' } do
|
||||
= _('Open')
|
||||
= gl_tab_counter_badge counts[:opened], { class: count_badge_classes }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
- return unless ::Gitlab::SilentMode.enabled?
|
||||
|
||||
= content_for :page_level_alert do
|
||||
%div{ class: [container_class, @content_class, 'gl-pt-5!'] }
|
||||
%div{ class: [container_class, @content_class, '!gl-pt-5'] }
|
||||
= render Pajamas::AlertComponent.new(title: s_('SilentMode|Silent mode is enabled'),
|
||||
dismissible: false,
|
||||
variant: :warning) do |c|
|
||||
|
|
|
|||
|
|
@ -3,4 +3,4 @@
|
|||
- fork_options = fork_modal_options(@project, blob)
|
||||
- css_classes = false unless local_assigns[:css_classes]
|
||||
|
||||
.gl-display-inline-block{ data: { options: button_data.merge(fork_options).to_json, web_ide_promo_popover_img: image_path('web-ide-promo-popover.svg'), css_classes: css_classes }, id: "js-#{type}-web-ide-link" }
|
||||
.gl-inline-block{ data: { options: button_data.merge(fork_options).to_json, web_ide_promo_popover_img: image_path('web-ide-promo-popover.svg'), css_classes: css_classes }, id: "js-#{type}-web-ide-link" }
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
= f.text_field :title, class: 'form-control gl-form-input gl-form-input-xl', required: true, data: { testid: 'deploy-key-title-field' }
|
||||
.form-group
|
||||
= f.label :key, class: "label-bold"
|
||||
= f.text_area :key, class: 'form-control gl-form-input gl-form-input-xl gl-h-auto!', rows: 5, required: true, data: { testid: 'deploy-key-field' }
|
||||
= f.text_area :key, class: 'form-control gl-form-input gl-form-input-xl !gl-h-auto', rows: 5, required: true, data: { testid: 'deploy-key-field' }
|
||||
.form-text.text-muted
|
||||
= _('Paste a public key here.')
|
||||
= link_to _('How do I generate it?'), help_page_path("user/ssh")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- show_cancel_button = local_assigns.fetch(:cancel, false)
|
||||
|
||||
= gitlab_ui_form_for @application, url: url, html: { role: 'form', class: 'doorkeeper-app-form gl-max-w-80 gl-display-inline-block' } do |f|
|
||||
= gitlab_ui_form_for @application, url: url, html: { role: 'form', class: 'doorkeeper-app-form gl-max-w-80 gl-inline-block' } do |f|
|
||||
= form_errors(@application)
|
||||
|
||||
.form-group
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
= render "shared/tokens/scopes_list", token: @application
|
||||
|
||||
.gl-display-flex.gl-justify-content-space-between
|
||||
.gl-flex.gl-justify-between
|
||||
%div
|
||||
- if @created
|
||||
= link_button_to _('Continue'), index_path, class: 'gl-mr-3', variant: :confirm
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
- preview_url = preview_markdown_path(project, target_type: model.class.name)
|
||||
|
||||
.form-group
|
||||
.gl-display-flex
|
||||
.gl-flex
|
||||
= form.label :description, _('Description'), class: 'gl-block'
|
||||
- if model.is_a?(MergeRequest)
|
||||
= render_if_exists "/shared/form_elements/summarize_merge_request"
|
||||
|
|
|
|||
|
|
@ -1,27 +1,27 @@
|
|||
- user = local_assigns.fetch(:user, current_user)
|
||||
- access = user&.max_member_access_for_group(group.id)
|
||||
|
||||
%li.group-row.py-3.gl-align-items-center{ class: "gl-display-flex!" }
|
||||
%li.group-row.py-3.gl-items-center{ class: "!gl-flex" }
|
||||
= link_to group do
|
||||
= render Pajamas::AvatarComponent.new(group, alt: group.name, size: 48, class: 'gl-mr-5')
|
||||
.gl-min-w-0.gl-flex-grow-1
|
||||
.gl-min-w-0.gl-grow
|
||||
.title
|
||||
= link_to group.full_name, group, class: 'group-name'
|
||||
|
||||
- if access&.nonzero?
|
||||
= render Pajamas::BadgeComponent.new(Gitlab::Access.human_access(access), variant: 'neutral', class: 'gl-bg-transparent! !gl-shadow-inner-1-gray-100')
|
||||
= render Pajamas::BadgeComponent.new(Gitlab::Access.human_access(access), variant: 'neutral', class: '!gl-bg-transparent !gl-shadow-inner-1-gray-100')
|
||||
|
||||
- if group.description.present?
|
||||
.description
|
||||
= markdown_field(group, :description)
|
||||
|
||||
.stats.gl-text-gray-500.gl-flex-shrink-0
|
||||
.stats.gl-text-gray-500.gl-shrink-0
|
||||
%span.gl-ml-5.has-tooltip{ title: _('Projects') }
|
||||
= sprite_icon('project', css_class: 'gl-vertical-align-text-bottom')
|
||||
= sprite_icon('project', css_class: 'gl-align-text-bottom')
|
||||
= number_with_delimiter(group.non_archived_projects.size)
|
||||
|
||||
%span.gl-ml-5.has-tooltip{ title: _('Users') }
|
||||
= sprite_icon('users', css_class: 'gl-vertical-align-text-bottom')
|
||||
= sprite_icon('users', css_class: 'gl-align-text-bottom')
|
||||
= number_with_delimiter(group.non_invite_group_members.size)
|
||||
|
||||
%span.gl-ml-5.visibility-icon.has-tooltip{ data: { container: 'body', placement: 'left' }, title: visibility_icon_description(group) }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%span.gl-display-flex.gl-align-items-center
|
||||
%span.gl-flex.gl-items-center
|
||||
%h5
|
||||
= gl_badge_tag "POST", { variant: :info }
|
||||
= hook_log.url
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
- c.with_body do
|
||||
= _('Error: %{error}') % { error: hook_log.internal_error_message }
|
||||
|
||||
%span.gl-display-flex.gl-align-items-center
|
||||
%span.gl-flex.gl-items-center
|
||||
%h3
|
||||
= _('Response')
|
||||
= render partial: 'shared/hook_logs/status_label', locals: { hook_log: hook_log }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
- breadcrumb_title @integration.title
|
||||
- page_title @integration.title, _('Integrations')
|
||||
|
||||
.gl-display-flex.gl-align-items-center.gl-gap-3.gl-mt-5
|
||||
.gl-flex.gl-items-center.gl-gap-3.gl-mt-5
|
||||
= render Pajamas::AvatarComponent.new(@integration, size: 64, alt: '')
|
||||
%h2.gl-m-0
|
||||
= @integration.title
|
||||
|
|
|
|||
|
|
@ -12,15 +12,15 @@
|
|||
%th= _('Created')
|
||||
%th
|
||||
%tr
|
||||
%td{ class: 'gl-py-3!' }
|
||||
%td{ class: '!gl-py-3' }
|
||||
= slack_integration.team_name
|
||||
- if integration.project_level?
|
||||
%td{ class: 'gl-py-3!' }
|
||||
%td{ class: '!gl-py-3' }
|
||||
= slack_integration.alias
|
||||
%td{ class: 'gl-py-3!' }
|
||||
%td{ class: '!gl-py-3' }
|
||||
= time_ago_with_tooltip(slack_integration.created_at)
|
||||
%td{ class: 'gl-py-3!' }
|
||||
.controls.gl-display-flex.gl-justify-content-end.gl-gap-3
|
||||
%td{ class: '!gl-py-3' }
|
||||
.controls.gl-flex.gl-justify-end.gl-gap-3
|
||||
- if integration.project_level?
|
||||
= render Pajamas::ButtonComponent.new(href: edit_project_settings_slack_path(integration.parent)) do
|
||||
= _('Edit')
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
.services-installation-info
|
||||
- unless integration.activated?
|
||||
= render Pajamas::ButtonComponent.new(href: new_project_mattermost_path(@project), button_text_classes: 'gl-display-flex gl-gap-2') do
|
||||
= render Pajamas::ButtonComponent.new(href: new_project_mattermost_path(@project), button_text_classes: 'gl-flex gl-gap-2') do
|
||||
= custom_icon('mattermost_logo')
|
||||
= s_("MattermostService|Add to Mattermost")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
- breadcrumb_title @integration.title
|
||||
- page_title @integration.title, _('Integrations')
|
||||
|
||||
%h1.page-title.gl-font-size-h-display
|
||||
%h1.page-title.gl-text-size-h-display
|
||||
= @integration.title
|
||||
|
||||
- if @integration.title == 'Beyond Identity' && Feature.enabled?(:beyond_identity_exclusions)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
- page_context_word = type.to_s.humanize(capitalize: false)
|
||||
- display_count = local_assigns.fetch(:display_count, true)
|
||||
|
||||
= gl_tabs_nav({ class: 'issues-state-filters gl-border-b-0 gl-flex-grow-1' }) do
|
||||
= gl_tabs_nav({ class: 'issues-state-filters gl-border-b-0 gl-grow' }) do
|
||||
= gl_tab_link_to page_filter_path(state: 'opened'), { item_active: params[:state] == 'opened', id: 'state-opened', title: _("Filter by %{page_context_word} that are currently open.") % { page_context_word: page_context_word }, data: { state: 'opened' } } do
|
||||
#{issuables_state_counter_text(type, :opened, display_count)}
|
||||
- if type == :merge_requests
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
- block_css_class = type != :productivity_analytics ? 'row-content-block second-block' : ''
|
||||
|
||||
.issues-filters
|
||||
.issues-details-filters.filtered-search-block.gl-flex.gl-flex-direction-column.gl-lg-flex-direction-row.gl-gap-3{ class: block_css_class }
|
||||
.gl-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-flex-grow-1.gl-w-full
|
||||
.issues-details-filters.filtered-search-block.gl-flex.gl-flex-col.lg:gl-flex-row.gl-gap-3{ class: block_css_class }
|
||||
.gl-flex.gl-flex-col.md:gl-flex-row.gl-grow.gl-w-full
|
||||
= form_tag page_filter_path, method: :get, class: 'filter-form js-filter-form gl-w-full' do
|
||||
- if params[:search].present?
|
||||
= hidden_field_tag :search, params[:search]
|
||||
|
|
@ -18,7 +18,7 @@
|
|||
- c.with_label do
|
||||
%span.gl-sr-only
|
||||
= _('Select all')
|
||||
.issues-other-filters.filtered-search-wrapper.gl-flex.gl-flex-direction-column.gl-md-flex-direction-row
|
||||
.issues-other-filters.filtered-search-wrapper.gl-flex.gl-flex-col.md:gl-flex-row
|
||||
.filtered-search-box
|
||||
- if type != :boards
|
||||
- text = tag.span(sprite_icon('history')) + tag.span(_('Recent searches'), class: "gl-sr-only")
|
||||
|
|
@ -205,7 +205,7 @@
|
|||
= render_if_exists 'shared/issuable/filter_weight', type: type
|
||||
= render_if_exists 'shared/issuable/filter_epic', type: type
|
||||
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, size: :small, icon: 'clear', icon_classes: "clear-search-icon", button_options: { class: 'clear-search hidden gl-align-self-center gl-mr-1 has-tooltip', title: _('Clear') })
|
||||
.filter-dropdown-container.gl-flex.gl-flex-direction-column.gl-md-flex-direction-row.gl-align-items-flex-start
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, size: :small, icon: 'clear', icon_classes: "clear-search-icon", button_options: { class: 'clear-search hidden gl-self-center gl-mr-1 has-tooltip', title: _('Clear') })
|
||||
.filter-dropdown-container.gl-flex.gl-flex-col.md:gl-flex-row.gl-items-start
|
||||
- if type != :productivity_analytics && show_sorting_dropdown
|
||||
= render 'shared/issuable/sort_dropdown'
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@
|
|||
- in_group_context_with_iterations = @project.group.present? && issuable_sidebar[:supports_iterations]
|
||||
- is_merge_request = issuable_type === 'merge_request'
|
||||
- add_page_specific_style 'page_bundles/labels'
|
||||
- sidebar_header_classes = 'md:gl-flex lg:!gl-hidden gl-justify-content-end' if is_merge_request
|
||||
- sidebar_header_classes = 'md:gl-flex lg:!gl-hidden gl-justify-end' if is_merge_request
|
||||
|
||||
%aside.right-sidebar.js-right-sidebar.js-issuable-sidebar{ data: { auto_collapse: true, always_show_toggle: true, signed: { in: signed_in }, issuable_type: issuable_type }, class: "#{sidebar_gutter_collapsed_class(is_merge_request)} #{'right-sidebar-merge-requests' if is_merge_request}", 'aria-live' => 'polite', 'aria-label': issuable_type }
|
||||
.issuable-sidebar{ class: "#{'is-merge-request' if is_merge_request}" }
|
||||
.issuable-sidebar-header{ class: sidebar_header_classes }
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: "gutter-toggle gl-float-right js-sidebar-toggle has-tooltip !gl-shadow-none gl-display-block #{'gl-mt-2' if notifications_todos_buttons_enabled?}" , type: 'button', 'aria-label' => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }) do
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: "gutter-toggle gl-float-right js-sidebar-toggle has-tooltip !gl-shadow-none gl-block #{'gl-mt-2' if notifications_todos_buttons_enabled?}" , type: 'button', 'aria-label' => _('Toggle sidebar'), title: sidebar_gutter_tooltip_text, data: { container: 'body', placement: 'left', boundary: 'viewport' } }) do
|
||||
= sidebar_gutter_toggle_icon
|
||||
- if signed_in
|
||||
- if !is_merge_request
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
- if notifications_todos_buttons_enabled?
|
||||
.js-sidebar-subscriptions-widget-root
|
||||
|
||||
= form_for issuable_type, url: issuable_sidebar[:issuable_json_path], remote: true, html: { class: "issuable-context-form inline-update js-issuable-update #{'gl-pr-2!' if is_merge_request}" } do |f|
|
||||
= form_for issuable_type, url: issuable_sidebar[:issuable_json_path], remote: true, html: { class: "issuable-context-form inline-update js-issuable-update #{'!gl-pr-2' if is_merge_request}" } do |f|
|
||||
.block.assignee{ class: "#{'gl-mt-3' if !signed_in}", data: { testid: 'assignee-block-container' } }
|
||||
= render "shared/issuable/sidebar_assignees", issuable_sidebar: issuable_sidebar, assignees: assignees, signed_in: signed_in
|
||||
|
||||
|
|
@ -63,7 +63,7 @@
|
|||
- if issuable_sidebar[:supports_time_tracking]
|
||||
.js-sidebar-time-tracking-root.block
|
||||
// Fallback while content is loading
|
||||
.title.hide-collapsed.gl-display-flex.gl-justify-content-space-between.gl-align-items-center{ class: 'gl-mb-0!' }
|
||||
.title.hide-collapsed.gl-flex.gl-justify-between.gl-items-center{ class: '!gl-mb-0' }
|
||||
%span.gl-font-bold= _('Time tracking')
|
||||
= gl_loading_icon(inline: true)
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,6 @@
|
|||
.js-sidebar-assignees-root{ data: { field: issuable_type,
|
||||
max_assignees: dropdown_options[:data][:"max-select"],
|
||||
directly_invite_members: can_admin_project_member?(@project) } }
|
||||
.title.hide-collapsed.gl-display-flex.gl-justify-content-space-between.gl-align-items-center{ class: 'gl-mb-0!' }
|
||||
.title.hide-collapsed.gl-flex.gl-justify-between.gl-items-center{ class: '!gl-mb-0' }
|
||||
%span.gl-font-bold= s_('Label|Assignee')
|
||||
= gl_loading_icon(inline: true)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
- issuable_type = issuable_sidebar[:type]
|
||||
|
||||
.js-sidebar-reviewers-root{ data: { field: issuable_type, signed_in: signed_in } }
|
||||
.title.hide-collapsed.gl-display-flex.gl-justify-content-space-between.gl-align-items-center{ class: 'gl-mb-0!' }
|
||||
.title.hide-collapsed.gl-flex.gl-justify-between.gl-items-center{ class: '!gl-mb-0' }
|
||||
%span.gl-font-bold= _('Reviewers')
|
||||
= gl_loading_icon(inline: true)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,4 +8,4 @@
|
|||
= hidden_field_tag "#{issuable.to_ability_name}[assignee_ids][]", 0, id: nil, data: { meta: '' }
|
||||
|
||||
= dropdown_tag(users_dropdown_label(issuable.assignees), options: assignees_dropdown_options(issuable.to_ability_name))
|
||||
= link_to _('Assign to me'), '#', class: "assign-to-me-link gl-whitespace-nowrap gl-md-pl-3 #{'hide' if issuable.assignees.include?(current_user)}", data: { testid: 'assign-to-me-link' }
|
||||
= link_to _('Assign to me'), '#', class: "assign-to-me-link gl-whitespace-nowrap md:gl-pl-3 #{'hide' if issuable.assignees.include?(current_user)}", data: { testid: 'assign-to-me-link' }
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
= f.label :color, _("Background color")
|
||||
.input-group
|
||||
.input-group-prepend
|
||||
%input.label-color-preview.gl-w-7.gl-h-full.gl-border-1.gl-border-solid.gl-border-gray-500.gl-border-r-0.gl-rounded-top-right-none.gl-rounded-bottom-right-none{ type: "color", placeholder: _('Select color') }
|
||||
%input.label-color-preview.gl-w-7.gl-h-full.gl-border-1.gl-border-solid.gl-border-gray-500.gl-border-r-0.gl-rounded-tr-none.gl-rounded-br-none{ type: "color", placeholder: _('Select color') }
|
||||
= f.text_field :color, class: "gl-form-input form-control", data: { testid: 'label-color-field' }
|
||||
.form-text.text-muted
|
||||
= _('Select a color from the color picker or from the presets below.')
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
_('Lock label after a merge request is merged'),
|
||||
help_text: label_lock_on_merge_help_text,
|
||||
checkbox_options: { disabled: @label.lock_on_merge }
|
||||
.gl-display-flex.gl-justify-content-space-between
|
||||
.gl-flex.gl-justify-between
|
||||
%div
|
||||
- if @label.persisted?
|
||||
= f.submit _('Save changes'), class: 'js-save-button gl-mr-2', pajamas_button: true
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
- subscribed = params[:subscribed]
|
||||
|
||||
.top-area.adjust
|
||||
= gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
|
||||
= gl_tabs_nav({ class: 'gl-grow gl-border-0' }) do
|
||||
= gl_tab_link_to _('All'), labels_filter_path, { item_active: subscribed != 'true' }
|
||||
- if current_user
|
||||
= gl_tab_link_to _('Subscribed'), labels_filter_path(subscribed: 'true'), { item_active: subscribed == 'true' }
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
|
||||
- if source.instance_of?(Group) && source != membership_source
|
||||
·
|
||||
= link_to source.full_name, source, class: "gl-display-inline-block inline-link"
|
||||
= link_to source.full_name, source, class: "gl-inline-block inline-link"
|
||||
|
||||
.gl-text-secondary.gl-text-sm
|
||||
- if member.request?
|
||||
|
|
@ -61,4 +61,4 @@
|
|||
- if show_roles
|
||||
.controls.member-controls.gl-items-center.gl-self-end
|
||||
= render_if_exists 'shared/members/ee/ldap_tag', can_override: member.can_override?
|
||||
= render Pajamas::BadgeComponent.new(member.human_access, variant: 'neutral', class: 'gl-bg-transparent! !gl-shadow-inner-1-gray-100')
|
||||
= render Pajamas::BadgeComponent.new(member.human_access, variant: 'neutral', class: '!gl-bg-transparent !gl-shadow-inner-1-gray-100')
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
.gl-px-3.gl-py-3.gl-display-flex.gl-flex-direction-column.gl-md-flex-direction-row
|
||||
.gl-px-3.gl-py-3.gl-flex.gl-flex-col.md:gl-flex-row
|
||||
= yield
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
.gl-display-flex.gl-md-align-items-center.gl-flex-direction-column.gl-md-flex-direction-row.row-content-block.second-block
|
||||
.gl-flex.md:gl-items-center.gl-flex-col.md:gl-flex-row.row-content-block.second-block
|
||||
= yield
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
%span.gl-flex-grow-1.gl-py-3.gl-pr-3
|
||||
%span.gl-grow.gl-py-3.gl-pr-3
|
||||
= yield
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
- can_promote = @project && can_admin_group_milestones? && milestone.project
|
||||
- can_read_milestone = can?(current_user, :read_milestone, @milestone)
|
||||
|
||||
.milestone-buttons.detail-page-header-actions.gl-display-flex.gl-align-self-start.gl-gap-3
|
||||
.milestone-buttons.detail-page-header-actions.gl-flex.gl-self-start.gl-gap-3
|
||||
- if milestone.active?
|
||||
= render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :close }), method: :put, button_options: { class: 'btn-close gl-hidden md:gl-inline-block' }) do
|
||||
= _('Close milestone')
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@
|
|||
- c.with_header do
|
||||
.gl-flex-grow-2
|
||||
= title
|
||||
.gl-ml-3.gl-flex-shrink-0.gl-font-bold.gl-whitespace-nowrap{ class: milestone_counter_class(primary) }
|
||||
.gl-ml-3.gl-shrink-0.gl-font-bold.gl-whitespace-nowrap{ class: milestone_counter_class(primary) }
|
||||
- if show_counter
|
||||
%span
|
||||
= sprite_icon('issues', css_class: 'gl-vertical-align-text-bottom')
|
||||
= sprite_icon('issues', css_class: 'gl-align-text-bottom')
|
||||
= number_with_delimiter(issuables.length)
|
||||
= render_if_exists "shared/milestones/issuables_weight", issuables: issuables
|
||||
- c.with_body do
|
||||
|
|
|
|||
|
|
@ -11,11 +11,11 @@
|
|||
- open_issues = milestone_issues_by_label_count(@milestone, label, state: :opened)
|
||||
- closed_issues = milestone_issues_by_label_count(@milestone, label, state: :closed)
|
||||
|
||||
%li.gl-list-style-none.gl-border-b.gl-last-of-type-border-b-0.md:gl-flex.gl-px-5.gl-py-4.gl-gap-5.gl-align-items-baseline
|
||||
.gl-md-w-20.gl-flex-shrink-0.gl-flex-grow-1.gl-mb-4.gl-md-mb-0
|
||||
%li.gl-list-none.gl-border-b.gl-last-of-type-border-b-0.md:gl-flex.gl-px-5.gl-py-4.gl-gap-5.gl-items-baseline
|
||||
.md:gl-w-20.gl-shrink-0.gl-grow.gl-mb-4.md:gl-mb-0
|
||||
= render_label(label, tooltip: false, link: milestones_issues_path(options))
|
||||
- if markdown_field(label, :description).present?
|
||||
.gl-w-full.gl-mb-4.gl-md-mb-0
|
||||
.gl-w-full.gl-mb-4.md:gl-mb-0
|
||||
= markdown_field(label, :description)
|
||||
= render Pajamas::ButtonComponent.new(variant: :link, disabled: open_issues == 0, href: milestones_issues_path(options.merge(state: 'opened'))) do
|
||||
= open_issues
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@
|
|||
- if can_admin_milestone
|
||||
- show_delete = @project.present? || @group.present?
|
||||
.col-1.order-2.order-md-3
|
||||
.gl-flex.gl-justify-content-end
|
||||
.gl-flex.gl-justify-end
|
||||
.js-vue-milestone-actions{ data: { id: milestone.id,
|
||||
title: milestone.title,
|
||||
is_active: milestone.active?.to_s,
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
%ul.bordered-list
|
||||
- users.each do |user|
|
||||
%li
|
||||
= link_to user, title: user.name, class: "gl-display-flex" do
|
||||
= link_to user, title: user.name, class: "gl-flex" do
|
||||
= render Pajamas::AvatarComponent.new(user, size: 32, class: "gl-mr-3")
|
||||
.gl-display-flex.gl-flex-direction-column
|
||||
.gl-flex.gl-flex-col
|
||||
%strong= truncate(user.name, length: 40)
|
||||
%small.gl-text-primary= user.username
|
||||
|
|
|
|||
|
|
@ -165,8 +165,8 @@
|
|||
- if milestone_ref.present?
|
||||
.block.reference
|
||||
= clipboard_button(text: milestone_ref, title: s_('MilestoneSidebar|Copy reference'), placement: "left", boundary: 'viewport', class: 'sidebar-collapsed-icon js-dont-change-state')
|
||||
.gl-display-flex.gl-align-items-center.gl-justify-content-space-between.gl-mb-2.hide-collapsed
|
||||
%span.gl-overflow-hidden.gl-text-overflow-ellipsis.gl-whitespace-nowrap
|
||||
.gl-flex.gl-items-center.gl-justify-between.gl-mb-2.hide-collapsed
|
||||
%span.gl-overflow-hidden.gl-text-ellipsis.gl-whitespace-nowrap
|
||||
= s_('MilestoneSidebar|Reference:')
|
||||
%span{ title: milestone_ref }
|
||||
= milestone_ref
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- noteable_name = @note.noteable.human_class_name
|
||||
|
||||
.js-comment-type-dropdown.float-left.gl-sm-mr-3{ data: { noteable_name: noteable_name } }
|
||||
.js-comment-type-dropdown.float-left.sm:gl-mr-3{ data: { noteable_name: noteable_name } }
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, variant: :confirm, button_options: { class: 'js-comment-button js-comment-submit-button', value: _('Comment'), data: { testid: 'comment-button' }}) do
|
||||
= _('Comment')
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
- else
|
||||
- preview_url = preview_markdown_path(@project)
|
||||
|
||||
= form_for form_resources, url: new_form_url, remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new-note js-new-note-form js-quick-submit common-note-form discussion-reply-holder gl-border-top-0!", "data-noteable-iid" => @note.noteable.try(:iid), }, authenticity_token: true do |f|
|
||||
= form_for form_resources, url: new_form_url, remote: true, html: { :'data-type' => 'json', multipart: true, id: nil, class: "new-note js-new-note-form js-quick-submit common-note-form discussion-reply-holder !gl-border-t-0", "data-noteable-iid" => @note.noteable.try(:iid), }, authenticity_token: true do |f|
|
||||
= hidden_field_tag :view, diff_view
|
||||
= hidden_field_tag :line_type
|
||||
= hidden_field_tag :merge_request_diff_head_sha, @note.noteable.try(:diff_head_sha)
|
||||
|
|
@ -35,7 +35,7 @@
|
|||
= render 'shared/notes/hints'
|
||||
.error-alert
|
||||
|
||||
.note-form-actions.clearfix.gl-display-flex.gl-flex-wrap
|
||||
.note-form-actions.clearfix.gl-flex.gl-flex-wrap
|
||||
= render partial: 'shared/notes/comment_button'
|
||||
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'js-close-discussion-note-form hide' }) do
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
- supports_file_upload = local_assigns.fetch(:supports_file_upload, true)
|
||||
.comment-toolbar.gl-px-2.gl-display-flex.gl-justify-content-end.gl-rounded-bottom-left-base.gl-rounded-bottom-right-base.clearfix
|
||||
.content-editor-switcher.gl-inline-flex.gl-align-items-center
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, icon: 'markdown-mark', size: :small, href: help_page_path('user/markdown'), target: '_blank', button_options: { class: 'gl-px-3!' })
|
||||
.comment-toolbar.gl-px-2.gl-flex.gl-justify-end.gl-rounded-bl-base.gl-rounded-br-base.clearfix
|
||||
.content-editor-switcher.gl-inline-flex.gl-items-center
|
||||
= render Pajamas::ButtonComponent.new(category: :tertiary, icon: 'markdown-mark', size: :small, href: help_page_path('user/markdown'), target: '_blank', button_options: { class: '!gl-px-3' })
|
||||
- if supports_file_upload
|
||||
%span.uploading-container.gl-leading-32.gl-font-sm
|
||||
%span.uploading-container.gl-leading-32.gl-text-sm
|
||||
%span.uploading-progress-container.hide
|
||||
= sprite_icon('paperclip', css_class: 'gl-icon gl-vertical-align-text-bottom')
|
||||
= sprite_icon('paperclip', css_class: 'gl-icon gl-align-text-bottom')
|
||||
%span.attaching-file-message
|
||||
-# Populated by app/assets/javascripts/dropzone_input.js
|
||||
%span.uploading-progress 0%
|
||||
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
%span.uploading-error-container.hide
|
||||
%span.uploading-error-icon
|
||||
= sprite_icon('paperclip', css_class: 'gl-icon gl-vertical-align-text-bottom')
|
||||
= sprite_icon('paperclip', css_class: 'gl-icon gl-align-text-bottom')
|
||||
%span.uploading-error-message
|
||||
-# Populated by app/assets/javascripts/dropzone_input.js
|
||||
= render Pajamas::ButtonComponent.new(variant: :link, button_options: { class: 'retry-uploading-link' }) do
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
- elsif note_counter == 0
|
||||
- counter = badge_counter if local_assigns[:badge_counter]
|
||||
- badge_class = "hidden" if @fresh_discussion || counter.nil?
|
||||
%span.gl-display-flex.gl-align-items-center.gl-justify-content-center.gl-font-sm.design-note-pin.small.user-avatar{ class: badge_class }
|
||||
%span.gl-flex.gl-items-center.gl-justify-center.gl-text-sm.design-note-pin.small.user-avatar{ class: badge_class }
|
||||
= counter
|
||||
.timeline-content
|
||||
.note-header
|
||||
|
|
@ -67,8 +67,8 @@
|
|||
- if note.system
|
||||
.system-note-commit-list-toggler.hide
|
||||
= _("Toggle commit list")
|
||||
= sprite_icon('chevron-down', css_class: 'js-chevron-down gl-ml-1 gl-vertical-align-text-bottom')
|
||||
= sprite_icon('chevron-up', css_class: 'js-chevron-up gl-ml-1 gl-vertical-align-text-bottom gl-hidden')
|
||||
= sprite_icon('chevron-down', css_class: 'js-chevron-down gl-ml-1 gl-align-text-bottom')
|
||||
= sprite_icon('chevron-up', css_class: 'js-chevron-up gl-ml-1 gl-align-text-bottom gl-hidden')
|
||||
- if note.attachment.url
|
||||
.note-attachment
|
||||
- if note.attachment.image?
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
- @sort ||= sort_value_latest_activity
|
||||
.dropdown.js-project-filter-dropdown-wrap.gl-inline{ class: 'gl-m-0!' }
|
||||
.dropdown.js-project-filter-dropdown-wrap.gl-inline{ class: '!gl-m-0' }
|
||||
= dropdown_toggle(projects_sort_options_hash[@sort], { toggle: 'dropdown', display: 'static' }, { id: 'sort-projects-dropdown' })
|
||||
%ul.dropdown-menu.dropdown-menu-right.dropdown-menu-selectable
|
||||
%li.dropdown-header
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@
|
|||
- load_max_project_member_accesses(projects) # Prime cache used in shared/projects/project view rendered below
|
||||
- load_catalog_resources(projects)
|
||||
- if card_mode
|
||||
.projects-list.gl-text-secondary.gl-w-full.gl-display-flex.gl-flex-direction-column.gl-lg-flex-direction-row.gl-gap-4.gl-overflow-x-auto{ class: css_classes }
|
||||
.projects-list.gl-text-secondary.gl-w-full.gl-flex.gl-flex-col.lg:gl-flex-row.gl-gap-4.gl-overflow-x-auto{ class: css_classes }
|
||||
- projects.take(projects_limit).each_with_index do |project, i| # rubocop: disable CodeReuse/ActiveRecord -- it's Enumerable#take
|
||||
|
||||
= render "shared/projects/project_card", project: project, skip_namespace: skip_namespace,
|
||||
|
|
|
|||
|
|
@ -9,12 +9,12 @@
|
|||
- use_creator_avatar = local_assigns[:use_creator_avatar]
|
||||
- show_last_commit_as_description = false unless local_assigns[:show_last_commit_as_description] == true && can_show_last_commit_in_list?(project)
|
||||
- access = max_project_member_access(project)
|
||||
- css_class = "sm:gl-flex gl-align-items-center !gl-align-middle" if project.description.blank? && !show_last_commit_as_description
|
||||
- css_class = "sm:gl-flex gl-items-center !gl-align-middle" if project.description.blank? && !show_last_commit_as_description
|
||||
- updated_tooltip = time_ago_with_tooltip(project.last_activity_at || project.updated_at)
|
||||
- show_pipeline_status_icon = pipeline_status && can?(current_user, :read_cross_project) && project.pipeline_status.has_status? && can?(current_user, :read_build, project)
|
||||
- last_pipeline = last_pipeline_from_status_cache(project) if show_pipeline_status_icon
|
||||
- css_controls_class = "with-pipeline-status" if show_pipeline_status_icon && last_pipeline.present?
|
||||
- css_metadata_classes = "gl-display-flex gl-align-items-center !gl-text-inherit icon-wrapper has-tooltip"
|
||||
- css_metadata_classes = "gl-flex gl-items-center !gl-text-inherit icon-wrapper has-tooltip"
|
||||
|
||||
%li.project-row
|
||||
- if avatar
|
||||
|
|
@ -26,9 +26,9 @@
|
|||
= render Pajamas::AvatarComponent.new(project, size: 48, alt: '')
|
||||
|
||||
.project-cell{ class: css_class }
|
||||
.project-details.gl-pr-9.gl-sm-pr-0.gl-w-full.gl-display-flex.gl-flex-direction-column{ data: { testid: 'project-content', qa_project_name: project.name } }
|
||||
.gl-display-flex.gl-align-items-baseline.gl-flex-wrap
|
||||
%h2.gl-font-base.gl-leading-20.gl-my-0.gl-wrap-anywhere
|
||||
.project-details.gl-pr-9.gl-sm-pr-0.gl-w-full.gl-flex.gl-flex-col{ data: { testid: 'project-content', qa_project_name: project.name } }
|
||||
.gl-flex.gl-items-baseline.gl-flex-wrap
|
||||
%h2.gl-text-base.gl-leading-20.gl-my-0.gl-wrap-anywhere
|
||||
= link_to project_path(project), class: 'gl-text-default hover:gl-text-default gl-mr-3 js-prefetch-document', title: project.name do
|
||||
%span.namespace-name.gl-font-normal
|
||||
- if project.namespace && !skip_namespace
|
||||
|
|
@ -43,26 +43,26 @@
|
|||
= visibility_level_content(project, css_class: 'gl-mr-2')
|
||||
|
||||
- if project.catalog_resource
|
||||
= render partial: 'shared/ci_catalog_badge', locals: { href: explore_catalog_path(project.catalog_resource), css_class: 'gl-align-self-center gl-mr-2' }
|
||||
= render partial: 'shared/ci_catalog_badge', locals: { href: explore_catalog_path(project.catalog_resource), css_class: 'gl-self-center gl-mr-2' }
|
||||
|
||||
- if explore_projects_tab? && project_license_name(project)
|
||||
%span.gl-inline-flex.gl-align-items-center.gl-mr-3
|
||||
%span.gl-inline-flex.gl-items-center.gl-mr-3
|
||||
= sprite_icon('scale', size: 14, css_class: 'gl-mr-2')
|
||||
= project_license_name(project)
|
||||
|
||||
- if !explore_projects_tab? && access&.nonzero?
|
||||
-# haml-lint:disable UnnecessaryStringOutput
|
||||
= ' ' # prevent haml from eating the space between elements
|
||||
= render Pajamas::BadgeComponent.new(localized_project_human_access(access), variant: 'neutral', class: 'gl-bg-transparent! !gl-shadow-inner-1-gray-100', data: { testid: 'user-access-role' })
|
||||
= render Pajamas::BadgeComponent.new(localized_project_human_access(access), variant: 'neutral', class: '!gl-bg-transparent !gl-shadow-inner-1-gray-100', data: { testid: 'user-access-role' })
|
||||
|
||||
- if !explore_projects_tab?
|
||||
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: project, additional_classes: 'gl-ml-2!'
|
||||
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: project, additional_classes: '!gl-ml-2'
|
||||
|
||||
- if show_last_commit_as_description
|
||||
.description.gl-hidden.sm:gl-block.gl-overflow-hidden.gl-mr-3.gl-mt-2.gl-font-sm
|
||||
.description.gl-hidden.sm:gl-block.gl-overflow-hidden.gl-mr-3.gl-mt-2.gl-text-sm
|
||||
= link_to_markdown(project.commit.title, project_commit_path(project, project.commit), class: "commit-row-message")
|
||||
- elsif project.description.present?
|
||||
.description.gl-hidden.sm:gl-block.gl-overflow-hidden.gl-mr-3.gl-mt-2.gl-font-sm
|
||||
.description.gl-hidden.sm:gl-block.gl-overflow-hidden.gl-mr-3.gl-mt-2.gl-text-sm
|
||||
= markdown_field(project, :description)
|
||||
|
||||
- if project.topics.any?
|
||||
|
|
@ -71,8 +71,8 @@
|
|||
|
||||
= render_if_exists 'shared/projects/removed', project: project
|
||||
|
||||
.gl-display-flex.gl-align-items-center.gl-mt-3{ class: "#{css_class} sm:!gl-hidden" }
|
||||
.controls.gl-display-flex.gl-align-items-center
|
||||
.gl-flex.gl-items-center.gl-mt-3{ class: "#{css_class} sm:!gl-hidden" }
|
||||
.controls.gl-flex.gl-items-center
|
||||
- if show_pipeline_status_icon && last_pipeline.present?
|
||||
- pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
|
||||
%span.icon-wrapper.pipeline-status
|
||||
|
|
@ -83,14 +83,14 @@
|
|||
= link_to project_starrers_path(project), class: "#{css_metadata_classes} stars", title: _('Stars'), data: { container: 'body', placement: 'top' } do
|
||||
= sprite_icon('star-o', size: 14, css_class: 'gl-mr-2')
|
||||
= badge_count(project.star_count)
|
||||
.updated-note.gl-font-sm.gl-ml-3.gl-sm-ml-0
|
||||
.updated-note.gl-text-sm.gl-ml-3.gl-sm-ml-0
|
||||
%span
|
||||
= _('Updated')
|
||||
= updated_tooltip
|
||||
= render_if_exists 'shared/projects/actions', project: project
|
||||
|
||||
.project-cell.project-controls{ class: "#{css_class} !gl-hidden sm:!gl-table-cell", data: { testid: 'project_controls'} }
|
||||
.controls.gl-display-flex.gl-align-items-center.gl-mb-2.gl-gap-4{ class: "#{css_controls_class} gl-pr-0! gl-justify-content-end!" }
|
||||
.controls.gl-flex.gl-items-center.gl-mb-2.gl-gap-4{ class: "#{css_controls_class} !gl-pr-0 !gl-justify-end" }
|
||||
- if show_pipeline_status_icon && last_pipeline.present?
|
||||
- pipeline_path = pipelines_project_commit_path(project.pipeline_status.project, project.pipeline_status.sha, ref: project.pipeline_status.ref)
|
||||
%span.icon-wrapper.pipeline-status
|
||||
|
|
@ -114,7 +114,7 @@
|
|||
= sprite_icon('issues', size: 14, css_class: 'gl-mr-2')
|
||||
= badge_count(project.open_issues_count)
|
||||
= render_if_exists 'shared/projects/actions', project: project
|
||||
.updated-note.gl-font-sm.gl-whitespace-nowrap.gl-justify-content-end
|
||||
.updated-note.gl-text-sm.gl-whitespace-nowrap.gl-justify-end
|
||||
%span
|
||||
= _('Updated')
|
||||
= updated_tooltip
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
.gl-w-full.gl-pt-2.gl-break-anywhere
|
||||
.gl-flex.gl-items-center.gl-flex-wrap
|
||||
%h2.gl-font-base.gl-leading-20.gl-my-0
|
||||
%h2.gl-text-base.gl-leading-20.gl-my-0
|
||||
= link_to project_path(project), class: 'gl-text-default hover:gl-text-default gl-mr-3 js-prefetch-document', title: project.name do
|
||||
%span.namespace-name.gl-font-normal
|
||||
- if project.namespace && !skip_namespace
|
||||
|
|
@ -38,10 +38,10 @@
|
|||
= visibility_level_content(project)
|
||||
|
||||
- if show_last_commit_as_description
|
||||
.description.gl-hidden.sm:gl-block.gl-mt-2.gl-font-sm
|
||||
.description.gl-hidden.sm:gl-block.gl-mt-2.gl-text-sm
|
||||
= link_to_markdown(project.commit.title, project_commit_path(project, project.commit), class: "commit-row-message")
|
||||
- elsif project.description.present?
|
||||
.description.gl-hidden.sm:gl-block.gl-mt-2.gl-font-sm
|
||||
.description.gl-hidden.sm:gl-block.gl-mt-2.gl-text-sm
|
||||
= markdown_field(project, :description)
|
||||
|
||||
- if project.topics.any?
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
= render 'ci/status/icon', status: last_pipeline.detailed_status(current_user), tooltip_placement: 'top', path: pipeline_path
|
||||
|
||||
= render_if_exists 'shared/projects/badges', project: project
|
||||
.updated-note.gl-font-sm.gl-whitespace-nowrap.gl-justify-content-start
|
||||
.updated-note.gl-text-sm.gl-whitespace-nowrap.gl-justify-start
|
||||
%span
|
||||
= _('Updated')
|
||||
= updated_tooltip
|
||||
|
|
|
|||
|
|
@ -47,5 +47,5 @@
|
|||
- if params[:namespace_id].present?
|
||||
- namespace = Namespace.find(params[:namespace_id])
|
||||
- selected_text = "#{namespace.kind}: #{namespace.full_path}" if namespace
|
||||
.gl-flex.gl-w-full.gl-md-w-auto{ class: '!gl-m-0' }
|
||||
.gl-flex.gl-w-full.md:gl-w-auto{ class: '!gl-m-0' }
|
||||
.js-namespace-select{ data: { field_name: 'namespace_id', selected_id: namespace&.id, selected_text: selected_text, update_location: 'true' } }
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
- max_project_topic_length = 15
|
||||
|
||||
- if project.topics.present?
|
||||
.gl-w-full.gl-inline-flex.gl-flex-wrap.gl-font-base.gl-font-normal.gl-align-items-center.-gl-mx-2.-gl-my-2{ 'data-testid': 'project_topic_list' }
|
||||
.gl-w-full.gl-inline-flex.gl-flex-wrap.gl-text-base.gl-font-normal.gl-items-center.-gl-mx-2.-gl-my-2{ 'data-testid': 'project_topic_list' }
|
||||
- project.topics_to_show.each do |topic|
|
||||
- explore_project_topic_path = topic_explore_projects_cleaned_path(topic_name: topic[:name])
|
||||
- if topic[:title].length > max_project_topic_length
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
%h1.page-title.gl-font-size-h-display.gl-display-flex.gl-align-items-center
|
||||
%h1.page-title.gl-text-size-h-display.gl-flex.gl-items-center
|
||||
= s_('Runners|Runner #%{runner_id}') % { runner_id: runner.id }
|
||||
= render 'shared/runners/runner_type_badge', runner: runner
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
- link_project = local_assigns.fetch(:link_project, false)
|
||||
- notes_count = @noteable_meta_data[snippet.id].user_notes_count
|
||||
|
||||
%li.gl-py-4.sm:gl-flex.gl-align-items-center.gl-justify-content-space-between.gl-border-b{ data: { testid: 'snippet-link', qa_snippet_title: snippet.title } }
|
||||
%li.gl-py-4.sm:gl-flex.gl-items-center.gl-justify-between.gl-border-b{ data: { testid: 'snippet-link', qa_snippet_title: snippet.title } }
|
||||
- unless current_path?('users#snippets')
|
||||
.gl-hidden.sm:gl-block.gl-sm-mr-3
|
||||
.gl-hidden.sm:gl-block.sm:gl-mr-3
|
||||
= render Pajamas::AvatarComponent.new(snippet.author, size: 32, alt: "")
|
||||
|
||||
.sm:gl-flex.gl-justify-content-space-between.gl-align-items-center.gl-flex-grow-1
|
||||
.sm:gl-flex.gl-justify-between.gl-items-center.gl-grow
|
||||
%div
|
||||
= link_to gitlab_snippet_path(snippet), class: "title gl-text-black-normal gl-font-bold" do
|
||||
= link_to gitlab_snippet_path(snippet), class: "title gl-text-default gl-font-bold" do
|
||||
= snippet.title
|
||||
- if snippet.hidden_due_to_author_ban?
|
||||
%span{ class: 'has-tooltip gl-bg-orange-50 gl-text-orange-600 border-radius-default gl-p-2', title: s_("Snippets|This snippet is hidden because its author has been banned") }
|
||||
= sprite_icon('spam', size: '16')
|
||||
|
||||
.snippet-info.gl-font-sm.gl-text-gray-500!
|
||||
.snippet-info.gl-text-sm{ class: '!gl-text-gray-500' }
|
||||
.gl-inline{ data: { testid: 'snippet-created-at'} }
|
||||
- created_at = time_ago_with_tooltip(snippet.created_at, placement: 'bottom')
|
||||
- author = link_to(snippet.author_name, user_snippets_path(snippet.author), data: { user_id: snippet.author.id }, class: 'gl-text-black-normal')
|
||||
- author = link_to(snippet.author_name, user_snippets_path(snippet.author), data: { user_id: snippet.author.id }, class: 'gl-text-default')
|
||||
#{snippet.to_reference} ·
|
||||
- if link_project && snippet.project_id?
|
||||
- project_link = link_to(snippet.project.full_name, project_path(snippet.project))
|
||||
|
|
@ -25,8 +25,8 @@
|
|||
- else
|
||||
= _('created %{timeAgo} by %{author}').html_safe % { timeAgo: created_at, author: author }
|
||||
|
||||
.sm:gl-flex.gl-flex-direction-column.gl-align-items-flex-end{ data: { testid: 'snippet-file-count-content', qa_snippet_files: snippet.statistics&.file_count } }
|
||||
.gl-display-flex.gl-gap-4.gl-align-items-center
|
||||
.sm:gl-flex.gl-flex-col.gl-items-end{ data: { testid: 'snippet-file-count-content', qa_snippet_files: snippet.statistics&.file_count } }
|
||||
.gl-flex.gl-gap-4.gl-items-center
|
||||
- if notes_count > 0
|
||||
%span.has-tooltip{ title: _('Comments') }
|
||||
= sprite_icon('comments')
|
||||
|
|
@ -34,4 +34,4 @@
|
|||
= snippet_file_count(snippet)
|
||||
%span.has-tooltip{ title: visibility_level_label(snippet.visibility_level), data: { testid: 'snippet-visibility-content', qa_snippet_visibility: visibility_level_label(snippet.visibility_level) } }
|
||||
= visibility_level_icon(snippet.visibility_level)
|
||||
.gl-whitespace-nowrap.gl-font-sm.gl-text-secondary= _('updated %{timeAgo}').html_safe % { timeAgo: time_ago_with_tooltip(snippet.updated_at, placement: 'bottom') }
|
||||
.gl-whitespace-nowrap.gl-text-sm.gl-text-secondary= _('updated %{timeAgo}').html_safe % { timeAgo: time_ago_with_tooltip(snippet.updated_at, placement: 'bottom') }
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
.col-lg-3.col-md-4.col-sm-12
|
||||
= render Pajamas::CardComponent.new(card_options: { class: 'gl-mb-5' },
|
||||
body_options: { class: 'gl-display-flex gl-align-items-center' }) do |c|
|
||||
body_options: { class: 'gl-flex gl-items-center' }) do |c|
|
||||
- c.with_body do
|
||||
= link_to detail_page_link do
|
||||
= render Pajamas::AvatarComponent.new(topic, size: 48, alt: '', class: 'gl-mr-3')
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
= yield :usage_quotas_subtitle
|
||||
|
||||
#js-usage-quotas-view
|
||||
.gl-font-lg.text-center
|
||||
.gl-text-lg.text-center
|
||||
%span.gl-mr-1= s_('UsageQuota|Loading Usage Quotas tabs')
|
||||
= render Pajamas::SpinnerComponent.new(inline: true, size: :md)
|
||||
= yield :usage_quotas_tabs
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
= gl_badge_tag(integration_webhook_event_human_name(trigger), variant: :neutral)
|
||||
= gl_badge_tag(sslBadgeText, variant: :neutral)
|
||||
|
||||
.gl-font-sm
|
||||
.gl-text-sm
|
||||
= truncate(hook.description, length: 200)
|
||||
|
||||
.gl-flex.gl-items-baseline.gl-gap-3
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@
|
|||
%strong
|
||||
= commit_author_link(commit, avatar: true, size: 24)
|
||||
- if commit.description.present?
|
||||
%pre.commit-description.gl-whitespace-pre-wrap.gl-line-height-normal
|
||||
%pre.commit-description.gl-whitespace-pre-wrap.gl-leading-normal
|
||||
= preserve(markdown_field(commit, :description))
|
||||
|
||||
= render 'projects/diffs/diffs', diffs: @diffs, diff_page_context: "is-wiki"
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
|
||||
- git_access_url = wiki_path(@wiki, action: :git_access)
|
||||
|
||||
.wiki-page-header.top-area.gl-flex-direction-column.gl-lg-flex-direction-row
|
||||
.wiki-page-header.top-area.gl-flex-col.lg:gl-flex-row
|
||||
.gl-mt-5.gl-mb-3
|
||||
.gl-display-flex.gl-justify-content-space-between
|
||||
.gl-flex.gl-justify-between
|
||||
%h2.gl-mt-0.gl-mb-5{ data: { testid: 'page-heading' } }= @page ? @page.human_title : _('Failed to retrieve page')
|
||||
.js-wiki-page-content.md.gl-pt-2{ data: { testid: 'wiki-page-content' } }
|
||||
= _('The page could not be displayed because it timed out.')
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
name: rules_exist_expand_globs_early
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/386595
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/160446
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/477245
|
||||
milestone: '17.3'
|
||||
group: group::pipeline authoring
|
||||
type: gitlab_com_derisk
|
||||
name: prompt_migration_refactor_code
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/475050
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/162716
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/479117
|
||||
milestone: '17.4'
|
||||
group: group::custom models
|
||||
type: experiment
|
||||
default_enabled: false
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
- name: Troubleshoot failed jobs with root cause analysis
|
||||
description: |
|
||||
Root cause analysis is now generally available. With root cause analysis, you can troubleshoot failed jobs in CI/CD pipelines faster. This AI-powered feature analyzes the failed job log, quickly determines the root cause of the job failure, and suggests a fix for you.
|
||||
stage: verify
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/gitlab_duo_chat/examples.html#troubleshoot-failed-cicd-jobs-with-root-cause-analysis
|
||||
image_url: https://img.youtube.com/vi/Yf7Iidf2GW8/hqdefault.jpg
|
||||
published_at: 2024-08-15
|
||||
release: 17.3
|
||||
|
||||
- name: Resolve a vulnerability with AI
|
||||
description: |
|
||||
Vulnerability resolution uses AI to give specific code suggestions for users to fix vulnerabilities. With the click of a button you can open a merge request to get started resolving any SAST vulnerability from the [list of supported CWE identifiers](https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#availability).
|
||||
stage: govern
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/application_security/vulnerabilities/#vulnerability-resolution
|
||||
image_url: https://about.gitlab.com/images/17_3/vulnerability_resolution.png
|
||||
published_at: 2024-08-15
|
||||
release: 17.3
|
||||
|
||||
- name: Add multiple compliance frameworks to a single project
|
||||
description: |
|
||||
You can create a compliance framework to identify that your project has certain compliance requirements or needs additional oversight.
|
||||
The compliance framework can optionally enforce compliance pipeline configuration to the projects on which it is applied.
|
||||
|
||||
Previously, you could apply only one compliance framework to a project, which limited how many compliance requirements could be set on a project.
|
||||
We have now provided the ability for a user to apply multiple different compliance frameworks per project. The project is then set with the compliance requirements of each framework.
|
||||
stage: govern
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Premium, Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/group/compliance_frameworks.html#add-a-compliance-framework-to-a-project
|
||||
image_url: https://about.gitlab.com/images/17_3/multiple-compliance-frameworks.png
|
||||
published_at: 2024-08-15
|
||||
release: 17.3
|
||||
|
||||
- name: Delete a pod from the GitLab UI
|
||||
description: |
|
||||
Have you ever needed to restart or delete a failing pod in Kubernetes? Until now, you had to leave GitLab, use another tool to connect to the cluster, stop the pod, and wait for a new pod to start. GitLab now has built-in support for deleting pods, so you can smoothly troubleshoot your Kubernetes clusters.
|
||||
|
||||
You can stop a pod from a [dashboard for Kubernetes](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html), which lists all the pods across your cluster or namespace.
|
||||
stage: deploy
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Free, Premium, Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html#delete-a-pod
|
||||
image_url: https://about.gitlab.com/images/17_3/delete-pod.png
|
||||
published_at: 2024-08-15
|
||||
release: 17.3
|
||||
|
||||
- name: Easily connect to a cluster from your local terminal
|
||||
description: |
|
||||
Do you want to connect to a Kubernetes cluster from your local terminal or using one of the desktop Kubernetes GUI tools?
|
||||
GitLab allows you to connect to a terminal using the [user access feature of the agent for Kubernetes](https://docs.gitlab.com/ee/user/clusters/agent/user_access.html). Previously, finding commands required navigating out of GitLab to browse the documentation. Now, GitLab provides the **connect** command from the UI. GitLab can even help you configure user access!
|
||||
|
||||
To retrieve the connection command, either go to a [Kubernetes dashboard](https://docs.gitlab.com/ee/ci/environments/kubernetes_dashboard.html), or to the [agent list](https://docs.gitlab.com/ee/user/clusters/agent/work_with_agent.html#view-your-agents).
|
||||
stage: deploy
|
||||
self-managed: true
|
||||
gitlab-com: true
|
||||
available_in: [Free, Premium, Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/clusters/agent/user_access.html
|
||||
image_url: https://about.gitlab.com/images/17_3/17-3-connect-agent.png
|
||||
published_at: 2024-08-15
|
||||
release: 17.3
|
||||
|
||||
- name: Health check for GitLab Duo in beta
|
||||
description: |
|
||||
You can now troubleshoot the setup for GitLab Duo on your self-managed instance. In the **Admin** area, on the GitLab Duo page, select **Run health check**. This health check performs a series of validations and suggests appropriate corrective actions to ensure GitLab Duo is operational.
|
||||
|
||||
The health check for GitLab Duo is available on Self-managed and GitLab Dedicated as a beta feature.
|
||||
stage: data_store
|
||||
self-managed: true
|
||||
gitlab-com: false
|
||||
available_in: [Premium, Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/gitlab_duo/turn_on_off.html#run-a-health-check-for-gitlab-duo
|
||||
image_url: https://about.gitlab.com/images/17_3/Failed_GitLab_Duo_health_check.png
|
||||
published_at: 2024-08-15
|
||||
release: 17.3
|
||||
|
||||
- name: "AI Impact analytics: Code Suggestions acceptance rate and GitLab Duo seats usage"
|
||||
description: |
|
||||
These two new metrics highlight the effectiveness and utilization of GitLab Duo, and are now included in the [AI Impact analytics in the Value Streams Dashboard](https://about.gitlab.com/blog/2024/05/15/developing-gitlab-duo-ai-impact-analytics-dashboard-measures-the-roi-of-ai/), which helps organizations understand the impact of GitLab Duo on delivering business value.
|
||||
|
||||
The **Code Suggestions acceptance rate** metric indicates how frequently developers accept code suggestions made by GitLab Duo. This metric reflects both the effectiveness of these suggestions and the level of trust contributors have in AI capabilities. Specifically, the metric represents the percentage of code suggestions provided by GitLab Duo that have been accepted by code contributors in the last 30 days.
|
||||
|
||||
The **GitLab Duo seats assigned and used** metric shows the percentage of consumed licensed seats, helping organizations plan effectively for license utilization, resource allocation, and understanding of usage patterns. This metric tracks the ratio of assigned seats that have used at least one AI feature in the last 30 days.
|
||||
|
||||
With the addition of these new metrics, we have also introduced new overview tiles — a new visualization which provides a clear summary of the metrics, helping you quickly assess the current state of your AI features.
|
||||
stage: data_store
|
||||
self-managed: true
|
||||
gitlab-com: false
|
||||
available_in: [Ultimate]
|
||||
documentation_link: https://docs.gitlab.com/ee/user/analytics/value_streams_dashboard.html#ai-impact-analytics
|
||||
image_url: https://about.gitlab.com/images/17_3/173_ai_tiles.png
|
||||
published_at: 2024-08-15
|
||||
release: 17.3
|
||||
|
|
@ -8,4 +8,4 @@ description: A set of cost factors per runner which are applied to ci job durati
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111977
|
||||
milestone: '15.10'
|
||||
gitlab_schema: gitlab_ci
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/460076
|
||||
exempt_from_sharding: true # Cell-local table storing cost information for instance runners
|
||||
|
|
|
|||
|
|
@ -182,15 +182,32 @@ To enable an Outbound Private Link:
|
|||
required validation, and let GitLab know in the support ticket that you are using this option. If `Acceptance Required` is set to Yes on your
|
||||
Endpoint Service, also note this on the support ticket because Dedicated will need to initiate the connection without Private DNS, wait for you
|
||||
to confirm it has been accepted, and then update the connection to enable the use of Private DNS.
|
||||
- Dedicated can manage a Private Hosted Zone (PHZ) within the Dedicated AWS Account and alias any arbitrary DNS names to the Endpoint, directing
|
||||
requests for those names to your Endpoint Service. This may be useful if you have multiple DNS names/aliases that will be accessed using a
|
||||
single Endpoint (for example, if you are running a reverse proxy to connect to more than one service in your environment), or if the domain you
|
||||
want to use is not public and cannot be validated for use by Private DNS. Let GitLab know on the support ticket if you are using this option and
|
||||
provide a list of DNS names that should resolve to the Private Link Endpoint. This list can be updated as needed in future.
|
||||
- Dedicated can manage a private hosted zone (PHZ) within the Dedicated AWS account and alias DNS names to the endpoint, directing requests for those names to your endpoint service. These aliases are often referred to as PHZ entries. For more information, see [Private hosted zones](#private-hosted-zones).
|
||||
|
||||
GitLab then configures the tenant instance to create the necessary Endpoint Interfaces based on the service names you provided. Any matching outbound
|
||||
connections made from the tenant instance are directed through the PrivateLink into your VPC.
|
||||
|
||||
#### Private hosted zones
|
||||
|
||||
You can use a private hosted zone (PHZ) if:
|
||||
|
||||
- You have multiple DNS names or aliases that will be accessed using a single endpoint. For example, if you are running a reverse proxy to connect to more than one service in your environment.
|
||||
- The domain you want to use is not public and cannot be validated for use by private DNS.
|
||||
|
||||
To use private hosted zones, submit a [support ticket](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=4414917877650). In the support ticket, provide a list of DNS names that should resolve to the endpoint service for the outbound private link. The list can be updated as needed.
|
||||
|
||||
When using your Dedicated instance's domain as part of an alias, you must include two subdomains before the main domain. This is because:
|
||||
|
||||
1. The first subdomain becomes the name of the PHZ.
|
||||
1. The second subdomain becomes the record entry for the alias.
|
||||
|
||||
For example:
|
||||
|
||||
- This is a valid PHZ entry: `subdomain2.subdomain1.<your-tenant-id>.gitlab-dedicated.com`.
|
||||
- This is an invalid PHZ entry: `subdomain1.<your-tenant-id>.gitlab-dedicated.com`.
|
||||
|
||||
If you don't use the Dedicated instance domain, the PHZ name and a PHZ entry in the format `phz-entry.phz-name.com` is still required.
|
||||
|
||||
### Custom certificates
|
||||
|
||||
In some cases, the GitLab Dedicated instance can't reach an internal service you own because it exposes a certificate that can't be validated using a public Certification Authority (CA). In these cases, custom certificates are required.
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ when a snippet's original author wasn't available. For example, when the user wa
|
|||
|
||||
Other examples of internal users:
|
||||
|
||||
- [GitLab Admin Bot](https://gitlab.com/gitlab-org/gitlab/-/blob/278bc9018dd1515a10cbf15b6c6cd55cb5431407/app/models/user.rb#L950-960)
|
||||
- [GitLab Automation Bot](../user/group/iterations/index.md#gitlab-automation-bot-user)
|
||||
- [Alert Bot](../operations/incident_management/alerts.md#trigger-actions-from-alerts)
|
||||
- [Ghost User](../user/profile/account/delete_account.md#associated-records)
|
||||
|
|
@ -36,3 +35,15 @@ Other examples of internal users:
|
|||
- Resource access tokens, including [project access tokens](../user/project/settings/project_access_tokens.md)
|
||||
and [group access tokens](../user/group/settings/group_access_tokens.md), which are
|
||||
`project_{project_id}_bot_{random_string}` and `group_{group_id}_bot_{random_string}` users with a `PersonalAccessToken`.
|
||||
|
||||
## GitLab Admin Bot
|
||||
|
||||
[GitLab Admin Bot](https://gitlab.com/gitlab-org/gitlab/-/blob/1d38cfdbed081f8b3fa14b69dd743440fe85081b/lib/users/internal.rb#L104)
|
||||
is an internal user that cannot be accessed or modified by regular users and is responsible for many tasks including:
|
||||
|
||||
- Applying [default compliance frameworks](../user/group/compliance_frameworks.md#default-compliance-frameworks) to
|
||||
projects.
|
||||
- [Automatically deactivating dormant users](moderate_users.md#automatically-deactivate-dormant-users).
|
||||
- [Automatically deleting unconfirmed users](moderate_users.md#automatically-delete-unconfirmed-users).
|
||||
- [Deleting inactive projects](inactive_project_deletion.md).
|
||||
- [Locking users](../security/unlock_user.md).
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ POST /projects/:id/ci/lint
|
|||
Example request:
|
||||
|
||||
```shell
|
||||
curl --header "Content-Type: application/json" "https://gitlab.example.com/api/v4/projects/:id/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"types\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
|
||||
curl --header "Content-Type: application/json" "https://gitlab.example.com/api/v4/projects/:id/ci/lint" --data '{"content": "{ \"image\": \"ruby:2.6\", \"services\": [\"postgres\"], \"before_script\": [\"bundle install\", \"bundle exec rake db:create\"], \"variables\": {\"DB_NAME\": \"postgres\"}, \"stages\": [\"test\", \"deploy\", \"notify\"], \"rspec\": { \"script\": \"rake spec\", \"tags\": [\"ruby\", \"postgres\"], \"only\": [\"branches\"]}}"}'
|
||||
```
|
||||
|
||||
Example responses:
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: 'compute_minutes.md'
|
||||
remove_date: '2024-08-13'
|
||||
---
|
||||
|
||||
This document was moved to [another location](compute_minutes.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2024-08-13>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -435,7 +435,7 @@ Use sentence case for **Code explanation**.
|
|||
On first mention on a page, use **GitLab Duo Code explanation**.
|
||||
Thereafter, use **Code explanation** by itself.
|
||||
|
||||
## Code Generation
|
||||
## code generation
|
||||
|
||||
Code Suggestions has evolved to include two primary features:
|
||||
|
||||
|
|
|
|||
|
|
@ -32,8 +32,8 @@ Report any issues, bugs, or feature requests in the
|
|||
|
||||
## Related topics
|
||||
|
||||
- [Download the plugin](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio)
|
||||
- [Plugin documentation](https://gitlab.com/gitlab-org/editor-extensions/gitlab-visual-studio-extension/-/blob/main/README.md)
|
||||
- [Download the extension](https://marketplace.visualstudio.com/items?itemName=GitLab.GitLabExtensionForVisualStudio)
|
||||
- [Extension documentation](https://gitlab.com/gitlab-org/editor-extensions/gitlab-visual-studio-extension/-/blob/main/README.md)
|
||||
- [View source code](https://gitlab.com/gitlab-org/editor-extensions/gitlab-visual-studio-extension)
|
||||
|
||||
## Troubleshooting
|
||||
|
|
|
|||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: 'index.md'
|
||||
remove_date: '2024-08-06'
|
||||
---
|
||||
|
||||
This document was moved to [another location](index.md).
|
||||
|
||||
<!-- This redirect file can be deleted after <2024-08-06>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
---
|
||||
redirect_to: 'https://about.gitlab.com/blog/2023/07/27/gitlab-flow-duo/'
|
||||
remove_date: '2024-07-27'
|
||||
---
|
||||
|
||||
This document was moved to [another location](https://about.gitlab.com/blog/2023/07/27/gitlab-flow-duo/).
|
||||
|
||||
<!-- This redirect file can be deleted after <2024-07-27>. -->
|
||||
<!-- Redirects that point to other docs in the same project expire in three months. -->
|
||||
<!-- Redirects that point to docs in a different project or site (for example, link is not relative and starts with `https:`) expire in one year. -->
|
||||
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/redirects.html -->
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue