Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
d0a683e342
commit
a4068557f4
|
@ -6,6 +6,13 @@ import {
|
|||
GlInputGroupText,
|
||||
GlLink,
|
||||
GlAlert,
|
||||
GlButton,
|
||||
GlButtonGroup,
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlDropdownText,
|
||||
GlTruncate,
|
||||
GlSearchBoxByType,
|
||||
} from '@gitlab/ui';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
|
@ -15,6 +22,11 @@ import { createAlert } from '~/flash';
|
|||
import { slugify } from '~/lib/utils/text_utility';
|
||||
import axios from '~/lib/utils/axios_utils';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
import { MINIMUM_SEARCH_LENGTH } from '~/graphql_shared/constants';
|
||||
import { DEBOUNCE_DELAY } from '~/vue_shared/components/filtered_search_bar/constants';
|
||||
|
||||
import searchGroupsWhereUserCanCreateSubgroups from '../queries/search_groups_where_user_can_create_subgroups.query.graphql';
|
||||
|
||||
const DEBOUNCE_DURATION = 1000;
|
||||
|
||||
|
@ -22,7 +34,6 @@ export default {
|
|||
i18n: {
|
||||
inputs: {
|
||||
name: {
|
||||
label: s__('Groups|Group name'),
|
||||
placeholder: __('My awesome group'),
|
||||
description: s__(
|
||||
'Groups|Must start with letter, digit, emoji, or underscore. Can also contain periods, dashes, spaces, and parentheses.',
|
||||
|
@ -30,7 +41,6 @@ export default {
|
|||
invalidFeedback: s__('Groups|Enter a descriptive name for your group.'),
|
||||
},
|
||||
path: {
|
||||
label: s__('Groups|Group URL'),
|
||||
placeholder: __('my-awesome-group'),
|
||||
invalidFeedbackInvalidPattern: s__(
|
||||
'GroupSettings|Choose a group path that does not start with a dash or end with a period. It can also contain alphanumeric characters and underscores.',
|
||||
|
@ -40,9 +50,6 @@ export default {
|
|||
),
|
||||
validFeedback: s__('Groups|Group path is available.'),
|
||||
},
|
||||
groupId: {
|
||||
label: s__('Groups|Group ID'),
|
||||
},
|
||||
},
|
||||
apiLoadingMessage: s__('Groups|Checking group URL availability...'),
|
||||
apiErrorMessage: __(
|
||||
|
@ -51,7 +58,7 @@ export default {
|
|||
changingUrlWarningMessage: s__('Groups|Changing group URL can have unintended side effects.'),
|
||||
learnMore: s__('Groups|Learn more'),
|
||||
},
|
||||
nameInputSize: { md: 'lg' },
|
||||
inputSize: { md: 'lg' },
|
||||
changingGroupPathHelpPagePath: helpPagePath('user/group/index', {
|
||||
anchor: 'change-a-groups-path',
|
||||
}),
|
||||
|
@ -63,8 +70,35 @@ export default {
|
|||
GlInputGroupText,
|
||||
GlLink,
|
||||
GlAlert,
|
||||
GlButton,
|
||||
GlButtonGroup,
|
||||
GlDropdown,
|
||||
GlDropdownItem,
|
||||
GlDropdownText,
|
||||
GlTruncate,
|
||||
GlSearchBoxByType,
|
||||
},
|
||||
inject: ['fields', 'basePath', 'mattermostEnabled'],
|
||||
apollo: {
|
||||
currentUserGroups: {
|
||||
query: searchGroupsWhereUserCanCreateSubgroups,
|
||||
variables() {
|
||||
return {
|
||||
search: this.search,
|
||||
};
|
||||
},
|
||||
update(data) {
|
||||
return data.currentUser?.groups?.nodes || [];
|
||||
},
|
||||
skip() {
|
||||
const hasNotEnoughSearchCharacters =
|
||||
this.search.length > 0 && this.search.length < MINIMUM_SEARCH_LENGTH;
|
||||
|
||||
return this.shouldSkipQuery || hasNotEnoughSearchCharacters;
|
||||
},
|
||||
debounce: DEBOUNCE_DELAY,
|
||||
},
|
||||
},
|
||||
inject: ['fields', 'basePath', 'newSubgroup', 'mattermostEnabled'],
|
||||
data() {
|
||||
return {
|
||||
name: this.fields.name.value,
|
||||
|
@ -76,9 +110,27 @@ export default {
|
|||
pathFeedbackState: null,
|
||||
pathInvalidFeedback: null,
|
||||
activeApiRequestAbortController: null,
|
||||
search: '',
|
||||
currentUserGroups: {},
|
||||
shouldSkipQuery: true,
|
||||
selectedGroup: {
|
||||
id: this.fields.parentId.value,
|
||||
fullPath: this.fields.parentFullPath.value,
|
||||
},
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
inputLabels() {
|
||||
return {
|
||||
name: this.newSubgroup ? s__('Groups|Subgroup name') : s__('Groups|Group name'),
|
||||
path: this.newSubgroup ? s__('Groups|Subgroup slug') : s__('Groups|Group URL'),
|
||||
subgroupPath: s__('Groups|Subgroup URL'),
|
||||
groupId: s__('Groups|Group ID'),
|
||||
};
|
||||
},
|
||||
pathInputSize() {
|
||||
return this.newSubgroup ? {} : this.$options.inputSize;
|
||||
},
|
||||
computedPath() {
|
||||
return this.apiSuggestedPath || this.path;
|
||||
},
|
||||
|
@ -129,9 +181,11 @@ export default {
|
|||
try {
|
||||
const {
|
||||
data: { exists, suggests },
|
||||
} = await getGroupPathAvailability(this.path, this.fields.parentId?.value, {
|
||||
signal: this.activeApiRequestAbortController.signal,
|
||||
});
|
||||
} = await getGroupPathAvailability(
|
||||
this.path,
|
||||
this.selectedGroup.id || this.fields.parentId.value,
|
||||
{ signal: this.activeApiRequestAbortController.signal },
|
||||
);
|
||||
|
||||
this.apiLoading = false;
|
||||
|
||||
|
@ -198,6 +252,21 @@ export default {
|
|||
this.pathInvalidFeedback = this.$options.i18n.inputs.path.invalidFeedbackInvalidPattern;
|
||||
this.pathFeedbackState = false;
|
||||
},
|
||||
handleDropdownShown() {
|
||||
if (this.shouldSkipQuery) {
|
||||
this.shouldSkipQuery = false;
|
||||
}
|
||||
|
||||
this.$refs.search.focusInput();
|
||||
},
|
||||
handleDropdownItemClick({ id, fullPath }) {
|
||||
this.selectedGroup = {
|
||||
id: getIdFromGraphQLId(id),
|
||||
fullPath,
|
||||
};
|
||||
|
||||
this.debouncedValidatePath();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -208,10 +277,10 @@ export default {
|
|||
:id="fields.parentId.id"
|
||||
type="hidden"
|
||||
:name="fields.parentId.name"
|
||||
:value="fields.parentId.value"
|
||||
:value="selectedGroup.id"
|
||||
/>
|
||||
<gl-form-group
|
||||
:label="$options.i18n.inputs.name.label"
|
||||
:label="inputLabels.name"
|
||||
:description="$options.i18n.inputs.name.description"
|
||||
:label-for="fields.name.id"
|
||||
:invalid-feedback="$options.i18n.inputs.name.invalidFeedback"
|
||||
|
@ -220,46 +289,102 @@ export default {
|
|||
<gl-form-input
|
||||
:id="fields.name.id"
|
||||
v-model="name"
|
||||
class="gl-field-error-ignore"
|
||||
class="gl-field-error-ignore gl-h-auto!"
|
||||
required
|
||||
:name="fields.name.name"
|
||||
:placeholder="$options.i18n.inputs.name.placeholder"
|
||||
data-qa-selector="group_name_field"
|
||||
:size="$options.nameInputSize"
|
||||
:size="$options.inputSize"
|
||||
:state="nameFeedbackState"
|
||||
@invalid="handleInvalidName"
|
||||
/>
|
||||
</gl-form-group>
|
||||
<gl-form-group
|
||||
:label="$options.i18n.inputs.path.label"
|
||||
:label-for="fields.path.id"
|
||||
:description="pathDescription"
|
||||
:state="pathFeedbackState"
|
||||
:valid-feedback="$options.i18n.inputs.path.validFeedback"
|
||||
:invalid-feedback="pathInvalidFeedback"
|
||||
>
|
||||
<gl-form-input-group>
|
||||
<template #prepend>
|
||||
<gl-input-group-text class="group-root-path">{{ basePath }}</gl-input-group-text>
|
||||
</template>
|
||||
<gl-form-input
|
||||
:id="fields.path.id"
|
||||
class="gl-field-error-ignore"
|
||||
:name="fields.path.name"
|
||||
:value="computedPath"
|
||||
:placeholder="$options.i18n.inputs.path.placeholder"
|
||||
:maxlength="fields.path.maxLength"
|
||||
:pattern="fields.path.pattern"
|
||||
:state="pathFeedbackState"
|
||||
:size="$options.nameInputSize"
|
||||
required
|
||||
data-qa-selector="group_path_field"
|
||||
:data-bind-in="mattermostEnabled ? $options.mattermostDataBindName : null"
|
||||
@input="handlePathInput"
|
||||
@invalid="handleInvalidPath"
|
||||
/>
|
||||
</gl-form-input-group>
|
||||
</gl-form-group>
|
||||
|
||||
<div :class="newSubgroup && 'row gl-mb-3'">
|
||||
<gl-form-group v-if="newSubgroup" class="col-sm-6 gl-pr-0" :label="inputLabels.subgroupPath">
|
||||
<div class="input-group gl-flex-nowrap">
|
||||
<gl-button-group class="gl-w-full">
|
||||
<gl-button class="js-group-namespace-button gl-text-truncate gl-flex-grow-0!" label>
|
||||
{{ basePath }}
|
||||
</gl-button>
|
||||
|
||||
<gl-dropdown
|
||||
class="js-group-namespace-dropdown gl-flex-grow-1"
|
||||
toggle-class="gl-rounded-top-right-base! gl-rounded-bottom-right-base! gl-w-20"
|
||||
@shown="handleDropdownShown"
|
||||
>
|
||||
<template #button-text>
|
||||
<gl-truncate
|
||||
v-if="selectedGroup.fullPath"
|
||||
:text="selectedGroup.fullPath"
|
||||
position="start"
|
||||
with-tooltip
|
||||
/>
|
||||
</template>
|
||||
|
||||
<gl-search-box-by-type
|
||||
ref="search"
|
||||
v-model.trim="search"
|
||||
:is-loading="$apollo.queries.currentUserGroups.loading"
|
||||
/>
|
||||
|
||||
<template v-if="!$apollo.queries.currentUserGroups.loading">
|
||||
<template v-if="currentUserGroups.length">
|
||||
<gl-dropdown-item
|
||||
v-for="group of currentUserGroups"
|
||||
:key="group.id"
|
||||
data-testid="select_group_dropdown_item"
|
||||
@click="handleDropdownItemClick(group)"
|
||||
>
|
||||
{{ group.fullPath }}
|
||||
</gl-dropdown-item>
|
||||
</template>
|
||||
<gl-dropdown-text v-else>{{ __('No matches found') }}</gl-dropdown-text>
|
||||
</template>
|
||||
</gl-dropdown>
|
||||
</gl-button-group>
|
||||
|
||||
<div class="gl-align-self-center gl-pl-5">
|
||||
<span class="gl-display-none gl-md-display-inline">/</span>
|
||||
</div>
|
||||
</div>
|
||||
</gl-form-group>
|
||||
|
||||
<gl-form-group
|
||||
:class="newSubgroup && 'col-sm-6'"
|
||||
:label="inputLabels.path"
|
||||
:label-for="fields.path.id"
|
||||
:description="pathDescription"
|
||||
:state="pathFeedbackState"
|
||||
:valid-feedback="$options.i18n.inputs.path.validFeedback"
|
||||
:invalid-feedback="pathInvalidFeedback"
|
||||
>
|
||||
<gl-form-input-group>
|
||||
<template v-if="!newSubgroup" #prepend>
|
||||
<gl-input-group-text class="group-root-path">
|
||||
{{ basePath.concat(fields.parentFullPath.value) }}
|
||||
</gl-input-group-text>
|
||||
</template>
|
||||
<gl-form-input
|
||||
:id="fields.path.id"
|
||||
class="gl-field-error-ignore gl-h-auto!"
|
||||
:name="fields.path.name"
|
||||
:value="computedPath"
|
||||
:placeholder="$options.i18n.inputs.path.placeholder"
|
||||
:maxlength="fields.path.maxLength"
|
||||
:pattern="fields.path.pattern"
|
||||
:state="pathFeedbackState"
|
||||
:size="pathInputSize"
|
||||
required
|
||||
data-qa-selector="group_path_field"
|
||||
:data-bind-in="mattermostEnabled ? $options.mattermostDataBindName : null"
|
||||
@input="handlePathInput"
|
||||
@invalid="handleInvalidPath"
|
||||
/>
|
||||
</gl-form-input-group>
|
||||
</gl-form-group>
|
||||
</div>
|
||||
|
||||
<template v-if="isEditingGroup">
|
||||
<gl-alert class="gl-mb-5" :dismissible="false" variant="warning">
|
||||
{{ $options.i18n.changingUrlWarningMessage }}
|
||||
|
@ -267,7 +392,7 @@ export default {
|
|||
>{{ $options.i18n.learnMore }}
|
||||
</gl-link>
|
||||
</gl-alert>
|
||||
<gl-form-group :label="$options.i18n.inputs.groupId.label" :label-for="fields.groupId.id">
|
||||
<gl-form-group :label="inputLabels.groupId" :label-for="fields.groupId.id">
|
||||
<gl-form-input
|
||||
:id="fields.groupId.id"
|
||||
:value="fields.groupId.value"
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import Vue from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import createDefaultClient from '~/lib/graphql';
|
||||
import { parseRailsFormFields } from '~/lib/utils/forms';
|
||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||
import GroupNameAndPath from './components/group_name_and_path.vue';
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
export const initGroupNameAndPath = () => {
|
||||
const elements = document.querySelectorAll('.js-group-name-and-path');
|
||||
|
||||
|
@ -12,13 +16,17 @@ export const initGroupNameAndPath = () => {
|
|||
|
||||
elements.forEach((element) => {
|
||||
const fields = parseRailsFormFields(element);
|
||||
const { basePath, mattermostEnabled } = element.dataset;
|
||||
const { basePath, newSubgroup, mattermostEnabled } = element.dataset;
|
||||
|
||||
return new Vue({
|
||||
el: element,
|
||||
apolloProvider: new VueApollo({
|
||||
defaultClient: createDefaultClient(),
|
||||
}),
|
||||
provide: {
|
||||
fields,
|
||||
basePath,
|
||||
newSubgroup: parseBoolean(newSubgroup),
|
||||
mattermostEnabled: parseBoolean(mattermostEnabled),
|
||||
},
|
||||
render(h) {
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
query searchGroupsWhereUserCanCreateSubgroups($search: String) {
|
||||
currentUser {
|
||||
id
|
||||
groups(permissionScope: TRANSFER_PROJECTS, search: $search) {
|
||||
nodes {
|
||||
id
|
||||
fullPath
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,51 +2,74 @@
|
|||
import importGroupIllustration from '@gitlab/svgs/dist/illustrations/group-import.svg';
|
||||
import newGroupIllustration from '@gitlab/svgs/dist/illustrations/group-new.svg';
|
||||
|
||||
import { s__ } from '~/locale';
|
||||
import { __, s__ } from '~/locale';
|
||||
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
|
||||
import createGroupDescriptionDetails from './create_group_description_details.vue';
|
||||
|
||||
const PANELS = [
|
||||
{
|
||||
name: 'create-group-pane',
|
||||
selector: '#create-group-pane',
|
||||
title: s__('GroupsNew|Create group'),
|
||||
description: s__(
|
||||
'GroupsNew|Assemble related projects together and grant members access to several projects at once.',
|
||||
),
|
||||
illustration: newGroupIllustration,
|
||||
details: createGroupDescriptionDetails,
|
||||
},
|
||||
{
|
||||
name: 'import-group-pane',
|
||||
selector: '#import-group-pane',
|
||||
title: s__('GroupsNew|Import group'),
|
||||
description: s__('GroupsNew|Import a group and related data from another GitLab instance.'),
|
||||
illustration: importGroupIllustration,
|
||||
details: 'Migrate your existing groups from another instance of GitLab.',
|
||||
},
|
||||
];
|
||||
|
||||
export default {
|
||||
components: {
|
||||
NewNamespacePage,
|
||||
},
|
||||
props: {
|
||||
parentGroupName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
importExistingGroupPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
hasErrors: {
|
||||
type: Boolean,
|
||||
required: false,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
PANELS,
|
||||
computed: {
|
||||
initialBreadcrumb() {
|
||||
return this.parentGroupName || __('New group');
|
||||
},
|
||||
panels() {
|
||||
return [
|
||||
{
|
||||
name: 'create-group-pane',
|
||||
selector: '#create-group-pane',
|
||||
title: this.parentGroupName
|
||||
? s__('GroupsNew|Create subgroup')
|
||||
: s__('GroupsNew|Create group'),
|
||||
description: s__(
|
||||
'GroupsNew|Assemble related projects together and grant members access to several projects at once.',
|
||||
),
|
||||
illustration: newGroupIllustration,
|
||||
details: createGroupDescriptionDetails,
|
||||
detailProps: {
|
||||
parentGroupName: this.parentGroupName,
|
||||
importExistingGroupPath: this.importExistingGroupPath,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'import-group-pane',
|
||||
selector: '#import-group-pane',
|
||||
title: s__('GroupsNew|Import group'),
|
||||
description: s__(
|
||||
'GroupsNew|Import a group and related data from another GitLab instance.',
|
||||
),
|
||||
illustration: importGroupIllustration,
|
||||
details: 'Migrate your existing groups from another instance of GitLab.',
|
||||
},
|
||||
];
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<new-namespace-page
|
||||
:jump-to-last-persisted-panel="hasErrors"
|
||||
:initial-breadcrumb="__('New group')"
|
||||
:panels="$options.PANELS"
|
||||
:initial-breadcrumb="initialBreadcrumb"
|
||||
:panels="panels"
|
||||
:title="s__('GroupsNew|Create new group')"
|
||||
persistence-key="new_group_last_active_tab"
|
||||
/>
|
||||
|
|
|
@ -1,6 +1,22 @@
|
|||
<script>
|
||||
import { GlSprintf, GlLink } from '@gitlab/ui';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import { s__ } from '~/locale';
|
||||
|
||||
const DESCRIPTION_DETAILS = {
|
||||
group: [
|
||||
s__(
|
||||
'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.',
|
||||
),
|
||||
s__('GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}.'),
|
||||
],
|
||||
subgroup: [
|
||||
s__(
|
||||
'GroupsNew|%{groupsLinkStart}Groups%{groupsLinkEnd} and %{subgroupsLinkStart}subgroups%{subgroupsLinkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.',
|
||||
),
|
||||
s__('GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}.'),
|
||||
],
|
||||
};
|
||||
|
||||
export default {
|
||||
components: {
|
||||
|
@ -11,30 +27,46 @@ export default {
|
|||
groupsHelpPath: helpPagePath('user/group/index'),
|
||||
subgroupsHelpPath: helpPagePath('user/group/subgroups/index'),
|
||||
},
|
||||
props: {
|
||||
parentGroupName: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
importExistingGroupPath: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
descriptionDetails: DESCRIPTION_DETAILS,
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<p>
|
||||
<gl-sprintf
|
||||
:message="
|
||||
s__(
|
||||
'GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects.',
|
||||
)
|
||||
"
|
||||
>
|
||||
<gl-sprintf v-if="parentGroupName" :message="$options.descriptionDetails.subgroup[0]">
|
||||
<template #groupsLink="{ content }">
|
||||
<gl-link :href="$options.paths.groupsHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
<template #subgroupsLink="{ content }">
|
||||
<gl-link :href="$options.paths.subgroupsHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
<gl-sprintf v-else :message="$options.descriptionDetails.group[0]">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="$options.paths.groupsHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</p>
|
||||
<p>
|
||||
<gl-sprintf
|
||||
:message="
|
||||
s__('GroupsNew|Groups can also be nested by creating %{linkStart}subgroups%{linkEnd}.')
|
||||
"
|
||||
>
|
||||
<gl-sprintf v-if="parentGroupName" :message="$options.descriptionDetails.subgroup[1]">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="importExistingGroupPath">{{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
<gl-sprintf v-else :message="$options.descriptionDetails.group[1]">
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="$options.paths.subgroupsHelpPath" target="_blank">{{ content }}</gl-link>
|
||||
</template>
|
||||
|
|
|
@ -16,9 +16,18 @@ BindInOut.initAll();
|
|||
initFilePickers();
|
||||
|
||||
function initNewGroupCreation(el) {
|
||||
const { hasErrors, verificationRequired, verificationFormUrl, subscriptionsUrl } = el.dataset;
|
||||
const {
|
||||
hasErrors,
|
||||
parentGroupName,
|
||||
importExistingGroupPath,
|
||||
verificationRequired,
|
||||
verificationFormUrl,
|
||||
subscriptionsUrl,
|
||||
} = el.dataset;
|
||||
|
||||
const props = {
|
||||
parentGroupName,
|
||||
importExistingGroupPath,
|
||||
hasErrors: parseBoolean(hasErrors),
|
||||
};
|
||||
|
||||
|
|
|
@ -34,6 +34,36 @@ const nonStandardEvents = {
|
|||
},
|
||||
counter: {},
|
||||
},
|
||||
metrics: {
|
||||
uniqueUser: {
|
||||
expand: ['i_testing_metrics_report_widget_total'],
|
||||
},
|
||||
counter: {},
|
||||
},
|
||||
browserPerformance: {
|
||||
uniqueUser: {
|
||||
expand: ['i_testing_web_performance_widget_total'],
|
||||
},
|
||||
counter: {},
|
||||
},
|
||||
licenseCompliance: {
|
||||
uniqueUser: {
|
||||
expand: ['i_testing_license_compliance_widget_total'],
|
||||
},
|
||||
counter: {},
|
||||
},
|
||||
loadPerformance: {
|
||||
uniqueUser: {
|
||||
expand: ['i_testing_load_performance_widget_total'],
|
||||
},
|
||||
counter: {},
|
||||
},
|
||||
statusChecks: {
|
||||
uniqueUser: {
|
||||
expand: ['i_testing_status_checks_widget'],
|
||||
},
|
||||
counter: {},
|
||||
},
|
||||
};
|
||||
|
||||
function combineDeepArray(path, ...objects) {
|
||||
|
|
|
@ -6,7 +6,6 @@ import { EXTENSION_ICONS } from '../../constants';
|
|||
export default {
|
||||
name: 'WidgetAccessibility',
|
||||
enablePolling: true,
|
||||
telemetry: false,
|
||||
i18n: {
|
||||
loading: s__('Reports|Accessibility scanning results are being parsed'),
|
||||
error: s__('Reports|Accessibility scanning failed loading results'),
|
||||
|
|
|
@ -14,6 +14,7 @@ import { glEmojiTag } from '~/emoji';
|
|||
import createFlash from '~/flash';
|
||||
import { followUser, unfollowUser } from '~/rest_api';
|
||||
import { isUserBusy } from '~/set_status_modal/utils';
|
||||
import Tracking from '~/tracking';
|
||||
import { USER_POPOVER_DELAY } from './constants';
|
||||
|
||||
const MAX_SKELETON_LINES = 4;
|
||||
|
@ -37,6 +38,7 @@ export default {
|
|||
directives: {
|
||||
SafeHtml: GlSafeHtmlDirective,
|
||||
},
|
||||
mixins: [Tracking.mixin()],
|
||||
props: {
|
||||
target: {
|
||||
type: HTMLElement,
|
||||
|
@ -117,6 +119,11 @@ export default {
|
|||
},
|
||||
async follow() {
|
||||
this.toggleFollowLoading = true;
|
||||
|
||||
this.track('click_button', {
|
||||
label: 'follow_from_user_popover',
|
||||
});
|
||||
|
||||
try {
|
||||
await followUser(this.user.id);
|
||||
this.$emit('follow');
|
||||
|
@ -132,6 +139,11 @@ export default {
|
|||
},
|
||||
async unfollow() {
|
||||
this.toggleFollowLoading = true;
|
||||
|
||||
this.track('click_button', {
|
||||
label: 'unfollow_from_user_popover',
|
||||
});
|
||||
|
||||
try {
|
||||
await unfollowUser(this.user.id);
|
||||
this.$emit('unfollow');
|
||||
|
|
|
@ -125,7 +125,7 @@ export default {
|
|||
<h4>{{ activePanel.title }}</h4>
|
||||
|
||||
<p v-if="hasTextDetails">{{ details }}</p>
|
||||
<component :is="details" v-else />
|
||||
<component :is="details" v-else v-bind="activePanel.detailProps || {}" />
|
||||
|
||||
<slot name="extra-description"></slot>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
= content_tag tag, {**@button_options, **base_attributes, class: button_class, href: @href, target: @target } do
|
||||
= content_for :pajamas_button_content, flush: true do
|
||||
- if @loading
|
||||
= gl_loading_icon(inline: true, css_class: 'gl-button-icon gl-button-loading-indicator')
|
||||
- if @icon && (!@loading || content)
|
||||
|
@ -6,3 +6,10 @@
|
|||
- if content
|
||||
%span.gl-button-text{ class: @button_text_classes }
|
||||
= content
|
||||
|
||||
- if link?
|
||||
= link_to @href, { **@button_options, **base_attributes, class: button_class, target: @target, method: @method } do
|
||||
= content_for :pajamas_button_content
|
||||
- else
|
||||
= content_tag 'button', { **@button_options, **base_attributes, class: button_class } do
|
||||
= content_for :pajamas_button_content
|
||||
|
|
|
@ -13,6 +13,7 @@ module Pajamas
|
|||
# @param [String] icon
|
||||
# @param [String] href
|
||||
# @param [String] target
|
||||
# @param [Symbol] method
|
||||
# @param [Hash] button_options
|
||||
# @param [String] button_text_classes
|
||||
# @param [String] icon_classes
|
||||
|
@ -28,6 +29,7 @@ module Pajamas
|
|||
icon: nil,
|
||||
href: nil,
|
||||
target: nil,
|
||||
method: nil,
|
||||
button_options: {},
|
||||
button_text_classes: nil,
|
||||
icon_classes: nil
|
||||
|
@ -43,6 +45,7 @@ module Pajamas
|
|||
@icon = icon
|
||||
@href = href
|
||||
@target = filter_attribute(target, TARGET_OPTIONS)
|
||||
@method = filter_attribute(method, METHOD_OPTIONS)
|
||||
@button_options = button_options
|
||||
@button_text_classes = button_text_classes
|
||||
@icon_classes = icon_classes
|
||||
|
@ -75,6 +78,7 @@ module Pajamas
|
|||
SIZE_OPTIONS = [:small, :medium].freeze
|
||||
TYPE_OPTIONS = [:button, :reset, :submit].freeze
|
||||
TARGET_OPTIONS = %w[_self _blank _parent _top].freeze
|
||||
METHOD_OPTIONS = [:get, :post, :put, :delete, :patch].freeze
|
||||
|
||||
CATEGORY_CLASSES = {
|
||||
primary: '',
|
||||
|
@ -101,8 +105,8 @@ module Pajamas
|
|||
delegate :sprite_icon, to: :helpers
|
||||
delegate :gl_loading_icon, to: :helpers
|
||||
|
||||
def tag
|
||||
@href ? 'a' : 'button'
|
||||
def link?
|
||||
@href.present?
|
||||
end
|
||||
|
||||
def base_attributes
|
||||
|
|
|
@ -13,7 +13,6 @@ module Mutations
|
|||
|
||||
if pipeline.cancelable?
|
||||
pipeline.cancel_running
|
||||
pipeline.cancel
|
||||
|
||||
{ success: true, errors: [] }
|
||||
else
|
||||
|
|
|
@ -134,6 +134,13 @@ module GroupsHelper
|
|||
@group_projects_sort || @sort || params[:sort] || sort_value_recently_created
|
||||
end
|
||||
|
||||
def subgroup_creation_data(group)
|
||||
{
|
||||
parent_group_name: group.parent&.name,
|
||||
import_existing_group_path: new_group_path(parent_id: group.parent_id, anchor: 'import-group-pane')
|
||||
}
|
||||
end
|
||||
|
||||
def verification_for_group_creation_data
|
||||
# overridden in EE
|
||||
{}
|
||||
|
@ -144,11 +151,9 @@ module GroupsHelper
|
|||
false
|
||||
end
|
||||
|
||||
def group_name_and_path_app_data(group)
|
||||
parent = group.parent
|
||||
|
||||
def group_name_and_path_app_data
|
||||
{
|
||||
base_path: URI.join(root_url, parent&.full_path || "").to_s,
|
||||
base_path: root_url,
|
||||
mattermost_enabled: Gitlab.config.mattermost.enabled.to_s
|
||||
}
|
||||
end
|
||||
|
@ -156,7 +161,7 @@ module GroupsHelper
|
|||
def subgroups_and_projects_list_app_data(group)
|
||||
{
|
||||
show_schema_markup: 'true',
|
||||
new_subgroup_path: new_group_path(parent_id: group.id),
|
||||
new_subgroup_path: new_group_path(parent_id: group.id, anchor: 'create-group-pane'),
|
||||
new_project_path: new_project_path(namespace_id: group.id),
|
||||
new_subgroup_illustration: image_path('illustrations/subgroup-create-new-sm.svg'),
|
||||
new_project_illustration: image_path('illustrations/project-create-new-sm.svg'),
|
||||
|
|
|
@ -42,7 +42,7 @@ module Nav
|
|||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
id: 'new_subgroup',
|
||||
title: _('New subgroup'),
|
||||
href: new_group_path(parent_id: group.id),
|
||||
href: new_group_path(parent_id: group.id, anchor: 'create-group-pane'),
|
||||
data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
|
||||
)
|
||||
)
|
||||
|
|
|
@ -15,23 +15,7 @@ module Emails
|
|||
email = user.notification_email_or_default
|
||||
mail to: email, subject: "Unsubscribed from GitLab administrator notifications"
|
||||
end
|
||||
|
||||
def user_auto_banned_email(admin_id, user_id, max_project_downloads:, within_seconds:, group: nil)
|
||||
admin = User.find(admin_id)
|
||||
@user = User.find(user_id)
|
||||
@max_project_downloads = max_project_downloads
|
||||
@within_minutes = within_seconds / 60
|
||||
@ban_scope = if group.present?
|
||||
_('your group (%{group_name})' % { group_name: group.name })
|
||||
else
|
||||
_('your GitLab instance')
|
||||
end
|
||||
|
||||
Gitlab::I18n.with_locale(admin.preferred_language) do
|
||||
email_with_layout(
|
||||
to: admin.notification_email_or_default,
|
||||
subject: subject(_("We've detected unusual activity")))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Emails::AdminNotification.prepend_mod
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
= _('Update your group name, description, avatar, and visibility.')
|
||||
= link_to _('Learn more about groups.'), help_page_path('user/group/index')
|
||||
.col-lg-8
|
||||
= render 'shared/group_form', f: f
|
||||
= render 'shared/groups/group_name_and_path_fields', f: f
|
||||
= render 'shared/group_form_description', f: f
|
||||
.form-group.gl-form-group{ role: 'group' }
|
||||
= f.label :avatar, _("Group avatar"), class: 'gl-display-block col-form-label'
|
||||
|
|
|
@ -33,7 +33,10 @@
|
|||
.js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: @group.id, container_class: 'gl-mx-2 gl-mt-3 gl-vertical-align-top', no_flip: 'true' } }
|
||||
- if can_create_subgroups
|
||||
.gl-px-2.gl-sm-w-auto.gl-w-full
|
||||
= link_to _("New subgroup"), new_group_path(parent_id: @group.id), class: "btn btn-default gl-button gl-mt-3 gl-sm-w-auto gl-w-full", data: { qa_selector: 'new_subgroup_button' }
|
||||
= link_to _("New subgroup"),
|
||||
new_group_path(parent_id: @group.id, anchor: 'create-group-pane'),
|
||||
class: "btn btn-default gl-button gl-mt-3 gl-sm-w-auto gl-w-full",
|
||||
data: { qa_selector: 'new_subgroup_button' }
|
||||
- if can_create_projects
|
||||
.gl-px-2.gl-sm-w-auto.gl-w-full
|
||||
= link_to _("New project"), new_project_path(namespace_id: @group.id), class: "btn btn-confirm gl-button gl-mt-3 gl-sm-w-auto gl-w-full", data: { qa_selector: 'new_project_button' }
|
||||
|
|
|
@ -1,31 +1,34 @@
|
|||
- parent = @group.parent
|
||||
- submit_label = parent ? s_('GroupsNew|Create subgroup') : s_('GroupsNew|Create group')
|
||||
= form_errors(@group, pajamas_alert: true)
|
||||
= render 'shared/group_form', f: f, autofocus: true
|
||||
= render 'shared/groups/group_name_and_path_fields', f: f, autofocus: true, new_subgroup: !!parent
|
||||
|
||||
.row
|
||||
.form-group.gl-form-group.col-sm-12
|
||||
%label.label-bold
|
||||
= _('Visibility level')
|
||||
%p
|
||||
= _('Who will be able to see this group?')
|
||||
= link_to _('View the documentation'), help_page_path("user/public_access"), target: '_blank', rel: 'noopener noreferrer'
|
||||
= render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group, with_label: false
|
||||
|
||||
- if Gitlab.config.mattermost.enabled
|
||||
- unless parent
|
||||
.row
|
||||
= render 'create_chat_team', f: f
|
||||
.form-group.gl-form-group.col-sm-12
|
||||
%label.label-bold
|
||||
= _('Visibility level')
|
||||
%p
|
||||
= _('Who will be able to see this group?')
|
||||
= link_to _('View the documentation'), help_page_path("user/public_access"), target: '_blank', rel: 'noopener noreferrer'
|
||||
= render 'shared/visibility_level', f: f, visibility_level: default_group_visibility, can_change_visibility_level: true, form_model: @group, with_label: false
|
||||
|
||||
- unless Gitlab::CurrentSettings.current_application_settings.hide_third_party_offers?
|
||||
= render 'personalize', f: f
|
||||
- if Gitlab.config.mattermost.enabled
|
||||
.row
|
||||
= render 'create_chat_team', f: f
|
||||
|
||||
.row.js-invite-members-section
|
||||
.col-sm-4
|
||||
= render_if_exists 'shared/groups/invite_members'
|
||||
- unless Gitlab::CurrentSettings.current_application_settings.hide_third_party_offers?
|
||||
= render 'personalize', f: f
|
||||
|
||||
- if captcha_required?
|
||||
.row.recaptcha
|
||||
.row.js-invite-members-section
|
||||
.col-sm-4
|
||||
= recaptcha_tags nonce: content_security_policy_nonce
|
||||
= render_if_exists 'shared/groups/invite_members'
|
||||
|
||||
- if captcha_required?
|
||||
.row.recaptcha
|
||||
.col-sm-4
|
||||
= recaptcha_tags nonce: content_security_policy_nonce
|
||||
.row
|
||||
.col-sm-12
|
||||
= f.submit _('Create group'), class: "btn gl-button btn-confirm"
|
||||
= f.submit submit_label, class: "btn gl-button btn-confirm", data: { qa_selector: 'create_group_button' }
|
||||
= link_to _('Cancel'), dashboard_groups_path, class: 'btn gl-button btn-default btn-cancel'
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
|
||||
.group-edit-container.gl-mt-5
|
||||
|
||||
.js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s }.merge(verification_for_group_creation_data) }
|
||||
.js-new-group-creation{ data: { has_errors: @group.errors.any?.to_s }.merge(subgroup_creation_data(@group),
|
||||
verification_for_group_creation_data) }
|
||||
|
||||
.row{ 'v-cloak': true }
|
||||
#create-group-pane.tab-pane
|
||||
|
|
|
@ -1,4 +1,23 @@
|
|||
- return unless google_tag_manager_enabled?
|
||||
- if Feature.enabled?(:gitlab_gtm_datalayer, type: :ops)
|
||||
= javascript_tag do
|
||||
:plain
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag(){dataLayer.push(arguments);}
|
||||
|
||||
gtag('consent', 'default', {
|
||||
'analytics_storage': 'denied',
|
||||
'ad_storage': 'denied',
|
||||
'functionality_storage': 'denied',
|
||||
'region': ['EU', 'UK', 'PE', 'RU'],
|
||||
'wait_for_update': 500
|
||||
});
|
||||
gtag('consent', 'default', {
|
||||
'analytics_storage': 'granted',
|
||||
'ad_storage': 'granted',
|
||||
'functionality_storage': 'granted',
|
||||
'wait_for_update': 500
|
||||
});
|
||||
|
||||
- if Feature.enabled?(:gtm_nonce, type: :ops)
|
||||
= javascript_tag nonce: content_security_policy_nonce do
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe
|
||||
- link_end = '</a>'.html_safe
|
||||
= email_default_heading(_("We've detected some unusual activity"))
|
||||
%p
|
||||
= _('We want to let you know %{username} has been banned from %{scope} due to them downloading more than %{max_project_downloads} project repositories within %{within_minutes} minutes.') % { username: sanitize_name(@user.name), max_project_downloads: @max_project_downloads, within_minutes: @within_minutes, scope: @ban_scope }
|
||||
%p
|
||||
= _('If this is a mistake, you can %{link_start}unban them%{link_end}.').html_safe % { link_start: link_start % { url: admin_users_url(filter: 'banned') }, link_end: link_end }
|
||||
%p
|
||||
= _('You can adjust rules on auto-banning %{link_start}here%{link_end}.').html_safe % { link_start: link_start % { url: network_admin_application_settings_url(anchor: 'js-ip-limits-settings') }, link_end: link_end }
|
|
@ -1,7 +0,0 @@
|
|||
<%= _("We've detected some unusual activity") %>
|
||||
|
||||
<%= _('We want to let you know %{username} has been banned from %{scope} due to them downloading more than %{max_project_downloads} project repositories within %{within_minutes} minutes.') % { username: sanitize_name(@user.name), max_project_downloads: @max_project_downloads, within_minutes: @within_minutes, scope: @ban_scope } %>
|
||||
|
||||
<%= _('If this is a mistake, you can unban them: %{url}.') % { url: admin_users_url(filter: 'banned') } %>
|
||||
|
||||
<%= _('You can adjust rules on auto-banning here: %{url}.') % { url: network_admin_application_settings_url(anchor: 'js-ip-limits-settings') } %>
|
|
@ -1,6 +0,0 @@
|
|||
- parent = @group.parent
|
||||
- group_path = root_url
|
||||
- group_path << parent.full_path + '/' if parent
|
||||
|
||||
|
||||
= render 'shared/groups/group_name_and_path_fields', f: f
|
|
@ -1,5 +1,6 @@
|
|||
.js-group-name-and-path{ data: group_name_and_path_app_data(@group) }
|
||||
.js-group-name-and-path{ data: group_name_and_path_app_data.merge(new_subgroup: local_assigns[:new_subgroup].to_s) }
|
||||
= f.hidden_field :name, data: { js_name: 'name' }
|
||||
= f.hidden_field :path, maxlength: ::Namespace::URL_MAX_LENGTH, pattern: Gitlab::PathRegex::NAMESPACE_FORMAT_REGEX_JS, data: { js_name: 'path' }
|
||||
= f.hidden_field :parent_id, value: @group.parent&.id, data: { js_name: 'parentId' }
|
||||
= f.hidden_field :parent_full_path, value: @group.parent&.full_path, data: { js_name: 'parentFullPath' }
|
||||
= f.hidden_field :id, data: { js_name: 'groupId' }
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
#promote-milestone-modal
|
||||
|
||||
- if milestone.active?
|
||||
= render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :close }), button_options: { class: 'btn-grouped btn-close', data: { method: 'put' }, rel: 'nofollow' }) do
|
||||
= render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :close }), method: :put, button_options: { class: 'btn-grouped btn-close' }) do
|
||||
= _('Close milestone')
|
||||
- else
|
||||
= render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :activate }), button_options: { class: 'btn-grouped', data: { method: 'put' }, rel: 'nofollow' }) do
|
||||
= render Pajamas::ButtonComponent.new(href: update_milestone_path(milestone, { state_event: :activate }), method: :put, button_options: { class: 'btn-grouped' }) do
|
||||
= _('Reopen milestone')
|
||||
|
||||
= render 'shared/milestones/delete_button'
|
||||
|
|
|
@ -42,11 +42,13 @@
|
|||
= sprite_icon('user')
|
||||
- if current_user && current_user.id != @user.id
|
||||
- if current_user.following?(@user)
|
||||
= link_to user_unfollow_path(@user, :json) , class: link_classes + 'btn gl-button btn-default', method: :post do
|
||||
= _('Unfollow')
|
||||
= form_tag user_unfollow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
|
||||
= render Pajamas::ButtonComponent.new(type: :submit, button_options: { class: 'gl-w-full', data: { track_action: 'click_button', track_label: 'unfollow_from_profile' } }) do
|
||||
= _('Unfollow')
|
||||
- else
|
||||
= link_to user_follow_path(@user, :json) , class: link_classes + 'btn gl-button btn-confirm', method: :post, data: { qa_selector: 'follow_user_link' } do
|
||||
= _('Follow')
|
||||
= form_tag user_follow_path(@user, :json), class: link_classes + 'gl-display-inline-block' do
|
||||
= render Pajamas::ButtonComponent.new(variant: :confirm, type: :submit, button_options: { class: 'gl-w-full', data: { qa_selector: 'follow_user_link', track_action: 'click_button', track_label: 'follow_from_profile' } }) do
|
||||
= _('Follow')
|
||||
|
||||
.profile-header{ class: [('with-no-profile-tabs' if profile_tabs.empty?)] }
|
||||
.avatar-holder
|
||||
|
|
|
@ -12,9 +12,23 @@ module Ci
|
|||
feature_category :runner_fleet
|
||||
urgency :low
|
||||
|
||||
deduplicate :until_executed
|
||||
idempotent!
|
||||
|
||||
def perform
|
||||
def perform(cronjob_scheduled = true)
|
||||
if cronjob_scheduled
|
||||
# Introduce some randomness across the day so that instances don't all hit the GitLab Releases API
|
||||
# around the same time of day
|
||||
period = rand(0..12.hours.in_seconds)
|
||||
self.class.perform_in(period, false)
|
||||
|
||||
Sidekiq.logger.info(
|
||||
class: self.class.name,
|
||||
message: "rescheduled job for #{period.seconds.from_now}")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
result = ::Ci::Runners::ReconcileExistingRunnerVersionsService.new.execute
|
||||
result.each { |key, value| log_extra_metadata_on_done(key, value) }
|
||||
end
|
||||
|
|
|
@ -542,7 +542,7 @@ production: &base
|
|||
|
||||
# Periodically update ci_runner_versions table with up-to-date versions and status.
|
||||
ci_runner_versions_reconciliation_worker:
|
||||
cron: "20 * * * *"
|
||||
cron: "@daily"
|
||||
|
||||
# GitLab EE only jobs. These jobs are automatically enabled for an EE
|
||||
# installation, and ignored for a CE installation.
|
||||
|
|
|
@ -631,7 +631,7 @@ Settings.cron_jobs['loose_foreign_keys_cleanup_worker'] ||= Settingslogic.new({}
|
|||
Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['cron'] ||= '*/1 * * * *'
|
||||
Settings.cron_jobs['loose_foreign_keys_cleanup_worker']['job_class'] = 'LooseForeignKeys::CleanupWorker'
|
||||
Settings.cron_jobs['ci_runner_versions_reconciliation_worker'] ||= Settingslogic.new({})
|
||||
Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['cron'] ||= '20 * * * *'
|
||||
Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['cron'] ||= '@daily'
|
||||
Settings.cron_jobs['ci_runner_versions_reconciliation_worker']['job_class'] = 'Ci::Runners::ReconcileExistingRunnerVersionsCronWorker'
|
||||
|
||||
Gitlab.ee do
|
||||
|
|
|
@ -5,34 +5,42 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
type: reference, howto
|
||||
---
|
||||
|
||||
# DAST browser-based crawler **(ULTIMATE)**
|
||||
# DAST browser-based analyzer **(ULTIMATE)**
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/323423) in GitLab 13.12.
|
||||
|
||||
WARNING:
|
||||
This product is in an early-access stage and is considered a [beta](../../../policy/alpha-beta-support.md#beta-features) feature.
|
||||
|
||||
GitLab DAST's new browser-based crawler is a crawl engine built by GitLab to test Single Page Applications (SPAs) and traditional web applications.
|
||||
Due to the reliance of modern web applications on JavaScript, handling SPAs or applications that are dependent on JavaScript is paramount to ensuring proper coverage of an application for Dynamic Application Security Testing (DAST).
|
||||
GitLab DAST's browser-based analyzer was built by GitLab to test Single Page Applications (SPAs) and
|
||||
traditional web applications. It both crawls the web application and analyzes the resulting output
|
||||
for vulnerabilities. Analysis of modern applications, heavily reliant on JavaScript, is vital to
|
||||
ensuring DAST coverage.
|
||||
|
||||
The browser-based crawler works by loading the target application into a specially-instrumented Chromium browser. A snapshot of the page is taken before a search to find any actions that a user might perform,
|
||||
such as clicking on a link or filling in a form. For each action found, the crawler executes it, takes a new snapshot, and determines what in the page changed from the previous snapshot.
|
||||
Crawling continues by taking more snapshots and finding subsequent actions.
|
||||
The browser-based scanner works by loading the target application into a specially-instrumented
|
||||
Chromium browser. A snapshot of the page is taken before a search to find any actions that a user
|
||||
might perform, such as clicking on a link or filling in a form. For each action found, the
|
||||
browser-based scanner executes it, takes a new snapshot, and determines what in the page changed
|
||||
from the previous snapshot. Crawling continues by taking more snapshots and finding subsequent
|
||||
actions. The benefit of scanning by following user actions in a browser is that the crawler can
|
||||
interact with the target application much like a real user would, identifying complex flows that
|
||||
traditional web crawlers don't understand. This results in better coverage of the website.
|
||||
|
||||
The benefit of crawling by following user actions in a browser is that the crawler can interact with the target application much like a real user would, identifying complex flows that traditional web crawlers don't understand. This results in better coverage of the website.
|
||||
The browser-based scanner should provide greater coverage for most web applications, compared
|
||||
with the current DAST AJAX crawler. While both crawlers are
|
||||
used together with the current DAST scanner, the combination of the browser-based crawler with the
|
||||
current DAST scanner is much more effective at finding and testing every page in an application.
|
||||
|
||||
Using the browser-based crawler should provide greater coverage for most web applications, compared with the current DAST AJAX crawler. The new crawler replaces the AJAX crawler and is specifically designed to maximize crawl coverage in modern web applications. While both crawlers are currently used in conjunction with the existing DAST scanner, the combination of the browser-based crawler with the current DAST scanner is much more effective at finding and testing every page in an application.
|
||||
## Enable browser-based analyzer
|
||||
|
||||
## Enable browser-based crawler
|
||||
|
||||
The browser-based crawler is an extension to the GitLab DAST product. DAST should be included in the CI/CD configuration and the browser-based crawler enabled using CI/CD variables:
|
||||
To enable the browser-based analyzer:
|
||||
|
||||
1. Ensure the DAST [prerequisites](index.md#prerequisites) are met.
|
||||
1. Include the [DAST CI template](index.md#include-the-dast-template).
|
||||
1. Set the target website using the `DAST_WEBSITE` CI/CD variable.
|
||||
1. Include the [DAST CI/CD template](index.md#include-the-dast-template).
|
||||
1. Set the target website using the [`DAST_WEBSITE` CI/CD variable](index.md#available-cicd-variables).
|
||||
1. Set the CI/CD variable `DAST_BROWSER_SCAN` to `true`.
|
||||
|
||||
An example configuration might look like the following:
|
||||
Example extract of `.gitlab-ci.yml` file:
|
||||
|
||||
```yaml
|
||||
include:
|
||||
|
@ -77,13 +85,20 @@ The [DAST variables](index.md#available-cicd-variables) `SECURE_ANALYZERS_PREFIX
|
|||
|
||||
## Vulnerability detection
|
||||
|
||||
While the browser-based crawler crawls modern web applications efficiently, vulnerability detection is still managed by the standard DAST/Zed Attack Proxy (ZAP) solution.
|
||||
Vulnerability detection is gradually being migrated from the default Zed Attack Proxy (ZAP) solution
|
||||
to the browser-based analyzer. For details of the vulnerability detection already migrated, see
|
||||
[browser-based vulnerability checks](checks/index.md).
|
||||
|
||||
The crawler runs the target website in a browser with DAST/ZAP configured as the proxy server. This ensures that all requests and responses made by the browser are passively scanned by DAST/ZAP.
|
||||
When running a full scan, active vulnerability checks executed by DAST/ZAP do not use a browser. This difference in how vulnerabilities are checked can cause issues that require certain features of the target website to be disabled to ensure the scan works as intended.
|
||||
The crawler runs the target website in a browser with DAST/ZAP configured as the proxy server. This
|
||||
ensures that all requests and responses made by the browser are passively scanned by DAST/ZAP. When
|
||||
running a full scan, active vulnerability checks executed by DAST/ZAP do not use a browser. This
|
||||
difference in how vulnerabilities are checked can cause issues that require certain features of the
|
||||
target website to be disabled to ensure the scan works as intended.
|
||||
|
||||
For example, for a target website that contains forms with Anti-CSRF tokens, a passive scan works as intended because the browser displays pages and forms as if a user is viewing the page.
|
||||
However, active vulnerability checks that run in a full scan cannot submit forms containing Anti-CSRF tokens. In such cases, we recommend you disable Anti-CSRF tokens when running a full scan.
|
||||
For example, for a target website that contains forms with Anti-CSRF tokens, a passive scan works as
|
||||
intended because the browser displays pages and forms as if a user is viewing the page. However,
|
||||
active vulnerability checks that run in a full scan cannot submit forms containing Anti-CSRF tokens.
|
||||
In such cases, we recommend you disable Anti-CSRF tokens when running a full scan.
|
||||
|
||||
## Managing scan time
|
||||
|
||||
|
|
|
@ -68,12 +68,14 @@ bugsCharts:
|
|||
description: "Open bugs created per month"
|
||||
type: bar
|
||||
query:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
```
|
||||
|
||||
Each chart definition is made up of a hash composed of key-value pairs.
|
||||
|
@ -85,12 +87,14 @@ For example, here's single chart definition:
|
|||
description: "Open bugs created per month"
|
||||
type: bar
|
||||
query:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
```
|
||||
|
||||
## Configuration parameters
|
||||
|
@ -104,7 +108,7 @@ The following table lists available parameters for charts:
|
|||
| [`title`](#title) | The title of the chart. This displays on the Insights page. |
|
||||
| [`description`](#description) | A description for the individual chart. This displays above the relevant chart. |
|
||||
| [`type`](#type) | The type of chart: `bar`, `line` or `stacked-bar`. |
|
||||
| [`query`](#query) | A hash that defines the conditions for issues / merge requests to be part of the chart. |
|
||||
| [`query`](#query) | A hash that defines the data source and filtering conditions for the chart. |
|
||||
|
||||
## Parameter details
|
||||
|
||||
|
@ -155,11 +159,33 @@ Supported values are:
|
|||
|
||||
### `query`
|
||||
|
||||
`query` allows to define the conditions for issues / merge requests to be part
|
||||
of the chart.
|
||||
`query` allows to define the data source and various filtering conditions for the chart.
|
||||
|
||||
Example:
|
||||
|
||||
```yaml
|
||||
monthlyBugsCreated:
|
||||
title: "Monthly bugs created"
|
||||
description: "Open bugs created per month"
|
||||
type: bar
|
||||
query:
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
collection_labels:
|
||||
- S1
|
||||
- S2
|
||||
- S3
|
||||
- S4
|
||||
group_by: week
|
||||
period_limit: 104
|
||||
```
|
||||
|
||||
The legacy format without the `data_source` parameter is still supported:
|
||||
|
||||
```yaml
|
||||
monthlyBugsCreated:
|
||||
title: "Monthly bugs created"
|
||||
|
@ -179,7 +205,15 @@ monthlyBugsCreated:
|
|||
period_limit: 104
|
||||
```
|
||||
|
||||
#### `query.issuable_type`
|
||||
#### `query.data_source`
|
||||
|
||||
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/725) in GitLab 15.3.
|
||||
|
||||
The `data_source` parameter was introduced to allow visualizing data from different data sources. Currently `issuable` is the only supported value.
|
||||
|
||||
#### `Issuable` query parameters
|
||||
|
||||
##### `query.params.issuable_type`
|
||||
|
||||
Defines the type of "issuable" you want to create a chart for.
|
||||
|
||||
|
@ -188,7 +222,7 @@ Supported values are:
|
|||
- `issue`: The chart displays issues' data.
|
||||
- `merge_request`: The chart displays merge requests' data.
|
||||
|
||||
#### `query.issuable_state`
|
||||
##### `query.params.issuable_state`
|
||||
|
||||
Filter by the current state of the queried "issuable".
|
||||
|
||||
|
@ -202,7 +236,7 @@ Supported values are:
|
|||
- `merged`: Merged merge requests.
|
||||
- `all`: Issues / merge requests in all states
|
||||
|
||||
#### `query.filter_labels`
|
||||
##### `query.params.filter_labels`
|
||||
|
||||
Filter by labels currently applied to the queried "issuable".
|
||||
|
||||
|
@ -216,14 +250,16 @@ monthlyBugsCreated:
|
|||
title: "Monthly regressions created"
|
||||
type: bar
|
||||
query:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
- regression
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
- regression
|
||||
```
|
||||
|
||||
#### `query.collection_labels`
|
||||
#### `query.params.collection_labels`
|
||||
|
||||
Group "issuable" by the configured labels.
|
||||
|
||||
|
@ -237,15 +273,17 @@ weeklyBugsBySeverity:
|
|||
title: "Weekly bugs by severity"
|
||||
type: stacked-bar
|
||||
query:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
collection_labels:
|
||||
- S1
|
||||
- S2
|
||||
- S3
|
||||
- S4
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
collection_labels:
|
||||
- S1
|
||||
- S2
|
||||
- S3
|
||||
- S4
|
||||
```
|
||||
|
||||
#### `query.group_by`
|
||||
|
@ -325,10 +363,12 @@ monthlyBugsCreated:
|
|||
description: "Open bugs created per month"
|
||||
type: bar
|
||||
query:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
projects:
|
||||
only:
|
||||
- 3 # You can use the project ID
|
||||
|
@ -355,41 +395,47 @@ bugsCharts:
|
|||
type: bar
|
||||
<<: *projectsOnly
|
||||
query:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
|
||||
- title: "Weekly bugs by severity"
|
||||
type: stacked-bar
|
||||
<<: *projectsOnly
|
||||
query:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
collection_labels:
|
||||
- S1
|
||||
- S2
|
||||
- S3
|
||||
- S4
|
||||
group_by: week
|
||||
period_limit: 104
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: issue
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
collection_labels:
|
||||
- S1
|
||||
- S2
|
||||
- S3
|
||||
- S4
|
||||
group_by: week
|
||||
period_limit: 104
|
||||
|
||||
- title: "Monthly bugs by team"
|
||||
type: line
|
||||
<<: *projectsOnly
|
||||
query:
|
||||
issuable_type: merge_request
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
collection_labels:
|
||||
- Manage
|
||||
- Plan
|
||||
- Create
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
data_source: issuables
|
||||
params:
|
||||
issuable_type: merge_request
|
||||
issuable_state: opened
|
||||
filter_labels:
|
||||
- bug
|
||||
collection_labels:
|
||||
- Manage
|
||||
- Plan
|
||||
- Create
|
||||
group_by: month
|
||||
period_limit: 24
|
||||
```
|
||||
|
|
|
@ -18802,6 +18802,9 @@ msgstr ""
|
|||
msgid "GroupsEmptyState|You do not have necessary permissions to create a subgroup or project in this group. Please contact an owner of this group to create a new subgroup or project."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupsNew|%{groupsLinkStart}Groups%{groupsLinkEnd} and %{subgroupsLinkStart}subgroups%{subgroupsLinkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupsNew|%{linkStart}Groups%{linkEnd} allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects."
|
||||
msgstr ""
|
||||
|
||||
|
@ -18820,6 +18823,9 @@ msgstr ""
|
|||
msgid "GroupsNew|Create new group"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupsNew|Create subgroup"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupsNew|Create this in the %{pat_link_start}user settings%{pat_link_end} of the source GitLab instance. For %{short_living_link_start}security reasons%{short_living_link_end}, use a short expiration date when creating the token."
|
||||
msgstr ""
|
||||
|
||||
|
@ -18865,6 +18871,9 @@ msgstr ""
|
|||
msgid "GroupsNew|Upload file"
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupsNew|You can also %{linkStart}import an existing group%{linkEnd}."
|
||||
msgstr ""
|
||||
|
||||
msgid "GroupsNew|e.g. h8d3f016698e..."
|
||||
msgstr ""
|
||||
|
||||
|
@ -18943,6 +18952,15 @@ msgstr ""
|
|||
msgid "Groups|Save changes"
|
||||
msgstr ""
|
||||
|
||||
msgid "Groups|Subgroup URL"
|
||||
msgstr ""
|
||||
|
||||
msgid "Groups|Subgroup name"
|
||||
msgstr ""
|
||||
|
||||
msgid "Groups|Subgroup slug"
|
||||
msgstr ""
|
||||
|
||||
msgid "Guideline"
|
||||
msgstr ""
|
||||
|
||||
|
@ -23516,9 +23534,6 @@ msgstr ""
|
|||
msgid "LinkedResources|Linked resources"
|
||||
msgstr ""
|
||||
|
||||
msgid "LinkedResources|Read more about linked resources"
|
||||
msgstr ""
|
||||
|
||||
msgid "LinkedResources|Remove"
|
||||
msgstr ""
|
||||
|
||||
|
@ -23534,6 +23549,9 @@ msgstr ""
|
|||
msgid "LinkedResources|Text (Optional)"
|
||||
msgstr ""
|
||||
|
||||
msgid "LinkedResources|Use this space to add links to the resources your team needs as they work to resolve the incident."
|
||||
msgstr ""
|
||||
|
||||
msgid "Links"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -123,7 +123,7 @@
|
|||
"graphql": "^15.7.2",
|
||||
"graphql-tag": "^2.11.0",
|
||||
"highlight.js": "^11.5.1",
|
||||
"immer": "^7.0.7",
|
||||
"immer": "^9.0.15",
|
||||
"ipaddr.js": "^1.9.1",
|
||||
"jed": "^1.1.1",
|
||||
"jquery": "^3.6.0",
|
||||
|
@ -239,7 +239,7 @@
|
|||
"md5": "^2.2.1",
|
||||
"miragejs": "^0.1.40",
|
||||
"mock-apollo-client": "1.2.0",
|
||||
"nodemon": "^2.0.4",
|
||||
"nodemon": "^2.0.19",
|
||||
"prettier": "2.2.1",
|
||||
"prosemirror-schema-basic": "^1.1.2",
|
||||
"prosemirror-schema-list": "^1.1.6",
|
||||
|
|
|
@ -12,7 +12,7 @@ module QA
|
|||
end
|
||||
|
||||
view 'app/views/groups/_new_group_fields.html.haml' do
|
||||
element :create_group_button, "submit _('Create group')" # rubocop:disable QA/ElementWithPattern
|
||||
element :create_group_button
|
||||
end
|
||||
|
||||
view 'app/views/groups/_import_group_from_another_instance_panel.html.haml' do
|
||||
|
@ -34,6 +34,10 @@ module QA
|
|||
click_button 'Create group'
|
||||
end
|
||||
|
||||
def create_subgroup
|
||||
click_button 'Create subgroup'
|
||||
end
|
||||
|
||||
def set_gitlab_url(url)
|
||||
fill_element(:import_gitlab_url, url)
|
||||
end
|
||||
|
|
|
@ -6,6 +6,7 @@ module QA
|
|||
module Settings
|
||||
class Integrations < QA::Page::Base
|
||||
view 'app/assets/javascripts/integrations/index/components/integrations_table.vue' do
|
||||
element :jenkins_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
|
||||
element :prometheus_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
|
||||
element :jira_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
|
||||
element :pipelines_email_link, %q(:data-qa-selector="`${item.name}_link`") # rubocop:disable QA/ElementWithPattern
|
||||
|
@ -22,10 +23,12 @@ module QA
|
|||
def click_jira_link
|
||||
click_element :jira_link
|
||||
end
|
||||
|
||||
def click_jenkins_ci_link
|
||||
click_element :jenkins_link
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
QA::Page::Project::Settings::Integrations.prepend_mod_with('Page::Project::Settings::Integrations', namespace: QA)
|
||||
|
|
|
@ -38,10 +38,8 @@ module QA
|
|||
group_show.go_to_new_subgroup
|
||||
|
||||
Page::Group::New.perform do |group_new|
|
||||
group_new.click_create_group
|
||||
group_new.set_path(path)
|
||||
group_new.set_visibility('Public')
|
||||
group_new.create
|
||||
group_new.create_subgroup
|
||||
end
|
||||
|
||||
# Ensure that the group was actually created
|
||||
|
|
|
@ -9,7 +9,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
|
|||
let(:content) { "Button content" }
|
||||
let(:options) { {} }
|
||||
|
||||
describe 'basic usage' do
|
||||
RSpec.shared_examples 'basic button behavior' do
|
||||
before do
|
||||
render_inline(subject) do |c|
|
||||
content
|
||||
|
@ -59,7 +59,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
|
|||
describe 'disabled' do
|
||||
context 'by default (false)' do
|
||||
it 'does not have disabled styling and behavior' do
|
||||
expect(page).not_to have_css ".disabled[disabled='disabled'][aria-disabled='true']"
|
||||
expect(page).not_to have_css ".disabled[disabled][aria-disabled]"
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -67,7 +67,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
|
|||
let(:options) { { disabled: true } }
|
||||
|
||||
it 'has disabled styling and behavior' do
|
||||
expect(page).to have_css ".disabled[disabled='disabled'][aria-disabled='true']"
|
||||
expect(page).to have_css ".disabled[disabled][aria-disabled]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -75,7 +75,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
|
|||
describe 'loading' do
|
||||
context 'by default (false)' do
|
||||
it 'is not disabled' do
|
||||
expect(page).not_to have_css ".disabled[disabled='disabled']"
|
||||
expect(page).not_to have_css ".disabled[disabled]"
|
||||
end
|
||||
|
||||
it 'does not render a spinner' do
|
||||
|
@ -87,7 +87,7 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
|
|||
let(:options) { { loading: true } }
|
||||
|
||||
it 'is disabled' do
|
||||
expect(page).to have_css ".disabled[disabled='disabled']"
|
||||
expect(page).to have_css ".disabled[disabled]"
|
||||
end
|
||||
|
||||
it 'renders a spinner' do
|
||||
|
@ -218,9 +218,13 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'button component renders a button' do
|
||||
include_examples 'basic button behavior'
|
||||
|
||||
describe 'type' do
|
||||
context 'by default (without href)' do
|
||||
context 'by default' do
|
||||
it 'has type "button"' do
|
||||
expect(page).to have_css "button[type='button']"
|
||||
end
|
||||
|
@ -238,34 +242,42 @@ RSpec.describe Pajamas::ButtonComponent, type: :component do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when set to unkown type' do
|
||||
context 'when set to unknown type' do
|
||||
let(:options) { { type: :madeup } }
|
||||
|
||||
it 'has type "button"' do
|
||||
expect(page).to have_css "button[type='button']"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for links (with href)' do
|
||||
let(:options) { { href: 'https://example.com', type: :reset } }
|
||||
context 'button component renders a link' do
|
||||
let(:options) { { href: 'https://gitlab.com', target: '_blank' } }
|
||||
|
||||
it 'ignores type' do
|
||||
expect(page).not_to have_css "[type]"
|
||||
end
|
||||
it "renders a link instead of the button" do
|
||||
expect(page).not_to have_css "button[type='button']"
|
||||
expect(page).to have_css "a[href='https://gitlab.com'][target='_blank']"
|
||||
end
|
||||
|
||||
include_examples 'basic button behavior'
|
||||
|
||||
describe 'type' do
|
||||
let(:options) { { href: 'https://example.com', type: :reset } }
|
||||
|
||||
it 'ignores type' do
|
||||
expect(page).not_to have_css "[type]"
|
||||
end
|
||||
end
|
||||
|
||||
describe 'link button' do
|
||||
it 'renders a button tag with type="button" when "href" is not set' do
|
||||
expect(page).to have_css "button[type='button']"
|
||||
end
|
||||
describe 'method' do
|
||||
where(:method) { [:get, :post, :put, :delete, :patch] }
|
||||
|
||||
context 'when "href" is provided' do
|
||||
let(:options) { { href: 'https://gitlab.com', target: '_blank' } }
|
||||
let(:options) { { href: 'https://gitlab.com', method: method } }
|
||||
|
||||
it "renders a link instead of the button" do
|
||||
expect(page).not_to have_css "button[type='button']"
|
||||
expect(page).to have_css "a[href='https://gitlab.com'][target='_blank']"
|
||||
with_them do
|
||||
it 'has the correct data-method attribute' do
|
||||
expect(page).to have_css "a[data-method='#{method}']"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -84,7 +84,7 @@ RSpec.describe 'Group show page' do
|
|||
it 'shows `Create new subgroup` link' do
|
||||
expect(page).to have_link(
|
||||
s_('GroupsEmptyState|Create new subgroup'),
|
||||
href: new_group_path(parent_id: group.id)
|
||||
href: new_group_path(parent_id: group.id, anchor: 'create-group-pane')
|
||||
)
|
||||
end
|
||||
|
||||
|
|
|
@ -221,14 +221,13 @@ RSpec.describe 'Group' do
|
|||
let(:user) { create(:admin) }
|
||||
|
||||
before do
|
||||
visit new_group_path(parent_id: group.id)
|
||||
visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
|
||||
end
|
||||
|
||||
context 'when admin mode is enabled', :enable_admin_mode do
|
||||
it 'creates a nested group' do
|
||||
click_link 'Create group'
|
||||
fill_in 'Group name', with: 'bar'
|
||||
click_button 'Create group'
|
||||
fill_in 'Subgroup name', with: 'bar'
|
||||
click_button 'Create subgroup'
|
||||
|
||||
expect(page).to have_current_path(group_path('foo/bar'), ignore_query: true)
|
||||
expect(page).to have_selector 'h1', text: 'bar'
|
||||
|
@ -237,7 +236,7 @@ RSpec.describe 'Group' do
|
|||
|
||||
context 'when admin mode is disabled' do
|
||||
it 'is not allowed' do
|
||||
expect(page).not_to have_button('Create group')
|
||||
expect(page).not_to have_button('Create subgroup')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -250,11 +249,10 @@ RSpec.describe 'Group' do
|
|||
sign_out(:user)
|
||||
sign_in(user)
|
||||
|
||||
visit new_group_path(parent_id: group.id)
|
||||
click_link 'Create group'
|
||||
visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
|
||||
|
||||
fill_in 'Group name', with: 'bar'
|
||||
click_button 'Create group'
|
||||
fill_in 'Subgroup name', with: 'bar'
|
||||
click_button 'Create subgroup'
|
||||
|
||||
expect(page).to have_current_path(group_path('foo/bar'), ignore_query: true)
|
||||
expect(page).to have_selector 'h1', text: 'bar'
|
||||
|
@ -268,7 +266,7 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
|
||||
context 'when creating subgroup' do
|
||||
let(:path) { new_group_path(parent_id: group.id) }
|
||||
let(:path) { new_group_path(parent_id: group.id, anchor: 'create-group-pane') }
|
||||
|
||||
it 'does not render recaptcha' do
|
||||
visit path
|
||||
|
@ -278,24 +276,50 @@ RSpec.describe 'Group' do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when many parent groups are available' do
|
||||
let_it_be(:group2) { create(:group, path: 'foo2') }
|
||||
let_it_be(:group3) { create(:group, path: 'foo3') }
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
group2.add_maintainer(user)
|
||||
group3.add_developer(user)
|
||||
visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
|
||||
end
|
||||
|
||||
it 'creates private subgroup' do
|
||||
fill_in 'Subgroup name', with: 'bar'
|
||||
click_button 'foo'
|
||||
|
||||
expect(page).to have_css('[data-testid="select_group_dropdown_item"]', text: 'foo2')
|
||||
expect(page).not_to have_css('[data-testid="select_group_dropdown_item"]', text: 'foo3')
|
||||
|
||||
click_button 'foo2'
|
||||
click_button 'Create subgroup'
|
||||
|
||||
expect(page).to have_current_path(group_path('foo2/bar'), ignore_query: true)
|
||||
expect(page).to have_selector('h1', text: 'bar')
|
||||
expect(page).to have_selector('.visibility-icon [data-testid="lock-icon"]')
|
||||
end
|
||||
end
|
||||
|
||||
describe 'real-time group url validation', :js do
|
||||
let_it_be(:subgroup) { create(:group, path: 'sub', parent: group) }
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
visit new_group_path(parent_id: group.id)
|
||||
click_link 'Create group'
|
||||
visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
|
||||
end
|
||||
|
||||
it 'shows a message if group url is available' do
|
||||
fill_in 'Group URL', with: group.path
|
||||
fill_in 'Subgroup slug', with: group.path
|
||||
wait_for_requests
|
||||
|
||||
expect(page).to have_content('Group path is available')
|
||||
end
|
||||
|
||||
it 'shows an error if group url is taken' do
|
||||
fill_in 'Group URL', with: subgroup.path
|
||||
fill_in 'Subgroup slug', with: subgroup.path
|
||||
wait_for_requests
|
||||
|
||||
expect(page).to have_content("Group path is unavailable. Path has been replaced with a suggested available path.")
|
||||
|
@ -308,7 +332,7 @@ RSpec.describe 'Group' do
|
|||
|
||||
sign_out(:user)
|
||||
sign_in(create(:user))
|
||||
visit new_group_path(parent_id: group.id)
|
||||
visit new_group_path(parent_id: group.id, anchor: 'create-group-pane')
|
||||
|
||||
expect(page).to have_title('Not Found')
|
||||
expect(page).to have_content('Page Not Found')
|
||||
|
|
|
@ -394,7 +394,7 @@ RSpec.describe 'Pipeline', :js do
|
|||
expect(page).to have_selector('button[aria-label="Cancel downstream pipeline"]')
|
||||
end
|
||||
|
||||
context 'when canceling' do
|
||||
context 'when canceling', :sidekiq_inline do
|
||||
before do
|
||||
find('button[aria-label="Cancel downstream pipeline"]').click
|
||||
wait_for_requests
|
||||
|
|
|
@ -132,10 +132,10 @@ RSpec.describe 'User page' do
|
|||
let_it_be(:followee) { create(:user) }
|
||||
let_it_be(:follower) { create(:user) }
|
||||
|
||||
it 'does not show link to follow' do
|
||||
it 'does not show button to follow' do
|
||||
subject
|
||||
|
||||
expect(page).not_to have_link(text: 'Follow', class: 'gl-button')
|
||||
expect(page).not_to have_button(text: 'Follow', class: 'gl-button')
|
||||
end
|
||||
|
||||
it 'shows 0 followers and 0 following' do
|
||||
|
@ -155,11 +155,11 @@ RSpec.describe 'User page' do
|
|||
expect(page).to have_content('1 following')
|
||||
end
|
||||
|
||||
it 'does show link to follow' do
|
||||
it 'does show button to follow' do
|
||||
sign_in(user)
|
||||
visit user_path(followee)
|
||||
|
||||
expect(page).to have_link(text: 'Follow', class: 'gl-button')
|
||||
expect(page).to have_button(text: 'Follow', class: 'gl-button')
|
||||
end
|
||||
|
||||
it 'does show link to unfollow' do
|
||||
|
@ -168,7 +168,7 @@ RSpec.describe 'User page' do
|
|||
|
||||
visit user_path(followee)
|
||||
|
||||
expect(page).to have_link(text: 'Unfollow', class: 'gl-button')
|
||||
expect(page).to have_button(text: 'Unfollow', class: 'gl-button')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,18 +1,23 @@
|
|||
import { nextTick } from 'vue';
|
||||
import Vue, { nextTick } from 'vue';
|
||||
import VueApollo from 'vue-apollo';
|
||||
import { merge } from 'lodash';
|
||||
import { GlAlert } from '@gitlab/ui';
|
||||
import { GlAlert, GlDropdown, GlTruncate, GlDropdownItem } from '@gitlab/ui';
|
||||
import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import GroupNameAndPath from '~/groups/components/group_name_and_path.vue';
|
||||
import { getGroupPathAvailability } from '~/rest_api';
|
||||
import { createAlert } from '~/flash';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
import searchGroupsWhereUserCanCreateSubgroups from '~/groups/queries/search_groups_where_user_can_create_subgroups.query.graphql';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/rest_api', () => ({
|
||||
getGroupPathAvailability: jest.fn(),
|
||||
}));
|
||||
|
||||
Vue.use(VueApollo);
|
||||
|
||||
describe('GroupNameAndPath', () => {
|
||||
let wrapper;
|
||||
|
||||
|
@ -20,6 +25,17 @@ describe('GroupNameAndPath', () => {
|
|||
const mockGroupUrl = 'my-awesome-group';
|
||||
const mockGroupUrlSuggested = 'my-awesome-group1';
|
||||
|
||||
const mockQueryResponse = jest.fn().mockResolvedValue({
|
||||
data: {
|
||||
currentUser: {
|
||||
id: '1',
|
||||
groups: {
|
||||
nodes: [{ id: '2', fullPath: '/path2' }],
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const defaultProvide = {
|
||||
basePath: 'http://gitlab.com/',
|
||||
fields: {
|
||||
|
@ -32,13 +48,20 @@ describe('GroupNameAndPath', () => {
|
|||
pattern: '[a-zA-Z0-9_\\.][a-zA-Z0-9_\\-\\.]*[a-zA-Z0-9_\\-]|[a-zA-Z0-9_]',
|
||||
},
|
||||
parentId: { name: 'group[parent_id]', id: 'group_parent_id', value: '1' },
|
||||
parentFullPath: { name: 'group[parent_full_path]', id: 'group_full_path', value: '/path1' },
|
||||
groupId: { name: 'group[id]', id: 'group_id', value: '' },
|
||||
},
|
||||
newSubgroup: false,
|
||||
mattermostEnabled: false,
|
||||
};
|
||||
|
||||
const createComponent = ({ provide = {} } = {}) => {
|
||||
wrapper = mountExtended(GroupNameAndPath, { provide: merge({}, defaultProvide, provide) });
|
||||
wrapper = mountExtended(GroupNameAndPath, {
|
||||
provide: merge({}, defaultProvide, provide),
|
||||
apolloProvider: createMockApollo([
|
||||
[searchGroupsWhereUserCanCreateSubgroups, mockQueryResponse],
|
||||
]),
|
||||
});
|
||||
};
|
||||
const createComponentEditGroup = ({ path = mockGroupUrl } = {}) => {
|
||||
createComponent({
|
||||
|
@ -46,8 +69,11 @@ describe('GroupNameAndPath', () => {
|
|||
});
|
||||
};
|
||||
|
||||
const findGroupNameField = () => wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.name.label);
|
||||
const findGroupUrlField = () => wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.path.label);
|
||||
const findGroupNameField = () => wrapper.findByLabelText('Group name');
|
||||
const findGroupUrlField = () => wrapper.findByLabelText('Group URL');
|
||||
const findSubgroupNameField = () => wrapper.findByLabelText('Subgroup name');
|
||||
const findSubgroupSlugField = () => wrapper.findByLabelText('Subgroup slug');
|
||||
const findSelectedGroup = () => wrapper.findComponent(GlTruncate);
|
||||
const findAlert = () => extendedWrapper(wrapper.findComponent(GlAlert));
|
||||
|
||||
const apiMockAvailablePath = () => {
|
||||
|
@ -79,6 +105,41 @@ describe('GroupNameAndPath', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when creating a new subgroup', () => {
|
||||
beforeEach(() => {
|
||||
createComponent({ provide: { newSubgroup: true } });
|
||||
});
|
||||
|
||||
it('updates `Subgroup slug` field as user types', async () => {
|
||||
await findSubgroupNameField().setValue(mockGroupName);
|
||||
|
||||
expect(findSubgroupSlugField().element.value).toBe(mockGroupUrl);
|
||||
});
|
||||
|
||||
describe('when user selects parent group', () => {
|
||||
it('updates `Subgroup URL` dropdown and calls API', async () => {
|
||||
expect(findSelectedGroup().text()).toContain('/path1');
|
||||
|
||||
await findSubgroupNameField().setValue(mockGroupName);
|
||||
|
||||
wrapper.findComponent(GlDropdown).vm.$emit('shown');
|
||||
await wrapper.vm.$apollo.queries.currentUserGroups.refetch();
|
||||
jest.runOnlyPendingTimers();
|
||||
await waitForPromises();
|
||||
|
||||
wrapper.findComponent(GlDropdownItem).vm.$emit('click');
|
||||
await nextTick();
|
||||
|
||||
expect(findSelectedGroup().text()).toContain('/path2');
|
||||
expect(getGroupPathAvailability).toHaveBeenCalled();
|
||||
|
||||
expect(wrapper.findByText(GroupNameAndPath.i18n.inputs.path.validFeedback).exists()).toBe(
|
||||
true,
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('when editing a group', () => {
|
||||
it('does not update `Group URL` field and does not call API', async () => {
|
||||
const groupUrl = 'foo-bar';
|
||||
|
@ -346,9 +407,7 @@ describe('GroupNameAndPath', () => {
|
|||
it('shows `Group ID` field', () => {
|
||||
createComponentEditGroup();
|
||||
|
||||
expect(
|
||||
wrapper.findByLabelText(GroupNameAndPath.i18n.inputs.groupId.label).element.value,
|
||||
).toBe('1');
|
||||
expect(wrapper.findByLabelText('Group ID').element.value).toBe('1');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import App from '~/pages/groups/new/components/app.vue';
|
||||
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
|
||||
|
||||
describe('App component', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = (propsData = {}) => {
|
||||
wrapper = shallowMount(App, { propsData });
|
||||
};
|
||||
|
||||
const findNewNamespacePage = () => wrapper.findComponent(NewNamespacePage);
|
||||
|
||||
const findCreateGroupPanel = () =>
|
||||
findNewNamespacePage()
|
||||
.props('panels')
|
||||
.find((panel) => panel.name === 'create-group-pane');
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it('creates correct component for group creation', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findNewNamespacePage().props('initialBreadcrumb')).toBe('New group');
|
||||
expect(findCreateGroupPanel().title).toBe('Create group');
|
||||
});
|
||||
|
||||
it('creates correct component for subgroup creation', () => {
|
||||
const props = { parentGroupName: 'parent', importExistingGroupPath: '/path' };
|
||||
|
||||
createComponent(props);
|
||||
|
||||
expect(findNewNamespacePage().props('initialBreadcrumb')).toBe('parent');
|
||||
expect(findCreateGroupPanel().title).toBe('Create subgroup');
|
||||
expect(findCreateGroupPanel().detailProps).toEqual(props);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,57 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlSprintf, GlLink } from '@gitlab/ui';
|
||||
import CreateGroupDescriptionDetails from '~/pages/groups/new/components/create_group_description_details.vue';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
describe('CreateGroupDescriptionDetails component', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = (propsData = {}) => {
|
||||
wrapper = shallowMount(CreateGroupDescriptionDetails, {
|
||||
propsData,
|
||||
stubs: { GlSprintf, GlLink },
|
||||
});
|
||||
};
|
||||
|
||||
const findLinkHref = (at) => wrapper.findAllComponents(GlLink).at(at);
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
it('creates correct component for group creation', () => {
|
||||
createComponent();
|
||||
|
||||
const groupsLink = findLinkHref(0);
|
||||
expect(groupsLink.attributes('href')).toBe(helpPagePath('user/group/index'));
|
||||
expect(groupsLink.text()).toBe('Groups');
|
||||
|
||||
const subgroupsLink = findLinkHref(1);
|
||||
expect(subgroupsLink.text()).toBe('subgroups');
|
||||
expect(subgroupsLink.attributes('href')).toBe(helpPagePath('user/group/subgroups/index'));
|
||||
|
||||
expect(wrapper.text()).toBe(
|
||||
'Groups allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. Groups can also be nested by creating subgroups.',
|
||||
);
|
||||
});
|
||||
|
||||
it('creates correct component for subgroup creation', () => {
|
||||
createComponent({ parentGroupName: 'parent', importExistingGroupPath: '/path' });
|
||||
|
||||
const groupsLink = findLinkHref(0);
|
||||
expect(groupsLink.attributes('href')).toBe(helpPagePath('user/group/index'));
|
||||
expect(groupsLink.text()).toBe('Groups');
|
||||
|
||||
const subgroupsLink = findLinkHref(1);
|
||||
expect(subgroupsLink.text()).toBe('subgroups');
|
||||
expect(subgroupsLink.attributes('href')).toBe(helpPagePath('user/group/subgroups/index'));
|
||||
|
||||
const importGroupLink = findLinkHref(2);
|
||||
expect(importGroupLink.text()).toBe('import an existing group');
|
||||
expect(importGroupLink.attributes('href')).toBe('/path');
|
||||
|
||||
expect(wrapper.text()).toBe(
|
||||
'Groups and subgroups allow you to manage and collaborate across multiple projects. Members of a group have access to all of its projects. You can also import an existing group.',
|
||||
);
|
||||
});
|
||||
});
|
|
@ -6,6 +6,7 @@ import UserPopover from '~/vue_shared/components/user_popover/user_popover.vue';
|
|||
import axios from '~/lib/utils/axios_utils';
|
||||
import createFlash from '~/flash';
|
||||
import { followUser, unfollowUser } from '~/api/user_api';
|
||||
import { mockTracking } from 'helpers/tracking_helper';
|
||||
|
||||
jest.mock('~/flash');
|
||||
jest.mock('~/api/user_api', () => ({
|
||||
|
@ -51,6 +52,18 @@ describe('User Popover Component', () => {
|
|||
const findUserLocalTime = () => wrapper.findByTestId('user-popover-local-time');
|
||||
const findToggleFollowButton = () => wrapper.findByTestId('toggle-follow-button');
|
||||
|
||||
const itTracksToggleFollowButtonClick = (expectedLabel) => {
|
||||
it('tracks click', async () => {
|
||||
const trackingSpy = mockTracking(undefined, wrapper.element, jest.spyOn);
|
||||
|
||||
await findToggleFollowButton().trigger('click');
|
||||
|
||||
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_button', {
|
||||
label: expectedLabel,
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const createWrapper = (props = {}) => {
|
||||
wrapper = mountExtended(UserPopover, {
|
||||
propsData: {
|
||||
|
@ -341,6 +354,8 @@ describe('User Popover Component', () => {
|
|||
expect(wrapper.emitted().unfollow).toBeFalsy();
|
||||
});
|
||||
|
||||
itTracksToggleFollowButtonClick('follow_from_user_popover');
|
||||
|
||||
describe('when an error occurs', () => {
|
||||
beforeEach(() => {
|
||||
followUser.mockRejectedValue({});
|
||||
|
@ -388,6 +403,8 @@ describe('User Popover Component', () => {
|
|||
expect(wrapper.emitted().unfollow.length).toBe(1);
|
||||
});
|
||||
|
||||
itTracksToggleFollowButtonClick('unfollow_from_user_popover');
|
||||
|
||||
describe('when an error occurs', () => {
|
||||
beforeEach(async () => {
|
||||
unfollowUser.mockRejectedValue({});
|
||||
|
|
|
@ -452,9 +452,31 @@ RSpec.describe GroupsHelper do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#group_name_and_path_app_data' do
|
||||
let_it_be(:group) { build(:group, name: 'My awesome group', path: 'my-awesome-group') }
|
||||
describe '#subgroup_creation_data' do
|
||||
let_it_be(:name) { 'parent group' }
|
||||
let_it_be(:group) { build(:group, name: name) }
|
||||
let_it_be(:subgroup) { build(:group, parent: group) }
|
||||
|
||||
context 'when group has a parent' do
|
||||
it 'returns expected hash' do
|
||||
expect(subgroup_creation_data(subgroup)).to eq({
|
||||
import_existing_group_path: '/groups/new#import-group-pane',
|
||||
parent_group_name: name
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
context 'when group does not have a parent' do
|
||||
it 'returns expected hash' do
|
||||
expect(subgroup_creation_data(group)).to eq({
|
||||
import_existing_group_path: '/groups/new#import-group-pane',
|
||||
parent_group_name: nil
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#group_name_and_path_app_data' do
|
||||
let_it_be(:root_url) { 'https://gitlab.com/' }
|
||||
|
||||
before do
|
||||
|
@ -464,17 +486,10 @@ RSpec.describe GroupsHelper do
|
|||
|
||||
context 'when group has a parent' do
|
||||
it 'returns expected hash' do
|
||||
expect(group_name_and_path_app_data(subgroup)).to match(
|
||||
{ base_path: 'https://gitlab.com/my-awesome-group', mattermost_enabled: 'true' }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when group does not have a parent' do
|
||||
it 'returns expected hash' do
|
||||
expect(group_name_and_path_app_data(group)).to match(
|
||||
{ base_path: root_url, mattermost_enabled: 'true' }
|
||||
)
|
||||
expect(group_name_and_path_app_data).to match({
|
||||
base_path: 'https://gitlab.com/',
|
||||
mattermost_enabled: 'true'
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -493,7 +508,7 @@ RSpec.describe GroupsHelper do
|
|||
it 'returns expected hash' do
|
||||
expect(helper.subgroups_and_projects_list_app_data(group)).to match({
|
||||
show_schema_markup: 'true',
|
||||
new_subgroup_path: including("groups/new?parent_id=#{group.id}"),
|
||||
new_subgroup_path: including("groups/new?parent_id=#{group.id}#create-group-pane"),
|
||||
new_project_path: including("/projects/new?namespace_id=#{group.id}"),
|
||||
new_subgroup_illustration: including('illustrations/subgroup-create-new-sm'),
|
||||
new_project_illustration: including('illustrations/project-create-new-sm'),
|
||||
|
|
|
@ -173,7 +173,7 @@ RSpec.describe Nav::NewDropdownHelper do
|
|||
menu_item: ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
id: 'new_subgroup',
|
||||
title: 'New subgroup',
|
||||
href: "/groups/new?parent_id=#{group.id}",
|
||||
href: "/groups/new?parent_id=#{group.id}#create-group-pane",
|
||||
data: { track_action: 'click_link_new_subgroup', track_label: 'plus_menu_dropdown' }
|
||||
)
|
||||
)
|
||||
|
|
|
@ -11,68 +11,4 @@ RSpec.describe Emails::AdminNotification do
|
|||
expect(Notify).to be_respond_to(email_method)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'user_auto_banned_email' do
|
||||
let_it_be(:admin) { create(:user) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
let(:max_project_downloads) { 5 }
|
||||
let(:time_period) { 600 }
|
||||
let(:group) { nil }
|
||||
|
||||
subject do
|
||||
Notify.user_auto_banned_email(
|
||||
admin.id, user.id,
|
||||
max_project_downloads: max_project_downloads,
|
||||
within_seconds: time_period,
|
||||
group: group
|
||||
)
|
||||
end
|
||||
|
||||
it_behaves_like 'an email sent from GitLab'
|
||||
it_behaves_like 'it should not have Gmail Actions links'
|
||||
it_behaves_like 'a user cannot unsubscribe through footer link'
|
||||
it_behaves_like 'appearance header and footer enabled'
|
||||
it_behaves_like 'appearance header and footer not enabled'
|
||||
|
||||
it 'is sent to the administrator' do
|
||||
is_expected.to deliver_to admin.email
|
||||
end
|
||||
|
||||
it 'has the correct subject' do
|
||||
is_expected.to have_subject "We've detected unusual activity"
|
||||
end
|
||||
|
||||
it 'includes the name of the user' do
|
||||
is_expected.to have_body_text user.name
|
||||
end
|
||||
|
||||
it 'includes the scope of the ban' do
|
||||
is_expected.to have_body_text "banned from your GitLab instance"
|
||||
end
|
||||
|
||||
it 'includes the reason' do
|
||||
is_expected.to have_body_text "due to them downloading more than 5 project repositories within 10 minutes"
|
||||
end
|
||||
|
||||
it 'includes a link to unban the user' do
|
||||
is_expected.to have_body_text admin_users_url(filter: 'banned')
|
||||
end
|
||||
|
||||
it 'includes a link to change the settings' do
|
||||
is_expected.to have_body_text network_admin_application_settings_url(anchor: 'js-ip-limits-settings')
|
||||
end
|
||||
|
||||
it 'includes the email reason' do
|
||||
is_expected.to have_body_text %r{You're receiving this email because of your account on <a .*>localhost<\/a>}
|
||||
end
|
||||
|
||||
context 'when scoped to a group' do
|
||||
let(:group) { create(:group) }
|
||||
|
||||
it 'includes the scope of the ban' do
|
||||
is_expected.to have_body_text "banned from your group (#{group.name})"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -40,7 +40,7 @@ RSpec.describe 'PipelineCancel' do
|
|||
expect(build).not_to be_canceled
|
||||
end
|
||||
|
||||
it "cancels all cancelable builds from a pipeline" do
|
||||
it 'cancels all cancelable builds from a pipeline', :sidekiq_inline do
|
||||
build = create(:ci_build, :running, pipeline: pipeline)
|
||||
|
||||
post_graphql_mutation(mutation, current_user: user)
|
||||
|
|
|
@ -162,12 +162,29 @@ RSpec.describe API::IssueLinks do
|
|||
end
|
||||
|
||||
context 'when unauthenticated' do
|
||||
it 'returns 401' do
|
||||
issue_link = create(:issue_link)
|
||||
context 'when accessing an issue of a private project' do
|
||||
it 'returns 401' do
|
||||
issue_link = create(:issue_link)
|
||||
|
||||
perform_request(issue_link.id)
|
||||
perform_request(issue_link.id)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
|
||||
# This isn't ideal, see https://gitlab.com/gitlab-org/gitlab/-/issues/364077
|
||||
context 'when accessing an issue of a public project' do
|
||||
let(:project) { create(:project, :public) }
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
let(:public_issue) { create(:issue, project: project) }
|
||||
|
||||
it 'returns 401' do
|
||||
issue_link = create(:issue_link, source: issue, target: public_issue)
|
||||
|
||||
perform_request(issue_link.id)
|
||||
|
||||
expect(response).to have_gitlab_http_status(:unauthorized)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -40,7 +40,10 @@ RSpec.describe 'layouts/header/_new_dropdown' do
|
|||
it 'has a "New subgroup" link' do
|
||||
render
|
||||
|
||||
expect(rendered).to have_link('New subgroup', href: new_group_path(parent_id: group.id))
|
||||
expect(rendered).to have_link(
|
||||
'New subgroup',
|
||||
href: new_group_path(parent_id: group.id, anchor: 'create-group-pane')
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Ci::Runners::ReconcileExistingRunnerVersionsCronWorker do
|
||||
subject(:worker) { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
context 'when scheduled by cronjob' do
|
||||
it 'reschedules itself' do
|
||||
expect(described_class).to(receive(:perform_in).with(a_value_between(0, 12.hours.in_seconds), false))
|
||||
expect(::Ci::Runners::ReconcileExistingRunnerVersionsService).not_to receive(:new)
|
||||
|
||||
worker.perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'when self-scheduled' do
|
||||
include_examples 'an idempotent worker' do
|
||||
subject(:perform) { perform_multiple(false, worker: worker) }
|
||||
|
||||
it 'executes the service' do
|
||||
expect_next_instance_of(Ci::Runners::ReconcileExistingRunnerVersionsService) do |service|
|
||||
expect(service).to receive(:execute).and_return({})
|
||||
end.exactly(worker_exec_times)
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
|
||||
it 'logs the service result' do
|
||||
expect_next_instance_of(Ci::Runners::ReconcileExistingRunnerVersionsService) do |service|
|
||||
expect(service).to receive(:execute).and_return({ some_job_result_key: 'some_value' })
|
||||
end
|
||||
|
||||
worker.perform(false)
|
||||
|
||||
expect(worker.logging_extras).to eq({
|
||||
'extra.ci_runners_reconcile_existing_runner_versions_cron_worker.some_job_result_key' => 'some_value'
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -19,6 +19,10 @@ mapping:
|
|||
- source: ee/lib/(.+)\.rb
|
||||
test: ee/spec/lib/%s_spec.rb
|
||||
|
||||
# See https://gitlab.com/gitlab-org/gitlab/-/issues/368628
|
||||
- source: lib/gitlab/usage_data_counters/(.+)\.rb
|
||||
test: spec/lib/gitlab/usage_data_spec.rb
|
||||
|
||||
# FOSS lib & tooling should map to respective spec
|
||||
- source: (tooling/)?lib/(.+)\.rb
|
||||
test: spec/%slib/%s_spec.rb
|
||||
|
|
502
yarn.lock
502
yarn.lock
|
@ -1607,11 +1607,6 @@
|
|||
"@sentry/types" "5.30.0"
|
||||
tslib "^1.9.3"
|
||||
|
||||
"@sindresorhus/is@^0.14.0":
|
||||
version "0.14.0"
|
||||
resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea"
|
||||
integrity sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==
|
||||
|
||||
"@sinonjs/commons@^1.7.0":
|
||||
version "1.8.1"
|
||||
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.1.tgz#e7df00f98a203324f6dc7cc606cad9d4a8ab2217"
|
||||
|
@ -1631,13 +1626,6 @@
|
|||
resolved "https://registry.yarnpkg.com/@sourcegraph/code-host-integration/-/code-host-integration-0.0.60.tgz#2043877fabb7eb986fcb61b67ee480afbb29f4f0"
|
||||
integrity sha512-T+MvM8SUF7daA279hyQgwmva3J5LvPqwgQ/mWwxdVshehOQIPLUd310I0c6x6nZ0F/x4UjDWgRWzAqy6NLwV1w==
|
||||
|
||||
"@szmarczak/http-timer@^1.1.2":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421"
|
||||
integrity sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==
|
||||
dependencies:
|
||||
defer-to-connect "^1.0.1"
|
||||
|
||||
"@testing-library/dom@^7.16.2":
|
||||
version "7.24.5"
|
||||
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-7.24.5.tgz#862124eec8c37ad184716379f09742476b23815d"
|
||||
|
@ -2628,13 +2616,6 @@ ajv@^8.0.0, ajv@^8.0.1, ajv@^8.10.0, ajv@^8.8.0:
|
|||
require-from-string "^2.0.2"
|
||||
uri-js "^4.2.2"
|
||||
|
||||
ansi-align@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.0.tgz#b536b371cf687caaef236c18d3e21fe3797467cb"
|
||||
integrity sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==
|
||||
dependencies:
|
||||
string-width "^3.0.0"
|
||||
|
||||
ansi-colors@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348"
|
||||
|
@ -2653,9 +2634,9 @@ ansi-html-community@^0.0.8:
|
|||
integrity sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==
|
||||
|
||||
ansi-regex@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
|
||||
integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed"
|
||||
integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==
|
||||
|
||||
ansi-regex@^5.0.0, ansi-regex@^5.0.1:
|
||||
version "5.0.1"
|
||||
|
@ -3131,20 +3112,6 @@ bootstrap@4.5.3, "bootstrap@>=4.5.3 <5.0.0":
|
|||
resolved "https://registry.yarnpkg.com/bootstrap/-/bootstrap-4.5.3.tgz#c6a72b355aaf323920be800246a6e4ef30997fe6"
|
||||
integrity sha512-o9ppKQioXGqhw8Z7mah6KdTYpNQY//tipnkxppWhPbiSWdD+1raYsnhwEZjkTHYbGee4cVQ0Rx65EhOY/HNLcQ==
|
||||
|
||||
boxen@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/boxen/-/boxen-4.2.0.tgz#e411b62357d6d6d36587c8ac3d5d974daa070e64"
|
||||
integrity sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==
|
||||
dependencies:
|
||||
ansi-align "^3.0.0"
|
||||
camelcase "^5.3.1"
|
||||
chalk "^3.0.0"
|
||||
cli-boxes "^2.2.0"
|
||||
string-width "^4.1.0"
|
||||
term-size "^2.1.0"
|
||||
type-fest "^0.8.1"
|
||||
widest-line "^3.1.0"
|
||||
|
||||
brace-expansion@^1.1.7:
|
||||
version "1.1.11"
|
||||
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
|
||||
|
@ -3385,19 +3352,6 @@ cache-loader@^4.1.0:
|
|||
neo-async "^2.6.1"
|
||||
schema-utils "^2.0.0"
|
||||
|
||||
cacheable-request@^6.0.0:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/cacheable-request/-/cacheable-request-6.1.0.tgz#20ffb8bd162ba4be11e9567d823db651052ca912"
|
||||
integrity sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==
|
||||
dependencies:
|
||||
clone-response "^1.0.2"
|
||||
get-stream "^5.1.0"
|
||||
http-cache-semantics "^4.0.0"
|
||||
keyv "^3.0.0"
|
||||
lowercase-keys "^2.0.0"
|
||||
normalize-url "^4.1.0"
|
||||
responselike "^1.0.2"
|
||||
|
||||
call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
|
||||
|
@ -3473,14 +3427,6 @@ chalk@^2.0.0, chalk@^2.1.0, chalk@^2.4.1, chalk@^2.4.2:
|
|||
escape-string-regexp "^1.0.5"
|
||||
supports-color "^5.3.0"
|
||||
|
||||
chalk@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4"
|
||||
integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==
|
||||
dependencies:
|
||||
ansi-styles "^4.1.0"
|
||||
supports-color "^7.1.0"
|
||||
|
||||
chalk@^4.0.0, chalk@^4.1.0, chalk@^4.1.2:
|
||||
version "4.1.2"
|
||||
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
|
||||
|
@ -3528,7 +3474,7 @@ cheerio@^1.0.0-rc.9:
|
|||
parse5-htmlparser2-tree-adapter "^6.0.1"
|
||||
tslib "^2.2.0"
|
||||
|
||||
"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.2.2, chokidar@^3.4.1, chokidar@^3.5.3:
|
||||
"chokidar@>=3.0.0 <4.0.0", chokidar@^2.1.8, chokidar@^3.4.1, chokidar@^3.5.2, chokidar@^3.5.3:
|
||||
version "3.5.3"
|
||||
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
|
||||
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
|
||||
|
@ -3600,11 +3546,6 @@ clean-stack@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
|
||||
integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==
|
||||
|
||||
cli-boxes@^2.2.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.0.tgz#538ecae8f9c6ca508e3c3c95b453fe93cb4c168d"
|
||||
integrity sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==
|
||||
|
||||
clipboard@^2.0.0, clipboard@^2.0.8:
|
||||
version "2.0.8"
|
||||
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.8.tgz#ffc6c103dd2967a83005f3f61976aa4655a4cdba"
|
||||
|
@ -3639,13 +3580,6 @@ clone-regexp@^2.1.0:
|
|||
dependencies:
|
||||
is-regexp "^2.0.0"
|
||||
|
||||
clone-response@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b"
|
||||
integrity sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=
|
||||
dependencies:
|
||||
mimic-response "^1.0.0"
|
||||
|
||||
co@^4.6.0:
|
||||
version "4.6.0"
|
||||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||
|
@ -3837,18 +3771,6 @@ config-chain@^1.1.12:
|
|||
ini "^1.3.4"
|
||||
proto-list "~1.2.1"
|
||||
|
||||
configstore@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/configstore/-/configstore-5.0.1.tgz#d365021b5df4b98cdd187d6a3b0e3f6a7cc5ed96"
|
||||
integrity sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==
|
||||
dependencies:
|
||||
dot-prop "^5.2.0"
|
||||
graceful-fs "^4.1.2"
|
||||
make-dir "^3.0.0"
|
||||
unique-string "^2.0.0"
|
||||
write-file-atomic "^3.0.0"
|
||||
xdg-basedir "^4.0.0"
|
||||
|
||||
confusing-browser-globals@^1.0.10:
|
||||
version "1.0.10"
|
||||
resolved "https://registry.yarnpkg.com/confusing-browser-globals/-/confusing-browser-globals-1.0.10.tgz#30d1e7f3d1b882b25ec4933d1d1adac353d20a59"
|
||||
|
@ -4098,11 +4020,6 @@ crypto-browserify@^3.11.0:
|
|||
randombytes "^2.0.0"
|
||||
randomfill "^1.0.3"
|
||||
|
||||
crypto-random-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-2.0.0.tgz#ef2a7a966ec11083388369baa02ebead229b30d5"
|
||||
integrity sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==
|
||||
|
||||
css-color-names@0.0.4:
|
||||
version "0.0.4"
|
||||
resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0"
|
||||
|
@ -4161,9 +4078,9 @@ css-values@^0.1.0:
|
|||
postcss-value-parser "^3.3.0"
|
||||
|
||||
css-what@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.0.0.tgz#f0bf4f8bac07582722346ab243f6a35b512cfc47"
|
||||
integrity sha512-qxyKHQvgKwzwDWC/rGbT821eJalfupxYW2qbSJSAtdSTimsr/MlaGONoNLllaUPZWf8QnbcKM/kPVYUQuEKAFA==
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/css-what/-/css-what-5.1.0.tgz#3f7b707aadf633baf62c2ceb8579b545bb40f7fe"
|
||||
integrity sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==
|
||||
|
||||
css@^2.1.0:
|
||||
version "2.2.4"
|
||||
|
@ -4773,7 +4690,7 @@ debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9:
|
|||
dependencies:
|
||||
ms "2.0.0"
|
||||
|
||||
debug@^3.2.6, debug@^3.2.7:
|
||||
debug@^3.2.7:
|
||||
version "3.2.7"
|
||||
resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a"
|
||||
integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==
|
||||
|
@ -4822,13 +4739,6 @@ decode-uri-component@^0.2.0:
|
|||
resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545"
|
||||
integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=
|
||||
|
||||
decompress-response@^3.3.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3"
|
||||
integrity sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=
|
||||
dependencies:
|
||||
mimic-response "^1.0.0"
|
||||
|
||||
deep-equal@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
|
||||
|
@ -4856,11 +4766,6 @@ default-gateway@^6.0.3:
|
|||
dependencies:
|
||||
execa "^5.0.0"
|
||||
|
||||
defer-to-connect@^1.0.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/defer-to-connect/-/defer-to-connect-1.1.3.tgz#331ae050c08dcf789f8c83a7b81f0ed94f4ac591"
|
||||
integrity sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==
|
||||
|
||||
define-lazy-prop@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
|
||||
|
@ -5090,27 +4995,15 @@ domutils@^2.5.2, domutils@^2.6.0:
|
|||
domelementtype "^2.2.0"
|
||||
domhandler "^4.2.0"
|
||||
|
||||
dot-prop@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.2.0.tgz#c34ecc29556dc45f1f4c22697b6f4904e0cc4fcb"
|
||||
integrity sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==
|
||||
dependencies:
|
||||
is-obj "^2.0.0"
|
||||
|
||||
dropzone@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.yarnpkg.com/dropzone/-/dropzone-4.2.0.tgz#fbe7acbb9918e0706489072ef663effeef8a79f3"
|
||||
integrity sha1-++esu5kY4HBkiQcu9mPv/u+KefM=
|
||||
|
||||
dset@^3.1.0:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.1.tgz#07de5af7a8d03eab337ad1a8ba77fe17bba61a8c"
|
||||
integrity sha512-hYf+jZNNqJBD2GiMYb+5mqOIX4R4RRHXU3qWMWYN+rqcR2/YpRL2bUHr8C8fU+5DNvqYjJ8YvMGSLuVPWU1cNg==
|
||||
|
||||
duplexer3@^0.1.4:
|
||||
version "0.1.4"
|
||||
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"
|
||||
integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/dset/-/dset-3.1.2.tgz#89c436ca6450398396dc6538ea00abc0c54cd45a"
|
||||
integrity sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==
|
||||
|
||||
duplexer@^0.1.2:
|
||||
version "0.1.2"
|
||||
|
@ -5191,11 +5084,6 @@ emoji-regex@^10.0.0:
|
|||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-10.0.0.tgz#96559e19f82231b436403e059571241d627c42b8"
|
||||
integrity sha512-KmJa8l6uHi1HrBI34udwlzZY1jOEuID/ft4d8BSSEdRyap7PwBEt910453PJa5MuGvxkLqlt4Uvhu7tttFHViw==
|
||||
|
||||
emoji-regex@^7.0.1:
|
||||
version "7.0.3"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37"
|
||||
|
@ -5327,11 +5215,6 @@ escalade@^3.1.1:
|
|||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
|
||||
escape-goat@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675"
|
||||
integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==
|
||||
|
||||
escape-html@~1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988"
|
||||
|
@ -6254,14 +6137,14 @@ get-stdin@~9.0.0:
|
|||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-9.0.0.tgz#3983ff82e03d56f1b2ea0d3e60325f39d703a575"
|
||||
integrity sha512-dVKBjfWisLAicarI2Sf+JuBE/DghV4UzNAVe9yhEJuzeREd3JhOTE9cUaJTeSa77fsbQUK3pcOpJfM59+VKZaA==
|
||||
|
||||
get-stream@^4.0.0, get-stream@^4.1.0:
|
||||
get-stream@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5"
|
||||
integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==
|
||||
dependencies:
|
||||
pump "^3.0.0"
|
||||
|
||||
get-stream@^5.0.0, get-stream@^5.1.0:
|
||||
get-stream@^5.0.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
|
||||
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
|
||||
|
@ -6332,13 +6215,6 @@ glob-parent@^5.1.1, glob-parent@^5.1.2, glob-parent@~5.1.2:
|
|||
once "^1.3.0"
|
||||
path-is-absolute "^1.0.0"
|
||||
|
||||
global-dirs@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-2.0.1.tgz#acdf3bb6685bcd55cb35e8a052266569e9469201"
|
||||
integrity sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==
|
||||
dependencies:
|
||||
ini "^1.3.5"
|
||||
|
||||
global-modules@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
|
||||
|
@ -6399,23 +6275,6 @@ good-listener@^1.2.2:
|
|||
dependencies:
|
||||
delegate "^3.1.2"
|
||||
|
||||
got@^9.6.0:
|
||||
version "9.6.0"
|
||||
resolved "https://registry.yarnpkg.com/got/-/got-9.6.0.tgz#edf45e7d67f99545705de1f7bbeeeb121765ed85"
|
||||
integrity sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==
|
||||
dependencies:
|
||||
"@sindresorhus/is" "^0.14.0"
|
||||
"@szmarczak/http-timer" "^1.1.2"
|
||||
cacheable-request "^6.0.0"
|
||||
decompress-response "^3.3.0"
|
||||
duplexer3 "^0.1.4"
|
||||
get-stream "^4.1.0"
|
||||
lowercase-keys "^1.0.1"
|
||||
mimic-response "^1.0.1"
|
||||
p-cancelable "^1.0.0"
|
||||
to-readable-stream "^1.0.0"
|
||||
url-parse-lax "^3.0.0"
|
||||
|
||||
graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.4, graceful-fs@^4.2.6:
|
||||
version "4.2.10"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||
|
@ -6579,11 +6438,6 @@ has-values@^1.0.0:
|
|||
is-number "^3.0.0"
|
||||
kind-of "^4.0.0"
|
||||
|
||||
has-yarn@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/has-yarn/-/has-yarn-2.1.0.tgz#137e11354a7b5bf11aa5cb649cf0c6f3ff2b2e77"
|
||||
integrity sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==
|
||||
|
||||
has@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
|
||||
|
@ -6725,9 +6579,9 @@ hoist-non-react-statics@^3.3.2:
|
|||
react-is "^16.7.0"
|
||||
|
||||
hosted-git-info@^2.1.4:
|
||||
version "2.8.8"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.8.tgz#7539bd4bc1e0e0a895815a2e0262420b12858488"
|
||||
integrity sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==
|
||||
version "2.8.9"
|
||||
resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9"
|
||||
integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==
|
||||
|
||||
hosted-git-info@^4.0.1:
|
||||
version "4.1.0"
|
||||
|
@ -6783,11 +6637,6 @@ htmlparser2@^6.1.0:
|
|||
domutils "^2.5.2"
|
||||
entities "^2.0.0"
|
||||
|
||||
http-cache-semantics@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz#49e91c5cbf36c9b94bcfcd71c23d5249ec74e390"
|
||||
integrity sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==
|
||||
|
||||
http-deceiver@^1.2.7:
|
||||
version "1.2.7"
|
||||
resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87"
|
||||
|
@ -6924,10 +6773,10 @@ immediate@~3.0.5:
|
|||
resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b"
|
||||
integrity sha1-nbHb0Pr43m++D13V5Wu2BigN5ps=
|
||||
|
||||
immer@^7.0.7:
|
||||
version "7.0.7"
|
||||
resolved "https://registry.yarnpkg.com/immer/-/immer-7.0.7.tgz#9dfe713d49bf871cc59aedfce59b1992fa37a977"
|
||||
integrity sha512-Q8yYwVADJXrNfp1ZUAh4XDHkcoE3wpdpb4mC5abDSajs2EbW8+cGdPyAnglMyLnm7EF6ojD2xBFX7L5i4TIytw==
|
||||
immer@^9.0.15:
|
||||
version "9.0.15"
|
||||
resolved "https://registry.yarnpkg.com/immer/-/immer-9.0.15.tgz#0b9169e5b1d22137aba7d43f8a81a495dd1b62dc"
|
||||
integrity sha512-2eB/sswms9AEUSkOm4SbV5Y7Vmt/bKRwByd52jfLkW4OLYeaTP3EEiJ9agqU0O/tq6Dk62Zfj+TJSqfm1rLVGQ==
|
||||
|
||||
immutable@^4.0.0:
|
||||
version "4.1.0"
|
||||
|
@ -6942,11 +6791,6 @@ import-fresh@^3.0.0, import-fresh@^3.2.1:
|
|||
parent-module "^1.0.0"
|
||||
resolve-from "^4.0.0"
|
||||
|
||||
import-lazy@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43"
|
||||
integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=
|
||||
|
||||
import-lazy@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153"
|
||||
|
@ -7003,7 +6847,7 @@ inherits@2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de"
|
||||
integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=
|
||||
|
||||
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
|
||||
ini@^1.3.4, ini@^1.3.5:
|
||||
version "1.3.8"
|
||||
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c"
|
||||
integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==
|
||||
|
@ -7193,11 +7037,6 @@ is-extglob@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||
|
||||
is-fullwidth-code-point@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||
integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=
|
||||
|
||||
is-fullwidth-code-point@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
|
||||
|
@ -7215,24 +7054,11 @@ is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
|
|||
dependencies:
|
||||
is-extglob "^2.1.1"
|
||||
|
||||
is-installed-globally@^0.3.1:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.3.2.tgz#fd3efa79ee670d1187233182d5b0a1dd00313141"
|
||||
integrity sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==
|
||||
dependencies:
|
||||
global-dirs "^2.0.1"
|
||||
is-path-inside "^3.0.1"
|
||||
|
||||
is-negative-zero@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
|
||||
integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
|
||||
|
||||
is-npm@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-4.0.0.tgz#c90dd8380696df87a7a6d823c20d0b12bbe3c84d"
|
||||
integrity sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==
|
||||
|
||||
is-number-object@^1.0.4:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc"
|
||||
|
@ -7252,16 +7078,6 @@ is-number@^7.0.0:
|
|||
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
|
||||
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
|
||||
|
||||
is-obj@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
|
||||
integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
|
||||
|
||||
is-path-inside@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
|
||||
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==
|
||||
|
||||
is-plain-obj@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e"
|
||||
|
@ -7372,11 +7188,6 @@ is-wsl@^2.1.1, is-wsl@^2.2.0:
|
|||
dependencies:
|
||||
is-docker "^2.0.0"
|
||||
|
||||
is-yarn-global@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/is-yarn-global/-/is-yarn-global-0.3.0.tgz#d502d3382590ea3004893746754c89139973e232"
|
||||
integrity sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==
|
||||
|
||||
isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11"
|
||||
|
@ -8011,11 +7822,6 @@ jsesc@~0.5.0:
|
|||
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
|
||||
integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=
|
||||
|
||||
json-buffer@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.0.tgz#5b1f397afc75d677bde8bcfc0e47e1f9a3d9a898"
|
||||
integrity sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=
|
||||
|
||||
json-parse-better-errors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||
|
@ -8036,10 +7842,10 @@ json-schema-traverse@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
|
||||
integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
|
||||
|
||||
json-schema@0.2.3:
|
||||
version "0.2.3"
|
||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
|
||||
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
|
||||
json-schema@0.4.0:
|
||||
version "0.4.0"
|
||||
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.4.0.tgz#f7de4cf6efab838ebaeb3236474cbba5a1930ab5"
|
||||
integrity sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==
|
||||
|
||||
json-stable-stringify-without-jsonify@^1.0.1:
|
||||
version "1.0.1"
|
||||
|
@ -8076,13 +7882,13 @@ jsonfile@^4.0.0:
|
|||
graceful-fs "^4.1.6"
|
||||
|
||||
jsprim@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
|
||||
version "1.4.2"
|
||||
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.2.tgz#712c65533a15c878ba59e9ed5f0e26d5b77c5feb"
|
||||
integrity sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==
|
||||
dependencies:
|
||||
assert-plus "1.0.0"
|
||||
extsprintf "1.3.0"
|
||||
json-schema "0.2.3"
|
||||
json-schema "0.4.0"
|
||||
verror "1.10.0"
|
||||
|
||||
jszip-utils@^0.0.2:
|
||||
|
@ -8108,13 +7914,6 @@ katex@^0.13.2:
|
|||
dependencies:
|
||||
commander "^6.0.0"
|
||||
|
||||
keyv@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.1.0.tgz#ecc228486f69991e49e9476485a5be1e8fc5c4d9"
|
||||
integrity sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==
|
||||
dependencies:
|
||||
json-buffer "3.0.0"
|
||||
|
||||
khroma@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/khroma/-/khroma-2.0.0.tgz#7577de98aed9f36c7a474c4d453d94c0d6c6588b"
|
||||
|
@ -8173,13 +7972,6 @@ known-css-properties@^0.25.0:
|
|||
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776"
|
||||
integrity sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==
|
||||
|
||||
latest-version@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-5.1.0.tgz#119dfe908fe38d15dfa43ecd13fa12ec8832face"
|
||||
integrity sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==
|
||||
dependencies:
|
||||
package-json "^6.3.0"
|
||||
|
||||
leven@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
|
||||
|
@ -8428,16 +8220,6 @@ loose-envify@^1.4.0:
|
|||
dependencies:
|
||||
js-tokens "^3.0.0 || ^4.0.0"
|
||||
|
||||
lowercase-keys@^1.0.0, lowercase-keys@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f"
|
||||
integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==
|
||||
|
||||
lowercase-keys@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-2.0.0.tgz#2603e78b7b4b0006cbca2fbcc8a3202558ac9479"
|
||||
integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==
|
||||
|
||||
lowlight@^1.20.0:
|
||||
version "1.20.0"
|
||||
resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888"
|
||||
|
@ -9174,11 +8956,6 @@ mimic-fn@^2.1.0:
|
|||
resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b"
|
||||
integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==
|
||||
|
||||
mimic-response@^1.0.0, mimic-response@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
|
||||
|
||||
min-document@^2.19.0:
|
||||
version "2.19.0"
|
||||
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
|
||||
|
@ -9520,9 +9297,9 @@ node-modules-regexp@^1.0.0:
|
|||
integrity sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=
|
||||
|
||||
node-notifier@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.0.tgz#a7eee2d51da6d0f7ff5094bc7108c911240c1620"
|
||||
integrity sha512-46z7DUmcjoYdaWyXouuFNNfUo6eFa94t23c53c+lG/9Cvauk4a98rAUp9672X5dxGdQmLpPzTxzu8f/OeEPaFA==
|
||||
version "8.0.2"
|
||||
resolved "https://registry.yarnpkg.com/node-notifier/-/node-notifier-8.0.2.tgz#f3167a38ef0d2c8a866a83e318c1ba0efeb702c5"
|
||||
integrity sha512-oJP/9NAdd9+x2Q+rfphB2RJCHjod70RcRLjosiPMMu5gjIfwVnOUGq2nbTjTUbmy0DJ/tFIVT30+Qe3nzl4TJg==
|
||||
dependencies:
|
||||
growly "^1.3.0"
|
||||
is-wsl "^2.2.0"
|
||||
|
@ -9536,21 +9313,21 @@ node-releases@^2.0.3:
|
|||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.5.tgz#280ed5bc3eba0d96ce44897d8aee478bfb3d9666"
|
||||
integrity sha512-U9h1NLROZTq9uE1SNffn6WuPDg8icmi3ns4rEl/oTfIle4iLjTliCzgTsbaIFMq/Xn078/lfY/BL0GWZ+psK4Q==
|
||||
|
||||
nodemon@^2.0.4:
|
||||
version "2.0.4"
|
||||
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.4.tgz#55b09319eb488d6394aa9818148c0c2d1c04c416"
|
||||
integrity sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==
|
||||
nodemon@^2.0.19:
|
||||
version "2.0.19"
|
||||
resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-2.0.19.tgz#cac175f74b9cb8b57e770d47841995eebe4488bd"
|
||||
integrity sha512-4pv1f2bMDj0Eeg/MhGqxrtveeQ5/G/UVe9iO6uTZzjnRluSA4PVWf8CW99LUPwGB3eNIA7zUFoP77YuI7hOc0A==
|
||||
dependencies:
|
||||
chokidar "^3.2.2"
|
||||
debug "^3.2.6"
|
||||
chokidar "^3.5.2"
|
||||
debug "^3.2.7"
|
||||
ignore-by-default "^1.0.1"
|
||||
minimatch "^3.0.4"
|
||||
pstree.remy "^1.1.7"
|
||||
pstree.remy "^1.1.8"
|
||||
semver "^5.7.1"
|
||||
simple-update-notifier "^1.0.7"
|
||||
supports-color "^5.5.0"
|
||||
touch "^3.1.0"
|
||||
undefsafe "^2.0.2"
|
||||
update-notifier "^4.0.0"
|
||||
undefsafe "^2.0.5"
|
||||
|
||||
nopt@^4.0.3:
|
||||
version "4.0.3"
|
||||
|
@ -9599,11 +9376,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
|||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||
|
||||
normalize-url@^4.1.0:
|
||||
version "4.5.0"
|
||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
|
||||
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
|
||||
|
||||
npm-run-path@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f"
|
||||
|
@ -9814,11 +9586,6 @@ osenv@^0.1.4:
|
|||
os-homedir "^1.0.0"
|
||||
os-tmpdir "^1.0.0"
|
||||
|
||||
p-cancelable@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-1.1.0.tgz#d078d15a3af409220c886f1d9a0ca2e441ab26cc"
|
||||
integrity sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==
|
||||
|
||||
p-each-series@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/p-each-series/-/p-each-series-2.1.0.tgz#961c8dd3f195ea96c747e636b262b800a6b1af48"
|
||||
|
@ -9896,16 +9663,6 @@ p-try@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6"
|
||||
integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==
|
||||
|
||||
package-json@^6.3.0:
|
||||
version "6.5.0"
|
||||
resolved "https://registry.yarnpkg.com/package-json/-/package-json-6.5.0.tgz#6feedaca35e75725876d0b0e64974697fed145b0"
|
||||
integrity sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==
|
||||
dependencies:
|
||||
got "^9.6.0"
|
||||
registry-auth-token "^4.0.0"
|
||||
registry-url "^5.0.0"
|
||||
semver "^6.2.0"
|
||||
|
||||
pako@~1.0.2, pako@~1.0.5:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.6.tgz#0101211baa70c4bca4a0f63f2206e97b7dfaf258"
|
||||
|
@ -10243,11 +10000,6 @@ prelude-ls@~1.1.2:
|
|||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
|
||||
|
||||
prepend-http@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897"
|
||||
integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=
|
||||
|
||||
pretender@^3.4.3:
|
||||
version "3.4.3"
|
||||
resolved "https://registry.yarnpkg.com/pretender/-/pretender-3.4.3.tgz#a3b4160516007075d29127262f3a0063d19896e9"
|
||||
|
@ -10495,7 +10247,7 @@ psl@^1.1.28:
|
|||
resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24"
|
||||
integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==
|
||||
|
||||
pstree.remy@^1.1.7:
|
||||
pstree.remy@^1.1.8:
|
||||
version "1.1.8"
|
||||
resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
|
||||
integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==
|
||||
|
@ -10546,13 +10298,6 @@ punycode@^2.1.0, punycode@^2.1.1:
|
|||
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
|
||||
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
|
||||
|
||||
pupa@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/pupa/-/pupa-2.0.1.tgz#dbdc9ff48ffbea4a26a069b6f9f7abb051008726"
|
||||
integrity sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==
|
||||
dependencies:
|
||||
escape-goat "^2.0.0"
|
||||
|
||||
purgecss-from-html@^4.0.3:
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/purgecss-from-html/-/purgecss-from-html-4.0.3.tgz#28d86d3dc8292581c4ab529a77a57daf7c2dd940"
|
||||
|
@ -10646,16 +10391,6 @@ raw-loader@^4.0.2:
|
|||
loader-utils "^2.0.0"
|
||||
schema-utils "^3.0.0"
|
||||
|
||||
rc@^1.2.8:
|
||||
version "1.2.8"
|
||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
|
||||
dependencies:
|
||||
deep-extend "^0.6.0"
|
||||
ini "~1.3.0"
|
||||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-is@^16.7.0, react-is@^16.8.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
|
@ -10804,20 +10539,6 @@ regexpu-core@^5.0.1:
|
|||
unicode-match-property-ecmascript "^2.0.0"
|
||||
unicode-match-property-value-ecmascript "^2.0.0"
|
||||
|
||||
registry-auth-token@^4.0.0:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-4.1.1.tgz#40a33be1e82539460f94328b0f7f0f84c16d9479"
|
||||
integrity sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==
|
||||
dependencies:
|
||||
rc "^1.2.8"
|
||||
|
||||
registry-url@^5.0.0:
|
||||
version "5.1.0"
|
||||
resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-5.1.0.tgz#e98334b50d5434b81136b44ec638d9c2009c5009"
|
||||
integrity sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==
|
||||
dependencies:
|
||||
rc "^1.2.8"
|
||||
|
||||
regjsgen@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.6.0.tgz#83414c5354afd7d6627b16af5f10f41c4e71808d"
|
||||
|
@ -10988,13 +10709,6 @@ resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.17.0, resolve@^1.2
|
|||
path-parse "^1.0.7"
|
||||
supports-preserve-symlinks-flag "^1.0.0"
|
||||
|
||||
responselike@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/responselike/-/responselike-1.0.2.tgz#918720ef3b631c5642be068f15ade5a46f4ba1e7"
|
||||
integrity sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=
|
||||
dependencies:
|
||||
lowercase-keys "^1.0.0"
|
||||
|
||||
ret@~0.1.10:
|
||||
version "0.1.15"
|
||||
resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc"
|
||||
|
@ -11225,24 +10939,17 @@ selfsigned@^2.0.1:
|
|||
dependencies:
|
||||
node-forge "^1"
|
||||
|
||||
semver-diff@^3.1.1:
|
||||
version "3.1.1"
|
||||
resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-3.1.1.tgz#05f77ce59f325e00e2706afd67bb506ddb1ca32b"
|
||||
integrity sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==
|
||||
dependencies:
|
||||
semver "^6.3.0"
|
||||
|
||||
"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.1:
|
||||
version "5.7.1"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||
|
||||
semver@7.0.0:
|
||||
semver@7.0.0, semver@~7.0.0:
|
||||
version "7.0.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e"
|
||||
integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==
|
||||
|
||||
semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.2.0, semver@^6.3.0:
|
||||
semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d"
|
||||
integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==
|
||||
|
@ -11415,6 +11122,13 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
|
|||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
simple-update-notifier@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz#7edf75c5bdd04f88828d632f762b2bc32996a9cc"
|
||||
integrity sha512-BBKgR84BJQJm6WjWFMHgLVuo61FBDSj1z/xSFUIozqO6wO7ii0JxCqlIud7Enr/+LhlbNI0whErq96P2qHNWew==
|
||||
dependencies:
|
||||
semver "~7.0.0"
|
||||
|
||||
sirv@^1.0.7:
|
||||
version "1.0.11"
|
||||
resolved "https://registry.yarnpkg.com/sirv/-/sirv-1.0.11.tgz#81c19a29202048507d6ec0d8ba8910fda52eb5a4"
|
||||
|
@ -11632,16 +11346,16 @@ sshpk@^1.7.0:
|
|||
tweetnacl "~0.14.0"
|
||||
|
||||
ssri@^6.0.1:
|
||||
version "6.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8"
|
||||
integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA==
|
||||
version "6.0.2"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.2.tgz#157939134f20464e7301ddba3e90ffa8f7728ac5"
|
||||
integrity sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==
|
||||
dependencies:
|
||||
figgy-pudding "^3.5.1"
|
||||
|
||||
ssri@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.0.tgz#79ca74e21f8ceaeddfcb4b90143c458b8d988808"
|
||||
integrity sha512-aq/pz989nxVYwn16Tsbj1TqFpD5LLrQxHf5zaHuieFV+R0Bbr4y8qUsOA45hXT/N4/9UNXTarBjnjVmjSOVaAA==
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af"
|
||||
integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==
|
||||
dependencies:
|
||||
minipass "^3.1.1"
|
||||
|
||||
|
@ -11720,16 +11434,7 @@ string-length@^4.0.1:
|
|||
char-regex "^1.0.2"
|
||||
strip-ansi "^6.0.0"
|
||||
|
||||
string-width@^3.0.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
||||
integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
|
||||
dependencies:
|
||||
emoji-regex "^7.0.1"
|
||||
is-fullwidth-code-point "^2.0.0"
|
||||
strip-ansi "^5.1.0"
|
||||
|
||||
string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
|
||||
version "4.2.3"
|
||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
|
||||
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
|
||||
|
@ -11768,7 +11473,7 @@ string_decoder@~0.10.x:
|
|||
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94"
|
||||
integrity sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=
|
||||
|
||||
strip-ansi@^5.1.0, strip-ansi@^5.2.0:
|
||||
strip-ansi@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
||||
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
|
||||
|
@ -12018,11 +11723,6 @@ tar@^6.0.2:
|
|||
mkdirp "^1.0.3"
|
||||
yallist "^4.0.0"
|
||||
|
||||
term-size@^2.1.0:
|
||||
version "2.2.0"
|
||||
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753"
|
||||
integrity sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==
|
||||
|
||||
terminal-link@^2.0.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994"
|
||||
|
@ -12047,9 +11747,9 @@ terser-webpack-plugin@^1.4.3:
|
|||
worker-farm "^1.7.0"
|
||||
|
||||
terser@^4.1.2:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.3.1.tgz#09820bcb3398299c4b48d9a86aefc65127d0ed65"
|
||||
integrity sha512-pnzH6dnFEsR2aa2SJaKb1uSCl3QmIsJ8dEkj0Fky+2AwMMcC9doMqLOQIH6wVTEKaVfKVvLSk5qxPBEZT9mywg==
|
||||
version "4.8.1"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-4.8.1.tgz#a00e5634562de2239fd404c649051bf6fc21144f"
|
||||
integrity sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==
|
||||
dependencies:
|
||||
commander "^2.20.0"
|
||||
source-map "~0.6.1"
|
||||
|
@ -12149,9 +11849,9 @@ tmp@^0.0.33:
|
|||
os-tmpdir "~1.0.2"
|
||||
|
||||
tmpl@1.0.x:
|
||||
version "1.0.4"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.4.tgz#23640dd7b42d00433911140820e5cf440e521dd1"
|
||||
integrity sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
|
||||
integrity sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==
|
||||
|
||||
to-arraybuffer@^1.0.0:
|
||||
version "1.0.1"
|
||||
|
@ -12170,11 +11870,6 @@ to-object-path@^0.3.0:
|
|||
dependencies:
|
||||
kind-of "^3.0.2"
|
||||
|
||||
to-readable-stream@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/to-readable-stream/-/to-readable-stream-1.0.0.tgz#ce0aa0c2f3df6adf852efb404a783e77c0475771"
|
||||
integrity sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==
|
||||
|
||||
to-regex-range@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38"
|
||||
|
@ -12408,12 +12103,10 @@ unbox-primitive@^1.0.2:
|
|||
has-symbols "^1.0.3"
|
||||
which-boxed-primitive "^1.0.2"
|
||||
|
||||
undefsafe@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76"
|
||||
integrity sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY=
|
||||
dependencies:
|
||||
debug "^2.2.0"
|
||||
undefsafe@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
|
||||
integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
|
||||
|
||||
underscore-contrib@~0.3.0:
|
||||
version "0.3.0"
|
||||
|
@ -12433,9 +12126,9 @@ underscore@~1.8.3:
|
|||
integrity sha1-Tz+1OxBuYJf8+ctBCfKl6b36UCI=
|
||||
|
||||
undici@^5.0.0:
|
||||
version "5.0.0"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.0.0.tgz#3c1e08c7f0df90c485d5d8dbb0517e11e34f2090"
|
||||
integrity sha512-VhUpiZ3No1DOPPQVQnsDZyfcbTTcHdcgWej1PdFnSvOeJmOVDgiOHkunJmBLfmjt4CqgPQddPVjSWW0dsTs5Yg==
|
||||
version "5.8.0"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-5.8.0.tgz#dec9a8ccd90e5a1d81d43c0eab6503146d649a4f"
|
||||
integrity sha512-1F7Vtcez5w/LwH2G2tGnFIihuWUlc58YidwLiCv+jR2Z50x0tNXpRRw7eOIJ+GvqCqIkg9SB7NWAJ/T9TLfv8Q==
|
||||
|
||||
unicode-canonical-property-names-ecmascript@^2.0.0:
|
||||
version "2.0.0"
|
||||
|
@ -12497,13 +12190,6 @@ unique-slug@^2.0.0:
|
|||
dependencies:
|
||||
imurmurhash "^0.1.4"
|
||||
|
||||
unique-string@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-2.0.0.tgz#39c6451f81afb2749de2b233e3f7c5e8843bd89d"
|
||||
integrity sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==
|
||||
dependencies:
|
||||
crypto-random-string "^2.0.0"
|
||||
|
||||
unist-builder@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-3.0.0.tgz#728baca4767c0e784e1e64bb44b5a5a753021a04"
|
||||
|
@ -12594,25 +12280,6 @@ unset-value@^1.0.0:
|
|||
has-value "^0.3.1"
|
||||
isobject "^3.0.0"
|
||||
|
||||
update-notifier@^4.0.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-4.1.0.tgz#4866b98c3bc5b5473c020b1250583628f9a328f3"
|
||||
integrity sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==
|
||||
dependencies:
|
||||
boxen "^4.2.0"
|
||||
chalk "^3.0.0"
|
||||
configstore "^5.0.1"
|
||||
has-yarn "^2.1.0"
|
||||
import-lazy "^2.1.0"
|
||||
is-ci "^2.0.0"
|
||||
is-installed-globally "^0.3.1"
|
||||
is-npm "^4.0.0"
|
||||
is-yarn-global "^0.3.0"
|
||||
latest-version "^5.0.0"
|
||||
pupa "^2.0.1"
|
||||
semver-diff "^3.1.1"
|
||||
xdg-basedir "^4.0.0"
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||
|
@ -12634,13 +12301,6 @@ url-loader@^4.1.1:
|
|||
mime-types "^2.1.27"
|
||||
schema-utils "^3.0.0"
|
||||
|
||||
url-parse-lax@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-3.0.0.tgz#16b5cafc07dbe3676c1b1999177823d6503acb0c"
|
||||
integrity sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=
|
||||
dependencies:
|
||||
prepend-http "^2.0.0"
|
||||
|
||||
url@0.10.3:
|
||||
version "0.10.3"
|
||||
resolved "https://registry.yarnpkg.com/url/-/url-0.10.3.tgz#021e4d9c7705f21bbf37d03ceb58767402774c64"
|
||||
|
@ -13200,13 +12860,6 @@ which@^2.0.1, which@^2.0.2:
|
|||
dependencies:
|
||||
isexe "^2.0.0"
|
||||
|
||||
widest-line@^3.1.0:
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca"
|
||||
integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==
|
||||
dependencies:
|
||||
string-width "^4.0.0"
|
||||
|
||||
wildcard@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
|
||||
|
@ -13274,11 +12927,6 @@ ws@^8.3.0, ws@^8.4.2:
|
|||
resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f"
|
||||
integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==
|
||||
|
||||
xdg-basedir@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-4.0.0.tgz#4bc8d9984403696225ef83a1573cbbcb4e79db13"
|
||||
integrity sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==
|
||||
|
||||
xhr-mock@^2.5.1:
|
||||
version "2.5.1"
|
||||
resolved "https://registry.yarnpkg.com/xhr-mock/-/xhr-mock-2.5.1.tgz#c591498a8269cc1ce5fefac20d590357affd348b"
|
||||
|
@ -13331,9 +12979,9 @@ xterm@3.14.5:
|
|||
integrity sha512-DVmQ8jlEtL+WbBKUZuMxHMBgK/yeIZwkXB81bH+MGaKKnJGYwA+770hzhXPfwEIokK9On9YIFPRleVp/5G7z9g==
|
||||
|
||||
y18n@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b"
|
||||
integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==
|
||||
version "4.0.3"
|
||||
resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf"
|
||||
integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==
|
||||
|
||||
yallist@^2.1.2:
|
||||
version "2.1.2"
|
||||
|
|
Loading…
Reference in New Issue