Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-01-05 15:13:51 +00:00
parent 6d29831123
commit 67d7efba05
46 changed files with 970 additions and 575 deletions

View File

@ -6,161 +6,6 @@
*.rb @gitlab-org/maintainers/rails-backend
*.rake @gitlab-org/maintainers/rails-backend
[Documentation Directories]
.markdownlint.yml @marcel.amirault @eread @aqualls @cnorris
/doc/.markdownlint @marcel.amirault @eread @aqualls @cnorris
/doc/ @gl-docsteam
/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
/doc/administration/geo/ @axil
/doc/administration/gitaly/ @eread
/doc/administration/lfs/ @aqualls
/doc/administration/monitoring/ @ngaskill
/doc/administration/operations/ @axil @eread @marcia
/doc/administration/packages/ @ngaskill
/doc/administration/pages/ @rdickenson @kpaizee
/doc/administration/postgresql/ @marcia
/doc/administration/raketasks/ @axil @eread
/doc/administration/redis/ @axil
/doc/administration/reference_architectures/ @axil
/doc/administration/snippets/ @aqualls
/doc/administration/troubleshooting @axil @marcia @eread
/doc/api/graphql/ @msedlakjakubowski @kpaizee
/doc/api/graphql/reference/ @kpaizee
/doc/api/group_activity_analytics.md @fneill
/doc/api/vulnerabilities.md @fneill
/doc/ci/ @marcel.amirault @sselhorn
/doc/ci/environments/ @rdickenson
/doc/ci/services/ @sselhorn
/doc/ci/test_cases/ @msedlakjakubowski
/doc/development/ @marcia
/doc/development/documentation/ @cnorris @dianalogan
/doc/development/i18n/ @ngaskill
/doc/development/value_stream_analytics.md @fneill
/doc/gitlab-basics/ @aqualls
/doc/install/ @axil
/doc/operations/ @ngaskill @rdickenson
/doc/push_rules/ @aqualls
/doc/security/ @eread
/doc/ssh/ @eread
/doc/subscriptions/ @sselhorn
/doc/topics/autodevops/ @marcia
/doc/topics/git/ @aqualls
/doc/update/ @axil @marcia
/doc/user/analytics/ @fneill @ngaskill
/doc/user/application_security/ @rdickenson
/doc/user/application_security/container_scanning/ @ngaskill
/doc/user/application_security/cluster_image_scanning/ @ngaskill
/doc/user/application_security/cve_id_request.md @fneill
/doc/user/application_security/security_dashboard @fneill
/doc/user/application_security/vulnerabilities @fneill
/doc/user/application_security/vulnerability_report @fneill
/doc/user/clusters/ @marcia
/doc/user/compliance/ @rdickenson @eread
/doc/user/group/ @msedlakjakubowski
/doc/user/group/devops_adoption/ @fneill
/doc/user/group/epics/ @msedlakjakubowski
/doc/user/group/insights/ @fneill
/doc/user/group/iterations/ @msedlakjakubowski
/doc/user/group/roadmap/ @msedlakjakubowski
/doc/user/group/value_stream_analytics/ @fneill
/doc/user/infrastructure/ @marcia
/doc/user/packages/ @ngaskill
/doc/user/packages/infrastructure_registry/ @marcia
/doc/user/packages/terraform_module_registry/ @marcia
/doc/user/profile/ @msedlakjakubowski @eread
/doc/user/project/ @aqualls @rdickenson @eread @msedlakjakubowski @ngaskill
/doc/user/project/clusters/ @marcia
/doc/user/project/import/ @ngaskill @msedlakjakubowski
/doc/user/project/issues/ @msedlakjakubowski
/doc/user/project/merge_requests/ @aqualls @eread
/doc/user/project/milestones/ @msedlakjakubowski
/doc/user/project/pages/ @rdickenson
/doc/user/project/repository/ @aqualls
/doc/user/project/settings/ @aqualls @eread
/doc/user/project/static_site_editor/index.md @aqualls
/doc/user/project/web_ide/index.md @aqualls
/doc/user/project/wiki/index.md @aqualls
/doc/user/search/ @marcia @aqualls
/doc/user/workspace/ @fneill
[Docs Create]
/doc/administration/file_hooks.md @aqualls
/doc/administration/git_protocol.md @aqualls
/doc/administration/invalidate_markdown_cache.md @aqualls
/doc/administration/issue_closing_pattern.md @aqualls
/doc/administration/merge_request_diffs.md @aqualls
/doc/administration/repository_checks.md @aqualls
/doc/administration/static_objects_external_storage.md @aqualls
/doc/api/access_requests.md @aqualls
/doc/api/branches.md @aqualls
/doc/api/commits.md @aqualls
/doc/api/discussions.md @aqualls
/doc/api/group_wikis.md @aqualls
/doc/api/keys.md @aqualls
/doc/api/markdown.md @aqualls
/doc/api/merge_request_approvals.md @aqualls
/doc/api/merge_request_context_commits.md @aqualls
/doc/api/merge_requests.md @aqualls
/doc/api/project_aliases.md @aqualls
/doc/api/project_badges.md @aqualls
/doc/api/project_import_export.md @aqualls
/doc/api/project_level_variables.md @aqualls
/doc/api/project_snippets.md @aqualls
/doc/api/project_statistics.md @aqualls
/doc/api/project_templates.md @aqualls
/doc/api/project_vulnerabilities.md @aqualls
/doc/api/protected_branches.md @aqualls
/doc/api/protected_tags.md @aqualls
/doc/api/remote_mirrors.md @aqualls
/doc/api/repositories.md @aqualls
/doc/api/repository_files.md @aqualls
/doc/api/repository_submodules.md @aqualls
/doc/api/search.md @aqualls
/doc/api/services.md @aqualls
/doc/api/snippets.md @aqualls
/doc/api/suggestions.md @aqualls
/doc/api/tags.md @aqualls
/doc/api/visual_review_discussions.md @aqualls
/doc/api/wikis.md @aqualls
/doc/intro/index.md @aqualls
/doc/topics/gitlab_flow.md @aqualls
/doc/user/admin_area/settings/account_and_limit_settings.md @aqualls
/doc/user/admin_area/settings/instance_template_repository.md @aqualls
/doc/user/admin_area/settings/project_integration_management.md @aqualls
/doc/user/admin_area/settings/push_event_activities_limit.md @aqualls
/doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls
/doc/user/asciidoc.md @aqualls
/doc/user/index.md @aqualls
/doc/user/markdown.md @aqualls
/doc/user/project/autocomplete_characters.md @aqualls
/doc/user/project/badges.md @aqualls
/doc/user/project/code_intelligence.md @aqualls
/doc/user/project/code_owners.md @aqualls
/doc/user/project/file_lock.md @aqualls
/doc/user/project/git_attributes.md @aqualls
/doc/user/project/highlighting.md @aqualls
/doc/user/project/index.md @aqualls
/doc/user/project/protected_branches.md @aqualls
/doc/user/project/protected_tags.md @aqualls
/doc/user/project/push_options.md @aqualls
/doc/user/project/settings/import_export.md @aqualls
/doc/user/snippets.md @aqualls
[Docs Ecosystem]
/doc/administration/integration/ @kpaizee
/doc/integration/ @kpaizee
/doc/user/project/integrations/ @kpaizee
/doc/user/project/integrations/prometheus_library/ @ngaskill
[Docs Growth]
/doc/administration/instance_review.md @kpaizee
/doc/api/invitations.md @kpaizee
/doc/api/experiments.md @kpaizee
/doc/development/experiment_guide/ @kpaizee
/doc/development/snowplow/ @fneill
/doc/development/service_ping/ @fneill
/doc/user/admin_area/license.md @kpaizee
[Frontend]
*.scss @annabeldunstone @gitlab-org/maintainers/frontend
*.js @gitlab-org/maintainers/frontend
@ -357,3 +202,158 @@ ee/lib/ee/gitlab/git_access.rb @proglottis @toon @zj-gitlab
ee/lib/ee/gitlab/git_access_*.rb @proglottis @toon @zj-gitlab
ee/lib/ee/gitlab/checks/** @proglottis @toon @zj-gitlab
lib/gitlab/checks/** @proglottis @toon @zj-gitlab
[Documentation Directories]
.markdownlint.yml @marcel.amirault @eread @aqualls @cnorris
/doc/.markdownlint @marcel.amirault @eread @aqualls @cnorris
/doc/ @gl-docsteam
/doc/.vale/ @marcel.amirault @eread @aqualls @cnorris
/doc/administration/geo/ @axil
/doc/administration/gitaly/ @eread
/doc/administration/lfs/ @aqualls
/doc/administration/monitoring/ @ngaskill
/doc/administration/operations/ @axil @eread @marcia
/doc/administration/packages/ @ngaskill
/doc/administration/pages/ @rdickenson @kpaizee
/doc/administration/postgresql/ @marcia
/doc/administration/raketasks/ @axil @eread
/doc/administration/redis/ @axil
/doc/administration/reference_architectures/ @axil
/doc/administration/snippets/ @aqualls
/doc/administration/troubleshooting @axil @marcia @eread
/doc/api/graphql/ @msedlakjakubowski @kpaizee
/doc/api/graphql/reference/ @kpaizee
/doc/api/group_activity_analytics.md @fneill
/doc/api/vulnerabilities.md @fneill
/doc/ci/ @marcel.amirault @sselhorn
/doc/ci/environments/ @rdickenson
/doc/ci/services/ @sselhorn
/doc/ci/test_cases/ @msedlakjakubowski
/doc/development/ @marcia
/doc/development/documentation/ @cnorris @dianalogan
/doc/development/i18n/ @ngaskill
/doc/development/value_stream_analytics.md @fneill
/doc/gitlab-basics/ @aqualls
/doc/install/ @axil
/doc/operations/ @ngaskill @rdickenson
/doc/push_rules/ @aqualls
/doc/security/ @eread
/doc/ssh/ @eread
/doc/subscriptions/ @sselhorn
/doc/topics/autodevops/ @marcia
/doc/topics/git/ @aqualls
/doc/update/ @axil @marcia
/doc/user/analytics/ @fneill @ngaskill
/doc/user/application_security/ @rdickenson
/doc/user/application_security/container_scanning/ @ngaskill
/doc/user/application_security/cluster_image_scanning/ @ngaskill
/doc/user/application_security/cve_id_request.md @fneill
/doc/user/application_security/security_dashboard @fneill
/doc/user/application_security/vulnerabilities @fneill
/doc/user/application_security/vulnerability_report @fneill
/doc/user/clusters/ @marcia
/doc/user/compliance/ @rdickenson @eread
/doc/user/group/ @msedlakjakubowski
/doc/user/group/devops_adoption/ @fneill
/doc/user/group/epics/ @msedlakjakubowski
/doc/user/group/insights/ @fneill
/doc/user/group/iterations/ @msedlakjakubowski
/doc/user/group/roadmap/ @msedlakjakubowski
/doc/user/group/value_stream_analytics/ @fneill
/doc/user/infrastructure/ @marcia
/doc/user/packages/ @ngaskill
/doc/user/packages/infrastructure_registry/ @marcia
/doc/user/packages/terraform_module_registry/ @marcia
/doc/user/profile/ @msedlakjakubowski @eread
/doc/user/project/ @aqualls @rdickenson @eread @msedlakjakubowski @ngaskill
/doc/user/project/clusters/ @marcia
/doc/user/project/import/ @ngaskill @msedlakjakubowski
/doc/user/project/issues/ @msedlakjakubowski
/doc/user/project/merge_requests/ @aqualls @eread
/doc/user/project/milestones/ @msedlakjakubowski
/doc/user/project/pages/ @rdickenson
/doc/user/project/repository/ @aqualls
/doc/user/project/settings/ @aqualls @eread
/doc/user/project/static_site_editor/index.md @aqualls
/doc/user/project/web_ide/index.md @aqualls
/doc/user/project/wiki/index.md @aqualls
/doc/user/search/ @marcia @aqualls
/doc/user/workspace/ @fneill
[Docs Create]
/doc/administration/file_hooks.md @aqualls
/doc/administration/git_protocol.md @aqualls
/doc/administration/invalidate_markdown_cache.md @aqualls
/doc/administration/issue_closing_pattern.md @aqualls
/doc/administration/merge_request_diffs.md @aqualls
/doc/administration/repository_checks.md @aqualls
/doc/administration/static_objects_external_storage.md @aqualls
/doc/api/access_requests.md @aqualls
/doc/api/branches.md @aqualls
/doc/api/commits.md @aqualls
/doc/api/discussions.md @aqualls
/doc/api/group_wikis.md @aqualls
/doc/api/keys.md @aqualls
/doc/api/markdown.md @aqualls
/doc/api/merge_request_approvals.md @aqualls
/doc/api/merge_request_context_commits.md @aqualls
/doc/api/merge_requests.md @aqualls
/doc/api/project_aliases.md @aqualls
/doc/api/project_badges.md @aqualls
/doc/api/project_import_export.md @aqualls
/doc/api/project_level_variables.md @aqualls
/doc/api/project_snippets.md @aqualls
/doc/api/project_statistics.md @aqualls
/doc/api/project_templates.md @aqualls
/doc/api/project_vulnerabilities.md @aqualls
/doc/api/protected_branches.md @aqualls
/doc/api/protected_tags.md @aqualls
/doc/api/remote_mirrors.md @aqualls
/doc/api/repositories.md @aqualls
/doc/api/repository_files.md @aqualls
/doc/api/repository_submodules.md @aqualls
/doc/api/search.md @aqualls
/doc/api/services.md @aqualls
/doc/api/snippets.md @aqualls
/doc/api/suggestions.md @aqualls
/doc/api/tags.md @aqualls
/doc/api/visual_review_discussions.md @aqualls
/doc/api/wikis.md @aqualls
/doc/intro/index.md @aqualls
/doc/topics/gitlab_flow.md @aqualls
/doc/user/admin_area/settings/account_and_limit_settings.md @aqualls
/doc/user/admin_area/settings/instance_template_repository.md @aqualls
/doc/user/admin_area/settings/project_integration_management.md @aqualls
/doc/user/admin_area/settings/push_event_activities_limit.md @aqualls
/doc/user/admin_area/settings/visibility_and_access_controls.md @aqualls
/doc/user/asciidoc.md @aqualls
/doc/user/index.md @aqualls
/doc/user/markdown.md @aqualls
/doc/user/project/autocomplete_characters.md @aqualls
/doc/user/project/badges.md @aqualls
/doc/user/project/code_intelligence.md @aqualls
/doc/user/project/code_owners.md @aqualls
/doc/user/project/file_lock.md @aqualls
/doc/user/project/git_attributes.md @aqualls
/doc/user/project/highlighting.md @aqualls
/doc/user/project/index.md @aqualls
/doc/user/project/protected_branches.md @aqualls
/doc/user/project/protected_tags.md @aqualls
/doc/user/project/push_options.md @aqualls
/doc/user/project/settings/import_export.md @aqualls
/doc/user/snippets.md @aqualls
[Docs Ecosystem]
/doc/administration/integration/ @kpaizee
/doc/integration/ @kpaizee
/doc/user/project/integrations/ @kpaizee
/doc/user/project/integrations/prometheus_library/ @ngaskill
[Docs Growth]
/doc/administration/instance_review.md @kpaizee
/doc/api/invitations.md @kpaizee
/doc/api/experiments.md @kpaizee
/doc/development/experiment_guide/ @kpaizee
/doc/development/snowplow/ @fneill
/doc/development/service_ping/ @fneill
/doc/user/admin_area/license.md @kpaizee

View File

@ -26,6 +26,7 @@ proper-names:
names: [
"Akismet",
"Alertmanager",
"AlmaLinux",
"API",
"Asana",
"Auth0",

View File

@ -443,7 +443,8 @@ end
gem 'octokit', '~> 4.15'
# https://gitlab.com/gitlab-org/gitlab/issues/207207
# Updating this gem version here is deprecated. See:
# https://docs.gitlab.com/ee/development/emails.html#mailroom-gem-updates
gem 'gitlab-mail_room', '~> 0.0.9', require: 'mail_room'
gem 'email_reply_trimmer', '~> 0.1'

View File

@ -124,14 +124,14 @@ GEM
aws-sigv4 (~> 1.1)
aws-sigv4 (1.2.1)
aws-eventstream (~> 1, >= 1.0.2)
azure-storage-blob (2.0.1)
azure-storage-blob (2.0.3)
azure-storage-common (~> 2.0)
nokogiri (~> 1.11.0.rc2)
azure-storage-common (2.0.2)
nokogiri (~> 1, >= 1.10.8)
azure-storage-common (2.0.4)
faraday (~> 1.0)
faraday_middleware (~> 1.0.0.rc1)
faraday_middleware (~> 1.0, >= 1.0.0.rc1)
net-http-persistent (~> 4.0)
nokogiri (~> 1.11.0.rc2)
nokogiri (~> 1, >= 1.10.8)
babosa (1.0.4)
backport (1.2.0)
base32 (0.3.2)

View File

@ -35,31 +35,33 @@ const trackInputRule = (contentType, inputRule) => {
};
const trackInputRulesAndShortcuts = (tiptapExtension) => {
return tiptapExtension.extend({
addKeyboardShortcuts() {
const shortcuts = this.parent?.() || {};
const { name } = this;
/**
* We dont want to track keyboard shortcuts
* that are not deliberately executed to create
* new types of content
*/
const dotNotTrackKeys = [ENTER_KEY, BACKSPACE_KEY];
const decorated = mapValues(shortcuts, (commandFn, shortcut) =>
dotNotTrackKeys.includes(shortcut)
? commandFn
: trackKeyboardShortcut(name, commandFn, shortcut),
);
return tiptapExtension
.extend({
addKeyboardShortcuts() {
const shortcuts = this.parent?.() || {};
const { name } = this;
/**
* We dont want to track keyboard shortcuts
* that are not deliberately executed to create
* new types of content
*/
const dotNotTrackKeys = [ENTER_KEY, BACKSPACE_KEY];
const decorated = mapValues(shortcuts, (commandFn, shortcut) =>
dotNotTrackKeys.includes(shortcut)
? commandFn
: trackKeyboardShortcut(name, commandFn, shortcut),
);
return decorated;
},
addInputRules() {
const inputRules = this.parent?.() || [];
const { name } = this;
return decorated;
},
addInputRules() {
const inputRules = this.parent?.() || [];
const { name } = this;
return inputRules.map((inputRule) => trackInputRule(name, inputRule));
},
});
return inputRules.map((inputRule) => trackInputRule(name, inputRule));
},
})
.configure(tiptapExtension.options);
};
export default trackInputRulesAndShortcuts;

