Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-09-30 09:10:11 +00:00
parent 3c02fe8326
commit 418c3b2900
113 changed files with 2209 additions and 372 deletions

View File

@ -35,7 +35,6 @@ export function membersBeforeSave(members) {
: '';
return {
type: member.type,
username: member.username,
avatarTag: autoCompleteAvatar.length === 1 ? txtAvatar : imgAvatar,
title: sanitize(title),
@ -280,11 +279,7 @@ class GfmAutoComplete {
if (command === MEMBER_COMMAND.ASSIGN) {
// Only include members which are not assigned to Issuable currently
return data.filter(
member => member.type === 'User' && !assignees.includes(member.search),
);
} else if (command === MEMBER_COMMAND.REASSIGN) {
return data.filter(member => member.type === 'User');
return data.filter(member => !assignees.includes(member.search));
} else if (command === MEMBER_COMMAND.UNASSIGN) {
// Only include members which are assigned to Issuable currently
return data.filter(member => assignees.includes(member.search));

View File

@ -41,7 +41,7 @@ export default {
:disabled="savingChanges"
@click="$emit('editSettings')"
>
{{ __('Settings') }}
{{ __('Page settings') }}
</gl-button>
<gl-button
ref="submit"

View File

@ -4,6 +4,7 @@ import createDefaultClient from '~/lib/graphql';
import typeDefs from './typedefs.graphql';
import fileResolver from './resolvers/file';
import submitContentChangesResolver from './resolvers/submit_content_changes';
import hasSubmittedChangesResolver from './resolvers/has_submitted_changes';
Vue.use(VueApollo);
@ -15,6 +16,7 @@ const createApolloProvider = appData => {
},
Mutation: {
submitContentChanges: submitContentChangesResolver,
hasSubmittedChanges: hasSubmittedChangesResolver,
},
},
{

View File

@ -0,0 +1,5 @@
mutation hasSubmittedChanges($input: HasSubmittedChangesInput) {
hasSubmittedChanges(input: $input) @client {
hasSubmittedChanges
}
}

View File

@ -1,6 +1,7 @@
query appData {
appData @client {
isSupportedContent
hasSubmittedChanges
project
sourcePath
username

View File

@ -0,0 +1,17 @@
import query from '../queries/app_data.query.graphql';
const hasSubmittedChangesResolver = (_, { input: { hasSubmittedChanges } }, { cache }) => {
const { appData } = cache.readQuery({ query });
cache.writeQuery({
query,
data: {
appData: {
__typename: 'AppData',
...appData,
hasSubmittedChanges,
},
},
});
};
export default hasSubmittedChangesResolver;

View File

@ -16,12 +16,17 @@ type SavedContentMeta {
type AppData {
isSupportedContent: Boolean!
hasSubmittedChanges: Boolean!
project: String!
returnUrl: String
sourcePath: String!
username: String!
}
input HasSubmittedChangesInput {
hasSubmittedChanges: Boolean!
}
input SubmitContentChangesInput {
project: String!
sourcePath: String!
@ -40,4 +45,5 @@ extend type Query {
extend type Mutation {
submitContentChanges(input: SubmitContentChangesInput!): SavedContentMeta
hasSubmittedChanges(input: HasSubmittedChangesInput!): AppData
}

View File

@ -19,6 +19,7 @@ const initStaticSiteEditor = el => {
const router = createRouter(baseUrl);
const apolloProvider = createApolloProvider({
isSupportedContent: parseBoolean(isSupportedContent),
hasSubmittedChanges: false,
project: `${namespace}/${project}`,
returnUrl,
sourcePath,

View File

@ -5,6 +5,7 @@ import InvalidContentMessage from '../components/invalid_content_message.vue';
import SubmitChangesError from '../components/submit_changes_error.vue';
import appDataQuery from '../graphql/queries/app_data.query.graphql';
import sourceContentQuery from '../graphql/queries/source_content.query.graphql';
import hasSubmittedChangesMutation from '../graphql/mutations/has_submitted_changes.mutation.graphql';
import submitContentChangesMutation from '../graphql/mutations/submit_content_changes.mutation.graphql';
import { deprecatedCreateFlash as createFlash } from '~/flash';
import Tracking from '~/tracking';
@ -74,6 +75,20 @@ export default {
submitChanges(images) {
this.isSavingChanges = true;
// eslint-disable-next-line promise/catch-or-return
this.$apollo
.mutate({
mutation: hasSubmittedChangesMutation,
variables: {
input: {
hasSubmittedChanges: true,
},
},
})
.finally(() => {
this.$router.push(SUCCESS_ROUTE);
});
this.$apollo
.mutate({
mutation: submitContentChangesMutation,
@ -87,9 +102,6 @@ export default {
},
},
})
.then(() => {
this.$router.push(SUCCESS_ROUTE);
})
.catch(e => {
this.submitChangesError = e.message;
})

View File

@ -1,5 +1,5 @@
<script>
import { GlEmptyState, GlButton } from '@gitlab/ui';
import { GlButton, GlEmptyState, GlLoadingIcon } from '@gitlab/ui';
import { s__, __, sprintf } from '~/locale';
import savedContentMetaQuery from '../graphql/queries/saved_content_meta.query.graphql';
@ -8,8 +8,9 @@ import { HOME_ROUTE } from '../router/constants';
export default {
components: {
GlEmptyState,
GlButton,
GlEmptyState,
GlLoadingIcon,
},
props: {
mergeRequestsIllustrationPath: {
@ -33,7 +34,7 @@ export default {
},
},
created() {
if (!this.savedContentMeta) {
if (!this.appData.hasSubmittedChanges) {
this.$router.push(HOME_ROUTE);
}
},
@ -50,14 +51,21 @@ export default {
assignMergeRequestInstruction: s__(
'StaticSiteEditor|3. Assign a person to review and accept the merge request.',
),
submittingTitle: s__('StaticSiteEditor|Creating your merge request'),
submittingNotePrimary: s__(
'StaticSiteEditor|You can set an assignee to get your changes reviewed and deployed once your merge request is created.',
),
submittingNoteSecondary: s__(
'StaticSiteEditor|A link to view the merge request will appear once ready.',
),
};
</script>
<template>
<div
v-if="savedContentMeta"
class="container gl-flex-grow-1 gl-display-flex gl-flex-direction-column"
>
<div class="gl-fixed gl-left-0 gl-right-0 gl-border-b-solid gl-border-b-1 gl-border-b-gray-100">
<div class="container gl-flex-grow-1 gl-display-flex gl-flex-direction-column">
<div
v-if="savedContentMeta"
class="gl-fixed gl-left-0 gl-right-0 gl-border-b-solid gl-border-b-1 gl-border-b-gray-100"
>
<div class="container gl-py-4">
<gl-button
v-if="appData.returnUrl"
@ -73,16 +81,23 @@ export default {
</div>
<gl-empty-state
class="gl-my-9"
:primary-button-text="$options.primaryButtonText"
:title="$options.title"
:primary-button-link="savedContentMeta.mergeRequest.url"
:title="savedContentMeta ? $options.title : $options.submittingTitle"
:primary-button-text="savedContentMeta && $options.primaryButtonText"
:primary-button-link="savedContentMeta && savedContentMeta.mergeRequest.url"
:svg-path="mergeRequestsIllustrationPath"
>
<template #description>
<p>{{ $options.mergeRequestInstructionsHeading }}</p>
<p>{{ $options.addTitleInstruction }}</p>
<p>{{ $options.addDescriptionInstruction }}</p>
<p>{{ $options.assignMergeRequestInstruction }}</p>
<div v-if="savedContentMeta">
<p>{{ $options.mergeRequestInstructionsHeading }}</p>
<p>{{ $options.addTitleInstruction }}</p>
<p>{{ $options.addDescriptionInstruction }}</p>
<p>{{ $options.assignMergeRequestInstruction }}</p>
</div>
<div v-else>
<p>{{ $options.submittingNotePrimary }}</p>
<p>{{ $options.submittingNoteSecondary }}</p>
<gl-loading-icon size="xl" />
</div>
</template>
</gl-empty-state>
</div>

View File

@ -0,0 +1,73 @@
import jsYaml from 'js-yaml';
const NEW_LINE = '\n';
const hasMatter = (firstThreeChars, fourthChar) => {
const isYamlDelimiter = firstThreeChars === '---';
const isFourthCharNewline = fourthChar === NEW_LINE;
return isYamlDelimiter && isFourthCharNewline;
};
export const frontMatterify = source => {
let index = 3;
let offset;
const delimiter = source.slice(0, index);
const type = 'yaml';
const NO_FRONTMATTER = {
source,
matter: null,
spacing: null,
content: source,
delimiter: null,
type: null,
};
if (!hasMatter(delimiter, source.charAt(index))) {
return NO_FRONTMATTER;
}
offset = source.indexOf(delimiter, index);
// Finds the end delimiter that starts at a new line
while (offset !== -1 && source.charAt(offset - 1) !== NEW_LINE) {
index = offset + delimiter.length;
offset = source.indexOf(delimiter, index);
}
if (offset === -1) {
return NO_FRONTMATTER;
}
const matterStr = source.slice(index, offset);
const matter = jsYaml.safeLoad(matterStr);
let content = source.slice(offset + delimiter.length);
let spacing = '';
let idx = 0;
while (content.charAt(idx).match(/(\s|\n)/)) {
spacing += content.charAt(idx);
idx += 1;
}
content = content.replace(spacing, '');
return {
source,
matter,
spacing,
content,
delimiter,
type,
};
};
export const stringify = ({ matter, spacing, content, delimiter }, newMatter) => {
const matterObj = newMatter || matter;
if (!matterObj) {
return content;
}
const header = `${delimiter}${NEW_LINE}${jsYaml.safeDump(matterObj)}${delimiter}`;
const body = `${spacing}${content}`;
return `${header}${body}`;
};

View File

@ -1,7 +1,7 @@
import grayMatter from 'gray-matter';
import { frontMatterify, stringify } from './front_matterify';
const parseSourceFile = raw => {
const remake = source => grayMatter(source, {});
const remake = source => frontMatterify(source);
let editable = remake(raw);
@ -13,20 +13,17 @@ const parseSourceFile = raw => {
}
};
const trimmedEditable = () => grayMatter.stringify(editable).trim();
const content = (isBody = false) => (isBody ? editable.content : stringify(editable));
const content = (isBody = false) => (isBody ? editable.content.trim() : trimmedEditable()); // gray-matter internally adds an eof newline so we trim to bypass, open issue: https://github.com/jonschlinkert/gray-matter/issues/96
const matter = () => editable.data;
const matter = () => editable.matter;
const syncMatter = settings => {
const source = grayMatter.stringify(editable.content, settings);
syncContent(source);
editable.matter = settings;
};
const isModified = () => trimmedEditable() !== raw;
const isModified = () => stringify(editable) !== raw;
const hasMatter = () => editable.matter.length > 0;
const hasMatter = () => Boolean(editable.matter);
return {
matter,

View File

@ -66,12 +66,10 @@ const autoCompleteMap = {
}
if (doesCurrentLineStartWith('/assign', fullText, selectionStart)) {
return this.members.filter(
member => member.type === 'User' && !this.assignees.includes(member.username),
);
} else if (doesCurrentLineStartWith('/reassign', fullText, selectionStart)) {
return this.members.filter(member => member.type === 'User');
} else if (doesCurrentLineStartWith('/unassign', fullText, selectionStart)) {
return this.members.filter(member => !this.assignees.includes(member.username));
}
if (doesCurrentLineStartWith('/unassign', fullText, selectionStart)) {
return this.members.filter(member => this.assignees.includes(member.username));
}

View File

@ -62,3 +62,5 @@ export const MEMBER_TYPES = {
invite: 'invite',
accessRequest: 'accessRequest',
};
export const DAYS_TO_EXPIRE_SOON = 7;

View File

@ -0,0 +1,40 @@
<script>
import { GlSprintf } from '@gitlab/ui';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
export default {
name: 'CreatedAt',
components: { GlSprintf, TimeAgoTooltip },
props: {
date: {
type: String,
required: false,
default: null,
},
createdBy: {
type: Object,
required: false,
default: null,
},
},
computed: {
showCreatedBy() {
return this.createdBy?.name && this.createdBy?.webUrl;
},
},
};
</script>
<template>
<span>
<gl-sprintf v-if="showCreatedBy" :message="s__('Members|%{time} by %{user}')">
<template #time>
<time-ago-tooltip :time="date" />
</template>
<template #user>
<a :href="createdBy.webUrl">{{ createdBy.name }}</a>
</template>
</gl-sprintf>
<time-ago-tooltip v-else :time="date" />
</span>
</template>

View File

@ -0,0 +1,66 @@
<script>
import { GlSprintf, GlTooltipDirective } from '@gitlab/ui';
import {
approximateDuration,
differenceInSeconds,
formatDate,
getDayDifference,
} from '~/lib/utils/datetime_utility';
import { DAYS_TO_EXPIRE_SOON } from '../constants';
export default {
name: 'ExpiresAt',
components: { GlSprintf },
directives: {
GlTooltip: GlTooltipDirective,
},
props: {
date: {
type: String,
required: false,
default: null,
},
},
computed: {
noExpirationSet() {
return this.date === null;
},
parsed() {
return new Date(this.date);
},
differenceInSeconds() {
return differenceInSeconds(new Date(), this.parsed);
},
isExpired() {
return this.differenceInSeconds <= 0;
},
inWords() {
return approximateDuration(this.differenceInSeconds);
},
formatted() {
return formatDate(this.parsed);
},
expiresSoon() {
return getDayDifference(new Date(), this.parsed) < DAYS_TO_EXPIRE_SOON;
},
cssClass() {
return {
'gl-text-red-500': this.isExpired,
'gl-text-orange-500': this.expiresSoon,
};
},
},
};
</script>
<template>
<span v-if="noExpirationSet">{{ s__('Members|No expiration set') }}</span>
<span v-else v-gl-tooltip.hover :title="formatted" :class="cssClass">
<template v-if="isExpired">{{ s__('Members|Expired') }}</template>
<gl-sprintf v-else :message="s__('Members|in %{time}')">
<template #time>
{{ inWords }}
</template>
</gl-sprintf>
</span>
</template>

View File

@ -5,6 +5,8 @@ import { FIELDS } from '../constants';
import initUserPopovers from '~/user_popovers';
import MemberAvatar from './member_avatar.vue';
import MemberSource from './member_source.vue';
import CreatedAt from './created_at.vue';
import ExpiresAt from './expires_at.vue';
import MembersTableCell from './members_table_cell.vue';
export default {
@ -12,6 +14,8 @@ export default {
components: {
GlTable,
MemberAvatar,
CreatedAt,
ExpiresAt,
MembersTableCell,
MemberSource,
},
@ -51,6 +55,22 @@ export default {
</members-table-cell>
</template>
<template #cell(granted)="{ item: { createdAt, createdBy } }">
<created-at :date="createdAt" :created-by="createdBy" />
</template>
<template #cell(invited)="{ item: { createdAt, createdBy } }">
<created-at :date="createdAt" :created-by="createdBy" />
</template>
<template #cell(requested)="{ item: { createdAt } }">
<created-at :date="createdAt" />
</template>
<template #cell(expires)="{ item: { expiresAt } }">
<expires-at :date="expiresAt" />
</template>
<template #head(actions)="{ label }">
<span data-testid="col-actions" class="gl-sr-only">{{ label }}</span>
</template>

View File

@ -1,6 +1,9 @@
<script>
import { mapState, mapActions } from 'vuex';
import { GlDrawer, GlBadge, GlIcon, GlLink } from '@gitlab/ui';
import Tracking from '~/tracking';
const trackingMixin = Tracking.mixin();
export default {
components: {
@ -9,6 +12,7 @@ export default {
GlIcon,
GlLink,
},
mixins: [trackingMixin],
props: {
features: {
type: String,
@ -37,6 +41,11 @@ export default {
},
mounted() {
this.openDrawer(this.storageKey);
const body = document.querySelector('body');
const namespaceId = body.getAttribute('data-namespace-id');
this.track('click_whats_new_drawer', { label: 'namespace_id', value: namespaceId });
},
methods: {
...mapActions(['openDrawer', 'closeDrawer']),
@ -52,7 +61,14 @@ export default {
</template>
<div class="pb-6">
<div v-for="feature in parsedFeatures" :key="feature.title" class="mb-6">
<gl-link :href="feature.url" target="_blank">
<gl-link
:href="feature.url"
target="_blank"
data-testid="whats-new-title-link"
data-track-event="click_whats_new_item"
:data-track-label="feature.title"
:data-track-property="feature.url"
>
<h5 class="gl-font-base">{{ feature.title }}</h5>
</gl-link>
<div class="mb-2">
@ -62,7 +78,13 @@ export default {
</gl-badge>
</template>
</div>
<gl-link :href="feature.url" target="_blank">
<gl-link
:href="feature.url"
target="_blank"
data-track-event="click_whats_new_item"
:data-track-label="feature.title"
:data-track-property="feature.url"
>
<img
:alt="feature.title"
:src="feature.image_url"
@ -70,7 +92,14 @@ export default {
/>
</gl-link>
<p class="pt-2">{{ feature.body }}</p>
<gl-link :href="feature.url" target="_blank">{{ __('Learn more') }}</gl-link>
<gl-link
:href="feature.url"
target="_blank"
data-track-event="click_whats_new_item"
:data-track-label="feature.title"
:data-track-property="feature.url"
>{{ __('Learn more') }}</gl-link
>
</div>
</div>
</gl-drawer>

View File

@ -36,17 +36,6 @@
// EE-only stylesheets
@import 'application_ee';
// CSS util classes
/**
These are deprecated in favor of the Gitlab UI utilities imported below.
Please check https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss
to see the available utility classes.
**/
@import 'utilities';
// Gitlab UI util classes
@import '@gitlab/ui/src/scss/utilities';
/* print styles */
@media print {
@import 'print';

View File

@ -0,0 +1,12 @@
@import 'page_bundles/mixins_and_variables_and_functions';
// CSS util classes
/**
These are deprecated in favor of the Gitlab UI utilities imported below.
Please check https://unpkg.com/browse/@gitlab/ui/src/scss/utilities.scss
to see the available utility classes.
**/
@import 'utilities';
// Gitlab UI util classes
@import '@gitlab/ui/src/scss/utilities';

View File

@ -0,0 +1,3 @@
@import './themes/dark';
@import 'application_utilities';

View File

@ -357,6 +357,12 @@ module ApplicationHelper
}
end
def add_page_specific_style(path)
content_for :page_specific_styles do
stylesheet_link_tag_defer path
end
end
def page_startup_api_calls
@api_startup_calls
end

View File

@ -69,7 +69,7 @@ module QuickActions
def extract_users(params)
return [] if params.nil?
users = extract_references(params, :mentioned_user)
users = extract_references(params, :user)
if users.empty?
users =

View File

@ -80,7 +80,7 @@ class AddressableUrlValidator < ActiveModel::EachValidator
value = strip_value!(record, attribute, value)
Gitlab::UrlBlocker.validate!(value, blocker_args)
Gitlab::UrlBlocker.validate!(value, **blocker_args)
rescue Gitlab::UrlBlocker::BlockedUrlError => e
record.errors.add(attribute, options.fetch(:blocked_message) % { exception_message: e.message })
end

View File

@ -1,7 +1,7 @@
- @hide_top_links = true
- page_title _('Milestones')
- header_title _('Milestones'), dashboard_milestones_path
= stylesheet_link_tag 'page_bundles/milestone'
- add_page_specific_style 'page_bundles/milestone'
.page-title-holder.d-flex.align-items-center
%h1.page-title= _('Milestones')

View File

@ -3,7 +3,7 @@
- header_title _("To-Do List"), dashboard_todos_path
= render_dashboard_gold_trial(current_user)
= stylesheet_link_tag 'page_bundles/todos'
- add_page_specific_style 'page_bundles/todos'
.page-title-holder.d-flex.align-items-center
%h1.page-title= _('To-Do List')

View File

@ -1,5 +1,5 @@
- page_title _("Milestones")
= stylesheet_link_tag 'page_bundles/milestone'
- add_page_specific_style 'page_bundles/milestone'
.top-area
= render 'shared/milestones_filter', counts: @milestone_states

View File

@ -1,4 +1,4 @@
= stylesheet_link_tag 'page_bundles/milestone'
- add_page_specific_style 'page_bundles/milestone'
= render "header_title"
= render 'shared/milestones/top', milestone: @milestone, group: @group
= render 'shared/milestones/tabs', milestone: @milestone, show_project_name: true

View File

@ -1,8 +1,7 @@
- @body_class = 'ide-layout'
- page_title _('IDE')
- content_for :page_specific_javascripts do
= stylesheet_link_tag 'page_bundles/ide'
- add_page_specific_style 'page_bundles/ide'
#ide.ide-loading{ data: ide_data }
.text-center

View File

@ -25,4 +25,4 @@
%td= link_to 'Remove', jira_connect_subscription_path(subscription), class: 'remove-subscription'
= page_specific_javascript_tag('jira_connect.js')
= stylesheet_link_tag 'page_bundles/jira_connect'
- add_page_specific_style 'page_bundles/jira_connect'

View File

@ -50,8 +50,14 @@
= render 'layouts/startup_css'
- if user_application_theme == 'gl-dark'
= stylesheet_link_tag_defer "application_dark"
- if content_for?(:page_specific_styles)
= yield :page_specific_styles
= stylesheet_link_tag_defer "application_utilities_dark"
- else
= stylesheet_link_tag_defer "application"
- if content_for?(:page_specific_styles)
= yield :page_specific_styles
= stylesheet_link_tag_defer "application_utilities"
- unless use_startup_css?
= stylesheet_link_tag_defer "themes/#{user_application_theme_css_filename}" if user_application_theme_css_filename
= stylesheet_link_tag "disable_animations", media: "all" if Rails.env.test? || Gitlab.config.gitlab['disable_animations']

View File

@ -7,6 +7,8 @@
= stylesheet_link_tag 'https://unpkg.com/@atlaskit/reduced-ui-pack@10.5.5/dist/bundle.css'
= javascript_include_tag 'https://connect-cdn.atl-paas.net/all.js'
= javascript_include_tag 'https://unpkg.com/jquery@3.3.1/dist/jquery.min.js'
- if content_for?(:page_specific_styles)
= yield :page_specific_styles
= yield :head
%body
.ac-content

View File

@ -1,6 +1,5 @@
- page_title _("Value Stream Analytics")
- content_for :page_specific_javascripts do
= stylesheet_link_tag 'page_bundles/cycle_analytics'
- add_page_specific_style 'page_bundles/cycle_analytics'
#cycle-analytics{ "v-cloak" => "true", data: { request_path: project_cycle_analytics_path(@project) } }
- if @cycle_analytics_no_data

View File

@ -1,9 +1,7 @@
- add_to_breadcrumbs _("Environments"), project_environments_path(@project)
- breadcrumb_title @environment.name
- page_title _("Environments")
- content_for :page_specific_javascripts do
= stylesheet_link_tag 'page_bundles/xterm'
- add_page_specific_style 'page_bundles/xterm'
#environments-detail-view{ data: { name: @environment.name, id: @environment.id, delete_path: environment_delete_path(@environment)} }
- if @environment.available? && can?(current_user, :stop_environment, @environment)

View File

@ -2,7 +2,7 @@
- page_title _("Issues")
- new_issue_email = @project.new_issuable_address(current_user, 'issue')
= stylesheet_link_tag 'page_bundles/issues'
- add_page_specific_style 'page_bundles/issues'
= content_for :meta_tags do
= auto_discovery_link_tag(:atom, safe_params.merge(rss_url_options).to_h, title: "#{@project.name} issues")

View File

@ -12,7 +12,7 @@
- can_report_spam = @issue.submittable_as_spam_by?(current_user)
- can_create_issue = show_new_issue_link?(@project)
- related_branches_path = related_branches_project_issue_path(@project, @issue)
= stylesheet_link_tag 'page_bundles/issues'
- add_page_specific_style 'page_bundles/issues'
= render_if_exists "projects/issues/alert_blocked", issue: @issue, current_user: current_user
= render "projects/issues/alert_moved_from_service_desk", issue: @issue

View File

@ -1,9 +1,7 @@
- add_to_breadcrumbs _("Jobs"), project_jobs_path(@project)
- breadcrumb_title "##{@build.id}"
- page_title "#{@build.name} (##{@build.id})", _("Jobs")
- content_for :page_specific_javascripts do
= stylesheet_link_tag 'page_bundles/xterm'
- add_page_specific_style 'page_bundles/xterm'
= render_if_exists "shared/shared_runners_minutes_limit_flash_message"

View File

@ -1,5 +1,5 @@
- page_title _('Milestones')
= stylesheet_link_tag 'page_bundles/milestone'
- add_page_specific_style 'page_bundles/milestone'
.top-area
= render 'shared/milestones_filter', counts: milestone_counts(@project.milestones)

View File

@ -2,7 +2,7 @@
- breadcrumb_title @milestone.title
- page_title @milestone.title, _('Milestones')
- page_description @milestone.description
= stylesheet_link_tag 'page_bundles/milestone'
- add_page_specific_style 'page_bundles/milestone'
= render 'shared/milestones/header', milestone: @milestone
= render 'shared/milestones/description', milestone: @milestone

View File

@ -8,7 +8,7 @@
- @content_class = "issue-boards-content js-focus-mode-board"
- breadcrumb_title _("Issue Boards")
- page_title("#{board.name}", _("Boards"))
= stylesheet_link_tag 'page_bundles/boards'
- add_page_specific_style 'page_bundles/boards'
- content_for :page_specific_javascripts do

View File

@ -0,0 +1,5 @@
---
title: Add projects_creating_incidents to usage ping counts
merge_request: 42934
author:
type: added

View File

@ -1,5 +0,0 @@
---
title: Prevent assignment of groups using quick actions
merge_request: 42810
author:
type: fixed

View File

@ -0,0 +1,5 @@
---
title: Update user feedback to a dedicated page as opposed to solely a button with a loader
merge_request: 43189
author:
type: changed

View File

@ -0,0 +1,6 @@
---
title: Add a database column to enable or disable the setting that puts newly registered
users in a pending state, requiring admin approval for their activation
merge_request: 43661
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Update programming language colors and metadata
merge_request: 43111
author:
type: changed

View File

@ -174,6 +174,8 @@ module Gitlab
config.assets.paths << Gemojione.images_path
config.assets.paths << "#{config.root}/vendor/assets/fonts"
config.assets.precompile << "application_utilities.css"
config.assets.precompile << "application_utilities_dark.css"
config.assets.precompile << "application_dark.css"
config.assets.precompile << "startup/*.css"

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
require 'yaml'
class UpdateProgrammingLanguageColors < ActiveRecord::Migration[6.0]
DOWNTIME = false
class ProgrammingLanguage < ActiveRecord::Base; end
def up
YAML.load_file("vendor/languages.yml").each do |name, metadata|
color = metadata["color"]
next unless color.present?
ProgrammingLanguage.where(name: name).update(color: color)
end
end
def down
# noop
end
end

View File

@ -0,0 +1,20 @@
# frozen_string_literal: true
class AddIncidentIssueTypeIndexToIssues < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
disable_ddl_transaction!
INCIDENT_ISSUE_TYPE = 1
INDEX_NAME = 'index_issues_project_id_issue_type_incident'
def up
add_concurrent_index :issues, :project_id, where: "issue_type = #{INCIDENT_ISSUE_TYPE}", name: INDEX_NAME
end
def down
remove_concurrent_index_by_name(:issues, INDEX_NAME)
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
class AddRequireAdminApprovalAfterUserSignupToApplicationSettings < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column :application_settings, :require_admin_approval_after_user_signup, :boolean, default: false, null: false
end
end

View File

@ -0,0 +1 @@
f19e61e3863905885c8b5b2129be2586d912d616a5b3b54e99a72c5760082059

View File

@ -0,0 +1 @@
8e0c5be3d6fe2d0d718c7b7a99d84b14dfc6006f780ec0622eb5aae937e6b367

View File

@ -0,0 +1 @@
9ef08404b964ccae3e12332340f16c6b8bb2bbdb2c04ba105fe1c0c7e6bf84f2

View File

@ -9270,6 +9270,7 @@ CREATE TABLE application_settings (
gitpod_enabled boolean DEFAULT false NOT NULL,
gitpod_url text DEFAULT 'https://gitpod.io/'::text,
abuse_notification_email character varying,
require_admin_approval_after_user_signup boolean DEFAULT false NOT NULL,
CONSTRAINT check_2dba05b802 CHECK ((char_length(gitpod_url) <= 255)),
CONSTRAINT check_51700b31b5 CHECK ((char_length(default_branch_name) <= 255)),
CONSTRAINT check_9c6c447a13 CHECK ((char_length(maintenance_mode_message) <= 255)),
@ -20372,6 +20373,8 @@ CREATE INDEX index_issues_on_updated_at ON issues USING btree (updated_at);
CREATE INDEX index_issues_on_updated_by_id ON issues USING btree (updated_by_id) WHERE (updated_by_id IS NOT NULL);
CREATE INDEX index_issues_project_id_issue_type_incident ON issues USING btree (project_id) WHERE (issue_type = 1);
CREATE UNIQUE INDEX index_jira_connect_installations_on_client_key ON jira_connect_installations USING btree (client_key);
CREATE INDEX index_jira_connect_subscriptions_on_namespace_id ON jira_connect_subscriptions USING btree (namespace_id);

View File

@ -21,6 +21,9 @@ Updating Geo nodes involves performing:
NOTE: **Note:**
These general update steps are not intended for [high-availability deployments](https://docs.gitlab.com/omnibus/update/README.html#multi-node--ha-deployment), and will cause downtime. If you want to avoid downtime, consider using [zero downtime updates](https://docs.gitlab.com/omnibus/update/README.html#zero-downtime-updates).
DANGER: **Danger:**
In GitLab 13.2 and later versions, promoting a secondary node to a primary while the secondary is paused fails. We are [investigating the issue](https://gitlab.com/gitlab-org/gitlab/-/issues/225173). Do not pause replication before promoting a secondary. If the node is paused, please resume before promoting.
To update the Geo nodes when a new GitLab version is released, update **primary**
and all **secondary** nodes:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 46 KiB

View File

@ -1,3 +1,9 @@
---
stage: Enablement
group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Configure GitLab using an external PostgreSQL service
If you're hosting GitLab on a cloud provider, you can optionally use a

View File

@ -1,11 +1,14 @@
---
stage: Enablement
group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---
# Configuring PostgreSQL for scaling
In this section, you'll be guided through configuring a PostgreSQL database to
be used with GitLab in one of our [Scalable and Highly Available Setups](../reference_architectures/index.md).
be used with GitLab in one of our [reference architectures](../reference_architectures/index.md).
There are essentially three setups to choose from.
## PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM ONLY)**

View File

@ -1,4 +1,7 @@
---
stage: Enablement
group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
type: reference
---

View File

@ -1,10 +1,16 @@
---
stage: Enablement
group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# PostgreSQL replication and failover with Omnibus GitLab **(PREMIUM ONLY)**
This document will focus only on configuration supported with [GitLab Premium](https://about.gitlab.com/pricing/), using the Omnibus GitLab package.
If you are a Community Edition or Starter user, consider using a cloud hosted solution.
This document will not cover installations from source.
This document focuses on configuration supported with [GitLab Premium](https://about.gitlab.com/pricing/), using the Omnibus GitLab package.
If you're a Community Edition or Starter user, consider using a cloud hosted solution.
This document doesn't cover installations from source.
If a setup with replication and failover is not what you were looking for, see
If a setup with replication and failover isn't what you were looking for, see
the [database configuration document](https://docs.gitlab.com/omnibus/settings/database.html)
for the Omnibus GitLab packages.

View File

@ -1,15 +1,21 @@
---
stage: Enablement
group: Database
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers
---
# Standalone PostgreSQL using Omnibus GitLab **(CORE ONLY)**
If you wish to have your database service hosted separately from your GitLab
application server(s), you can do this using the PostgreSQL binaries packaged
application servers, you can do this using the PostgreSQL binaries packaged
together with Omnibus GitLab. This is recommended as part of our
[reference architecture for up to 2,000 users](../reference_architectures/2k_users.md).
## Setting it up
1. SSH into the PostgreSQL server.
1. [Download/install](https://about.gitlab.com/install/) the Omnibus GitLab
package you want using **steps 1 and 2** from the GitLab downloads page.
1. SSH in to the PostgreSQL server.
1. [Download and install](https://about.gitlab.com/install/) the Omnibus GitLab
package you want using *steps 1 and 2* from the GitLab downloads page.
- Do not complete any other steps on the download page.
1. Generate a password hash for PostgreSQL. This assumes you will use the default
username of `gitlab` (recommended). The command will request a password

View File

@ -223,6 +223,58 @@ Example response:
}
```
## List all billable members of a group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217384) in GitLab 13.5.
Gets a list of group members who counts as billable, including members in the sub group/project.
This function takes [pagination](README.md#pagination) parameters `page` and `per_page` to restrict the list of users.
```plaintext
GET /groups/:id/billable_members
```
| Attribute | Type | Required | Description |
| --------- | ---- | -------- | ----------- |
| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user |
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/billable_members"
```
Example response:
```json
[
{
"id": 1,
"username": "raymond_smith",
"name": "Raymond Smith",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
},
{
"id": 2,
"username": "john_doe",
"name": "John Doe",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root",
"email": "john@example.com"
},
{
"id": 3,
"username": "foo_bar",
"name": "Foo bar",
"state": "active",
"avatar_url": "https://www.gravatar.com/avatar/c2525a7f58ae3776070e44c106c48e15?s=80&d=identicon",
"web_url": "http://192.168.1.8:3000/root"
}
]
```
## Add a member to a group or project
Adds a member to a group or project.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -780,6 +780,25 @@ to advertise the need for lookahead:
For an example of real world use, please
see [`ResolvesMergeRequests`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/resolvers/concerns/resolves_merge_requests.rb).
### Negated arguments
Negated filters can filter some resources (for example, find all issues that
have the `bug` label, but don't have the `bug2` label assigned). The `not`
argument is the preferred syntax to pass negated arguments:
```graphql
issues(labelName: "bug", not: {labelName: "bug2"}) {
nodes {
id
title
}
}
```
To avoid duplicated argument definitions, you can place these arguments in a reusable module (or
class, if the arguments are nested). Alternatively, you can consider to add a
[helper resolver method](https://gitlab.com/gitlab-org/gitlab/-/issues/258969).
## Pass a parent object into a child Presenter
Sometimes you need to access the resolved query parent in a child context to compute fields. Usually the parent is only

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 61 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 33 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 144 KiB

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 165 KiB

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 152 KiB

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -16,7 +16,7 @@ module Gitlab
) do
include Gitlab::Utils::StrongMemoize
def initialize(**params)
def initialize(params = {})
params.each do |key, value|
self[key] = value
end

View File

@ -36,9 +36,9 @@ module Gitlab
def self.fabricate(resource)
case resource
when Hash
self.new(resource.symbolize_keys)
self.new(**resource.symbolize_keys)
when ::Ci::HasVariable
self.new(resource.to_runner_variable)
self.new(**resource.to_runner_variable)
when self
resource.dup
else

View File

@ -79,7 +79,7 @@ module Gitlab
end
def fabricate(entry_class, value = nil)
entry_class.new(value, @metadata) do |node|
entry_class.new(value, **@metadata) do |node|
node.key = @attributes[:key]
node.parent = @attributes[:parent]
node.default = @attributes[:default]

View File

@ -19,7 +19,7 @@ module Gitlab
entry = self.class.entry_class(strategy)
@subject = entry.new(config, metadata, &blk)
@subject = entry.new(config, **metadata, &blk)
super(@subject)
end

View File

@ -138,6 +138,7 @@ module Gitlab
pages_domains: count(PagesDomain),
pool_repositories: count(PoolRepository),
projects: count(Project),
projects_creating_incidents: distinct_count(Issue.incident, :project_id),
projects_imported_from_github: count(Project.where(import_type: 'github')),
projects_with_repositories_enabled: count(ProjectFeature.where('repository_access_level > ?', ProjectFeature::DISABLED)),
projects_with_error_tracking_enabled: count(::ErrorTracking::ProjectErrorTrackingSetting.where(enabled: true)),

View File

@ -8,8 +8,6 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-09-22 19:32+0200\n"
"PO-Revision-Date: 2020-09-22 19:32+0200\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
@ -15700,6 +15698,18 @@ msgstr ""
msgid "Members with access to %{strong_start}%{group_name}%{strong_end}"
msgstr ""
msgid "Members|%{time} by %{user}"
msgstr ""
msgid "Members|Expired"
msgstr ""
msgid "Members|No expiration set"
msgstr ""
msgid "Members|in %{time}"
msgstr ""
msgid "Memory Usage"
msgstr ""
@ -24434,6 +24444,9 @@ msgstr ""
msgid "StaticSiteEditor|3. Assign a person to review and accept the merge request."
msgstr ""
msgid "StaticSiteEditor|A link to view the merge request will appear once ready."
msgstr ""
msgid "StaticSiteEditor|An error occurred while submitting your changes."
msgstr ""
@ -24446,6 +24459,9 @@ msgstr ""
msgid "StaticSiteEditor|Could not create merge request."
msgstr ""
msgid "StaticSiteEditor|Creating your merge request"
msgstr ""
msgid "StaticSiteEditor|Incompatible file content"
msgstr ""
@ -24467,6 +24483,9 @@ msgstr ""
msgid "StaticSiteEditor|View documentation"
msgstr ""
msgid "StaticSiteEditor|You can set an assignee to get your changes reviewed and deployed once your merge request is created."
msgstr ""
msgid "StaticSiteEditor|Your merge request has been created"
msgstr ""

View File

@ -93,7 +93,6 @@
"glob": "^7.1.6",
"graphql": "^14.7.0",
"graphql-tag": "^2.10.1",
"gray-matter": "^4.0.2",
"immer": "^7.0.7",
"imports-loader": "^0.8.0",
"ipaddr.js": "^1.9.1",

Some files were not shown because too many files have changed in this diff Show More