View File

@ -1,44 +0,0 @@
<script>
import { GlEmptyState } from '@gitlab/ui';
import {
NO_TAGS_TITLE,
NO_TAGS_MESSAGE,
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
} from '../../constants/index';
export default {
components: {
GlEmptyState,
},
props: {
noContainersImage: {
type: String,
required: false,
default: '',
},
isEmptyImage: {
type: Boolean,
default: false,
required: false,
},
},
computed: {
title() {
return this.isEmptyImage ? MISSING_OR_DELETED_IMAGE_TITLE : NO_TAGS_TITLE;
},
description() {
return this.isEmptyImage ? MISSING_OR_DELETED_IMAGE_MESSAGE : NO_TAGS_MESSAGE;
},
},
};
</script>
<template>
<gl-empty-state
:title="title"
:svg-path="noContainersImage"
:description="description"
class="gl-mx-auto gl-my-0"
/>
</template>

View File

@ -1,28 +1,38 @@
<script>
import { GlEmptyState } from '@gitlab/ui';
import createFlash from '~/flash';
import { n__ } from '~/locale';
import { joinPaths } from '~/lib/utils/url_utility';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import {
REMOVE_TAGS_BUTTON_TITLE,
TAGS_LIST_TITLE,
GRAPHQL_PAGE_SIZE,
FETCH_IMAGES_LIST_ERROR_MESSAGE,
NAME_SORT_FIELD,
NO_TAGS_TITLE,
NO_TAGS_MESSAGE,
NO_TAGS_MATCHING_FILTERS_TITLE,
NO_TAGS_MATCHING_FILTERS_DESCRIPTION,
} from '../../constants/index';
import getContainerRepositoryTagsQuery from '../../graphql/queries/get_container_repository_tags.query.graphql';
import EmptyState from './empty_state.vue';
import TagsListRow from './tags_list_row.vue';
import TagsLoader from './tags_loader.vue';
export default {
name: 'TagsList',
components: {
GlEmptyState,
TagsListRow,
EmptyState,
TagsLoader,
RegistryList,
PersistedSearch,
},
inject: ['config'],
props: {
id: {
type: [Number, String],
@ -44,6 +54,7 @@ export default {
required: false,
},
},
searchConfig: { NAME_SORT_FIELD },
i18n: {
REMOVE_TAGS_BUTTON_TITLE,
TAGS_LIST_TITLE,
@ -51,6 +62,9 @@ export default {
apollo: {
containerRepository: {
query: getContainerRepositoryTagsQuery,
skip() {
return !this.sort;
},
variables() {
return this.queryVariables;
},
@ -62,6 +76,8 @@ export default {
data() {
return {
containerRepository: {},
filters: {},
sort: null,
};
},
computed: {
@ -78,6 +94,8 @@ export default {
return {
id: joinPaths(this.config.gidPrefix, `${this.id}`),
first: GRAPHQL_PAGE_SIZE,
name: this.filters?.name,
sort: this.sort,
};
},
showMultiDeleteButton() {
@ -87,7 +105,16 @@ export default {
return this.tags.length === 0;
},
isLoading() {
return this.isImageLoading || this.$apollo.queries.containerRepository.loading;
return this.isImageLoading || this.$apollo.queries.containerRepository.loading || !this.sort;
},
hasFilters() {
return this.filters?.name;
},
emptyStateTitle() {
return this.hasFilters ? NO_TAGS_MATCHING_FILTERS_TITLE : NO_TAGS_TITLE;
},
emptyStateDescription() {
return this.hasFilters ? NO_TAGS_MATCHING_FILTERS_DESCRIPTION : NO_TAGS_MESSAGE;
},
},
methods: {
@ -114,15 +141,47 @@ export default {
},
});
},
handleSearchUpdate({ sort, filters }) {
this.sort = sort;
const parsed = {
name: '',
};
// This takes in account the fact that we will be adding more filters types
// this is why is an object and not an array or a simple string
this.filters = filters.reduce((acc, filter) => {
if (filter.type === FILTERED_SEARCH_TERM) {
return {
...acc,
name: `${acc.name} ${filter.value.data}`.trim(),
};
}
return acc;
}, parsed);
},
},
};
</script>
<template>
<div>
<persisted-search
class="gl-mb-5"
:sortable-fields="[$options.searchConfig.NAME_SORT_FIELD]"
:default-order="$options.searchConfig.NAME_SORT_FIELD.orderBy"
default-sort="asc"
@update="handleSearchUpdate"
/>
<tags-loader v-if="isLoading" />
<template v-else>
<empty-state v-if="hasNoTags" :no-containers-image="config.noContainersImage" />
<gl-empty-state
v-if="hasNoTags"
:title="emptyStateTitle"
:svg-path="config.noContainersImage"
:description="emptyStateDescription"
class="gl-mx-auto gl-my-0"
/>
<template v-else>
<registry-list
:title="listTitle"

View File

@ -2,3 +2,5 @@ import { s__, __ } from '~/locale';
export const ROOT_IMAGE_TEXT = s__('ContainerRegistry|Root image');
export const MORE_ACTIONS_TEXT = __('More actions');
export const NAME_SORT_FIELD = { orderBy: 'NAME', label: __('Name') };

View File

@ -116,6 +116,13 @@ export const ROOT_IMAGE_TOOLTIP = s__(
'ContainerRegistry|Image repository with no name located at the project URL.',
);
export const NO_TAGS_MATCHING_FILTERS_TITLE = s__(
'ContainerRegistry|The filter returned no results',
);
export const NO_TAGS_MATCHING_FILTERS_DESCRIPTION = s__(
'ContainerRegistry|Please try different search criteria',
);
// Parameters
export const DEFAULT_PAGE = 1;

View File

@ -1,4 +1,5 @@
import { s__, __ } from '~/locale';
import { NAME_SORT_FIELD } from './common';
// Translations strings
@ -49,5 +50,5 @@ export const GRAPHQL_PAGE_SIZE = 10;
export const SORT_FIELDS = [
{ orderBy: 'UPDATED', label: __('Updated') },
{ orderBy: 'CREATED', label: __('Created') },
{ orderBy: 'NAME', label: __('Name') },
NAME_SORT_FIELD,
];

View File

@ -6,11 +6,13 @@ query getContainerRepositoryTags(
$last: Int
$after: String
$before: String
$name: String
$sort: ContainerRepositoryTagSort
) {
containerRepository(id: $id) {
id
tagsCount
tags(after: $after, before: $before, first: $first, last: $last) {
tags(after: $after, before: $before, first: $first, last: $last, name: $name, sort: $sort) {
nodes {
digest
location

View File

@ -1,5 +1,5 @@
<script>
import { GlResizeObserverDirective } from '@gitlab/ui';
import { GlResizeObserverDirective, GlEmptyState } from '@gitlab/ui';
import { GlBreakpointInstance } from '@gitlab/ui/dist/utils';
import createFlash from '~/flash';
import axios from '~/lib/utils/axios_utils';
@ -9,7 +9,6 @@ import DeleteImage from '../components/delete_image.vue';
import DeleteAlert from '../components/details_page/delete_alert.vue';
import DeleteModal from '../components/details_page/delete_modal.vue';
import DetailsHeader from '../components/details_page/details_header.vue';
import EmptyState from '../components/details_page/empty_state.vue';
import PartialCleanupAlert from '../components/details_page/partial_cleanup_alert.vue';
import StatusAlert from '../components/details_page/status_alert.vue';
import TagsList from '../components/details_page/tags_list.vue';
@ -26,6 +25,8 @@ import {
MISSING_OR_DELETED_IMAGE_BREADCRUMB,
ROOT_IMAGE_TEXT,
GRAPHQL_PAGE_SIZE,
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
} from '../constants/index';
import deleteContainerRepositoryTagsMutation from '../graphql/mutations/delete_container_repository_tags.mutation.graphql';
import getContainerRepositoryDetailsQuery from '../graphql/queries/get_container_repository_details.query.graphql';
@ -34,13 +35,13 @@ import getContainerRepositoryTagsQuery from '../graphql/queries/get_container_re
export default {
name: 'RegistryDetailsPage',
components: {
GlEmptyState,
DeleteAlert,
PartialCleanupAlert,
DetailsHeader,
DeleteModal,
TagsList,
TagsLoader,
EmptyState,
StatusAlert,
DeleteImage,
},
@ -49,6 +50,10 @@ export default {
},
mixins: [Tracking.mixin()],
inject: ['breadCrumbState', 'config'],
i18n: {
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
},
apollo: {
containerRepository: {
query: getContainerRepositoryDetailsQuery,
@ -230,6 +235,12 @@ export default {
@cancel="track('cancel_delete')"
/>
</template>
<empty-state v-else is-empty-image :no-containers-image="config.noContainersImage" />
<gl-empty-state
v-else
:title="$options.i18n.MISSING_OR_DELETED_IMAGE_TITLE"
:description="$options.i18n.MISSING_OR_DELETED_IMAGE_MESSAGE"
:svg-path="config.noContainersImage"
class="gl-mx-auto gl-my-0"
/>
</div>
</template>

View File

@ -0,0 +1,80 @@
<script>
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { extractFilterAndSorting, getQueryParams } from '~/packages_and_registries/shared/utils';
export default {
components: { RegistrySearch, UrlSync },
props: {
sortableFields: {
type: Array,
required: true,
},
defaultOrder: {
type: String,
required: true,
},
defaultSort: {
type: String,
required: true,
},
},
data() {
return {
filters: [],
sorting: {
orderBy: this.defaultOrder,
sort: this.defaultSort,
},
mountRegistrySearch: false,
};
},
computed: {
parsedSorting() {
const cleanOrderBy = this.sorting?.orderBy.replace('_at', '');
return `${cleanOrderBy}_${this.sorting?.sort}`.toUpperCase();
},
},
mounted() {
const queryParams = getQueryParams(window.document.location.search);
const { sorting, filters } = extractFilterAndSorting(queryParams);
this.updateSorting(sorting);
this.updateFilters(filters);
this.mountRegistrySearch = true;
this.emitUpdate();
},
methods: {
updateFilters(newValue) {
this.filters = newValue;
},
updateSorting(newValue) {
this.sorting = { ...this.sorting, ...newValue };
},
updateSortingAndEmitUpdate(newValue) {
this.updateSorting(newValue);
this.emitUpdate();
},
emitUpdate() {
this.$emit('update', { sort: this.parsedSorting, filters: this.filters });
},
},
};
</script>
<template>
<url-sync>
<template #default="{ updateQuery }">
<registry-search
v-if="mountRegistrySearch"
:filter="filters"
:sorting="sorting"
:tokens="$options.tokens"
:sortable-fields="sortableFields"
@sorting:changed="updateSortingAndEmitUpdate"
@filter:changed="updateFilters"
@filter:submit="emitUpdate"
@query:changed="updateQuery"
/>
</template>
</url-sync>
</template>

View File

@ -3,15 +3,12 @@
.form-group
%b= s_('ProjectSettings|Merge commit message template')
%p.text-secondary
- configure_the_merge_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
- configure_the_merge_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_merge_commit_message_help_link_url }
= s_('ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}').html_safe % { link_start: configure_the_merge_commit_message_help_link_start, link_end: '</a>'.html_safe }
= s_('ProjectSettings|The commit message used when merging, if the merge method creates a merge commit.')
.mb-2
- default_merge_commit_template = "Merge branch '%{source_branch}' into '%{target_branch}'\n\n%{title}\n\n%{issues}\n\nSee merge request %{reference}"
= form.text_area :merge_commit_template, class: 'form-control gl-form-input', rows: 8, maxlength: 500, placeholder: default_merge_commit_template
%p.form-text.text-muted
= s_('ProjectSettings|Maximum 500 characters.')
= s_('ProjectSettings|Supported variables:')
- Gitlab::MergeRequests::CommitMessageGenerator::PLACEHOLDERS.keys.each do |placeholder|
%code
= "%{#{placeholder}}".html_safe
- configure_the_merge_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
- configure_the_merge_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_merge_commit_message_help_link_url }
= s_('ProjectSettings|%{link_start}What variables can I use?%{link_end}').html_safe % { link_start: configure_the_merge_commit_message_help_link_start, link_end: '</a>'.html_safe }

View File

@ -3,13 +3,10 @@
.form-group
%b= s_('ProjectSettings|Merge suggestions')
%p.text-secondary
- configure_the_commit_message_for_applied_suggestions_help_link_url = help_page_path('user/project/merge_requests/reviews/suggestions.md', anchor: 'configure-the-commit-message-for-applied-suggestions')
- configure_the_commit_message_for_applied_suggestions_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_commit_message_for_applied_suggestions_help_link_url }
= s_('ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}').html_safe % { link_start: configure_the_commit_message_for_applied_suggestions_help_link_start, link_end: '</a>'.html_safe }
= s_('ProjectSettings|The commit message used when applying merge request suggestions.')
.mb-2
= form.text_field :suggestion_commit_message, class: 'form-control mb-2', placeholder: Gitlab::Suggestions::CommitMessage::DEFAULT_SUGGESTION_COMMIT_MESSAGE
%p.form-text.text-muted
= s_('ProjectSettings|Supported variables:')
- Gitlab::Suggestions::CommitMessage::PLACEHOLDERS.keys.each do |placeholder|
%code
= "%{#{placeholder}}".html_safe
- configure_the_commit_message_for_applied_suggestions_help_link_url = help_page_path('user/project/merge_requests/reviews/suggestions.md', anchor: 'configure-the-commit-message-for-applied-suggestions')
- configure_the_commit_message_for_applied_suggestions_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_commit_message_for_applied_suggestions_help_link_url }
= s_('ProjectSettings|%{link_start}What variables can I use?%{link_end}').html_safe % { link_start: configure_the_commit_message_for_applied_suggestions_help_link_start, link_end: '</a>'.html_safe }

View File

@ -3,14 +3,11 @@
.form-group
%b= s_('ProjectSettings|Squash commit message template')
%p.text-secondary
- configure_the_squash_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
- configure_the_squash_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_squash_commit_message_help_link_url }
= s_('ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}').html_safe % { link_start: configure_the_squash_commit_message_help_link_start, link_end: '</a>'.html_safe }
= s_('ProjectSettings|The commit message used when squashing commits.')
.mb-2
= form.text_area :squash_commit_template, class: 'form-control gl-form-input', rows: 8, maxlength: 500, placeholder: '%{title}'
%p.form-text.text-muted
= s_('ProjectSettings|Maximum 500 characters.')
= s_('ProjectSettings|Supported variables:')
- Gitlab::MergeRequests::CommitMessageGenerator::PLACEHOLDERS.keys.each do |placeholder|
%code
= "%{#{placeholder}}".html_safe
- configure_the_squash_commit_message_help_link_url = help_page_path('user/project/merge_requests/commit_templates.md')
- configure_the_squash_commit_message_help_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: configure_the_squash_commit_message_help_link_url }
= s_('ProjectSettings|%{link_start}What variables can I use?%{link_end}').html_safe % { link_start: configure_the_squash_commit_message_help_link_start, link_end: '</a>'.html_safe }

View File

@ -1,11 +1,8 @@
- page_title "#{@merge_request.title} (#{@merge_request.to_reference}", _("Merge requests")
- badge_start = '<span class="badge badge-pill gl-badge sm badge-info">'.html_safe
- badge_end = '</span>'.html_safe
- err_fork_project_removed = s_("MergeRequest|Can't show this merge request because the fork project was deleted.")
- err_source_branch = s_("MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch.")
- err_target_branch = s_("MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch.")
- err_source_branch = s_("MergeRequest|Can't show this merge request because the source branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the source branch.")
- err_target_branch = s_("MergeRequest|Can't show this merge request because the target branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the target branch.")
- err_internal = s_("MergeRequest|Can't show this merge request because of an internal error. Contact your administrator.")
.merge-request
@ -20,8 +17,8 @@
- if @merge_request.for_fork? && !@merge_request.source_project
= err_fork_project_removed
- elsif !@merge_request.source_branch_exists?
= err_source_branch.html_safe % { badge_start: badge_start, badge_end: badge_end, source_branch: @merge_request.source_branch, project_path: @merge_request.source_project_path }
= err_source_branch.html_safe % { branch_badge: gl_badge_tag(@merge_request.source_branch, variant: :info, size: :sm), path_badge: gl_badge_tag(@merge_request.source_project_path, variant: :info, size: :sm) }
- elsif !@merge_request.target_branch_exists?
= err_target_branch.html_safe % { badge_start: badge_start, badge_end: badge_end, target_branch: @merge_request.target_branch, project_path: @merge_request.source_project_path }
= err_target_branch.html_safe % { branch_badge: gl_badge_tag(@merge_request.target_branch, variant: :info, size: :sm), path_badge: gl_badge_tag(@merge_request.source_project_path, variant: :info, size: :sm) }
- else
= err_internal

View File

@ -22,7 +22,7 @@
.row
.form-group.col-sm-12
= f.label :role, _('Role'), class: 'label-bold'
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, {}, class: 'form-control js-user-role-dropdown', autofocus: true
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', autofocus: true, required: true
- if Feature.enabled?(:user_other_role_details)
.row
.form-group.col-sm-12.js-other-role-group.hidden

View File

@ -9,6 +9,7 @@ allowlist
allowlisted
allowlisting
allowlists
AlmaLinux
anonymization
anonymized
Ansible

View File

@ -170,6 +170,15 @@ Reply by email should now be working.
cd /home/git/gitlab
```
1. Install the `gitlab-mail_room` gem manually:
```shell
gem install gitlab-mail_room
```
NOTE: This step is necessary to avoid thread deadlocks and to support the latest MailRoom features. See
[this explanation](../development/emails.md#mailroom-gem-updates) for more details.
1. Find the `incoming_email` section in `config/gitlab.yml`, enable the feature
and fill in the details for your specific IMAP server and email account (see [examples](#configuration-examples) below).

View File

@ -17,6 +17,7 @@ The following lists the currently supported OSs and their possible EOL dates.
| OS Version | First supported GitLab version | Arch | OS EOL | Details |
| ---------------- | ------------------------------ | --------------- | ------------- | ------------------------------------------------------------ |
| AlmaLinux 8 | GitLab CE / GitLab EE 14.5.0 | x86_64, aarch64 | 2029 | <https://almalinux.org/> |
| CentOS 7 | GitLab CE / GitLab EE 7.10.0 | x86_64 | June 2024 | <https://wiki.centos.org/About/Product> |
| CentOS 8 | GitLab CE / GitLab EE 12.8.1 | x86_64, aarch64 | Dec 2021 | <https://wiki.centos.org/About/Product> |
| Debian 9 | GitLab CE / GitLab EE 9.3.0 | amd64 | 2022 | <https://wiki.debian.org/LTS> |

View File

@ -139,6 +139,44 @@ These are the only valid legacy formats for an email handler:
In GitLab, the handler for the Service Desk feature is `path/to/project`.
### MailRoom Gem updates
We use [`gitlab-mail_room`](https://gitlab.com/gitlab-org/gitlab-mail_room), a
fork of [`MailRoom`](https://github.com/tpitale/mail_room/), to ensure
that we can make updates quickly to the gem if necessary. We try to upstream
changes as soon as possible and keep the two projects in sync.
Updating the `gitlab-mail_room` dependency in `Gemfile` is deprecated at
the moment in favor of updating the version in
[Omnibus](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/master/config/software/mail_room.rb)
(see [example merge request](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/5816))
and Helm Chart configuration (see [example merge request](https://gitlab.com/gitlab-org/build/CNG/-/merge_requests/854)).
#### Rationale
This was done because to avoid [thread deadlocks](https://github.com/ruby/net-imap/issues/14), `MailRoom` needs
an updated version of the `net-imap` gem. However, this [version of the net-imap cannot be installed by an unprivileged
user](https://github.com/ruby/net-imap/issues/14) due to [an error installing the digest
gem](https://github.com/ruby/digest/issues/14). [This bug in the Ruby interpreter](https://bugs.ruby-lang.org/issues/17761) was fixed in Ruby
3.0.2.
Updating the gem directly in the GitLab Rails `Gemfile` caused a [production incident](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/4053)
since Kubernetes pods do not run as privileged users.
Note that Omnibus GitLab runs `/opt/gitlab/embedded/bin/mail_room`
instead of `bundle exec rake` to avoid loading the older version. With a
Kubernetes install, the MailRoom version has always been explicitly set
in the Helm Chart configuration rather than the `Gemfile`.
#### Preserving backwards compatibility
Removing the `Gemfile` would break incoming e-mail processing for source
installs. For now, source installs are advised to upgrade manually to
the version specified in Omnibus and run `bin/mail_room` directly as
done with Omnibus.
We can reconsider this deprecation once we upgrade to Ruby 3.0.
---
[Return to Development documentation](index.md)

View File

@ -15,12 +15,13 @@ as the hardware requirements that are needed to install and use GitLab.
- Ubuntu (16.04/18.04/20.04)
- Debian (9/10)
- CentOS (7/8)
- AlmaLinux (8)
- CentOS (7)
- openSUSE Leap (15.2)
- SUSE Linux Enterprise Server (12 SP2/12 SP5)
- Red Hat Enterprise Linux (please use the CentOS packages and instructions)
- Scientific Linux (please use the CentOS packages and instructions)
- Oracle Linux (please use the CentOS packages and instructions)
- Red Hat Enterprise Linux (use the AlmaLinux or CentOS instructions)
- Scientific Linux (use the CentOS instructions)
- Oracle Linux (use the CentOS instructions)
For the installation options, see [the main installation page](index.md).

View File

@ -60,6 +60,16 @@ to ensure the major components of GitLab are working:
1. If using Elasticsearch, verify that searches are successful.
1. If you are using [Reply by Email](../administration/reply_by_email.md) or [Service Desk](../user/project/service_desk.md),
manually install the latest version of `gitlab-mail_room`:
```shell
gem install gitlab-mail_room
```
NOTE: This step is necessary to avoid thread deadlocks and to support the latest MailRoom features. See
[this explanation](../development/emails.md#mailroom-gem-updates) for more details.
If in any case something goes wrong, see [how to troubleshoot](#troubleshooting).
## Rollback plan

View File

@ -15,10 +15,12 @@ and configure it in GitLab.
1. Open the Discord channel you want to receive GitLab event notifications.
1. From the channel menu, select **Edit channel**.
1. Click on **Webhooks** menu item.
1. Click the **Create Webhook** button and fill in the name of the bot to post the messages. Optionally, edit the avatar.
1. Note the URL from the **WEBHOOK URL** field.
1. Click the **Save** button.
1. Select **Integrations**.
1. If there are no existing webhooks, select **Create Webhook**. Otherwise, select **View Webhooks** then **New Webhook**.
1. Enter the name of the bot to post the message.
1. Optional. Edit the avatar.
1. Copy the URL from the **WEBHOOK URL** field.
1. Select **Save**.
## Configure created webhook in GitLab

View File

@ -59,20 +59,20 @@ Your Slack team now starts receiving GitLab event notifications as configured.
The following triggers are available for Slack notifications:
| Trigger name | Trigger event |
| ------------------------ | ------------------------------------------------------ |
| **Push** | A push to the repository. |
| **Issue** | An issue is created, updated, or closed. |
| **Confidential issue** | A confidential issue is created, updated, or closed. |
| **Merge request** | A merge request is created, updated, or merged. |
| **Note** | A comment is added. |
| **Confidential note** | A confidential note is added. |
| **Tag push** | A new tag is pushed to the repository. |
| **Pipeline** | A pipeline status changed. |
| **Wiki page** | A wiki page is created or updated. |
| **Deployment** | A deployment starts or finishes. |
| **Alert** | A new, unique alert is recorded. |
| **Vulnerability** | **(ULTIMATE)** A new, unique vulnerability is recorded. |
| Trigger name | Trigger event |
|--------------------------------------------------------------------------|------------------------------------------------------|
| **Push** | A push to the repository. |
| **Issue** | An issue is created, updated, or closed. |
| **Confidential issue** | A confidential issue is created, updated, or closed. |
| **Merge request** | A merge request is created, updated, or merged. |
| **Note** | A comment is added. |
| **Confidential note** | A confidential note is added. |
| **Tag push** | A new tag is pushed to the repository. |
| **Pipeline** | A pipeline status changed. |
| **Wiki page** | A wiki page is created or updated. |
| **Deployment** | A deployment starts or finishes. |
| **Alert** | A new, unique alert is recorded. |
| [**Vulnerability**](../../application_security/vulnerabilities/index.md) | A new, unique vulnerability is recorded. |
## Troubleshooting

Binary file not shown.

Before

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -89,7 +89,7 @@ These commit messages can be customized to follow any guidelines you might have.
To do so, expand the **Merge requests** tab within your project's **General**
settings and change the **Merge suggestions** text:
![Custom commit message for applied suggestions](img/suggestions_custom_commit_messages_v13_1.jpg)
![Custom commit message for applied suggestions](img/suggestions_custom_commit_messages_v14_7.png)
You can also use following variables besides static text:

View File

@ -9383,6 +9383,9 @@ msgstr ""
msgid "ContainerRegistry|Note: Any policy update will result in a change to the scheduled run date and time"
msgstr ""
msgid "ContainerRegistry|Please try different search criteria"
msgstr ""
msgid "ContainerRegistry|Published %{timeInfo}"
msgstr ""
@ -9472,6 +9475,9 @@ msgstr ""
msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}manually run cleanup now%{adminLinkEnd} or you can wait for the cleanup policy to automatically run again. %{docLinkStart}More information%{docLinkEnd}"
msgstr ""
msgid "ContainerRegistry|The filter returned no results"
msgstr ""
msgid "ContainerRegistry|The image repository could not be found."
msgstr ""
@ -22341,10 +22347,10 @@ msgstr ""
msgid "MergeRequest|Can't show this merge request because the fork project was deleted."
msgstr ""
msgid "MergeRequest|Can't show this merge request because the source branch %{badge_start}%{source_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the source branch."
msgid "MergeRequest|Can't show this merge request because the source branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the source branch."
msgstr ""
msgid "MergeRequest|Can't show this merge request because the target branch %{badge_start}%{target_branch}%{badge_end} is missing from project %{badge_start}%{project_path}%{badge_end}. Close this merge request or update the target branch."
msgid "MergeRequest|Can't show this merge request because the target branch %{branch_badge} is missing from project %{path_badge}. Close this merge request or update the target branch."
msgstr ""
msgid "MergeRequest|Compare %{target} and %{source}"
@ -27694,6 +27700,9 @@ msgstr ""
msgid "ProjectSettings|%{link_start}What are description templates?%{link_end}"
msgstr ""
msgid "ProjectSettings|%{link_start}What variables can I use?%{link_end}"
msgstr ""
msgid "ProjectSettings|Additional settings that influence how and when merges are done."
msgstr ""
@ -27946,19 +27955,16 @@ msgstr ""
msgid "ProjectSettings|Submit changes to be merged upstream."
msgstr ""
msgid "ProjectSettings|Supported variables:"
msgstr ""
msgid "ProjectSettings|Target project"
msgstr ""
msgid "ProjectSettings|The commit message used when applying merge request suggestions. %{link_start}Learn more about suggestions.%{link_end}"
msgid "ProjectSettings|The commit message used when applying merge request suggestions."
msgstr ""
msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit. %{link_start}Learn more about syntax and variables.%{link_end}"
msgid "ProjectSettings|The commit message used when merging, if the merge method creates a merge commit."
msgstr ""
msgid "ProjectSettings|The commit message used when squashing commits. %{link_start}Learn more about syntax and variables.%{link_end}"
msgid "ProjectSettings|The commit message used when squashing commits."
msgstr ""
msgid "ProjectSettings|The default target project for merge requests created in this fork project."

View File

@ -63,36 +63,36 @@
"@rails/ujs": "6.1.4-1",
"@sentry/browser": "5.30.0",
"@sourcegraph/code-host-integration": "0.0.60",
"@tiptap/core": "^2.0.0-beta.143",
"@tiptap/extension-blockquote": "^2.0.0-beta.25",
"@tiptap/extension-bold": "^2.0.0-beta.24",
"@tiptap/extension-bullet-list": "^2.0.0-beta.23",
"@tiptap/extension-code": "^2.0.0-beta.25",
"@tiptap/extension-code-block-lowlight": "2.0.0-beta.57",
"@tiptap/core": "^2.0.0-beta.160",
"@tiptap/extension-blockquote": "^2.0.0-beta.26",
"@tiptap/extension-bold": "^2.0.0-beta.25",
"@tiptap/extension-bullet-list": "^2.0.0-beta.26",
"@tiptap/extension-code": "^2.0.0-beta.26",
"@tiptap/extension-code-block-lowlight": "2.0.0-beta.63",
"@tiptap/extension-document": "^2.0.0-beta.15",
"@tiptap/extension-dropcursor": "^2.0.0-beta.25",
"@tiptap/extension-gapcursor": "^2.0.0-beta.33",
"@tiptap/extension-gapcursor": "^2.0.0-beta.34",
"@tiptap/extension-hard-break": "^2.0.0-beta.30",
"@tiptap/extension-heading": "^2.0.0-beta.23",
"@tiptap/extension-heading": "^2.0.0-beta.24",
"@tiptap/extension-history": "^2.0.0-beta.21",
"@tiptap/extension-horizontal-rule": "^2.0.0-beta.30",
"@tiptap/extension-image": "^2.0.0-beta.24",
"@tiptap/extension-italic": "^2.0.0-beta.24",
"@tiptap/extension-link": "^2.0.0-beta.28",
"@tiptap/extension-list-item": "^2.0.0-beta.19",
"@tiptap/extension-ordered-list": "^2.0.0-beta.24",
"@tiptap/extension-paragraph": "^2.0.0-beta.22",
"@tiptap/extension-strike": "^2.0.0-beta.26",
"@tiptap/extension-subscript": "^2.0.0-beta.9",
"@tiptap/extension-superscript": "^2.0.0-beta.9",
"@tiptap/extension-table": "^2.0.0-beta.43",
"@tiptap/extension-italic": "^2.0.0-beta.25",
"@tiptap/extension-link": "^2.0.0-beta.34",
"@tiptap/extension-list-item": "^2.0.0-beta.20",
"@tiptap/extension-ordered-list": "^2.0.0-beta.27",
"@tiptap/extension-paragraph": "^2.0.0-beta.23",
"@tiptap/extension-strike": "^2.0.0-beta.27",
"@tiptap/extension-subscript": "^2.0.0-beta.10",
"@tiptap/extension-superscript": "^2.0.0-beta.10",
"@tiptap/extension-table": "^2.0.0-beta.46",
"@tiptap/extension-table-cell": "^2.0.0-beta.20",
"@tiptap/extension-table-header": "^2.0.0-beta.22",
"@tiptap/extension-table-row": "^2.0.0-beta.19",
"@tiptap/extension-task-item": "^2.0.0-beta.29",
"@tiptap/extension-task-list": "^2.0.0-beta.23",
"@tiptap/extension-task-item": "^2.0.0-beta.30",
"@tiptap/extension-task-list": "^2.0.0-beta.26",
"@tiptap/extension-text": "^2.0.0-beta.15",
"@tiptap/vue-2": "^2.0.0-beta.69",
"@tiptap/vue-2": "^2.0.0-beta.74",
"@toast-ui/editor": "^2.5.2",
"@toast-ui/vue-editor": "^2.5.2",
"apollo-cache-inmemory": "^1.6.6",
@ -162,11 +162,11 @@
"popper.js": "^1.16.1",
"portal-vue": "^2.1.7",
"prismjs": "^1.21.0",
"prosemirror-markdown": "^1.6.0",
"prosemirror-model": "^1.15.0",
"prosemirror-markdown": "1.6.0",
"prosemirror-model": "^1.16.1",
"prosemirror-state": "^1.3.4",
"prosemirror-tables": "^1.1.1",
"prosemirror-view": "^1.23.3",
"prosemirror-view": "^1.23.5",
"raphael": "^2.2.7",
"raw-loader": "^4.0.2",
"scrollparent": "^2.0.1",

View File

@ -68,7 +68,10 @@ module QA
fill_element :access_level_dropdown, with: group_access
click_button 'Select a group'
fill_element :group_select_dropdown_search_field, group_name
# Helps stabilize race condition with concurrent group API calls while searching
# TODO: Replace with `fill_element :group_select_dropdown_search_field, group_name` when this bug is resolved: https://gitlab.com/gitlab-org/gitlab/-/issues/349379
send_keys_to_element(:group_select_dropdown_search_field, group_name)
Support::WaitForRequests.wait_for_requests

View File

@ -41,6 +41,11 @@ module QA
click_button 'Remove group'
end
end
def has_group?(group_name)
click_element :groups_list_tab
has_element?(:group_row, text: group_name)
end
end
end
end

View File

@ -0,0 +1,85 @@
# frozen_string_literal: true
module QA
# Tagging with issue for a transient invite group modal search bug, but does not require quarantine at this time
RSpec.describe 'Manage', :requires_admin, :transient, issue: 'https://gitlab.com/gitlab-org/gitlab/-/issues/349379' do
describe 'Invite group' do
shared_examples 'invites group to project' do
it 'verifies group is added and members can access project' do
Page::Project::Menu.perform(&:click_members)
Page::Project::Members.perform do |project_members|
project_members.invite_group(group.path)
expect(project_members).to have_group(group.path)
end
Flow::Login.sign_in(as: @user)
Page::Dashboard::Projects.perform do |projects|
expect(projects).to have_project_with_access_role(project.name, 'Guest')
end
project.visit!
Page::Project::Show.perform do |project_page|
expect(project_page).to have_name(project.name)
end
end
end
before(:context) do
@user = Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
end
before do
Runtime::Feature.enable(:invite_members_group_modal)
Flow::Login.sign_in
group.add_member(@user, Resource::Members::AccessLevel::GUEST)
project.visit!
end
context 'to personal namespace project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349223' do
let(:group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "group-for-personal-project-#{SecureRandom.hex(8)}"
end
end
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'personal-namespace-project'
project.personal_namespace = Runtime::User.username
project.visibility = :private
project.description = 'test personal namespace project'
end
end
it_behaves_like 'invites group to project'
end
context 'to group project', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/349340' do
let(:group) do
Resource::Group.fabricate_via_api! do |group|
group.path = "group-for-group-project-#{SecureRandom.hex(8)}"
end
end
let(:project) do
Resource::Project.fabricate_via_api! do |project|
project.name = 'group-project'
project.visibility = :private
project.description = 'test group project'
end
end
it_behaves_like 'invites group to project'
end
after do
project&.remove_via_api!
group&.remove_via_api!
Runtime::Feature.disable(:invite_members_group_modal)
end
end
end
end

View File

@ -33,7 +33,7 @@ describe('content_editor/extensions/link', () => {
${'documentation](readme.md'} | ${() => p('documentation](readme.md')}
${'http://example.com '} | ${() => p(link({ href: 'http://example.com' }, 'http://example.com'))}
${'https://example.com '} | ${() => p(link({ href: 'https://example.com' }, 'https://example.com'))}
${'www.example.com '} | ${() => p(link({ href: 'www.example.com' }, 'www.example.com'))}
${'www.example.com '} | ${() => p(link({ href: 'http://www.example.com' }, 'www.example.com'))}
${'example.com/ab.html '} | ${() => p('example.com/ab.html')}
${'https://www.google.com '} | ${() => p(link({ href: 'https://www.google.com' }, 'https://www.google.com'))}
`('with input=$input, then should insert a $insertedNode', ({ input, insertedNode }) => {

View File

@ -26,7 +26,7 @@ const INVITATIONS_API_MULTIPLE_EMAIL_RESTRICTED = {
const INVITATIONS_API_EMAIL_TAKEN = {
message: {
'email@example2.com': 'Invite email has already been taken',
'email@example.org': 'Invite email has already been taken',
},
status: 'error',
};

View File

@ -1,54 +0,0 @@
import { GlEmptyState } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue';
import {
NO_TAGS_TITLE,
NO_TAGS_MESSAGE,
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
} from '~/packages_and_registries/container_registry/explorer/constants';
describe('EmptyTagsState component', () => {
let wrapper;
const findEmptyState = () => wrapper.find(GlEmptyState);
const mountComponent = (propsData) => {
wrapper = shallowMount(component, {
stubs: {
GlEmptyState,
},
propsData,
});
};
afterEach(() => {
wrapper.destroy();
wrapper = null;
});
it('contains gl-empty-state', () => {
mountComponent();
expect(findEmptyState().exists()).toBe(true);
});
it.each`
isEmptyImage | title | description
${false} | ${NO_TAGS_TITLE} | ${NO_TAGS_MESSAGE}
${true} | ${MISSING_OR_DELETED_IMAGE_TITLE} | ${MISSING_OR_DELETED_IMAGE_MESSAGE}
`(
'when isEmptyImage is $isEmptyImage has the correct props',
({ isEmptyImage, title, description }) => {
mountComponent({
noContainersImage: 'foo',
isEmptyImage,
});
expect(findEmptyState().props()).toMatchObject({
title,
description,
svgPath: 'foo',
});
},
);
});

View File

@ -1,16 +1,25 @@
import { shallowMount, createLocalVue } from '@vue/test-utils';
import { nextTick } from 'vue';
import { GlEmptyState } from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { stripTypenames } from 'helpers/graphql_helpers';
import EmptyTagsState from '~/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue';
import component from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
import TagsListRow from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list_row.vue';
import TagsLoader from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_loader.vue';
import RegistryList from '~/packages_and_registries/shared/components/registry_list.vue';
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
import getContainerRepositoryTagsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_tags.query.graphql';
import { GRAPHQL_PAGE_SIZE } from '~/packages_and_registries/container_registry/explorer/constants/index';
import {
GRAPHQL_PAGE_SIZE,
NO_TAGS_TITLE,
NO_TAGS_MESSAGE,
NO_TAGS_MATCHING_FILTERS_TITLE,
NO_TAGS_MATCHING_FILTERS_DESCRIPTION,
} from '~/packages_and_registries/container_registry/explorer/constants/index';
import { FILTERED_SEARCH_TERM } from '~/packages_and_registries/shared/constants';
import { tagsMock, imageTagsMock, tagsPageInfo } from '../../mock_data';
const localVue = createLocalVue();
@ -21,11 +30,20 @@ describe('Tags List', () => {
let resolver;
const tags = [...tagsMock];
const defaultConfig = {
noContainersImage: 'noContainersImage',
};
const findPersistedSearch = () => wrapper.findComponent(PersistedSearch);
const findTagsListRow = () => wrapper.findAllComponents(TagsListRow);
const findRegistryList = () => wrapper.findComponent(RegistryList);
const findEmptyState = () => wrapper.findComponent(EmptyTagsState);
const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findTagsLoader = () => wrapper.findComponent(TagsLoader);
const fireFirstSortUpdate = () => {
findPersistedSearch().vm.$emit('update', { sort: 'NAME_ASC', filters: [] });
};
const waitForApolloRequestRender = async () => {
await waitForPromises();
await nextTick();
@ -44,7 +62,7 @@ describe('Tags List', () => {
stubs: { RegistryList },
provide() {
return {
config: {},
config: defaultConfig,
};
},
});
@ -61,10 +79,23 @@ describe('Tags List', () => {
describe('registry list', () => {
beforeEach(() => {
mountComponent();
fireFirstSortUpdate();
return waitForApolloRequestRender();
});
it('has a persisted search', () => {
expect(findPersistedSearch().props()).toMatchObject({
defaultOrder: 'NAME',
defaultSort: 'asc',
sortableFields: [
{
label: 'Name',
orderBy: 'NAME',
},
],
});
});
it('binds the correct props', () => {
expect(findRegistryList().props()).toMatchObject({
title: '2 tags',
@ -75,11 +106,13 @@ describe('Tags List', () => {
});
describe('events', () => {
it('prev-page fetch the previous page', () => {
it('prev-page fetch the previous page', async () => {
findRegistryList().vm.$emit('prev-page');
expect(resolver).toHaveBeenCalledWith({
first: null,
name: '',
sort: 'NAME_ASC',
before: tagsPageInfo.startCursor,
last: GRAPHQL_PAGE_SIZE,
id: '1',
@ -92,6 +125,8 @@ describe('Tags List', () => {
expect(resolver).toHaveBeenCalledWith({
after: tagsPageInfo.endCursor,
first: GRAPHQL_PAGE_SIZE,
name: '',
sort: 'NAME_ASC',
id: '1',
});
});
@ -108,6 +143,7 @@ describe('Tags List', () => {
describe('list rows', () => {
it('one row exist for each tag', async () => {
mountComponent();
fireFirstSortUpdate();
await waitForApolloRequestRender();
@ -116,6 +152,7 @@ describe('Tags List', () => {
it('the correct props are bound to it', async () => {
mountComponent({ propsData: { disabled: true, id: 1 } });
fireFirstSortUpdate();
await waitForApolloRequestRender();
@ -130,7 +167,7 @@ describe('Tags List', () => {
describe('events', () => {
it('select event update the selected items', async () => {
mountComponent();
fireFirstSortUpdate();
await waitForApolloRequestRender();
findTagsListRow().at(0).vm.$emit('select');
@ -142,7 +179,7 @@ describe('Tags List', () => {
it('delete event emit a delete event', async () => {
mountComponent();
fireFirstSortUpdate();
await waitForApolloRequestRender();
findTagsListRow().at(0).vm.$emit('delete');
@ -154,32 +191,45 @@ describe('Tags List', () => {
describe('when the list of tags is empty', () => {
beforeEach(() => {
resolver = jest.fn().mockResolvedValue(imageTagsMock([]));
mountComponent();
fireFirstSortUpdate();
return waitForApolloRequestRender();
});
it('has the empty state', async () => {
mountComponent();
await waitForApolloRequestRender();
expect(findEmptyState().exists()).toBe(true);
});
it('does not show the loader', async () => {
mountComponent();
await waitForApolloRequestRender();
it('does not show the loader', () => {
expect(findTagsLoader().exists()).toBe(false);
});
it('does not show the list', async () => {
mountComponent();
await waitForApolloRequestRender();
it('does not show the list', () => {
expect(findRegistryList().exists()).toBe(false);
});
describe('empty state', () => {
it('default empty state', () => {
expect(findEmptyState().props()).toMatchObject({
svgPath: defaultConfig.noContainersImage,
title: NO_TAGS_TITLE,
description: NO_TAGS_MESSAGE,
});
});
it('when filtered shows a filtered message', async () => {
findPersistedSearch().vm.$emit('update', {
sort: 'NAME_ASC',
filters: [{ type: FILTERED_SEARCH_TERM, value: { data: 'foo' } }],
});
await waitForApolloRequestRender();
expect(findEmptyState().props()).toMatchObject({
svgPath: defaultConfig.noContainersImage,
title: NO_TAGS_MATCHING_FILTERS_TITLE,
description: NO_TAGS_MATCHING_FILTERS_DESCRIPTION,
});
});
});
});
describe('loading state', () => {
it.each`
isImageLoading | queryExecuting | loadingVisible
@ -191,7 +241,7 @@ describe('Tags List', () => {
'when the isImageLoading is $isImageLoading, and is $queryExecuting that the query is still executing is $loadingVisible that the loader is shown',
async ({ isImageLoading, queryExecuting, loadingVisible }) => {
mountComponent({ propsData: { isImageLoading, isMobile: false, id: 1 } });
fireFirstSortUpdate();
if (!queryExecuting) {
await waitForApolloRequestRender();
}

View File

@ -1,4 +1,4 @@
import { GlKeysetPagination } from '@gitlab/ui';
import { GlKeysetPagination, GlEmptyState } from '@gitlab/ui';
import { shallowMount, createLocalVue } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import { nextTick } from 'vue';
@ -8,7 +8,6 @@ import axios from '~/lib/utils/axios_utils';
import DeleteImage from '~/packages_and_registries/container_registry/explorer/components/delete_image.vue';
import DeleteAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/delete_alert.vue';
import DetailsHeader from '~/packages_and_registries/container_registry/explorer/components/details_page/details_header.vue';
import EmptyTagsState from '~/packages_and_registries/container_registry/explorer/components/details_page/empty_state.vue';
import PartialCleanupAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/partial_cleanup_alert.vue';
import StatusAlert from '~/packages_and_registries/container_registry/explorer/components/details_page/status_alert.vue';
import TagsList from '~/packages_and_registries/container_registry/explorer/components/details_page/tags_list.vue';
@ -20,6 +19,8 @@ import {
ALERT_DANGER_IMAGE,
MISSING_OR_DELETED_IMAGE_BREADCRUMB,
ROOT_IMAGE_TEXT,
MISSING_OR_DELETED_IMAGE_TITLE,
MISSING_OR_DELETED_IMAGE_MESSAGE,
} from '~/packages_and_registries/container_registry/explorer/constants';
import deleteContainerRepositoryTagsMutation from '~/packages_and_registries/container_registry/explorer/graphql/mutations/delete_container_repository_tags.mutation.graphql';
import getContainerRepositoryDetailsQuery from '~/packages_and_registries/container_registry/explorer/graphql/queries/get_container_repository_details.query.graphql';
@ -50,7 +51,7 @@ describe('Details Page', () => {
const findTagsList = () => wrapper.find(TagsList);
const findDeleteAlert = () => wrapper.find(DeleteAlert);
const findDetailsHeader = () => wrapper.find(DetailsHeader);
const findEmptyState = () => wrapper.find(EmptyTagsState);
const findEmptyState = () => wrapper.find(GlEmptyState);
const findPartialCleanupAlert = () => wrapper.find(PartialCleanupAlert);
const findStatusAlert = () => wrapper.find(StatusAlert);
const findDeleteImage = () => wrapper.find(DeleteImage);
@ -61,6 +62,10 @@ describe('Details Page', () => {
updateName: jest.fn(),
};
const defaultConfig = {
noContainersImage: 'noContainersImage',
};
const cleanTags = tagsMock.map((t) => {
const result = { ...t };
// eslint-disable-next-line no-underscore-dangle
@ -78,7 +83,7 @@ describe('Details Page', () => {
mutationResolver = jest.fn().mockResolvedValue(graphQLDeleteImageRepositoryTagsMock),
tagsResolver = jest.fn().mockResolvedValue(graphQLImageDetailsMock(imageTagsMock)),
options,
config = {},
config = defaultConfig,
} = {}) => {
localVue.use(VueApollo);
@ -154,7 +159,11 @@ describe('Details Page', () => {
await waitForApolloRequestRender();
expect(findEmptyState().exists()).toBe(true);
expect(findEmptyState().props()).toMatchObject({
description: MISSING_OR_DELETED_IMAGE_MESSAGE,
svgPath: defaultConfig.noContainersImage,
title: MISSING_OR_DELETED_IMAGE_TITLE,
});
});
});

View File

@ -0,0 +1,145 @@
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import RegistrySearch from '~/vue_shared/components/registry/registry_search.vue';
import component from '~/packages_and_registries/shared/components/persisted_search.vue';
import UrlSync from '~/vue_shared/components/url_sync.vue';
import { useMockLocationHelper } from 'helpers/mock_window_location_helper';
import { getQueryParams, extractFilterAndSorting } from '~/packages_and_registries/shared/utils';
jest.mock('~/packages_and_registries/shared/utils');
useMockLocationHelper();
describe('Persisted Search', () => {
let wrapper;
const defaultQueryParamsMock = {
filters: ['foo'],
sorting: { sort: 'desc', orderBy: 'test' },
};
const defaultProps = {
sortableFields: [
{ orderBy: 'test', label: 'test' },
{ orderBy: 'foo', label: 'foo' },
],
defaultOrder: 'test',
defaultSort: 'asc',
};
const findRegistrySearch = () => wrapper.findComponent(RegistrySearch);
const findUrlSync = () => wrapper.findComponent(UrlSync);
const mountComponent = (propsData = defaultProps) => {
wrapper = shallowMountExtended(component, {
propsData,
stubs: {
UrlSync,
},
});
};
beforeEach(() => {
extractFilterAndSorting.mockReturnValue(defaultQueryParamsMock);
});
afterEach(() => {
wrapper.destroy();
});
it('has a registry search component', async () => {
mountComponent();
await nextTick();
expect(findRegistrySearch().exists()).toBe(true);
});
it('registry search is mounted after mount', async () => {
mountComponent();
expect(findRegistrySearch().exists()).toBe(false);
});
it('has a UrlSync component', () => {
mountComponent();
expect(findUrlSync().exists()).toBe(true);
});
it('on sorting:changed emits update event and update internal sort', async () => {
const payload = { sort: 'desc', orderBy: 'test' };
mountComponent();
await nextTick();
findRegistrySearch().vm.$emit('sorting:changed', payload);
await nextTick();
expect(findRegistrySearch().props('sorting')).toMatchObject(payload);
// there is always a first call on mounted that emits up default values
expect(wrapper.emitted('update')[1]).toEqual([
{
filters: ['foo'],
sort: 'TEST_DESC',
},
]);
});
it('on filter:changed updates the filters', async () => {
const payload = ['foo'];
mountComponent();
await nextTick();
findRegistrySearch().vm.$emit('filter:changed', payload);
await nextTick();
expect(findRegistrySearch().props('filter')).toEqual(['foo']);
});
it('on filter:submit emits update event', async () => {
mountComponent();
await nextTick();
findRegistrySearch().vm.$emit('filter:submit');
expect(wrapper.emitted('update')[1]).toEqual([
{
filters: ['foo'],
sort: 'TEST_DESC',
},
]);
});
it('on query:changed calls updateQuery from UrlSync', async () => {
jest.spyOn(UrlSync.methods, 'updateQuery').mockImplementation(() => {});
mountComponent();
await nextTick();
findRegistrySearch().vm.$emit('query:changed');
expect(UrlSync.methods.updateQuery).toHaveBeenCalled();
});
it('sets the component sorting and filtering based on the querystring', async () => {
mountComponent();
await nextTick();
expect(getQueryParams).toHaveBeenCalled();
expect(findRegistrySearch().props()).toMatchObject({
filter: defaultQueryParamsMock.filters,
sorting: defaultQueryParamsMock.sorting,
});
});
});

View File

@ -13,7 +13,7 @@ const normalParagraphNode = buildMockParagraphNode(
'This is just normal paragraph. It has multiple sentences.',
);
const identifierParagraphNode = buildMockParagraphNode(
`[another-identifier]: https://example.com "This example has a title" [identifier]: http://example1.com [this link]: http://example2.com`,
`[another-identifier]: https://example.com "This example has a title" [identifier]: http://example1.com [this link]: http://example.org`,
);
describe('rich_content_editor/renderers_render_identifier_paragraph', () => {

View File

@ -46,7 +46,7 @@ RSpec.describe TriggerableHooks do
describe '.select_active' do
it 'returns hooks that match the active filter' do
TestableHook.create!(url: 'http://example1.com', push_events: true)
TestableHook.create!(url: 'http://example2.com', push_events: true)
TestableHook.create!(url: 'http://example.org', push_events: true)
filter1 = double(:filter1)
filter2 = double(:filter2)
allow(ActiveHookFilter).to receive(:new).twice.and_return(filter1, filter2)

View File

@ -683,7 +683,7 @@ RSpec.describe Integration do
it "returns initial value when the property has been assigned multiple values" do
service.bamboo_url = "http://example.com"
service.bamboo_url = "http://example2.com"
service.bamboo_url = "http://example.org"
expect(service.bamboo_url_was).to eq('http://gitlab.com')
end

View File

@ -94,7 +94,7 @@ RSpec.shared_examples 'application settings examples' do
'1:2:3:4:5::7:8',
'[1:2:3:4:5::7:8]',
'[2001:db8:85a3:8d3:1319:8a2e:370:7348]:443',
'www.example2.com:8080',
'www.example.org:8080',
'example.com:8080'
]
@ -114,7 +114,7 @@ RSpec.shared_examples 'application settings examples' do
an_object_having_attributes(domain: 'example.com'),
an_object_having_attributes(domain: 'subdomain.example.com'),
an_object_having_attributes(domain: 'www.example.com'),
an_object_having_attributes(domain: 'www.example2.com', port: 8080),
an_object_having_attributes(domain: 'www.example.org', port: 8080),
an_object_having_attributes(domain: 'example.com', port: 8080)
]

View File

@ -29,19 +29,6 @@ RSpec.describe 'projects/edit' do
end
context 'merge suggestions settings' do
it 'displays all possible variables' do
render
expect(rendered).to have_content('%{branch_name}')
expect(rendered).to have_content('%{files_count}')
expect(rendered).to have_content('%{file_paths}')
expect(rendered).to have_content('%{project_name}')
expect(rendered).to have_content('%{project_path}')
expect(rendered).to have_content('%{user_full_name}')
expect(rendered).to have_content('%{username}')
expect(rendered).to have_content('%{suggestions_count}')
end
it 'displays a placeholder if none is set' do
render
@ -58,20 +45,6 @@ RSpec.describe 'projects/edit' do
end
context 'merge commit template' do
it 'displays all possible variables' do
render
expect(rendered).to have_content('%{source_branch}')
expect(rendered).to have_content('%{target_branch}')
expect(rendered).to have_content('%{title}')
expect(rendered).to have_content('%{issues}')
expect(rendered).to have_content('%{description}')
expect(rendered).to have_content('%{reference}')
expect(rendered).to have_content('%{approved_by}')
expect(rendered).to have_content('%{url}')
expect(rendered).to have_content('%{merged_by}')
end
it 'displays a placeholder if none is set' do
render

267
yarn.lock
View File

@ -1492,73 +1492,73 @@
dom-accessibility-api "^0.5.1"
pretty-format "^26.4.2"
"@tiptap/core@^2.0.0-beta.143":
version "2.0.0-beta.143"
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.143.tgz#e1eb470351867eb13a8f2169958f2231138a6dc1"
integrity sha512-3AoKMZmuc+Lh/ZsM7dj+mSQvRMFANgLVAT0Fza9DaEMREnbpS6nDZlpcbb0HnoExbd7ZLobuwDGxEIZG5uo3Lw==
"@tiptap/core@^2.0.0-beta.160":
version "2.0.0-beta.160"
resolved "https://registry.yarnpkg.com/@tiptap/core/-/core-2.0.0-beta.160.tgz#98f0625dc12a3498c6bbe2ae4aed4667b62a2a11"
integrity sha512-oKtx4vn4ew+mCH3kiBeD4UdPa5IVLLBCuSgGNnqdoIuRv397uh5SwOz7TiL5A+vTa6yke0xLSKxZ+QNR2qfVXg==
dependencies:
"@types/prosemirror-commands" "^1.0.4"
"@types/prosemirror-keymap" "^1.0.4"
"@types/prosemirror-model" "^1.13.2"
"@types/prosemirror-schema-list" "^1.0.3"
"@types/prosemirror-state" "^1.2.8"
"@types/prosemirror-transform" "^1.1.4"
"@types/prosemirror-view" "^1.19.1"
"@types/prosemirror-transform" "^1.1.5"
"@types/prosemirror-view" "^1.19.2"
prosemirror-commands "^1.1.12"
prosemirror-keymap "^1.1.5"
prosemirror-model "^1.15.0"
prosemirror-model "^1.16.1"
prosemirror-schema-list "^1.1.6"
prosemirror-state "^1.3.4"
prosemirror-transform "^1.3.3"
prosemirror-view "^1.23.1"
prosemirror-view "^1.23.5"
"@tiptap/extension-blockquote@^2.0.0-beta.25":
"@tiptap/extension-blockquote@^2.0.0-beta.26":
version "2.0.0-beta.26"
resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.26.tgz#e5ae4b7bd9376db37407a23e22080c7b11287f3b"
integrity sha512-A6yjcYovONJfOjQFk6vDYXswaCdCtCwjL7w9VTB0R2DLTuJvvRt9DWN0IDcMrj5G+aMgDq4GUUTitv+2Y8krDg==
"@tiptap/extension-bold@^2.0.0-beta.25":
version "2.0.0-beta.25"
resolved "https://registry.yarnpkg.com/@tiptap/extension-blockquote/-/extension-blockquote-2.0.0-beta.25.tgz#f133381163b92b34d9dc6e0d78a52cf56098eb40"
integrity sha512-994bQQhyOmPGCNTnzHY5UwZceBh42Xcr6MEB3XnnYk5kgfNnOlrnHHt3l8mJeSnC78Bs1cRSs1BKmDF8WufauQ==
resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.25.tgz#ec19e7c862d25bae49609c5d6a873f372c506dee"
integrity sha512-ZNdgFYDxKo8lAp0Pqzu45I0JH3ah8/X5TCYg9zNg3QwLUFT16g2LlWDMUDGT5pH9aXxgtFaEdoVacu0EyhlPnQ==
"@tiptap/extension-bold@^2.0.0-beta.24":
version "2.0.0-beta.24"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bold/-/extension-bold-2.0.0-beta.24.tgz#a8d1076922580db528cc6988fde08f731dcfe733"
integrity sha512-2VTCtY2JI0wpDwWT0a2fMFkjbgxDpwD3wvtY3/ndh5pyNX0JQCXtJarFzfZZurWvLNQ8QPRRel73182RBYUOHQ==
"@tiptap/extension-bubble-menu@^2.0.0-beta.50":
version "2.0.0-beta.50"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.50.tgz#96c09e71d84473c018fa63dc072fa3732c2b3e88"
integrity sha512-UYnIaUTbI1K759z3A44dahp/NyHKjSaRvIptMnAv7q312l5n+czGwBcjZo41YUxjLPhnwGk1Siny1V+b5+4yBA==
"@tiptap/extension-bubble-menu@^2.0.0-beta.54":
version "2.0.0-beta.54"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bubble-menu/-/extension-bubble-menu-2.0.0-beta.54.tgz#90ac838cb7899317207037abb74ed2f68528bd22"
integrity sha512-jSvNy+ZVHIzEvf8BY/pLpir7CB4lWL4RNUWLT6YMmGCzdzYJK3RZ6Qp0Yoo7UMTjA5JDGn3Ax1lDj4qcsoXwzA==
dependencies:
prosemirror-state "^1.3.4"
prosemirror-view "^1.23.1"
prosemirror-view "^1.23.5"
tippy.js "^6.3.7"
"@tiptap/extension-bullet-list@^2.0.0-beta.23":
version "2.0.0-beta.23"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.23.tgz#64698c98039ad301c94a9041bbd117e82957be21"
integrity sha512-ReoUiz9f1IX87RX+GRE+fCaLEzNNwmiP4kli3QH8/qrLK3qxvZYr9N31fUeOHecCctUofPSbQB79B39zSo9Ouw==
"@tiptap/extension-bullet-list@^2.0.0-beta.26":
version "2.0.0-beta.26"
resolved "https://registry.yarnpkg.com/@tiptap/extension-bullet-list/-/extension-bullet-list-2.0.0-beta.26.tgz#b42126d2d984c04041b14037e8d3ec1bcf16e7ec"
integrity sha512-1n5HV8gY1tLjPk4x48nva6SZlFHoPlRfF6pqSu9JcJxPO7FUSPxUokuz4swYNe0LRrtykfyNz44dUcxKVhoFow==
"@tiptap/extension-code-block-lowlight@2.0.0-beta.57":
version "2.0.0-beta.57"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.57.tgz#afaa3a59da8d688f4f402d31ad6e5bea6ff87390"
integrity sha512-HbUkhJkTiDusLX+qqaJsqCiTKpWR6LPWScKP/Sk7744EnjMmyiqbmNwyqSx538Z8GIS89TKj1vERLUAAAOGCIQ==
"@tiptap/extension-code-block-lowlight@2.0.0-beta.63":
version "2.0.0-beta.63"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block-lowlight/-/extension-code-block-lowlight-2.0.0-beta.63.tgz#5d99e7693c2181d15f6599b4a20aa386efdc9c00"
integrity sha512-Eam+j5YO7ulytOL+NMIhoEPZsAQag9hL19q17ctgl1k1yPwdLuUtU0lkIr0P+qxSzWXUGWX6q/nXM92Vb4hVPA==
dependencies:
"@tiptap/extension-code-block" "^2.0.0-beta.29"
"@tiptap/extension-code-block" "^2.0.0-beta.33"
"@types/lowlight" "^0.0.3"
lowlight "^1.20.0"
prosemirror-model "^1.15.0"
prosemirror-model "^1.16.1"
prosemirror-state "^1.3.4"
prosemirror-view "^1.23.1"
prosemirror-view "^1.23.5"
"@tiptap/extension-code-block@^2.0.0-beta.29":
version "2.0.0-beta.29"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.29.tgz#ad7f537bc1f12decf027d66c7328f36a8b07795c"
integrity sha512-IoBJxqZ4F7dApRL3NisvMCBJmzpV0LmfJlFQacgm64Li15dP/QyDuvXpku03gT3y9e4f9Gv/KTKwJizXEVABhw==
"@tiptap/extension-code-block@^2.0.0-beta.33":
version "2.0.0-beta.33"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code-block/-/extension-code-block-2.0.0-beta.33.tgz#963b06ec88f97f79e1c90b3b830eff826a4bad88"
integrity sha512-zKiGxbbnZJrKXr0DtBd0B7yXvY3wRk5Y5BsJqe0ZsyXR8lCEY4+DcOPpr6dja2gpgQIB9+vtqZvgBfnnUXXTcw==
dependencies:
prosemirror-state "^1.3.4"
"@tiptap/extension-code@^2.0.0-beta.25":
version "2.0.0-beta.25"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.25.tgz#055dc8dc6d19d3f0439f57dd8ba6433e2f2fd733"
integrity sha512-kXBR4Zp79lpUEfqJtBGv9tO1mj9jFQLMj0iVhj8e8ZporNKei5JfDOY83kwFcKAE60i7tiRDtV3OizpAKMeqDg==
"@tiptap/extension-code@^2.0.0-beta.26":
version "2.0.0-beta.26"
resolved "https://registry.yarnpkg.com/@tiptap/extension-code/-/extension-code-2.0.0-beta.26.tgz#bbfa600a252ee2cded6947b56b6c4c33d998e53a"
integrity sha512-QcFWdEFfbJ1n5UFFBD17QPPAJ3J5p/b7XV484u0shCzywO7aNPV32QeHy1z0eMoyZtCbOWf6hg/a7Ugv8IwpHw==
"@tiptap/extension-document@^2.0.0-beta.15":
version "2.0.0-beta.15"
@ -1573,32 +1573,32 @@
"@types/prosemirror-dropcursor" "^1.0.3"
prosemirror-dropcursor "^1.4.0"
"@tiptap/extension-floating-menu@^2.0.0-beta.45":
version "2.0.0-beta.45"
resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.45.tgz#0ccba4bc376171ff4cb0ad9b6e032bfa69488010"
integrity sha512-UjAXhdrcVInCydCoRq+9IOEHQC2lR6BSNACFiTzgzObY7aFaNmMus/9MZ/WZKSN3Rw8Mk4lr8PXFP/3zuNqbYA==
"@tiptap/extension-floating-menu@^2.0.0-beta.49":
version "2.0.0-beta.49"
resolved "https://registry.yarnpkg.com/@tiptap/extension-floating-menu/-/extension-floating-menu-2.0.0-beta.49.tgz#36682849f50e217137775d7f738af952a0434113"
integrity sha512-VY0d+fJmz8FP1CxqB9u09xCZe/9Wtwff+SxY+LGpflVf0JjS+CWcaVIDNF8zHG13SMobQ5xH6RRnSuTzlS2bRA==
dependencies:
prosemirror-state "^1.3.4"
prosemirror-view "^1.23.1"
prosemirror-view "^1.23.5"
tippy.js "^6.3.7"
"@tiptap/extension-gapcursor@^2.0.0-beta.33":
version "2.0.0-beta.33"
resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.33.tgz#99414204e61655d4df61efc27823732176719532"
integrity sha512-Yu6BJ1bseyXIgLlcw/2R/2wWe1mIQilMwW7hhfDJPLbFwLJrMINtA9hxd2qY7mtW19/CveT5HOihQS6QEk59iw==
"@tiptap/extension-gapcursor@^2.0.0-beta.34":
version "2.0.0-beta.34"
resolved "https://registry.yarnpkg.com/@tiptap/extension-gapcursor/-/extension-gapcursor-2.0.0-beta.34.tgz#0e4971affb1621934422dd5fc4bf2dd7a84f70f7"
integrity sha512-Vm8vMWWQ2kJcUOLfB5CEo5pYgyudI7JeeiZvX9ScPmUmgKVYhEpt3EAICY9pUYJ41aAVH35gZLXkUtsz2f9GHw==
dependencies:
"@types/prosemirror-gapcursor" "^1.0.4"
prosemirror-gapcursor "^1.2.0"
prosemirror-gapcursor "^1.2.1"
"@tiptap/extension-hard-break@^2.0.0-beta.30":
version "2.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@tiptap/extension-hard-break/-/extension-hard-break-2.0.0-beta.30.tgz#165494f1194a7bad08907e6d64d349dd15851b72"
integrity sha512-X9xj/S+CikrbIE7ccUFVwit5QHEbflnKVxod+4zPwr1cxogFbE9AyLZE2MpYdx3z9LcnTYYi9leBqFrP4T/Olw==
"@tiptap/extension-heading@^2.0.0-beta.23":
version "2.0.0-beta.23"
resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.23.tgz#8aafadc58a8d536b7f7885e4ff0f64d30908a868"
integrity sha512-/WLymJjY+MMvee79rWHSKDBGVRw4dbBUMrFLqKLjQQBS1xS8+UW2TYzRrAH6HAH4Tc6WO39ZDbd9K9kc9wqPnA==
"@tiptap/extension-heading@^2.0.0-beta.24":
version "2.0.0-beta.24"
resolved "https://registry.yarnpkg.com/@tiptap/extension-heading/-/extension-heading-2.0.0-beta.24.tgz#52ba163c8d16985739387682d5e5b28ddf242661"
integrity sha512-5a3vgdO7Cf2+z7sulCGs/1j23gBcKiZe3pA1FrC5h6blwLu86hA1xnMAVBVNilP9b6c9f3lN9yxMzEWsp6ZEkA==
"@tiptap/extension-history@^2.0.0-beta.21":
version "2.0.0-beta.21"
@ -1620,48 +1620,49 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-image/-/extension-image-2.0.0-beta.24.tgz#1010676f79925cbe11a44b6d8eee1251910fbc1d"
integrity sha512-7oiX/Ovj9WN4xTBqWbQWd4H3SUO2eNzOiKHebVo3eqWG8NxzOGfuU0iRCENtEa7vTiRrFgyeBotneMALDpDnTQ==
"@tiptap/extension-italic@^2.0.0-beta.24":
version "2.0.0-beta.24"
resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.24.tgz#0a08d06dbd8dbf10f18ed17f019aa42d7ac9dbe0"
integrity sha512-pMAWFaLFb0Z0SC5pjoTKzC6m4CQOdUYeVlHvTS/550Z9lf8cqMawQ8H6Yk6brIuANyh7iUi4/zpq4H4rAdUCuw==
"@tiptap/extension-italic@^2.0.0-beta.25":
version "2.0.0-beta.25"
resolved "https://registry.yarnpkg.com/@tiptap/extension-italic/-/extension-italic-2.0.0-beta.25.tgz#c2ec95cc5baf855134883c5e261da4ab0d3b9479"
integrity sha512-7PvhioTX9baVp5+AmmZU0qna+dFPZCRlSEN/GciH57N77d2uhJ/ZW5iQWTbvy5HBNddQB4Jts1UDIaC7WASrGA==
"@tiptap/extension-link@^2.0.0-beta.28":
version "2.0.0-beta.28"
resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.28.tgz#4385f36b6bb31fab34a86fb7c686ca05a37ed572"
integrity sha512-dZNaEjoDhgjmts44KqgtOYObCdDYZq/yFhsZ8QfqEgNHJMvBNTDaPXwBDW9i3BTkkyLTmwR/qwWxqDrfDdKh2A==
"@tiptap/extension-link@^2.0.0-beta.34":
version "2.0.0-beta.34"
resolved "https://registry.yarnpkg.com/@tiptap/extension-link/-/extension-link-2.0.0-beta.34.tgz#9f07b9db6a3b62192b0162afdab5480fcd93e731"
integrity sha512-v9qqPWyKfJ9BbV2eWR4a+za1cepZywV/2Rng+1gTivzLpfBgy6Q50vgUyMe7KTZpNZw5MuZO4sBwlvangmj6Vg==
dependencies:
linkifyjs "^3.0.3"
linkifyjs "^3.0.5"
prosemirror-model "^1.16.1"
prosemirror-state "^1.3.4"
"@tiptap/extension-list-item@^2.0.0-beta.19":
version "2.0.0-beta.19"
resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.19.tgz#657f2c5624a30f3effff723f4fadb0851a61dab8"
integrity sha512-z/5NrRKwwJc2ZkgoGxRQmA/VENxQugZoxKhUu2qoUdg5cJRcW+ERoKTiY1/AR+4M2k1izNWQMIz3nQNWMx1kQA==
"@tiptap/extension-list-item@^2.0.0-beta.20":
version "2.0.0-beta.20"
resolved "https://registry.yarnpkg.com/@tiptap/extension-list-item/-/extension-list-item-2.0.0-beta.20.tgz#7169528b226dee4590e013bdf6e5fc6d83729b0f"
integrity sha512-5IPEspJt38t9ROj4xLUesOVEYlTT/R9Skd9meHRxJQZX1qrzBICs5PC/WRIsnexrvTBhdxpYgCYjpvpsJBlKuQ==
"@tiptap/extension-ordered-list@^2.0.0-beta.24":
version "2.0.0-beta.24"
resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.24.tgz#69c56e2cfbf582b338d5dbc94c5eda4593775cb5"
integrity sha512-pXgwV+vuBAHMBGnUPa8fjxHapGCitfBJ1k8o3XvhotO7243Y7KOfYT7kg6XrY6dmTwCX2WLkIc912PP/E60y3A==
"@tiptap/extension-ordered-list@^2.0.0-beta.27":
version "2.0.0-beta.27"
resolved "https://registry.yarnpkg.com/@tiptap/extension-ordered-list/-/extension-ordered-list-2.0.0-beta.27.tgz#ed48a53a9b012d578613b68375db31e8664bfdc9"
integrity sha512-apFDeignxdZb3cA3p1HJu0zw1JgJdBYUBz1r7f99qdNybYuk3I/1MPUvlOuOgvIrBB/wydoyVDP+v9F7QN3tfQ==
"@tiptap/extension-paragraph@^2.0.0-beta.22":
version "2.0.0-beta.22"
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.22.tgz#7740fb6393296ec58e98332b2855ebdc3fd05226"
integrity sha512-BY6GWHlMvGiXLgPHcfZRUHKzMi1jKw3i1JrpMEQ8JLwYD3koI/6UOB/qphwUJkCkIPQXNkZw4/aSBxL9uChRDg==
"@tiptap/extension-paragraph@^2.0.0-beta.23":
version "2.0.0-beta.23"
resolved "https://registry.yarnpkg.com/@tiptap/extension-paragraph/-/extension-paragraph-2.0.0-beta.23.tgz#2ab77308519494994d7a9e5a4acd14042f45f28c"
integrity sha512-VWAxyzecErYWk97Kv/Gkghh97zAQTcaVOisEnYYArZAlyYDaYM48qVssAC/vnRRynP2eQxb1EkppbAxE+bMHAA==
"@tiptap/extension-strike@^2.0.0-beta.26":
version "2.0.0-beta.26"
resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.26.tgz#19eda1a61706ac9690ecbc794c711deb4e1efc3e"
integrity sha512-BA+oqqYOZzRLiMYlHX6BJXlIGaNIR9LObgkHEXAj/JPK7do4wDOcuVaw+dlWS+tzvTebLbC9GYAALfNqVBlTwA==
"@tiptap/extension-strike@^2.0.0-beta.27":
version "2.0.0-beta.27"
resolved "https://registry.yarnpkg.com/@tiptap/extension-strike/-/extension-strike-2.0.0-beta.27.tgz#c5187bf3c28837f95a5c0c0617d0dd31c318353d"
integrity sha512-2dmCgtesuDdivM/54Q+Y6Tc3JbGz1SkHP6c62piuqBiYLWg3xa16zChZOhfN8szbbQlBgLT6XRTDt3c2Ux+Dug==
"@tiptap/extension-subscript@^2.0.0-beta.9":
version "2.0.0-beta.9"
resolved "https://registry.yarnpkg.com/@tiptap/extension-subscript/-/extension-subscript-2.0.0-beta.9.tgz#4d86e904ec081384696562a5f550e81a1ddf2c76"
integrity sha512-wrmcDbXeilBW9HjJi34KpUioBCYD5zyaRu1hnIymVRwmfLNrwGpNyo/8VZTfNDdvliyMYHiRVFI4Mott6OzmgA==
"@tiptap/extension-subscript@^2.0.0-beta.10":
version "2.0.0-beta.10"
resolved "https://registry.yarnpkg.com/@tiptap/extension-subscript/-/extension-subscript-2.0.0-beta.10.tgz#177e9501f805d3cdcb359411b80b54dc7d77373e"
integrity sha512-er8/1lp0Rb+SKwEioW0w4oVf3EkdQZ0WS/5kPBG4W0DncfUMT+bw5de76S3kRL9PLZ9UShAL7wuXtuiSi5QsMw==
"@tiptap/extension-superscript@^2.0.0-beta.9":
version "2.0.0-beta.9"
resolved "https://registry.yarnpkg.com/@tiptap/extension-superscript/-/extension-superscript-2.0.0-beta.9.tgz#be43b0e85f6440ed200831309060c3f0691811f2"
integrity sha512-BxXvCDGtIiuPmY9JbgIEjNbrFzXN3SBj178CfmDcu/FrQimwcqmsfLP3JOu1ZbUwQJuNwubx026vHXPzHlLXDA==
"@tiptap/extension-superscript@^2.0.0-beta.10":
version "2.0.0-beta.10"
resolved "https://registry.yarnpkg.com/@tiptap/extension-superscript/-/extension-superscript-2.0.0-beta.10.tgz#f91c19c2d30aabe3f8c21e87f8e5e8b2e6a55893"
integrity sha512-TUUBS8XsD2MorGORYVlhGDH7wcc9diSbHscD4Dnz8pKWVR0JPUd/od4h5qSffDzAOKxtphTiX9LOFWk6zVooKg==
"@tiptap/extension-table-cell@^2.0.0-beta.20":
version "2.0.0-beta.20"
@ -1678,37 +1679,37 @@
resolved "https://registry.yarnpkg.com/@tiptap/extension-table-row/-/extension-table-row-2.0.0-beta.19.tgz#b45e82f29dfcc7405440ba237b069dbb93d1a94a"
integrity sha512-ldEVDpIUX7ZqbViTy4c/RfyNGRv++O/r3A/Ivuon1PykaDDTbPlp5JM89FunAD39cLAbo2HKtweqdmzCMlZsqA==
"@tiptap/extension-table@^2.0.0-beta.43":
version "2.0.0-beta.43"
resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.43.tgz#12fc8513f05dd49cba5f1a0d9dd14df9efc2050a"
integrity sha512-PALo2WCf/4RpICfJzBvbTaEOf6rpwmQK78jC3tR8kE9Sz6xOSydZmmbl4vovklXCHy3euaW9LCuyiiX+fjJDxw==
"@tiptap/extension-table@^2.0.0-beta.46":
version "2.0.0-beta.46"
resolved "https://registry.yarnpkg.com/@tiptap/extension-table/-/extension-table-2.0.0-beta.46.tgz#cce4d64fe58479031eb975626cc42e3ca9ae26bd"
integrity sha512-JP0eYb2gS9RW1xzB1yCAgcSX4eg1MvhnYNLOxL6VCKvoHf33RW7zQEGx11W/Lrc3lh5qaMjkWcCdQYq5d8qJOA==
dependencies:
prosemirror-tables "^1.1.1"
prosemirror-view "^1.23.1"
prosemirror-view "^1.23.5"
"@tiptap/extension-task-item@^2.0.0-beta.29":
version "2.0.0-beta.29"
resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.29.tgz#789bd2012fd9e89623c29a347da02c9cd6e34906"
integrity sha512-6pkY2NoLMJQxfaJsK8XY5Lv/fx0LVJBJ/J15RE8glUEzkDipNhHTBnHWcfzsa4Qzi6UcSy7NJKtT8ixiyqkRmw==
"@tiptap/extension-task-item@^2.0.0-beta.30":
version "2.0.0-beta.30"
resolved "https://registry.yarnpkg.com/@tiptap/extension-task-item/-/extension-task-item-2.0.0-beta.30.tgz#54c97d2dd84e0ff40689e02f7361dbd903a40161"
integrity sha512-56hS7vP/Hgv5R6otEPInTnd8z5n6UCBFm4sbMPA8d7yWWJDskkfuMp9YDEu2zgHZtTghPyGkw3wO6yxouGWlkg==
"@tiptap/extension-task-list@^2.0.0-beta.23":
version "2.0.0-beta.23"
resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.23.tgz#ca29039de53f7315e5612bfd1fb4ca6d471b9a2f"
integrity sha512-NjAQhtWDtkDpeKtJPItNeLi1fLLVACBFMq2yRCtKBXDGYg2X5w9CYPqXzh8gAIM2qs11wIgS60UtvF2No7Crxg==
"@tiptap/extension-task-list@^2.0.0-beta.26":
version "2.0.0-beta.26"
resolved "https://registry.yarnpkg.com/@tiptap/extension-task-list/-/extension-task-list-2.0.0-beta.26.tgz#75a20795429c40c3b12544483ea63014487d71c7"
integrity sha512-7zPpz9eOUCnFyWNDFYPCUJ39gjID+mCI5BuXyXrjJjDfm8wxg/xTgg9+KC6xakczos7DypnhzlRKSs4EFczeUg==
"@tiptap/extension-text@^2.0.0-beta.15":
version "2.0.0-beta.15"
resolved "https://registry.yarnpkg.com/@tiptap/extension-text/-/extension-text-2.0.0-beta.15.tgz#f08cff1b78f1c6996464dfba1fef8ec1e107617f"
integrity sha512-S3j2+HyV2gsXZP8Wg/HA+YVXQsZ3nrXgBM9HmGAxB0ESOO50l7LWfip0f3qcw1oRlh5H3iLPkA6/f7clD2/TFA==
"@tiptap/vue-2@^2.0.0-beta.69":
version "2.0.0-beta.69"
resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.69.tgz#65ed98e966c28c9614d4c5a6218e99397a2e0a26"
integrity sha512-Adm+YvhaihW3mpFIBgPH/3qlxG3hY7/g52gM3Kg0f//SNg/bDqK+AMLroZB5Je06ihCqBaRb1hrSD0/gTVMJ1g==
"@tiptap/vue-2@^2.0.0-beta.74":
version "2.0.0-beta.74"
resolved "https://registry.yarnpkg.com/@tiptap/vue-2/-/vue-2-2.0.0-beta.74.tgz#da9e56113018525d0cb55812a2452d57b9710d26"
integrity sha512-OY6RhR2DSvP4iIxtoWeg2qmQ1uYP4kJkdMT5ePQBFqVzs6l5+FpSjETskS8EwZVgM/IrLTMp5lHfKboP/YacOA==
dependencies:
"@tiptap/extension-bubble-menu" "^2.0.0-beta.50"
"@tiptap/extension-floating-menu" "^2.0.0-beta.45"
prosemirror-view "^1.23.1"
"@tiptap/extension-bubble-menu" "^2.0.0-beta.54"
"@tiptap/extension-floating-menu" "^2.0.0-beta.49"
prosemirror-view "^1.23.5"
"@toast-ui/editor@^2.5.2":
version "2.5.2"
@ -1944,17 +1945,17 @@
"@types/prosemirror-transform" "*"
"@types/prosemirror-view" "*"
"@types/prosemirror-transform@*", "@types/prosemirror-transform@^1.1.4":
version "1.1.4"
resolved "https://registry.yarnpkg.com/@types/prosemirror-transform/-/prosemirror-transform-1.1.4.tgz#c3565e81b2ef3ce3254e6927d6f63eb8d7bb20d0"
integrity sha512-HP1PauvkqSgDquZut8HaLOTUDQ6jja/LAy4OA7tTS1XG7wqRnX3gLUyEj0mD6vFd4y8BPkNddNdOh/BeGHlUjg==
"@types/prosemirror-transform@*", "@types/prosemirror-transform@^1.1.5":
version "1.1.5"
resolved "https://registry.yarnpkg.com/@types/prosemirror-transform/-/prosemirror-transform-1.1.5.tgz#e6949398c64a5d3ca53e6081352751aa9e9ce76e"
integrity sha512-Wr2HXaEF4JPklWpC17RTxE6PxyU54Taqk5FMhK1ojgcN93J+GpkYW8s0mD3rl7KfTmlhVwZPCHE9o0cYf2Go5A==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-view@*", "@types/prosemirror-view@^1.19.1":
version "1.19.1"
resolved "https://registry.yarnpkg.com/@types/prosemirror-view/-/prosemirror-view-1.19.1.tgz#f12309ef07dfb701d20c2e4d0292d42ba34a081b"
integrity sha512-fyQ4NVxAdfISWrE2qT8cpZdosXoH/1JuVYMBs9CdaXPbvi/8R2L2tkkcMRM314piKrO8nfYH5OBZKzP2Ax3jtA==
"@types/prosemirror-view@*", "@types/prosemirror-view@^1.19.2":
version "1.19.2"
resolved "https://registry.yarnpkg.com/@types/prosemirror-view/-/prosemirror-view-1.19.2.tgz#1bab4daf0f1f14313fe0d3f6b57f0a3b4ef6c50d"
integrity sha512-pmh2DuMJzva4D7SxspRKIzkV6FK2o52uAqGjq2dPYcQFPwu4+5RcS1TMjFVCh1R+Ia1Rx8wsCNIId/5+6DB0Bg==
dependencies:
"@types/prosemirror-model" "*"
"@types/prosemirror-state" "*"
@ -7927,10 +7928,10 @@ linkify-it@^3.0.1:
dependencies:
uc.micro "^1.0.1"
linkifyjs@^3.0.3:
version "3.0.3"
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-3.0.3.tgz#51ea2160b4c60c2c87c27757a1e9eacd422c6076"
integrity sha512-ba5opS5wRHSbDC8VaiDdN14nPGm6LqyRsIPQZGG4qXV4scFdrPneT/uoZOaq9QAPBf6W9I9D/6tNSzWH//815Q==
linkifyjs@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-3.0.5.tgz#99e51a3a0c0e232fcb63ebb89eea3ff923378f34"
integrity sha512-1Y9XQH65eQKA9p2xtk+zxvnTeQBG7rdAXSkUG97DmuI/Xhji9uaUzaWxRj6rf9YC0v8KKHkxav7tnLX82Sz5Fg==
load-json-file@^2.0.0:
version "2.0.0"
@ -9796,10 +9797,10 @@ prosemirror-dropcursor@^1.3.2, prosemirror-dropcursor@^1.4.0:
prosemirror-transform "^1.1.0"
prosemirror-view "^1.1.0"
prosemirror-gapcursor@^1.1.5, prosemirror-gapcursor@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.0.tgz#28fb60bf3d9baf1f920907d2c3e613137204e8f3"
integrity sha512-yCLy5+0rVqLir/KcHFathQj4Rf8aRHi80FmEfKtM0JmyzvwdomslLzDZ/pX4oFhFKDgjl/WBBBFNqDyNifWg7g==
prosemirror-gapcursor@^1.1.5, prosemirror-gapcursor@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prosemirror-gapcursor/-/prosemirror-gapcursor-1.2.1.tgz#02365e1bcc1ad25d390b0fb7f0e94a7fc173ad75"
integrity sha512-PHa9lj27iM/g4C46gxVzsefuXVfy/LrGQH4QjMRht7VDBgw77iWYWn8ZHMWSFkwtr9jQEuxI5gccHHHwWG80nw==
dependencies:
prosemirror-keymap "^1.0.0"
prosemirror-model "^1.0.0"
@ -9831,7 +9832,7 @@ prosemirror-keymap@^1.0.0, prosemirror-keymap@^1.1.2, prosemirror-keymap@^1.1.4,
prosemirror-state "^1.0.0"
w3c-keyname "^2.2.0"
prosemirror-markdown@^1.6.0:
prosemirror-markdown@1.6.0:
version "1.6.0"
resolved "https://registry.yarnpkg.com/prosemirror-markdown/-/prosemirror-markdown-1.6.0.tgz#141c88e03c8892f2e93cf58b1382ab0b6088d012"
integrity sha512-y/gRpJIIrNArtkyMax7ypYafb+ZMjddbVHI+AwlcUfCLCCXK57cOmfBMKYVq9kdEKJYVdYHdoyWsVNn1nWLHUg==
@ -9839,10 +9840,10 @@ prosemirror-markdown@^1.6.0:
markdown-it "^10.0.0"
prosemirror-model "^1.0.0"
prosemirror-model@^1.0.0, prosemirror-model@^1.13.1, prosemirror-model@^1.14.3, prosemirror-model@^1.15.0, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
version "1.15.0"
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.15.0.tgz#23bc09098daa7c309dba90a76a1b989ce6f61405"
integrity sha512-hQJv7SnIhlAy9ga3lhPPgaufhvCbQB9tHwscJ9E1H1pPHmN8w5V/lURueoYv9Kc3/bpNWoyHa8r3g//m7N0ChQ==
prosemirror-model@^1.0.0, prosemirror-model@^1.13.1, prosemirror-model@^1.16.0, prosemirror-model@^1.16.1, prosemirror-model@^1.2.0, prosemirror-model@^1.8.1:
version "1.16.1"
resolved "https://registry.yarnpkg.com/prosemirror-model/-/prosemirror-model-1.16.1.tgz#fb388270bc9609b66298d6a7e15d0cc1d6c61253"
integrity sha512-r1/w0HDU40TtkXp0DyKBnFPYwd8FSlUSJmGCGFv4DeynfeSlyQF2FD0RQbVEMOe6P3PpUSXM6LZBV7W/YNZ4mA==
dependencies:
orderedmap "^1.1.0"
@ -9896,12 +9897,12 @@ prosemirror-transform@^1.0.0, prosemirror-transform@^1.1.0, prosemirror-transfor
dependencies:
prosemirror-model "^1.0.0"
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.23.1, prosemirror-view@^1.23.3:
version "1.23.3"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.3.tgz#9ba85fefaf45e813c46562b694fc5f6f9a5cba9c"
integrity sha512-89icyMdXXwxmTxYj0TIuG5M/d0iKeu79tr+PVtC/4qtCOoHrPSPrblJcFOuOWcxGlA/Ei8PqJB4g5HkKR8jWvQ==
prosemirror-view@^1.0.0, prosemirror-view@^1.1.0, prosemirror-view@^1.13.3, prosemirror-view@^1.16.5, prosemirror-view@^1.23.5:
version "1.23.5"
resolved "https://registry.yarnpkg.com/prosemirror-view/-/prosemirror-view-1.23.5.tgz#0f4af48fa9d30aa0b945816e2b8e6cb1c82ac674"
integrity sha512-GlcCtoFdW17KNOKjOl7OZTU3btENgVfzN/i0RBvy1SEKAZfo88PdvcFrWTraNZHH+y/uhYR3PAdMiDK9DlN5UA==
dependencies:
prosemirror-model "^1.14.3"
prosemirror-model "^1.16.0"
prosemirror-state "^1.0.0"
prosemirror-transform "^1.1.0"