Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
86ace8a66c
commit
73507eaf1a
|
@ -602,9 +602,6 @@ Style/MultilineWhenThen:
|
||||||
Style/NumericPredicate:
|
Style/NumericPredicate:
|
||||||
EnforcedStyle: comparison
|
EnforcedStyle: comparison
|
||||||
|
|
||||||
Style/FloatDivision:
|
|
||||||
Enabled: false
|
|
||||||
|
|
||||||
Cop/BanCatchThrow:
|
Cop/BanCatchThrow:
|
||||||
Enabled: true
|
Enabled: true
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
Style/FloatDivision:
|
||||||
|
Exclude:
|
||||||
|
- 'ee/app/models/geo_node_status.rb'
|
||||||
|
- 'ee/app/models/namespaces/storage/root_size.rb'
|
||||||
|
- 'lib/learn_gitlab/onboarding.rb'
|
||||||
|
- 'qa/qa/support/formatters/allure_metadata_formatter.rb'
|
||||||
|
- 'qa/qa/tools/reliable_report.rb'
|
|
@ -1,11 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlLoadingIcon } from '@gitlab/ui';
|
import { GlLoadingIcon } from '@gitlab/ui';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import notebookLab from '~/notebook/index.vue';
|
import NotebookLab from '~/notebook/index.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
notebookLab,
|
NotebookLab,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -11,11 +11,11 @@ import {
|
||||||
import addAdminVariable from '../graphql/mutations/admin_add_variable.mutation.graphql';
|
import addAdminVariable from '../graphql/mutations/admin_add_variable.mutation.graphql';
|
||||||
import deleteAdminVariable from '../graphql/mutations/admin_delete_variable.mutation.graphql';
|
import deleteAdminVariable from '../graphql/mutations/admin_delete_variable.mutation.graphql';
|
||||||
import updateAdminVariable from '../graphql/mutations/admin_update_variable.mutation.graphql';
|
import updateAdminVariable from '../graphql/mutations/admin_update_variable.mutation.graphql';
|
||||||
import ciVariableSettings from './ci_variable_settings.vue';
|
import CiVariableSettings from './ci_variable_settings.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ciVariableSettings,
|
CiVariableSettings,
|
||||||
},
|
},
|
||||||
inject: ['endpoint'],
|
inject: ['endpoint'],
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -14,11 +14,11 @@ import {
|
||||||
import addGroupVariable from '../graphql/mutations/group_add_variable.mutation.graphql';
|
import addGroupVariable from '../graphql/mutations/group_add_variable.mutation.graphql';
|
||||||
import deleteGroupVariable from '../graphql/mutations/group_delete_variable.mutation.graphql';
|
import deleteGroupVariable from '../graphql/mutations/group_delete_variable.mutation.graphql';
|
||||||
import updateGroupVariable from '../graphql/mutations/group_update_variable.mutation.graphql';
|
import updateGroupVariable from '../graphql/mutations/group_update_variable.mutation.graphql';
|
||||||
import ciVariableSettings from './ci_variable_settings.vue';
|
import CiVariableSettings from './ci_variable_settings.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ciVariableSettings,
|
CiVariableSettings,
|
||||||
},
|
},
|
||||||
mixins: [glFeatureFlagsMixin()],
|
mixins: [glFeatureFlagsMixin()],
|
||||||
inject: ['endpoint', 'groupPath', 'groupId'],
|
inject: ['endpoint', 'groupPath', 'groupId'],
|
||||||
|
|
|
@ -16,11 +16,11 @@ import {
|
||||||
import addProjectVariable from '../graphql/mutations/project_add_variable.mutation.graphql';
|
import addProjectVariable from '../graphql/mutations/project_add_variable.mutation.graphql';
|
||||||
import deleteProjectVariable from '../graphql/mutations/project_delete_variable.mutation.graphql';
|
import deleteProjectVariable from '../graphql/mutations/project_delete_variable.mutation.graphql';
|
||||||
import updateProjectVariable from '../graphql/mutations/project_update_variable.mutation.graphql';
|
import updateProjectVariable from '../graphql/mutations/project_update_variable.mutation.graphql';
|
||||||
import ciVariableSettings from './ci_variable_settings.vue';
|
import CiVariableSettings from './ci_variable_settings.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ciVariableSettings,
|
CiVariableSettings,
|
||||||
},
|
},
|
||||||
inject: ['endpoint', 'projectFullPath', 'projectId'],
|
inject: ['endpoint', 'projectFullPath', 'projectId'],
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -108,7 +108,6 @@ export default {
|
||||||
return {
|
return {
|
||||||
newEnvironments: [],
|
newEnvironments: [],
|
||||||
isTipDismissed: getCookie(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
|
isTipDismissed: getCookie(AWS_TIP_DISMISSED_COOKIE_NAME) === 'true',
|
||||||
typeOptions: variableOptions,
|
|
||||||
validationErrorEventProperty: '',
|
validationErrorEventProperty: '',
|
||||||
variable: { ...defaultVariableState, ...this.selectedVariable },
|
variable: { ...defaultVariableState, ...this.selectedVariable },
|
||||||
};
|
};
|
||||||
|
@ -259,6 +258,7 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
defaultScope: allEnvironments.text,
|
defaultScope: allEnvironments.text,
|
||||||
|
variableOptions,
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -298,16 +298,20 @@ export default {
|
||||||
/>
|
/>
|
||||||
</gl-form-group>
|
</gl-form-group>
|
||||||
|
|
||||||
<div class="d-flex">
|
<div class="gl-display-flex">
|
||||||
<gl-form-group :label="__('Type')" label-for="ci-variable-type" class="w-50 gl-mr-5">
|
<gl-form-group :label="__('Type')" label-for="ci-variable-type" class="gl-w-half gl-mr-5">
|
||||||
<gl-form-select
|
<gl-form-select
|
||||||
id="ci-variable-type"
|
id="ci-variable-type"
|
||||||
v-model="variable.variableType"
|
v-model="variable.variableType"
|
||||||
:options="typeOptions"
|
:options="$options.variableOptions"
|
||||||
/>
|
/>
|
||||||
</gl-form-group>
|
</gl-form-group>
|
||||||
|
|
||||||
<gl-form-group label-for="ci-variable-env" class="w-50" data-testid="environment-scope">
|
<gl-form-group
|
||||||
|
label-for="ci-variable-env"
|
||||||
|
class="gl-w-half"
|
||||||
|
data-testid="environment-scope"
|
||||||
|
>
|
||||||
<template #label>
|
<template #label>
|
||||||
{{ __('Environment scope') }}
|
{{ __('Environment scope') }}
|
||||||
<gl-link
|
<gl-link
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const displayText = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export const variableTypes = {
|
export const variableTypes = {
|
||||||
variableType: 'ENV_VAR',
|
envType: 'ENV_VAR',
|
||||||
fileType: 'FILE',
|
fileType: 'FILE',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -29,13 +29,13 @@ export const allEnvironments = {
|
||||||
export const variableText = {
|
export const variableText = {
|
||||||
[types.variableType]: __('Variable'),
|
[types.variableType]: __('Variable'),
|
||||||
[types.fileType]: __('File'),
|
[types.fileType]: __('File'),
|
||||||
[variableTypes.variableType]: __('Variable'),
|
[variableTypes.envType]: __('Variable'),
|
||||||
[variableTypes.fileType]: __('File'),
|
[variableTypes.fileType]: __('File'),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const variableOptions = [
|
export const variableOptions = [
|
||||||
{ value: types.variableType, text: variableText[types.variableType] },
|
{ value: variableTypes.envType, text: variableText[variableTypes.envType] },
|
||||||
{ value: types.fileType, text: variableText[types.fileType] },
|
{ value: variableTypes.fileType, text: variableText[variableTypes.fileType] },
|
||||||
];
|
];
|
||||||
|
|
||||||
export const defaultVariableState = {
|
export const defaultVariableState = {
|
||||||
|
@ -44,7 +44,7 @@ export const defaultVariableState = {
|
||||||
masked: false,
|
masked: false,
|
||||||
protected: false,
|
protected: false,
|
||||||
value: '',
|
value: '',
|
||||||
variableType: types.variableType,
|
variableType: variableTypes.envType,
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||||
|
|
|
@ -5,3 +5,7 @@ export const trackViewsOptions = {
|
||||||
category: 'Customer Relations' /* eslint-disable-line @gitlab/require-i18n-strings */,
|
category: 'Customer Relations' /* eslint-disable-line @gitlab/require-i18n-strings */,
|
||||||
action: 'view_contacts_list',
|
action: 'view_contacts_list',
|
||||||
};
|
};
|
||||||
|
export const organizationTrackViewsOptions = {
|
||||||
|
category: 'Customer Relations' /* eslint-disable-line @gitlab/require-i18n-strings */,
|
||||||
|
action: 'view_organizations_list',
|
||||||
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@ import Vue from 'vue';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import VueRouter from 'vue-router';
|
import VueRouter from 'vue-router';
|
||||||
import createDefaultClient from '~/lib/graphql';
|
import createDefaultClient from '~/lib/graphql';
|
||||||
|
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||||
import CrmOrganizationsRoot from './components/organizations_root.vue';
|
import CrmOrganizationsRoot from './components/organizations_root.vue';
|
||||||
import routes from './routes';
|
import routes from './routes';
|
||||||
|
|
||||||
|
@ -21,7 +22,14 @@ export default () => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { basePath, canAdminCrmOrganization, groupFullPath, groupId, groupIssuesPath } = el.dataset;
|
const {
|
||||||
|
basePath,
|
||||||
|
canAdminCrmOrganization,
|
||||||
|
groupFullPath,
|
||||||
|
groupId,
|
||||||
|
groupIssuesPath,
|
||||||
|
textQuery,
|
||||||
|
} = el.dataset;
|
||||||
|
|
||||||
const router = new VueRouter({
|
const router = new VueRouter({
|
||||||
base: basePath,
|
base: basePath,
|
||||||
|
@ -33,7 +41,13 @@ export default () => {
|
||||||
el,
|
el,
|
||||||
router,
|
router,
|
||||||
apolloProvider,
|
apolloProvider,
|
||||||
provide: { canAdminCrmOrganization, groupFullPath, groupId, groupIssuesPath },
|
provide: {
|
||||||
|
canAdminCrmOrganization: parseBoolean(canAdminCrmOrganization),
|
||||||
|
groupFullPath,
|
||||||
|
groupId,
|
||||||
|
groupIssuesPath,
|
||||||
|
textQuery,
|
||||||
|
},
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement(CrmOrganizationsRoot);
|
return createElement(CrmOrganizationsRoot);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,12 +1,37 @@
|
||||||
#import "./crm_organization_fields.fragment.graphql"
|
#import "./crm_organization_fields.fragment.graphql"
|
||||||
|
|
||||||
query organizations($groupFullPath: ID!) {
|
query organizations(
|
||||||
|
$groupFullPath: ID!
|
||||||
|
$state: CustomerRelationsOrganizationState
|
||||||
|
$searchTerm: String
|
||||||
|
$sort: OrganizationSort
|
||||||
|
$firstPageSize: Int
|
||||||
|
$lastPageSize: Int
|
||||||
|
$prevPageCursor: String = ""
|
||||||
|
$nextPageCursor: String = ""
|
||||||
|
$ids: [CustomerRelationsOrganizationID!]
|
||||||
|
) {
|
||||||
group(fullPath: $groupFullPath) {
|
group(fullPath: $groupFullPath) {
|
||||||
id
|
id
|
||||||
organizations {
|
organizations(
|
||||||
|
state: $state
|
||||||
|
search: $searchTerm
|
||||||
|
sort: $sort
|
||||||
|
first: $firstPageSize
|
||||||
|
last: $lastPageSize
|
||||||
|
after: $nextPageCursor
|
||||||
|
before: $prevPageCursor
|
||||||
|
ids: $ids
|
||||||
|
) {
|
||||||
nodes {
|
nodes {
|
||||||
...OrganizationFragment
|
...OrganizationFragment
|
||||||
}
|
}
|
||||||
|
pageInfo {
|
||||||
|
hasNextPage
|
||||||
|
endCursor
|
||||||
|
hasPreviousPage
|
||||||
|
startCursor
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
query organizationsCountByState($groupFullPath: ID!, $searchTerm: String) {
|
||||||
|
group(fullPath: $groupFullPath) {
|
||||||
|
__typename
|
||||||
|
id
|
||||||
|
organizationStateCounts(search: $searchTerm) {
|
||||||
|
all
|
||||||
|
active
|
||||||
|
inactive
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,7 +36,7 @@ export default {
|
||||||
getQuery() {
|
getQuery() {
|
||||||
return {
|
return {
|
||||||
query: getGroupOrganizationsQuery,
|
query: getGroupOrganizationsQuery,
|
||||||
variables: { groupFullPath: this.groupFullPath },
|
variables: { groupFullPath: this.groupFullPath, ids: [this.organizationGraphQLId] },
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
title() {
|
title() {
|
||||||
|
|
|
@ -1,36 +1,54 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlAlert, GlButton, GlLoadingIcon, GlTable, GlTooltipDirective } from '@gitlab/ui';
|
import { GlButton, GlLoadingIcon, GlTable, GlTooltipDirective } from '@gitlab/ui';
|
||||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
|
||||||
import { s__, __ } from '~/locale';
|
import { s__, __ } from '~/locale';
|
||||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||||
import { EDIT_ROUTE_NAME, NEW_ROUTE_NAME } from '../../constants';
|
import PaginatedTableWithSearchAndTabs from '~/vue_shared/components/paginated_table_with_search_and_tabs/paginated_table_with_search_and_tabs.vue';
|
||||||
|
import {
|
||||||
|
bodyTrClass,
|
||||||
|
initialPaginationState,
|
||||||
|
} from '~/vue_shared/components/paginated_table_with_search_and_tabs/constants';
|
||||||
|
import { convertToSnakeCase } from '~/lib/utils/text_utility';
|
||||||
|
import { EDIT_ROUTE_NAME, NEW_ROUTE_NAME, organizationTrackViewsOptions } from '../../constants';
|
||||||
import getGroupOrganizationsQuery from './graphql/get_group_organizations.query.graphql';
|
import getGroupOrganizationsQuery from './graphql/get_group_organizations.query.graphql';
|
||||||
|
import getGroupOrganizationsCountByStateQuery from './graphql/get_group_organizations_count_by_state.query.graphql';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
GlAlert,
|
|
||||||
GlButton,
|
GlButton,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
GlTable,
|
GlTable,
|
||||||
|
PaginatedTableWithSearchAndTabs,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
GlTooltip: GlTooltipDirective,
|
GlTooltip: GlTooltipDirective,
|
||||||
},
|
},
|
||||||
inject: ['canAdminCrmOrganization', 'groupFullPath', 'groupIssuesPath'],
|
inject: ['canAdminCrmOrganization', 'groupFullPath', 'groupIssuesPath', 'textQuery'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
organizations: [],
|
organizations: { list: [] },
|
||||||
|
organizationsCount: {},
|
||||||
error: false,
|
error: false,
|
||||||
|
filteredByStatus: '',
|
||||||
|
pagination: initialPaginationState,
|
||||||
|
statusFilter: 'all',
|
||||||
|
searchTerm: this.textQuery,
|
||||||
|
sort: 'NAME_ASC',
|
||||||
|
sortDesc: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
apollo: {
|
apollo: {
|
||||||
organizations: {
|
organizations: {
|
||||||
query() {
|
query: getGroupOrganizationsQuery,
|
||||||
return getGroupOrganizationsQuery;
|
|
||||||
},
|
|
||||||
variables() {
|
variables() {
|
||||||
return {
|
return {
|
||||||
groupFullPath: this.groupFullPath,
|
groupFullPath: this.groupFullPath,
|
||||||
|
searchTerm: this.searchTerm,
|
||||||
|
state: this.statusFilter,
|
||||||
|
sort: this.sort,
|
||||||
|
firstPageSize: this.pagination.firstPageSize,
|
||||||
|
lastPageSize: this.pagination.lastPageSize,
|
||||||
|
prevPageCursor: this.pagination.prevPageCursor,
|
||||||
|
nextPageCursor: this.pagination.nextPageCursor,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
update(data) {
|
update(data) {
|
||||||
|
@ -40,19 +58,52 @@ export default {
|
||||||
this.error = true;
|
this.error = true;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
organizationsCount: {
|
||||||
|
query: getGroupOrganizationsCountByStateQuery,
|
||||||
|
variables() {
|
||||||
|
return {
|
||||||
|
groupFullPath: this.groupFullPath,
|
||||||
|
searchTerm: this.searchTerm,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
update(data) {
|
||||||
|
return data?.group?.organizationStateCounts;
|
||||||
|
},
|
||||||
|
error() {
|
||||||
|
this.error = true;
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
isLoading() {
|
isLoading() {
|
||||||
return this.$apollo.queries.organizations.loading;
|
return this.$apollo.queries.organizations.loading;
|
||||||
},
|
},
|
||||||
canAdmin() {
|
tbodyTrClass() {
|
||||||
return parseBoolean(this.canAdminCrmOrganization);
|
return {
|
||||||
|
[bodyTrClass]: !this.loading && !this.isEmpty,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
errorAlertDismissed() {
|
||||||
|
this.error = false;
|
||||||
|
},
|
||||||
extractOrganizations(data) {
|
extractOrganizations(data) {
|
||||||
const organizations = data?.group?.organizations?.nodes || [];
|
const organizations = data?.group?.organizations?.nodes || [];
|
||||||
return organizations.slice().sort((a, b) => a.name.localeCompare(b.name));
|
const pageInfo = data?.group?.organizations?.pageInfo || {};
|
||||||
|
return {
|
||||||
|
list: organizations,
|
||||||
|
pageInfo,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
fetchSortedData({ sortBy, sortDesc }) {
|
||||||
|
const sortingColumn = convertToSnakeCase(sortBy).toUpperCase();
|
||||||
|
const sortingDirection = sortDesc ? 'DESC' : 'ASC';
|
||||||
|
this.pagination = initialPaginationState;
|
||||||
|
this.sort = `${sortingColumn}_${sortingDirection}`;
|
||||||
|
},
|
||||||
|
filtersChanged({ searchTerm }) {
|
||||||
|
this.searchTerm = searchTerm;
|
||||||
},
|
},
|
||||||
getIssuesPath(path, value) {
|
getIssuesPath(path, value) {
|
||||||
return `${path}?crm_organization_id=${value}`;
|
return `${path}?crm_organization_id=${value}`;
|
||||||
|
@ -60,6 +111,13 @@ export default {
|
||||||
getEditRoute(id) {
|
getEditRoute(id) {
|
||||||
return { name: this.$options.EDIT_ROUTE_NAME, params: { id } };
|
return { name: this.$options.EDIT_ROUTE_NAME, params: { id } };
|
||||||
},
|
},
|
||||||
|
pageChanged(pagination) {
|
||||||
|
this.pagination = pagination;
|
||||||
|
},
|
||||||
|
statusChanged({ filters, status }) {
|
||||||
|
this.statusFilter = filters;
|
||||||
|
this.filteredByStatus = status;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
fields: [
|
fields: [
|
||||||
{ key: 'name', sortable: true },
|
{ key: 'name', sortable: true },
|
||||||
|
@ -83,60 +141,113 @@ export default {
|
||||||
},
|
},
|
||||||
EDIT_ROUTE_NAME,
|
EDIT_ROUTE_NAME,
|
||||||
NEW_ROUTE_NAME,
|
NEW_ROUTE_NAME,
|
||||||
|
statusTabs: [
|
||||||
|
{
|
||||||
|
title: __('Active'),
|
||||||
|
status: 'ACTIVE',
|
||||||
|
filters: 'active',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: __('Inactive'),
|
||||||
|
status: 'INACTIVE',
|
||||||
|
filters: 'inactive',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: __('All'),
|
||||||
|
status: 'ALL',
|
||||||
|
filters: 'all',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
organizationTrackViewsOptions,
|
||||||
|
emptyArray: [],
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<gl-alert v-if="error" variant="danger" class="gl-mt-6" @dismiss="error = false">
|
<paginated-table-with-search-and-tabs
|
||||||
{{ $options.i18n.errorText }}
|
:show-items="true"
|
||||||
</gl-alert>
|
:show-error-msg="false"
|
||||||
<div
|
:i18n="$options.i18n"
|
||||||
class="gl-display-flex gl-align-items-baseline gl-flex-direction-row gl-justify-content-space-between gl-mt-6"
|
:items="organizations.list"
|
||||||
|
:page-info="organizations.pageInfo"
|
||||||
|
:items-count="organizationsCount"
|
||||||
|
:status-tabs="$options.statusTabs"
|
||||||
|
:track-views-options="$options.organizationTrackViewsOptions"
|
||||||
|
:filter-search-tokens="$options.emptyArray"
|
||||||
|
filter-search-key="organizations"
|
||||||
|
@page-changed="pageChanged"
|
||||||
|
@tabs-changed="statusChanged"
|
||||||
|
@filters-changed="filtersChanged"
|
||||||
|
@error-alert-dismissed="errorAlertDismissed"
|
||||||
>
|
>
|
||||||
<h2 class="gl-font-size-h2 gl-my-0">
|
<template #header-actions>
|
||||||
{{ $options.i18n.title }}
|
<router-link v-if="canAdminCrmOrganization" :to="{ name: $options.NEW_ROUTE_NAME }">
|
||||||
</h2>
|
<gl-button
|
||||||
<div
|
class="gl-my-3 gl-mr-5"
|
||||||
v-if="canAdmin"
|
variant="confirm"
|
||||||
class="gl-display-none gl-md-display-flex gl-align-items-center gl-justify-content-end"
|
data-testid="new-organization-button"
|
||||||
>
|
>
|
||||||
<router-link :to="{ name: $options.NEW_ROUTE_NAME }">
|
|
||||||
<gl-button variant="confirm" data-testid="new-organization-button">
|
|
||||||
{{ $options.i18n.newOrganization }}
|
{{ $options.i18n.newOrganization }}
|
||||||
</gl-button>
|
</gl-button>
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<router-view />
|
|
||||||
<gl-loading-icon v-if="isLoading" class="gl-mt-5" size="lg" />
|
|
||||||
<gl-table
|
|
||||||
v-else
|
|
||||||
class="gl-mt-5"
|
|
||||||
:items="organizations"
|
|
||||||
:fields="$options.fields"
|
|
||||||
:empty-text="$options.i18n.emptyText"
|
|
||||||
show-empty
|
|
||||||
>
|
|
||||||
<template #cell(id)="{ value: id }">
|
|
||||||
<gl-button
|
|
||||||
v-gl-tooltip.hover.bottom="$options.i18n.issuesButtonLabel"
|
|
||||||
class="gl-mr-3"
|
|
||||||
data-testid="issues-link"
|
|
||||||
icon="issues"
|
|
||||||
:aria-label="$options.i18n.issuesButtonLabel"
|
|
||||||
:href="getIssuesPath(groupIssuesPath, id)"
|
|
||||||
/>
|
|
||||||
<router-link :to="getEditRoute(id)">
|
|
||||||
<gl-button
|
|
||||||
v-if="canAdmin"
|
|
||||||
v-gl-tooltip.hover.bottom="$options.i18n.editButtonLabel"
|
|
||||||
data-testid="edit-organization-button"
|
|
||||||
icon="pencil"
|
|
||||||
:aria-label="$options.i18n.editButtonLabel"
|
|
||||||
/>
|
|
||||||
</router-link>
|
|
||||||
</template>
|
</template>
|
||||||
</gl-table>
|
|
||||||
|
<template #title>
|
||||||
|
{{ $options.i18n.title }}
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #table>
|
||||||
|
<gl-table
|
||||||
|
:items="organizations.list"
|
||||||
|
:fields="$options.fields"
|
||||||
|
:busy="isLoading"
|
||||||
|
stacked="md"
|
||||||
|
:tbody-tr-class="tbodyTrClass"
|
||||||
|
sort-direction="asc"
|
||||||
|
:sort-desc.sync="sortDesc"
|
||||||
|
sort-by="createdAt"
|
||||||
|
show-empty
|
||||||
|
no-local-sorting
|
||||||
|
sort-icon-left
|
||||||
|
fixed
|
||||||
|
@sort-changed="fetchSortedData"
|
||||||
|
>
|
||||||
|
<template #cell(id)="{ value: id }">
|
||||||
|
<gl-button
|
||||||
|
v-gl-tooltip.hover.bottom="$options.i18n.issuesButtonLabel"
|
||||||
|
class="gl-mr-3"
|
||||||
|
data-testid="issues-link"
|
||||||
|
icon="issues"
|
||||||
|
:aria-label="$options.i18n.issuesButtonLabel"
|
||||||
|
:href="getIssuesPath(groupIssuesPath, id)"
|
||||||
|
/>
|
||||||
|
<router-link :to="getEditRoute(id)">
|
||||||
|
<gl-button
|
||||||
|
v-if="canAdminCrmOrganization"
|
||||||
|
v-gl-tooltip.hover.bottom="$options.i18n.editButtonLabel"
|
||||||
|
data-testid="edit-organization-button"
|
||||||
|
icon="pencil"
|
||||||
|
:aria-label="$options.i18n.editButtonLabel"
|
||||||
|
/>
|
||||||
|
</router-link>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #table-busy>
|
||||||
|
<gl-loading-icon size="lg" color="dark" class="mt-3" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #empty>
|
||||||
|
<span v-if="error">
|
||||||
|
{{ $options.i18n.errorText }}
|
||||||
|
</span>
|
||||||
|
<span v-else>
|
||||||
|
{{ $options.i18n.emptyText }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</gl-table>
|
||||||
|
</template>
|
||||||
|
</paginated-table-with-search-and-tabs>
|
||||||
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -4,11 +4,11 @@ import { head, tail } from 'lodash';
|
||||||
import { s__, sprintf } from '~/locale';
|
import { s__, sprintf } from '~/locale';
|
||||||
import timeagoMixin from '~/vue_shared/mixins/timeago';
|
import timeagoMixin from '~/vue_shared/mixins/timeago';
|
||||||
|
|
||||||
import actionBtn from './action_btn.vue';
|
import ActionBtn from './action_btn.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
actionBtn,
|
ActionBtn,
|
||||||
GlButton,
|
GlButton,
|
||||||
GlIcon,
|
GlIcon,
|
||||||
GlLink,
|
GlLink,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import deployKey from './key.vue';
|
import DeployKey from './key.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
deployKey,
|
DeployKey,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
keys: {
|
keys: {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import deployKeysApp from './components/app.vue';
|
import DeployKeysApp from './components/app.vue';
|
||||||
|
|
||||||
export default () =>
|
export default () =>
|
||||||
new Vue({
|
new Vue({
|
||||||
el: document.getElementById('js-deploy-keys'),
|
el: document.getElementById('js-deploy-keys'),
|
||||||
components: {
|
components: {
|
||||||
deployKeysApp,
|
DeployKeysApp,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import NoPreviewViewer from '~/vue_shared/components/diff_viewer/viewers/no_prev
|
||||||
import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
|
import NotDiffableViewer from '~/vue_shared/components/diff_viewer/viewers/not_diffable.vue';
|
||||||
import NoteForm from '~/notes/components/note_form.vue';
|
import NoteForm from '~/notes/components/note_form.vue';
|
||||||
import eventHub from '~/notes/event_hub';
|
import eventHub from '~/notes/event_hub';
|
||||||
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||||
import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
|
import { IMAGE_DIFF_POSITION_TYPE } from '../constants';
|
||||||
import { getDiffMode } from '../store/utils';
|
import { getDiffMode } from '../store/utils';
|
||||||
import DiffDiscussions from './diff_discussions.vue';
|
import DiffDiscussions from './diff_discussions.vue';
|
||||||
|
@ -28,7 +28,7 @@ export default {
|
||||||
ImageDiffOverlay,
|
ImageDiffOverlay,
|
||||||
NotDiffableViewer,
|
NotDiffableViewer,
|
||||||
NoPreviewViewer,
|
NoPreviewViewer,
|
||||||
userAvatarLink,
|
UserAvatarLink,
|
||||||
DiffFileDrafts,
|
DiffFileDrafts,
|
||||||
},
|
},
|
||||||
mixins: [diffLineNoteFormMixin, draftCommentsMixin],
|
mixins: [diffLineNoteFormMixin, draftCommentsMixin],
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
import { GlIcon } from '@gitlab/ui';
|
import { GlIcon } from '@gitlab/ui';
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
|
import DesignNotePin from '~/vue_shared/components/design_management/design_note_pin.vue';
|
||||||
import noteableDiscussion from '~/notes/components/noteable_discussion.vue';
|
import NoteableDiscussion from '~/notes/components/noteable_discussion.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
noteableDiscussion,
|
NoteableDiscussion,
|
||||||
GlIcon,
|
GlIcon,
|
||||||
DesignNotePin,
|
DesignNotePin,
|
||||||
},
|
},
|
||||||
|
|
|
@ -7,7 +7,7 @@ import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
|
||||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||||
import MultilineCommentForm from '~/notes/components/multiline_comment_form.vue';
|
import MultilineCommentForm from '~/notes/components/multiline_comment_form.vue';
|
||||||
import { commentLineOptions, formatLineRange } from '~/notes/components/multiline_comment_utils';
|
import { commentLineOptions, formatLineRange } from '~/notes/components/multiline_comment_utils';
|
||||||
import noteForm from '~/notes/components/note_form.vue';
|
import NoteForm from '~/notes/components/note_form.vue';
|
||||||
import autosave from '~/notes/mixins/autosave';
|
import autosave from '~/notes/mixins/autosave';
|
||||||
import {
|
import {
|
||||||
DIFF_NOTE_TYPE,
|
DIFF_NOTE_TYPE,
|
||||||
|
@ -18,7 +18,7 @@ import {
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
noteForm,
|
NoteForm,
|
||||||
MultilineCommentForm,
|
MultilineCommentForm,
|
||||||
},
|
},
|
||||||
mixins: [autosave, diffLineNoteFormMixin, glFeatureFlagsMixin()],
|
mixins: [autosave, diffLineNoteFormMixin, glFeatureFlagsMixin()],
|
||||||
|
|
|
@ -3,7 +3,7 @@ import { mapActions, mapState, mapGetters } from 'vuex';
|
||||||
import { getCookie, parseBoolean, removeCookie } from '~/lib/utils/common_utils';
|
import { getCookie, parseBoolean, removeCookie } from '~/lib/utils/common_utils';
|
||||||
|
|
||||||
import eventHub from '../notes/event_hub';
|
import eventHub from '../notes/event_hub';
|
||||||
import diffsApp from './components/app.vue';
|
import DiffsApp from './components/app.vue';
|
||||||
|
|
||||||
import { TREE_LIST_STORAGE_KEY, DIFF_WHITESPACE_COOKIE_NAME } from './constants';
|
import { TREE_LIST_STORAGE_KEY, DIFF_WHITESPACE_COOKIE_NAME } from './constants';
|
||||||
import { getReviewsForMergeRequest } from './utils/file_reviews';
|
import { getReviewsForMergeRequest } from './utils/file_reviews';
|
||||||
|
@ -14,7 +14,7 @@ export default function initDiffsApp(store) {
|
||||||
el: '#js-diffs-app',
|
el: '#js-diffs-app',
|
||||||
name: 'MergeRequestDiffs',
|
name: 'MergeRequestDiffs',
|
||||||
components: {
|
components: {
|
||||||
diffsApp,
|
DiffsApp,
|
||||||
},
|
},
|
||||||
store,
|
store,
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -20,13 +20,13 @@ import {
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import { s__, n__ } from '~/locale';
|
import { s__, n__ } from '~/locale';
|
||||||
import instanceComponent from '~/vue_shared/components/deployment_instance.vue';
|
import InstanceComponent from '~/vue_shared/components/deployment_instance.vue';
|
||||||
import { STATUS_MAP, CANARY_STATUS } from '../constants';
|
import { STATUS_MAP, CANARY_STATUS } from '../constants';
|
||||||
import CanaryIngress from './canary_ingress.vue';
|
import CanaryIngress from './canary_ingress.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
instanceComponent,
|
InstanceComponent,
|
||||||
CanaryIngress,
|
CanaryIngress,
|
||||||
GlIcon,
|
GlIcon,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import Vue from 'vue';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import createDefaultClient from '~/lib/graphql';
|
import createDefaultClient from '~/lib/graphql';
|
||||||
import Translate from '~/vue_shared/translate';
|
import Translate from '~/vue_shared/translate';
|
||||||
import environmentsFolderApp from './environments_folder_view.vue';
|
import EnvironmentsFolderApp from './environments_folder_view.vue';
|
||||||
|
|
||||||
Vue.use(Translate);
|
Vue.use(Translate);
|
||||||
Vue.use(VueApollo);
|
Vue.use(VueApollo);
|
||||||
|
@ -17,7 +17,7 @@ export default () => {
|
||||||
return new Vue({
|
return new Vue({
|
||||||
el,
|
el,
|
||||||
components: {
|
components: {
|
||||||
environmentsFolderApp,
|
EnvironmentsFolderApp,
|
||||||
},
|
},
|
||||||
apolloProvider,
|
apolloProvider,
|
||||||
provide: {
|
provide: {
|
||||||
|
|
|
@ -21,10 +21,10 @@ import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE, ITEM_TYPE } from '../const
|
||||||
|
|
||||||
import eventHub from '../event_hub';
|
import eventHub from '../event_hub';
|
||||||
|
|
||||||
import itemActions from './item_actions.vue';
|
import ItemActions from './item_actions.vue';
|
||||||
import itemCaret from './item_caret.vue';
|
import ItemCaret from './item_caret.vue';
|
||||||
import itemStats from './item_stats.vue';
|
import ItemStats from './item_stats.vue';
|
||||||
import itemTypeIcon from './item_type_icon.vue';
|
import ItemTypeIcon from './item_type_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
directives: {
|
directives: {
|
||||||
|
@ -41,10 +41,10 @@ export default {
|
||||||
GlPopover,
|
GlPopover,
|
||||||
GlLink,
|
GlLink,
|
||||||
UserAccessRoleBadge,
|
UserAccessRoleBadge,
|
||||||
itemCaret,
|
ItemCaret,
|
||||||
itemTypeIcon,
|
ItemTypeIcon,
|
||||||
itemActions,
|
ItemActions,
|
||||||
itemStats,
|
ItemStats,
|
||||||
},
|
},
|
||||||
inject: ['currentGroupVisibility'],
|
inject: ['currentGroupVisibility'],
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlBadge } from '@gitlab/ui';
|
import { GlBadge } from '@gitlab/ui';
|
||||||
import isProjectPendingRemoval from 'ee_else_ce/groups/mixins/is_project_pending_removal';
|
import isProjectPendingRemoval from 'ee_else_ce/groups/mixins/is_project_pending_removal';
|
||||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||||
import {
|
import {
|
||||||
ITEM_TYPE,
|
ITEM_TYPE,
|
||||||
VISIBILITY_TYPE_ICON,
|
VISIBILITY_TYPE_ICON,
|
||||||
GROUP_VISIBILITY_TYPE,
|
GROUP_VISIBILITY_TYPE,
|
||||||
PROJECT_VISIBILITY_TYPE,
|
PROJECT_VISIBILITY_TYPE,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import itemStatsValue from './item_stats_value.vue';
|
import ItemStatsValue from './item_stats_value.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
timeAgoTooltip,
|
TimeAgoTooltip,
|
||||||
itemStatsValue,
|
ItemStatsValue,
|
||||||
GlBadge,
|
GlBadge,
|
||||||
},
|
},
|
||||||
mixins: [isProjectPendingRemoval],
|
mixins: [isProjectPendingRemoval],
|
||||||
|
|
|
@ -4,9 +4,9 @@ import { parseBoolean } from '~/lib/utils/common_utils';
|
||||||
import UserCallout from '~/user_callout';
|
import UserCallout from '~/user_callout';
|
||||||
import Translate from '../vue_shared/translate';
|
import Translate from '../vue_shared/translate';
|
||||||
|
|
||||||
import groupsApp from './components/app.vue';
|
import GroupsApp from './components/app.vue';
|
||||||
import groupFolderComponent from './components/group_folder.vue';
|
import GroupFolderComponent from './components/group_folder.vue';
|
||||||
import groupItemComponent from './components/group_item.vue';
|
import GroupItemComponent from './components/group_item.vue';
|
||||||
import { GROUPS_LIST_HOLDER_CLASS, CONTENT_LIST_CLASS } from './constants';
|
import { GROUPS_LIST_HOLDER_CLASS, CONTENT_LIST_CLASS } from './constants';
|
||||||
import GroupFilterableList from './groups_filterable_list';
|
import GroupFilterableList from './groups_filterable_list';
|
||||||
import GroupsService from './service/groups_service';
|
import GroupsService from './service/groups_service';
|
||||||
|
@ -33,8 +33,8 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => {
|
||||||
dataEl = containerEl.querySelector(CONTENT_LIST_CLASS);
|
dataEl = containerEl.querySelector(CONTENT_LIST_CLASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
Vue.component('GroupFolder', groupFolderComponent);
|
Vue.component('GroupFolder', GroupFolderComponent);
|
||||||
Vue.component('GroupItem', groupItemComponent);
|
Vue.component('GroupItem', GroupItemComponent);
|
||||||
|
|
||||||
Vue.use(GlToast);
|
Vue.use(GlToast);
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ export default (containerId = 'js-groups-tree', endpoint, action = '') => {
|
||||||
new Vue({
|
new Vue({
|
||||||
el,
|
el,
|
||||||
components: {
|
components: {
|
||||||
groupsApp,
|
GroupsApp,
|
||||||
},
|
},
|
||||||
provide() {
|
provide() {
|
||||||
const {
|
const {
|
||||||
|
|
|
@ -26,11 +26,17 @@ export const GROUPS_CATEGORY = s__('GlobalSearch|Groups');
|
||||||
|
|
||||||
export const PROJECTS_CATEGORY = s__('GlobalSearch|Projects');
|
export const PROJECTS_CATEGORY = s__('GlobalSearch|Projects');
|
||||||
|
|
||||||
export const ISSUES_CATEGORY = 'Recent issues';
|
export const ISSUES_CATEGORY = s__('GlobalSearch|Recent issues');
|
||||||
|
|
||||||
export const MERGE_REQUEST_CATEGORY = 'Recent merge requests';
|
export const MERGE_REQUEST_CATEGORY = s__('GlobalSearch|Recent merge requests');
|
||||||
|
|
||||||
export const RECENT_EPICS_CATEGORY = 'Recent epics';
|
export const RECENT_EPICS_CATEGORY = s__('GlobalSearch|Recent epics');
|
||||||
|
|
||||||
|
export const IN_THIS_PROJECT_CATEGORY = s__('GlobalSearch|In this project');
|
||||||
|
|
||||||
|
export const SETTINGS_CATEGORY = s__('GlobalSearch|Settings');
|
||||||
|
|
||||||
|
export const HELP_CATEGORY = s__('GlobalSearch|Help');
|
||||||
|
|
||||||
export const LARGE_AVATAR_PX = 32;
|
export const LARGE_AVATAR_PX = 32;
|
||||||
|
|
||||||
|
@ -55,3 +61,16 @@ export const HEADER_INIT_EVENTS = ['input', 'focus'];
|
||||||
export const IS_SEARCHING = 'is-searching';
|
export const IS_SEARCHING = 'is-searching';
|
||||||
export const IS_FOCUSED = 'is-focused';
|
export const IS_FOCUSED = 'is-focused';
|
||||||
export const IS_NOT_FOCUSED = 'is-not-focused';
|
export const IS_NOT_FOCUSED = 'is-not-focused';
|
||||||
|
|
||||||
|
export const DROPDOWN_ORDER = [
|
||||||
|
MERGE_REQUEST_CATEGORY,
|
||||||
|
ISSUES_CATEGORY,
|
||||||
|
RECENT_EPICS_CATEGORY,
|
||||||
|
GROUPS_CATEGORY,
|
||||||
|
PROJECTS_CATEGORY,
|
||||||
|
IN_THIS_PROJECT_CATEGORY,
|
||||||
|
SETTINGS_CATEGORY,
|
||||||
|
HELP_CATEGORY,
|
||||||
|
];
|
||||||
|
|
||||||
|
export const FETCH_TYPES = ['generic', 'search'];
|
||||||
|
|
|
@ -1,10 +1,26 @@
|
||||||
|
import { omitBy, isNil } from 'lodash';
|
||||||
|
import { objectToQuery } from '~/lib/utils/url_utility';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
|
import { FETCH_TYPES } from '../constants';
|
||||||
import * as types from './mutation_types';
|
import * as types from './mutation_types';
|
||||||
|
|
||||||
export const fetchAutocompleteOptions = ({ commit, getters }) => {
|
export const autocompleteQuery = ({ state, fetchType }) => {
|
||||||
commit(types.REQUEST_AUTOCOMPLETE);
|
const query = omitBy(
|
||||||
|
{
|
||||||
|
term: state.search,
|
||||||
|
project_id: state.searchContext?.project?.id,
|
||||||
|
project_ref: state.searchContext?.ref,
|
||||||
|
filter: fetchType,
|
||||||
|
},
|
||||||
|
isNil,
|
||||||
|
);
|
||||||
|
|
||||||
|
return `${state.autocompletePath}?${objectToQuery(query)}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const doFetch = ({ commit, state, fetchType }) => {
|
||||||
return axios
|
return axios
|
||||||
.get(getters.autocompleteQuery)
|
.get(autocompleteQuery({ state, fetchType }))
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
commit(types.RECEIVE_AUTOCOMPLETE_SUCCESS, data);
|
commit(types.RECEIVE_AUTOCOMPLETE_SUCCESS, data);
|
||||||
})
|
})
|
||||||
|
@ -13,6 +29,13 @@ export const fetchAutocompleteOptions = ({ commit, getters }) => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fetchAutocompleteOptions = ({ commit, state }) => {
|
||||||
|
commit(types.REQUEST_AUTOCOMPLETE);
|
||||||
|
const promises = FETCH_TYPES.map((fetchType) => doFetch({ commit, state, fetchType }));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
|
};
|
||||||
|
|
||||||
export const clearAutocomplete = ({ commit }) => {
|
export const clearAutocomplete = ({ commit }) => {
|
||||||
commit(types.CLEAR_AUTOCOMPLETE);
|
commit(types.CLEAR_AUTOCOMPLETE);
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,6 +14,7 @@ import {
|
||||||
PROJECTS_CATEGORY,
|
PROJECTS_CATEGORY,
|
||||||
GROUPS_CATEGORY,
|
GROUPS_CATEGORY,
|
||||||
SEARCH_SHORTCUTS_MIN_CHARACTERS,
|
SEARCH_SHORTCUTS_MIN_CHARACTERS,
|
||||||
|
DROPDOWN_ORDER,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
|
|
||||||
export const searchQuery = (state) => {
|
export const searchQuery = (state) => {
|
||||||
|
@ -34,19 +35,6 @@ export const searchQuery = (state) => {
|
||||||
return `${state.searchPath}?${objectToQuery(query)}`;
|
return `${state.searchPath}?${objectToQuery(query)}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const autocompleteQuery = (state) => {
|
|
||||||
const query = omitBy(
|
|
||||||
{
|
|
||||||
term: state.search,
|
|
||||||
project_id: state.searchContext?.project?.id,
|
|
||||||
project_ref: state.searchContext?.ref,
|
|
||||||
},
|
|
||||||
isNil,
|
|
||||||
);
|
|
||||||
|
|
||||||
return `${state.autocompletePath}?${objectToQuery(query)}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const scopedIssuesPath = (state) => {
|
export const scopedIssuesPath = (state) => {
|
||||||
return (
|
return (
|
||||||
state.searchContext?.project_metadata?.issues_path ||
|
state.searchContext?.project_metadata?.issues_path ||
|
||||||
|
@ -197,7 +185,9 @@ export const autocompleteGroupedSearchOptions = (state) => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return results;
|
return results.sort(
|
||||||
|
(a, b) => DROPDOWN_ORDER.indexOf(a.category) - DROPDOWN_ORDER.indexOf(b.category),
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const searchOptions = (state, getters) => {
|
export const searchOptions = (state, getters) => {
|
||||||
|
|
|
@ -8,9 +8,11 @@ export default {
|
||||||
},
|
},
|
||||||
[types.RECEIVE_AUTOCOMPLETE_SUCCESS](state, data) {
|
[types.RECEIVE_AUTOCOMPLETE_SUCCESS](state, data) {
|
||||||
state.loading = false;
|
state.loading = false;
|
||||||
state.autocompleteOptions = data.map((d, i) => {
|
state.autocompleteOptions = [...state.autocompleteOptions].concat(
|
||||||
return { html_id: `autocomplete-${d.category}-${i}`, ...d };
|
data.map((d, i) => {
|
||||||
});
|
return { html_id: `autocomplete-${d.category}-${i}`, ...d };
|
||||||
|
}),
|
||||||
|
);
|
||||||
state.autocompleteError = false;
|
state.autocompleteError = false;
|
||||||
},
|
},
|
||||||
[types.RECEIVE_AUTOCOMPLETE_ERROR](state) {
|
[types.RECEIVE_AUTOCOMPLETE_ERROR](state) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { GlIcon, GlTooltipDirective } from '@gitlab/ui';
|
||||||
import { mapActions, mapState, mapGetters } from 'vuex';
|
import { mapActions, mapState, mapGetters } from 'vuex';
|
||||||
import timeAgoMixin from '~/vue_shared/mixins/timeago';
|
import timeAgoMixin from '~/vue_shared/mixins/timeago';
|
||||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||||
import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
import { rightSidebarViews } from '../constants';
|
import { rightSidebarViews } from '../constants';
|
||||||
import IdeStatusList from './ide_status_list.vue';
|
import IdeStatusList from './ide_status_list.vue';
|
||||||
import IdeStatusMr from './ide_status_mr.vue';
|
import IdeStatusMr from './ide_status_mr.vue';
|
||||||
|
@ -12,7 +12,7 @@ import IdeStatusMr from './ide_status_mr.vue';
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
GlIcon,
|
GlIcon,
|
||||||
userAvatarImage,
|
UserAvatarImage,
|
||||||
CiIcon,
|
CiIcon,
|
||||||
IdeStatusList,
|
IdeStatusList,
|
||||||
IdeStatusMr,
|
IdeStatusMr,
|
||||||
|
|
|
@ -4,12 +4,12 @@ import { mapActions } from 'vuex';
|
||||||
import { modalTypes } from '../../constants';
|
import { modalTypes } from '../../constants';
|
||||||
import ItemButton from './button.vue';
|
import ItemButton from './button.vue';
|
||||||
import NewModal from './modal.vue';
|
import NewModal from './modal.vue';
|
||||||
import upload from './upload.vue';
|
import Upload from './upload.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
GlIcon,
|
GlIcon,
|
||||||
upload,
|
Upload,
|
||||||
ItemButton,
|
ItemButton,
|
||||||
NewModal,
|
NewModal,
|
||||||
},
|
},
|
||||||
|
|
|
@ -17,11 +17,11 @@ import eventHub from '../event_hub';
|
||||||
import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
|
import getIssueStateQuery from '../queries/get_issue_state.query.graphql';
|
||||||
import Service from '../services/index';
|
import Service from '../services/index';
|
||||||
import Store from '../stores';
|
import Store from '../stores';
|
||||||
import descriptionComponent from './description.vue';
|
import DescriptionComponent from './description.vue';
|
||||||
import editedComponent from './edited.vue';
|
import EditedComponent from './edited.vue';
|
||||||
import formComponent from './form.vue';
|
import FormComponent from './form.vue';
|
||||||
import PinnedLinks from './pinned_links.vue';
|
import PinnedLinks from './pinned_links.vue';
|
||||||
import titleComponent from './title.vue';
|
import TitleComponent from './title.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
WorkspaceType,
|
WorkspaceType,
|
||||||
|
@ -29,9 +29,9 @@ export default {
|
||||||
GlIcon,
|
GlIcon,
|
||||||
GlBadge,
|
GlBadge,
|
||||||
GlIntersectionObserver,
|
GlIntersectionObserver,
|
||||||
titleComponent,
|
TitleComponent,
|
||||||
editedComponent,
|
EditedComponent,
|
||||||
formComponent,
|
FormComponent,
|
||||||
PinnedLinks,
|
PinnedLinks,
|
||||||
ConfidentialityBadge,
|
ConfidentialityBadge,
|
||||||
},
|
},
|
||||||
|
@ -181,7 +181,7 @@ export default {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: false,
|
required: false,
|
||||||
default: () => {
|
default: () => {
|
||||||
return descriptionComponent;
|
return DescriptionComponent;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
showTitleBorder: {
|
showTitleBorder: {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
/* eslint-disable @gitlab/vue-require-i18n-strings */
|
/* eslint-disable @gitlab/vue-require-i18n-strings */
|
||||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
timeAgoTooltip,
|
TimeAgoTooltip,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
updatedAt: {
|
updatedAt: {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
import markdownField from '~/vue_shared/components/markdown/field.vue';
|
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
|
||||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||||
import updateMixin from '../../mixins/update';
|
import updateMixin from '../../mixins/update';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
markdownField,
|
MarkdownField,
|
||||||
},
|
},
|
||||||
mixins: [updateMixin],
|
mixins: [updateMixin],
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -4,14 +4,14 @@ import { isEmpty } from 'lodash';
|
||||||
import Mousetrap from 'mousetrap';
|
import Mousetrap from 'mousetrap';
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||||
import clipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
|
||||||
import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard';
|
import { clickCopyToClipboardButton } from '~/behaviors/copy_to_clipboard';
|
||||||
import { keysFor, MR_COPY_SOURCE_BRANCH_NAME } from '~/behaviors/shortcuts/keybindings';
|
import { keysFor, MR_COPY_SOURCE_BRANCH_NAME } from '~/behaviors/shortcuts/keybindings';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
CiIcon,
|
CiIcon,
|
||||||
clipboardButton,
|
ClipboardButton,
|
||||||
GlDropdown,
|
GlDropdown,
|
||||||
GlDropdownItem,
|
GlDropdownItem,
|
||||||
GlLink,
|
GlLink,
|
||||||
|
|
|
@ -22,7 +22,7 @@ export default function initLinkedResources() {
|
||||||
name: 'LinkedResourcesRoot',
|
name: 'LinkedResourcesRoot',
|
||||||
apolloProvider,
|
apolloProvider,
|
||||||
components: {
|
components: {
|
||||||
resourceLinksBlock: ResourceLinksBlock,
|
ResourceLinksBlock,
|
||||||
},
|
},
|
||||||
render: (createElement) =>
|
render: (createElement) =>
|
||||||
createElement('resource-links-block', {
|
createElement('resource-links-block', {
|
||||||
|
|
|
@ -5,7 +5,7 @@ import initRevertCommitModal from '~/projects/commit/init_revert_commit_modal';
|
||||||
import initDiffsApp from '../diffs';
|
import initDiffsApp from '../diffs';
|
||||||
import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
|
import { resetServiceWorkersPublicPath } from '../lib/utils/webpack';
|
||||||
import MergeRequest from '../merge_request';
|
import MergeRequest from '../merge_request';
|
||||||
import discussionCounter from '../notes/components/discussion_counter.vue';
|
import DiscussionCounter from '../notes/components/discussion_counter.vue';
|
||||||
import initDiscussionFilters from '../notes/discussion_filters';
|
import initDiscussionFilters from '../notes/discussion_filters';
|
||||||
import initNotesApp from './init_notes';
|
import initNotesApp from './init_notes';
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ export default function initMrNotes() {
|
||||||
el,
|
el,
|
||||||
name: 'DiscussionCounter',
|
name: 'DiscussionCounter',
|
||||||
components: {
|
components: {
|
||||||
discussionCounter,
|
DiscussionCounter,
|
||||||
},
|
},
|
||||||
store,
|
store,
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { mapActions, mapState, mapGetters } from 'vuex';
|
||||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||||
import store from '~/mr_notes/stores';
|
import store from '~/mr_notes/stores';
|
||||||
import discussionNavigator from '../notes/components/discussion_navigator.vue';
|
import discussionNavigator from '../notes/components/discussion_navigator.vue';
|
||||||
import notesApp from '../notes/components/notes_app.vue';
|
import NotesApp from '../notes/components/notes_app.vue';
|
||||||
import initWidget from '../vue_merge_request_widget';
|
import initWidget from '../vue_merge_request_widget';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
|
@ -13,7 +13,7 @@ export default () => {
|
||||||
el: '#js-vue-mr-discussions',
|
el: '#js-vue-mr-discussions',
|
||||||
name: 'MergeRequestDiscussions',
|
name: 'MergeRequestDiscussions',
|
||||||
components: {
|
components: {
|
||||||
notesApp,
|
NotesApp,
|
||||||
},
|
},
|
||||||
store,
|
store,
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -137,7 +137,7 @@ marked.setOptions({
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
prompt: Prompt,
|
Prompt,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
SafeHtml,
|
SafeHtml,
|
||||||
|
|
|
@ -3,7 +3,7 @@ import Prompt from '../prompt.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
prompt: Prompt,
|
Prompt,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
count: {
|
count: {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import {
|
||||||
slugifyWithUnderscore,
|
slugifyWithUnderscore,
|
||||||
} from '~/lib/utils/text_utility';
|
} from '~/lib/utils/text_utility';
|
||||||
import { sprintf } from '~/locale';
|
import { sprintf } from '~/locale';
|
||||||
import markdownField from '~/vue_shared/components/markdown/field.vue';
|
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
|
||||||
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
||||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||||
|
|
||||||
|
@ -25,8 +25,8 @@ import { COMMENT_FORM } from '../i18n';
|
||||||
import issuableStateMixin from '../mixins/issuable_state';
|
import issuableStateMixin from '../mixins/issuable_state';
|
||||||
import CommentFieldLayout from './comment_field_layout.vue';
|
import CommentFieldLayout from './comment_field_layout.vue';
|
||||||
import CommentTypeDropdown from './comment_type_dropdown.vue';
|
import CommentTypeDropdown from './comment_type_dropdown.vue';
|
||||||
import discussionLockedWidget from './discussion_locked_widget.vue';
|
import DiscussionLockedWidget from './discussion_locked_widget.vue';
|
||||||
import noteSignedOutWidget from './note_signed_out_widget.vue';
|
import NoteSignedOutWidget from './note_signed_out_widget.vue';
|
||||||
|
|
||||||
const { UNPROCESSABLE_ENTITY } = httpStatusCodes;
|
const { UNPROCESSABLE_ENTITY } = httpStatusCodes;
|
||||||
|
|
||||||
|
@ -34,9 +34,9 @@ export default {
|
||||||
name: 'CommentForm',
|
name: 'CommentForm',
|
||||||
i18n: COMMENT_FORM,
|
i18n: COMMENT_FORM,
|
||||||
components: {
|
components: {
|
||||||
noteSignedOutWidget,
|
NoteSignedOutWidget,
|
||||||
discussionLockedWidget,
|
DiscussionLockedWidget,
|
||||||
markdownField,
|
MarkdownField,
|
||||||
GlAlert,
|
GlAlert,
|
||||||
GlButton,
|
GlButton,
|
||||||
TimelineEntryItem,
|
TimelineEntryItem,
|
||||||
|
|
|
@ -4,16 +4,16 @@ import { escape } from 'lodash';
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import { truncateSha } from '~/lib/utils/text_utility';
|
import { truncateSha } from '~/lib/utils/text_utility';
|
||||||
import { s__, __, sprintf } from '~/locale';
|
import { s__, __, sprintf } from '~/locale';
|
||||||
import noteEditedText from './note_edited_text.vue';
|
import NoteEditedText from './note_edited_text.vue';
|
||||||
import noteHeader from './note_header.vue';
|
import NoteHeader from './note_header.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DiffDiscussionHeader',
|
name: 'DiffDiscussionHeader',
|
||||||
components: {
|
components: {
|
||||||
GlAvatar,
|
GlAvatar,
|
||||||
GlAvatarLink,
|
GlAvatarLink,
|
||||||
noteEditedText,
|
NoteEditedText,
|
||||||
noteHeader,
|
NoteHeader,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
SafeHtml,
|
SafeHtml,
|
||||||
|
|
|
@ -8,17 +8,17 @@ import { __ } from '~/locale';
|
||||||
import '~/behaviors/markdown/render_gfm';
|
import '~/behaviors/markdown/render_gfm';
|
||||||
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
|
import Suggestions from '~/vue_shared/components/markdown/suggestions.vue';
|
||||||
import autosave from '../mixins/autosave';
|
import autosave from '../mixins/autosave';
|
||||||
import noteAttachment from './note_attachment.vue';
|
import NoteAttachment from './note_attachment.vue';
|
||||||
import noteAwardsList from './note_awards_list.vue';
|
import NoteAwardsList from './note_awards_list.vue';
|
||||||
import noteEditedText from './note_edited_text.vue';
|
import NoteEditedText from './note_edited_text.vue';
|
||||||
import noteForm from './note_form.vue';
|
import NoteForm from './note_form.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
noteEditedText,
|
NoteEditedText,
|
||||||
noteAwardsList,
|
NoteAwardsList,
|
||||||
noteAttachment,
|
NoteAttachment,
|
||||||
noteForm,
|
NoteForm,
|
||||||
Suggestions,
|
Suggestions,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
<script>
|
<script>
|
||||||
/* eslint-disable @gitlab/vue-require-i18n-strings */
|
/* eslint-disable @gitlab/vue-require-i18n-strings */
|
||||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'EditedNoteText',
|
name: 'EditedNoteText',
|
||||||
components: {
|
components: {
|
||||||
timeAgoTooltip,
|
TimeAgoTooltip,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
actionText: {
|
actionText: {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { mapGetters, mapActions, mapState } from 'vuex';
|
||||||
import { getDraft, updateDraft } from '~/lib/utils/autosave';
|
import { getDraft, updateDraft } from '~/lib/utils/autosave';
|
||||||
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import markdownField from '~/vue_shared/components/markdown/field.vue';
|
import MarkdownField from '~/vue_shared/components/markdown/field.vue';
|
||||||
import eventHub from '../event_hub';
|
import eventHub from '../event_hub';
|
||||||
import issuableStateMixin from '../mixins/issuable_state';
|
import issuableStateMixin from '../mixins/issuable_state';
|
||||||
import resolvable from '../mixins/resolvable';
|
import resolvable from '../mixins/resolvable';
|
||||||
|
@ -15,7 +15,7 @@ export default {
|
||||||
i18n: COMMENT_FORM,
|
i18n: COMMENT_FORM,
|
||||||
name: 'NoteForm',
|
name: 'NoteForm',
|
||||||
components: {
|
components: {
|
||||||
markdownField,
|
MarkdownField,
|
||||||
CommentFieldLayout,
|
CommentFieldLayout,
|
||||||
GlButton,
|
GlButton,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
|
|
|
@ -8,13 +8,13 @@ import {
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import { mapActions } from 'vuex';
|
import { mapActions } from 'vuex';
|
||||||
import { __, s__ } from '~/locale';
|
import { __, s__ } from '~/locale';
|
||||||
import timeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||||
import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
|
import UserNameWithStatus from '~/sidebar/components/assignees/user_name_with_status.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
|
safeHtmlConfig: { ADD_TAGS: ['gl-emoji'] },
|
||||||
components: {
|
components: {
|
||||||
timeAgoTooltip,
|
TimeAgoTooltip,
|
||||||
GitlabTeamMemberBadge: () =>
|
GitlabTeamMemberBadge: () =>
|
||||||
import('ee_component/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'),
|
import('ee_component/vue_shared/components/user_avatar/badges/gitlab_team_member_badge.vue'),
|
||||||
GlIcon,
|
GlIcon,
|
||||||
|
|
|
@ -10,25 +10,25 @@ import { ignoreWhilePending } from '~/lib/utils/ignore_while_pending';
|
||||||
import { s__, __, sprintf } from '~/locale';
|
import { s__, __, sprintf } from '~/locale';
|
||||||
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
|
import diffLineNoteFormMixin from '~/notes/mixins/diff_line_note_form';
|
||||||
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
||||||
import userAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
import UserAvatarLink from '~/vue_shared/components/user_avatar/user_avatar_link.vue';
|
||||||
import eventHub from '../event_hub';
|
import eventHub from '../event_hub';
|
||||||
import noteable from '../mixins/noteable';
|
import noteable from '../mixins/noteable';
|
||||||
import resolvable from '../mixins/resolvable';
|
import resolvable from '../mixins/resolvable';
|
||||||
import diffDiscussionHeader from './diff_discussion_header.vue';
|
import DiffDiscussionHeader from './diff_discussion_header.vue';
|
||||||
import diffWithNote from './diff_with_note.vue';
|
import DiffWithNote from './diff_with_note.vue';
|
||||||
import DiscussionActions from './discussion_actions.vue';
|
import DiscussionActions from './discussion_actions.vue';
|
||||||
import DiscussionNotes from './discussion_notes.vue';
|
import DiscussionNotes from './discussion_notes.vue';
|
||||||
import noteForm from './note_form.vue';
|
import NoteForm from './note_form.vue';
|
||||||
import noteSignedOutWidget from './note_signed_out_widget.vue';
|
import NoteSignedOutWidget from './note_signed_out_widget.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NoteableDiscussion',
|
name: 'NoteableDiscussion',
|
||||||
components: {
|
components: {
|
||||||
GlIcon,
|
GlIcon,
|
||||||
userAvatarLink,
|
UserAvatarLink,
|
||||||
diffDiscussionHeader,
|
DiffDiscussionHeader,
|
||||||
noteSignedOutWidget,
|
NoteSignedOutWidget,
|
||||||
noteForm,
|
NoteForm,
|
||||||
DraftNote,
|
DraftNote,
|
||||||
TimelineEntryItem,
|
TimelineEntryItem,
|
||||||
DiscussionNotes,
|
DiscussionNotes,
|
||||||
|
@ -120,7 +120,7 @@ export default {
|
||||||
return !this.shouldRenderDiffs;
|
return !this.shouldRenderDiffs;
|
||||||
},
|
},
|
||||||
wrapperComponent() {
|
wrapperComponent() {
|
||||||
return this.shouldRenderDiffs ? diffWithNote : 'div';
|
return this.shouldRenderDiffs ? DiffWithNote : 'div';
|
||||||
},
|
},
|
||||||
wrapperComponentProps() {
|
wrapperComponentProps() {
|
||||||
if (this.shouldRenderDiffs) {
|
if (this.shouldRenderDiffs) {
|
||||||
|
|
|
@ -22,16 +22,16 @@ import {
|
||||||
commentLineOptions,
|
commentLineOptions,
|
||||||
formatLineRange,
|
formatLineRange,
|
||||||
} from './multiline_comment_utils';
|
} from './multiline_comment_utils';
|
||||||
import noteActions from './note_actions.vue';
|
import NoteActions from './note_actions.vue';
|
||||||
import NoteBody from './note_body.vue';
|
import NoteBody from './note_body.vue';
|
||||||
import noteHeader from './note_header.vue';
|
import NoteHeader from './note_header.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NoteableNote',
|
name: 'NoteableNote',
|
||||||
components: {
|
components: {
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
noteHeader,
|
NoteHeader,
|
||||||
noteActions,
|
NoteActions,
|
||||||
NoteBody,
|
NoteBody,
|
||||||
TimelineEntryItem,
|
TimelineEntryItem,
|
||||||
GlAvatarLink,
|
GlAvatarLink,
|
||||||
|
|
|
@ -6,34 +6,34 @@ import { __ } from '~/locale';
|
||||||
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
|
||||||
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
|
import OrderedLayout from '~/vue_shared/components/ordered_layout.vue';
|
||||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||||
import draftNote from '~/batch_comments/components/draft_note.vue';
|
import DraftNote from '~/batch_comments/components/draft_note.vue';
|
||||||
import { getLocationHash, doesHashExistInUrl } from '~/lib/utils/url_utility';
|
import { getLocationHash, doesHashExistInUrl } from '~/lib/utils/url_utility';
|
||||||
import placeholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
|
import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
|
||||||
import placeholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
|
import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
|
||||||
import skeletonLoadingContainer from '~/vue_shared/components/notes/skeleton_note.vue';
|
import SkeletonLoadingContainer from '~/vue_shared/components/notes/skeleton_note.vue';
|
||||||
import systemNote from '~/vue_shared/components/notes/system_note.vue';
|
import SystemNote from '~/vue_shared/components/notes/system_note.vue';
|
||||||
import * as constants from '../constants';
|
import * as constants from '../constants';
|
||||||
import eventHub from '../event_hub';
|
import eventHub from '../event_hub';
|
||||||
import commentForm from './comment_form.vue';
|
import CommentForm from './comment_form.vue';
|
||||||
import discussionFilterNote from './discussion_filter_note.vue';
|
import DiscussionFilterNote from './discussion_filter_note.vue';
|
||||||
import noteableDiscussion from './noteable_discussion.vue';
|
import NoteableDiscussion from './noteable_discussion.vue';
|
||||||
import noteableNote from './noteable_note.vue';
|
import NoteableNote from './noteable_note.vue';
|
||||||
import SidebarSubscription from './sidebar_subscription.vue';
|
import SidebarSubscription from './sidebar_subscription.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'NotesApp',
|
name: 'NotesApp',
|
||||||
components: {
|
components: {
|
||||||
noteableNote,
|
NoteableNote,
|
||||||
noteableDiscussion,
|
NoteableDiscussion,
|
||||||
systemNote,
|
SystemNote,
|
||||||
commentForm,
|
CommentForm,
|
||||||
placeholderNote,
|
PlaceholderNote,
|
||||||
placeholderSystemNote,
|
PlaceholderSystemNote,
|
||||||
skeletonLoadingContainer,
|
SkeletonLoadingContainer,
|
||||||
discussionFilterNote,
|
DiscussionFilterNote,
|
||||||
OrderedLayout,
|
OrderedLayout,
|
||||||
SidebarSubscription,
|
SidebarSubscription,
|
||||||
draftNote,
|
DraftNote,
|
||||||
TimelineEntryItem,
|
TimelineEntryItem,
|
||||||
},
|
},
|
||||||
mixins: [glFeatureFlagsMixin()],
|
mixins: [glFeatureFlagsMixin()],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import notesApp from './components/notes_app.vue';
|
import NotesApp from './components/notes_app.vue';
|
||||||
import initDiscussionFilters from './discussion_filters';
|
import initDiscussionFilters from './discussion_filters';
|
||||||
import { store } from './stores';
|
import { store } from './stores';
|
||||||
import initTimelineToggle from './timeline';
|
import initTimelineToggle from './timeline';
|
||||||
|
@ -15,7 +15,7 @@ export default () => {
|
||||||
el,
|
el,
|
||||||
name: 'NotesRoot',
|
name: 'NotesRoot',
|
||||||
components: {
|
components: {
|
||||||
notesApp,
|
NotesApp,
|
||||||
},
|
},
|
||||||
store,
|
store,
|
||||||
data() {
|
data() {
|
||||||
|
|
|
@ -14,16 +14,17 @@ import NpmInstallation from './npm_installation.vue';
|
||||||
import NugetInstallation from './nuget_installation.vue';
|
import NugetInstallation from './nuget_installation.vue';
|
||||||
import PypiInstallation from './pypi_installation.vue';
|
import PypiInstallation from './pypi_installation.vue';
|
||||||
|
|
||||||
|
const components = {
|
||||||
|
[PACKAGE_TYPE_CONAN]: ConanInstallation,
|
||||||
|
[PACKAGE_TYPE_MAVEN]: MavenInstallation,
|
||||||
|
[PACKAGE_TYPE_NPM]: NpmInstallation,
|
||||||
|
[PACKAGE_TYPE_NUGET]: NugetInstallation,
|
||||||
|
[PACKAGE_TYPE_PYPI]: PypiInstallation,
|
||||||
|
[PACKAGE_TYPE_COMPOSER]: ComposerInstallation,
|
||||||
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'InstallationCommands',
|
name: 'InstallationCommands',
|
||||||
components: {
|
|
||||||
[PACKAGE_TYPE_CONAN]: ConanInstallation,
|
|
||||||
[PACKAGE_TYPE_MAVEN]: MavenInstallation,
|
|
||||||
[PACKAGE_TYPE_NPM]: NpmInstallation,
|
|
||||||
[PACKAGE_TYPE_NUGET]: NugetInstallation,
|
|
||||||
[PACKAGE_TYPE_PYPI]: PypiInstallation,
|
|
||||||
[PACKAGE_TYPE_COMPOSER]: ComposerInstallation,
|
|
||||||
},
|
|
||||||
props: {
|
props: {
|
||||||
packageEntity: {
|
packageEntity: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -32,7 +33,7 @@ export default {
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
installationComponent() {
|
installationComponent() {
|
||||||
return this.$options.components[this.packageEntity.packageType];
|
return components[this.packageEntity.packageType];
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
|
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
|
||||||
import Translate from '~/vue_shared/translate';
|
import Translate from '~/vue_shared/translate';
|
||||||
import stopJobsModal from './components/stop_jobs_modal.vue';
|
import StopJobsModal from './components/stop_jobs_modal.vue';
|
||||||
|
|
||||||
Vue.use(Translate);
|
Vue.use(Translate);
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ function initJobs() {
|
||||||
new Vue({
|
new Vue({
|
||||||
el: `#js-${modalId}`,
|
el: `#js-${modalId}`,
|
||||||
components: {
|
components: {
|
||||||
stopJobsModal,
|
StopJobsModal,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
stopJobsButton.classList.remove('disabled');
|
stopJobsButton.classList.remove('disabled');
|
||||||
|
|
|
@ -9,7 +9,7 @@ import GpgBadges from '~/gpg_badges';
|
||||||
import createDefaultClient from '~/lib/graphql';
|
import createDefaultClient from '~/lib/graphql';
|
||||||
import initBlob from '~/pages/projects/init_blob';
|
import initBlob from '~/pages/projects/init_blob';
|
||||||
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
|
import initWebIdeLink from '~/pages/projects/shared/web_ide_link';
|
||||||
import commitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
|
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
|
||||||
import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
|
import BlobContentViewer from '~/repository/components/blob_content_viewer.vue';
|
||||||
import '~/sourcegraph/load';
|
import '~/sourcegraph/load';
|
||||||
import createStore from '~/code_navigation/store';
|
import createStore from '~/code_navigation/store';
|
||||||
|
@ -64,7 +64,7 @@ if (statusLink) {
|
||||||
new Vue({
|
new Vue({
|
||||||
el: CommitPipelineStatusEl,
|
el: CommitPipelineStatusEl,
|
||||||
components: {
|
components: {
|
||||||
commitPipelineStatus,
|
CommitPipelineStatus,
|
||||||
},
|
},
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement('commit-pipeline-status', {
|
return createElement('commit-pipeline-status', {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { REF_TYPE_BRANCHES, REF_TYPE_TAGS } from '~/ref/constants';
|
||||||
import setupNativeFormVariableList from '~/ci_variable_list/native_form_variable_list';
|
import setupNativeFormVariableList from '~/ci_variable_list/native_form_variable_list';
|
||||||
import GlFieldErrors from '~/gl_field_errors';
|
import GlFieldErrors from '~/gl_field_errors';
|
||||||
import Translate from '~/vue_shared/translate';
|
import Translate from '~/vue_shared/translate';
|
||||||
import intervalPatternInput from './components/interval_pattern_input.vue';
|
import IntervalPatternInput from './components/interval_pattern_input.vue';
|
||||||
import TimezoneDropdown from './components/timezone_dropdown';
|
import TimezoneDropdown from './components/timezone_dropdown';
|
||||||
|
|
||||||
Vue.use(Translate);
|
Vue.use(Translate);
|
||||||
|
@ -19,7 +19,7 @@ function initIntervalPatternInput() {
|
||||||
return new Vue({
|
return new Vue({
|
||||||
el: intervalPatternMount,
|
el: intervalPatternMount,
|
||||||
components: {
|
components: {
|
||||||
intervalPatternInput,
|
IntervalPatternInput,
|
||||||
},
|
},
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement('interval-pattern-input', {
|
return createElement('interval-pattern-input', {
|
||||||
|
|
|
@ -14,8 +14,8 @@ import {
|
||||||
featureAccessLevelDescriptions,
|
featureAccessLevelDescriptions,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import { toggleHiddenClassBySelector } from '../external';
|
import { toggleHiddenClassBySelector } from '../external';
|
||||||
import projectFeatureSetting from './project_feature_setting.vue';
|
import ProjectFeatureSetting from './project_feature_setting.vue';
|
||||||
import projectSettingRow from './project_setting_row.vue';
|
import ProjectSettingRow from './project_setting_row.vue';
|
||||||
|
|
||||||
const FEATURE_ACCESS_LEVEL_ANONYMOUS = [30, s__('ProjectSettings|Everyone')];
|
const FEATURE_ACCESS_LEVEL_ANONYMOUS = [30, s__('ProjectSettings|Everyone')];
|
||||||
|
|
||||||
|
@ -56,8 +56,8 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
projectFeatureSetting,
|
ProjectFeatureSetting,
|
||||||
projectSettingRow,
|
ProjectSettingRow,
|
||||||
GlButton,
|
GlButton,
|
||||||
GlIcon,
|
GlIcon,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
|
@ -65,7 +65,7 @@ export default {
|
||||||
GlFormCheckbox,
|
GlFormCheckbox,
|
||||||
GlToggle,
|
GlToggle,
|
||||||
ConfirmDanger,
|
ConfirmDanger,
|
||||||
otherProjectSettings: () =>
|
OtherProjectSettings: () =>
|
||||||
import(
|
import(
|
||||||
'jh_component/pages/projects/shared/permissions/components/other_project_settings.vue'
|
'jh_component/pages/projects/shared/permissions/components/other_project_settings.vue'
|
||||||
),
|
),
|
||||||
|
|
|
@ -2,10 +2,10 @@
|
||||||
import pdfjsLib from 'pdfjs-dist/build/pdf';
|
import pdfjsLib from 'pdfjs-dist/build/pdf';
|
||||||
import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
|
import workerSrc from 'pdfjs-dist/build/pdf.worker.min';
|
||||||
|
|
||||||
import page from './page/index.vue';
|
import Page from './page/index.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { page },
|
components: { Page },
|
||||||
props: {
|
props: {
|
||||||
pdf: {
|
pdf: {
|
||||||
type: [String, Uint8Array],
|
type: [String, Uint8Array],
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
} from '@gitlab/ui';
|
} from '@gitlab/ui';
|
||||||
import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
|
import { setUrlFragment, redirectTo } from '~/lib/utils/url_utility';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import ciHeader from '~/vue_shared/components/header_ci_component.vue';
|
import CiHeader from '~/vue_shared/components/header_ci_component.vue';
|
||||||
import {
|
import {
|
||||||
LOAD_FAILURE,
|
LOAD_FAILURE,
|
||||||
POST_FAILURE,
|
POST_FAILURE,
|
||||||
|
@ -33,7 +33,7 @@ export default {
|
||||||
pipelineRetry: 'pipelineRetry',
|
pipelineRetry: 'pipelineRetry',
|
||||||
finishedStatuses: ['FAILED', 'SUCCESS', 'CANCELED'],
|
finishedStatuses: ['FAILED', 'SUCCESS', 'CANCELED'],
|
||||||
components: {
|
components: {
|
||||||
ciHeader,
|
CiHeader,
|
||||||
GlAlert,
|
GlAlert,
|
||||||
GlButton,
|
GlButton,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<script>
|
<script>
|
||||||
import ciIcon from '~/vue_shared/components/ci_icon.vue';
|
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that renders both the CI icon status and the job name.
|
* Component that renders both the CI icon status and the job name.
|
||||||
|
@ -9,7 +9,7 @@ import ciIcon from '~/vue_shared/components/ci_icon.vue';
|
||||||
*/
|
*/
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ciIcon,
|
CiIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
name: {
|
name: {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
<script>
|
<script>
|
||||||
import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
|
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
tooltipOnTruncate,
|
TooltipOnTruncate,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
jobName: {
|
jobName: {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { capitalize, escape } from 'lodash';
|
import { capitalize, escape } from 'lodash';
|
||||||
import tooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
|
import TooltipOnTruncate from '~/vue_shared/components/tooltip_on_truncate/tooltip_on_truncate.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
tooltipOnTruncate,
|
TooltipOnTruncate,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
stageName: {
|
stageName: {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import pipelineHeader from './components/header_component.vue';
|
import PipelineHeader from './components/header_component.vue';
|
||||||
|
|
||||||
Vue.use(VueApollo);
|
Vue.use(VueApollo);
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ export const createPipelineHeaderApp = (elSelector, apolloProvider, graphqlResou
|
||||||
new Vue({
|
new Vue({
|
||||||
el,
|
el,
|
||||||
components: {
|
components: {
|
||||||
pipelineHeader,
|
PipelineHeader,
|
||||||
},
|
},
|
||||||
apolloProvider,
|
apolloProvider,
|
||||||
provide: {
|
provide: {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
|
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
|
||||||
import Translate from '~/vue_shared/translate';
|
import Translate from '~/vue_shared/translate';
|
||||||
import deleteAccountModal from './components/delete_account_modal.vue';
|
import DeleteAccountModal from './components/delete_account_modal.vue';
|
||||||
import UpdateUsername from './components/update_username.vue';
|
import UpdateUsername from './components/update_username.vue';
|
||||||
|
|
||||||
export default () => {
|
export default () => {
|
||||||
|
@ -27,7 +27,7 @@ export default () => {
|
||||||
new Vue({
|
new Vue({
|
||||||
el: deleteAccountModalEl,
|
el: deleteAccountModalEl,
|
||||||
components: {
|
components: {
|
||||||
deleteAccountModal,
|
DeleteAccountModal,
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
deleteAccountButton.disabled = false;
|
deleteAccountButton.disabled = false;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import Visibility from 'visibilityjs';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import Poll from '~/lib/utils/poll';
|
import Poll from '~/lib/utils/poll';
|
||||||
import { __, s__, sprintf } from '~/locale';
|
import { __, s__, sprintf } from '~/locale';
|
||||||
import ciIcon from '~/vue_shared/components/ci_icon.vue';
|
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||||
import CommitPipelineService from '../services/commit_pipeline_service';
|
import CommitPipelineService from '../services/commit_pipeline_service';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -12,7 +12,7 @@ export default {
|
||||||
GlTooltip: GlTooltipDirective,
|
GlTooltip: GlTooltipDirective,
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
ciIcon,
|
CiIcon,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -7,14 +7,14 @@ import {
|
||||||
inputPlaceholderTextMap,
|
inputPlaceholderTextMap,
|
||||||
issuableTypesMap,
|
issuableTypesMap,
|
||||||
} from '../constants';
|
} from '../constants';
|
||||||
import issueToken from './issue_token.vue';
|
import IssueToken from './issue_token.vue';
|
||||||
|
|
||||||
const SPACE_FACTOR = 1;
|
const SPACE_FACTOR = 1;
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'RelatedIssuableInput',
|
name: 'RelatedIssuableInput',
|
||||||
components: {
|
components: {
|
||||||
issueToken,
|
IssueToken,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
inputId: {
|
inputId: {
|
||||||
|
|
|
@ -40,7 +40,7 @@ import RelatedIssuesBlock from './related_issues_block.vue';
|
||||||
export default {
|
export default {
|
||||||
name: 'RelatedIssuesRoot',
|
name: 'RelatedIssuesRoot',
|
||||||
components: {
|
components: {
|
||||||
relatedIssuesBlock: RelatedIssuesBlock,
|
RelatedIssuesBlock,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
endpoint: {
|
endpoint: {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlSprintf } from '@gitlab/ui';
|
import { GlSprintf } from '@gitlab/ui';
|
||||||
import editFormButtons from './edit_form_buttons.vue';
|
import EditFormButtons from './edit_form_buttons.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
editFormButtons,
|
EditFormButtons,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -6,7 +6,7 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||||
import createFlash from '~/flash';
|
import createFlash from '~/flash';
|
||||||
import eventHub from '~/sidebar/event_hub';
|
import eventHub from '~/sidebar/event_hub';
|
||||||
import toast from '~/vue_shared/plugins/global_toast';
|
import toast from '~/vue_shared/plugins/global_toast';
|
||||||
import editForm from './edit_form.vue';
|
import EditForm from './edit_form.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
issue: 'issue',
|
issue: 'issue',
|
||||||
|
@ -23,7 +23,7 @@ export default {
|
||||||
displayText: __('Unlocked'),
|
displayText: __('Unlocked'),
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
editForm,
|
EditForm,
|
||||||
GlIcon,
|
GlIcon,
|
||||||
},
|
},
|
||||||
directives: {
|
directives: {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlButton, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
|
import { GlButton, GlIcon, GlLoadingIcon, GlTooltipDirective } from '@gitlab/ui';
|
||||||
import { __, n__, sprintf } from '~/locale';
|
import { __, n__, sprintf } from '~/locale';
|
||||||
import userAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
import UserAvatarImage from '~/vue_shared/components/user_avatar/user_avatar_image.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
directives: {
|
directives: {
|
||||||
|
@ -11,7 +11,7 @@ export default {
|
||||||
GlButton,
|
GlButton,
|
||||||
GlIcon,
|
GlIcon,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
userAvatarImage,
|
UserAvatarImage,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
loading: {
|
loading: {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import { IssuableType } from '~/issues/constants';
|
import { IssuableType } from '~/issues/constants';
|
||||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
import { parseBoolean } from '~/lib/utils/common_utils';
|
||||||
import timeTracker from './components/time_tracking/time_tracker.vue';
|
import TimeTracker from './components/time_tracking/time_tracker.vue';
|
||||||
|
|
||||||
export default class SidebarMilestone {
|
export default class SidebarMilestone {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -23,13 +23,13 @@ export default class SidebarMilestone {
|
||||||
el,
|
el,
|
||||||
name: 'SidebarMilestoneRoot',
|
name: 'SidebarMilestoneRoot',
|
||||||
components: {
|
components: {
|
||||||
timeTracker,
|
TimeTracker,
|
||||||
},
|
},
|
||||||
provide: {
|
provide: {
|
||||||
issuableType: IssuableType.Milestone,
|
issuableType: IssuableType.Milestone,
|
||||||
},
|
},
|
||||||
render: (createElement) =>
|
render: (createElement) =>
|
||||||
createElement('timeTracker', {
|
createElement('time-tracker', {
|
||||||
props: {
|
props: {
|
||||||
limitToHours: parseBoolean(limitToHours),
|
limitToHours: parseBoolean(limitToHours),
|
||||||
issuableIid: iid.toString(),
|
issuableIid: iid.toString(),
|
||||||
|
|
|
@ -89,6 +89,19 @@ export default {
|
||||||
if (e.key !== 'Escape') return;
|
if (e.key !== 'Escape') return;
|
||||||
this.$emit('close');
|
this.$emit('close');
|
||||||
this.$refs.dismisser?.dismiss();
|
this.$refs.dismisser?.dismiss();
|
||||||
|
this.trackDismissal();
|
||||||
|
},
|
||||||
|
close() {
|
||||||
|
this.trackDismissal();
|
||||||
|
this.$emit('close');
|
||||||
|
},
|
||||||
|
trackDismissal() {
|
||||||
|
this.track('survey:mr_experience', {
|
||||||
|
label: 'dismiss',
|
||||||
|
extra: {
|
||||||
|
accountAge: this.accountAge,
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -119,7 +132,7 @@ export default {
|
||||||
icon="close"
|
icon="close"
|
||||||
@click="
|
@click="
|
||||||
dismiss();
|
dismiss();
|
||||||
$emit('close');
|
close();
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -24,7 +24,7 @@ const nonStandardEvents = {
|
||||||
},
|
},
|
||||||
issues: {
|
issues: {
|
||||||
uniqueUser: {
|
uniqueUser: {
|
||||||
expand: ['i_testing_load_performance_widget_total'],
|
expand: ['i_testing_issues_widget_total'],
|
||||||
},
|
},
|
||||||
counter: {},
|
counter: {},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import { GlLoadingIcon } from '@gitlab/ui';
|
import { GlLoadingIcon } from '@gitlab/ui';
|
||||||
import ciIcon from '~/vue_shared/components/ci_icon.vue';
|
import CiIcon from '~/vue_shared/components/ci_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
ciIcon,
|
CiIcon,
|
||||||
GlLoadingIcon,
|
GlLoadingIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import statusIcon from '../mr_widget_status_icon.vue';
|
import StatusIcon from '../mr_widget_status_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MRWidgetArchived',
|
name: 'MRWidgetArchived',
|
||||||
components: {
|
components: {
|
||||||
statusIcon,
|
StatusIcon,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<script>
|
<script>
|
||||||
import statusIcon from '../mr_widget_status_icon.vue';
|
import StatusIcon from '../mr_widget_status_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MRWidgetChecking',
|
name: 'MRWidgetChecking',
|
||||||
components: {
|
components: {
|
||||||
statusIcon,
|
StatusIcon,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<script>
|
<script>
|
||||||
import MrWidgetAuthorTime from '../mr_widget_author_time.vue';
|
import MrWidgetAuthorTime from '../mr_widget_author_time.vue';
|
||||||
import statusIcon from '../mr_widget_status_icon.vue';
|
import StatusIcon from '../mr_widget_status_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MRWidgetClosed',
|
name: 'MRWidgetClosed',
|
||||||
components: {
|
components: {
|
||||||
MrWidgetAuthorTime,
|
MrWidgetAuthorTime,
|
||||||
statusIcon,
|
StatusIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
/* TODO: This is providing all store and service down when it
|
/* TODO: This is providing all store and service down when it
|
||||||
|
|
|
@ -3,14 +3,14 @@ import { GlButton } from '@gitlab/ui';
|
||||||
import { stripHtml } from '~/lib/utils/text_utility';
|
import { stripHtml } from '~/lib/utils/text_utility';
|
||||||
import { sprintf, s__, n__ } from '~/locale';
|
import { sprintf, s__, n__ } from '~/locale';
|
||||||
import eventHub from '../../event_hub';
|
import eventHub from '../../event_hub';
|
||||||
import statusIcon from '../mr_widget_status_icon.vue';
|
import StatusIcon from '../mr_widget_status_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MRWidgetFailedToMerge',
|
name: 'MRWidgetFailedToMerge',
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
GlButton,
|
GlButton,
|
||||||
statusIcon,
|
StatusIcon,
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import simplePoll from '~/lib/utils/simple_poll';
|
||||||
import MergeRequest from '~/merge_request';
|
import MergeRequest from '~/merge_request';
|
||||||
import eventHub from '../../event_hub';
|
import eventHub from '../../event_hub';
|
||||||
import { MERGE_ACTIVE_STATUS_PHRASES, STATE_MACHINE } from '../../constants';
|
import { MERGE_ACTIVE_STATUS_PHRASES, STATE_MACHINE } from '../../constants';
|
||||||
import statusIcon from '../mr_widget_status_icon.vue';
|
import StatusIcon from '../mr_widget_status_icon.vue';
|
||||||
|
|
||||||
const { transitions } = STATE_MACHINE;
|
const { transitions } = STATE_MACHINE;
|
||||||
const { MERGE_FAILURE } = transitions;
|
const { MERGE_FAILURE } = transitions;
|
||||||
|
@ -12,7 +12,7 @@ const { MERGE_FAILURE } = transitions;
|
||||||
export default {
|
export default {
|
||||||
name: 'MRWidgetMerging',
|
name: 'MRWidgetMerging',
|
||||||
components: {
|
components: {
|
||||||
statusIcon,
|
StatusIcon,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
mr: {
|
mr: {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {
|
||||||
MR_WIDGET_MISSING_BRANCH_RESTORE,
|
MR_WIDGET_MISSING_BRANCH_RESTORE,
|
||||||
MR_WIDGET_MISSING_BRANCH_MANUALCLI,
|
MR_WIDGET_MISSING_BRANCH_MANUALCLI,
|
||||||
} from '../../i18n';
|
} from '../../i18n';
|
||||||
import statusIcon from '../mr_widget_status_icon.vue';
|
import StatusIcon from '../mr_widget_status_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MRWidgetMissingBranch',
|
name: 'MRWidgetMissingBranch',
|
||||||
|
@ -19,7 +19,7 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
GlIcon,
|
GlIcon,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
statusIcon,
|
StatusIcon,
|
||||||
},
|
},
|
||||||
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
|
mixins: [glFeatureFlagMixin(), mergeRequestQueryVariablesMixin],
|
||||||
apollo: {
|
apollo: {
|
||||||
|
|
|
@ -2,14 +2,14 @@
|
||||||
import { GlLink, GlSprintf } from '@gitlab/ui';
|
import { GlLink, GlSprintf } from '@gitlab/ui';
|
||||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
import statusIcon from '../mr_widget_status_icon.vue';
|
import StatusIcon from '../mr_widget_status_icon.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PipelineFailed',
|
name: 'PipelineFailed',
|
||||||
components: {
|
components: {
|
||||||
GlLink,
|
GlLink,
|
||||||
GlSprintf,
|
GlSprintf,
|
||||||
statusIcon,
|
StatusIcon,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
troubleshootingDocsPath() {
|
troubleshootingDocsPath() {
|
||||||
|
|
|
@ -59,28 +59,28 @@ export default {
|
||||||
Loading,
|
Loading,
|
||||||
ExtensionsContainer,
|
ExtensionsContainer,
|
||||||
WidgetContainer,
|
WidgetContainer,
|
||||||
'mr-widget-suggest-pipeline': WidgetSuggestPipeline,
|
MrWidgetSuggestPipeline: WidgetSuggestPipeline,
|
||||||
MrWidgetPipelineContainer,
|
MrWidgetPipelineContainer,
|
||||||
MrWidgetAlertMessage,
|
MrWidgetAlertMessage,
|
||||||
'mr-widget-merged': MergedState,
|
MrWidgetMerged: MergedState,
|
||||||
'mr-widget-closed': ClosedState,
|
MrWidgetClosed: ClosedState,
|
||||||
'mr-widget-merging': MergingState,
|
MrWidgetMerging: MergingState,
|
||||||
'mr-widget-failed-to-merge': FailedToMerge,
|
MrWidgetFailedToMerge: FailedToMerge,
|
||||||
'mr-widget-wip': WorkInProgressState,
|
MrWidgetWip: WorkInProgressState,
|
||||||
'mr-widget-archived': ArchivedState,
|
MrWidgetArchived: ArchivedState,
|
||||||
'mr-widget-conflicts': ConflictsState,
|
MrWidgetConflicts: ConflictsState,
|
||||||
'mr-widget-nothing-to-merge': NothingToMergeState,
|
MrWidgetNothingToMerge: NothingToMergeState,
|
||||||
'mr-widget-not-allowed': NotAllowedState,
|
MrWidgetNotAllowed: NotAllowedState,
|
||||||
'mr-widget-missing-branch': MissingBranchState,
|
MrWidgetMissingBranch: MissingBranchState,
|
||||||
'mr-widget-ready-to-merge': () => import('./components/states/new_ready_to_merge.vue'),
|
MrWidgetReadyToMerge: () => import('./components/states/new_ready_to_merge.vue'),
|
||||||
'sha-mismatch': ShaMismatch,
|
ShaMismatch,
|
||||||
'mr-widget-checking': CheckingState,
|
MrWidgetChecking: CheckingState,
|
||||||
'mr-widget-unresolved-discussions': UnresolvedDiscussionsState,
|
MrWidgetUnresolvedDiscussions: UnresolvedDiscussionsState,
|
||||||
'mr-widget-pipeline-blocked': PipelineBlockedState,
|
MrWidgetPipelineBlocked: PipelineBlockedState,
|
||||||
'mr-widget-pipeline-failed': PipelineFailedState,
|
MrWidgetPipelineFailed: PipelineFailedState,
|
||||||
MrWidgetAutoMergeEnabled,
|
MrWidgetAutoMergeEnabled,
|
||||||
'mr-widget-auto-merge-failed': AutoMergeFailed,
|
MrWidgetAutoMergeFailed: AutoMergeFailed,
|
||||||
'mr-widget-rebase': RebaseState,
|
MrWidgetRebase: RebaseState,
|
||||||
SourceBranchRemovalStatus,
|
SourceBranchRemovalStatus,
|
||||||
GroupedCodequalityReportsApp: () =>
|
GroupedCodequalityReportsApp: () =>
|
||||||
import('../reports/codequality_report/grouped_codequality_reports_app.vue'),
|
import('../reports/codequality_report/grouped_codequality_reports_app.vue'),
|
||||||
|
|
|
@ -29,7 +29,7 @@ import descriptionVersionHistoryMixin from 'ee_else_ce/notes/mixins/description_
|
||||||
import '~/behaviors/markdown/render_gfm';
|
import '~/behaviors/markdown/render_gfm';
|
||||||
import axios from '~/lib/utils/axios_utils';
|
import axios from '~/lib/utils/axios_utils';
|
||||||
import { __ } from '~/locale';
|
import { __ } from '~/locale';
|
||||||
import noteHeader from '~/notes/components/note_header.vue';
|
import NoteHeader from '~/notes/components/note_header.vue';
|
||||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||||
import { spriteIcon } from '~/lib/utils/common_utils';
|
import { spriteIcon } from '~/lib/utils/common_utils';
|
||||||
import TimelineEntryItem from './timeline_entry_item.vue';
|
import TimelineEntryItem from './timeline_entry_item.vue';
|
||||||
|
@ -43,7 +43,7 @@ export default {
|
||||||
name: 'SystemNote',
|
name: 'SystemNote',
|
||||||
components: {
|
components: {
|
||||||
GlIcon,
|
GlIcon,
|
||||||
noteHeader,
|
NoteHeader,
|
||||||
TimelineEntryItem,
|
TimelineEntryItem,
|
||||||
GlButton,
|
GlButton,
|
||||||
GlSkeletonLoader,
|
GlSkeletonLoader,
|
||||||
|
|
|
@ -24,7 +24,7 @@ export default function initWorkItemLinks() {
|
||||||
name: 'WorkItemLinksRoot',
|
name: 'WorkItemLinksRoot',
|
||||||
apolloProvider,
|
apolloProvider,
|
||||||
components: {
|
components: {
|
||||||
workItemLinks: WorkItemLinks,
|
WorkItemLinks,
|
||||||
},
|
},
|
||||||
provide: {
|
provide: {
|
||||||
projectPath,
|
projectPath,
|
||||||
|
|
|
@ -44,8 +44,7 @@ class MergeRequestsFinder < IssuableFinder
|
||||||
:reviewer_id,
|
:reviewer_id,
|
||||||
:reviewer_username,
|
:reviewer_username,
|
||||||
:target_branch,
|
:target_branch,
|
||||||
:wip,
|
:wip
|
||||||
:attention
|
|
||||||
]
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -70,7 +69,6 @@ class MergeRequestsFinder < IssuableFinder
|
||||||
items = by_approvals(items)
|
items = by_approvals(items)
|
||||||
items = by_deployments(items)
|
items = by_deployments(items)
|
||||||
items = by_reviewer(items)
|
items = by_reviewer(items)
|
||||||
items = by_attention(items)
|
|
||||||
|
|
||||||
by_source_project_id(items)
|
by_source_project_id(items)
|
||||||
end
|
end
|
||||||
|
@ -220,12 +218,6 @@ class MergeRequestsFinder < IssuableFinder
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def by_attention(items)
|
|
||||||
return items unless params.attention?
|
|
||||||
|
|
||||||
items.attention(params.attention)
|
|
||||||
end
|
|
||||||
|
|
||||||
def parse_datetime(input)
|
def parse_datetime(input)
|
||||||
# To work around http://www.ruby-lang.org/en/news/2021/11/15/date-parsing-method-regexp-dos-cve-2021-41817/
|
# To work around http://www.ruby-lang.org/en/news/2021/11/15/date-parsing-method-regexp-dos-cve-2021-41817/
|
||||||
DateTime.parse(input.byteslice(0, 128)) if input
|
DateTime.parse(input.byteslice(0, 128)) if input
|
||||||
|
|
|
@ -21,11 +21,5 @@ class MergeRequestsFinder
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def attention
|
|
||||||
strong_memoize(:attention) do
|
|
||||||
User.find_by_username(params[:attention])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,20 +6,12 @@ module MergeRequestReviewerState
|
||||||
included do
|
included do
|
||||||
enum state: {
|
enum state: {
|
||||||
unreviewed: 0,
|
unreviewed: 0,
|
||||||
reviewed: 1,
|
reviewed: 1
|
||||||
attention_requested: 2
|
# 2 was removed with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95446
|
||||||
}
|
}
|
||||||
|
|
||||||
validates :state,
|
validates :state,
|
||||||
presence: true,
|
presence: true,
|
||||||
inclusion: { in: self.states.keys }
|
inclusion: { in: self.states.keys }
|
||||||
|
|
||||||
belongs_to :updated_state_by, class_name: 'User', foreign_key: :updated_state_by_user_id
|
|
||||||
|
|
||||||
def attention_requested_by
|
|
||||||
return unless attention_requested?
|
|
||||||
|
|
||||||
updated_state_by
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -153,7 +153,7 @@ class Group < Namespace
|
||||||
|
|
||||||
after_create :post_create_hook
|
after_create :post_create_hook
|
||||||
after_destroy :post_destroy_hook
|
after_destroy :post_destroy_hook
|
||||||
after_save :update_two_factor_requirement
|
after_commit :update_two_factor_requirement
|
||||||
after_update :path_changed_hook, if: :saved_change_to_path?
|
after_update :path_changed_hook, if: :saved_change_to_path?
|
||||||
after_create -> { create_or_load_association(:group_feature) }
|
after_create -> { create_or_load_association(:group_feature) }
|
||||||
|
|
||||||
|
@ -898,6 +898,10 @@ class Group < Namespace
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def update_two_factor_requirement_for_members
|
||||||
|
direct_and_indirect_members.find_each(&:update_two_factor_requirement)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def feature_flag_enabled_for_self_or_ancestor?(feature_flag)
|
def feature_flag_enabled_for_self_or_ancestor?(feature_flag)
|
||||||
|
@ -920,7 +924,7 @@ class Group < Namespace
|
||||||
def update_two_factor_requirement
|
def update_two_factor_requirement
|
||||||
return unless saved_change_to_require_two_factor_authentication? || saved_change_to_two_factor_grace_period?
|
return unless saved_change_to_require_two_factor_authentication? || saved_change_to_two_factor_grace_period?
|
||||||
|
|
||||||
direct_and_indirect_members.find_each(&:update_two_factor_requirement)
|
Groups::UpdateTwoFactorRequirementForMembersWorker.perform_async(self.id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def path_changed_hook
|
def path_changed_hook
|
||||||
|
|
|
@ -417,17 +417,6 @@ class MergeRequest < ApplicationRecord
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
scope :attention, ->(user) do
|
|
||||||
# rubocop: disable Gitlab/Union
|
|
||||||
union = Gitlab::SQL::Union.new([
|
|
||||||
MergeRequestReviewer.select(:merge_request_id).where(user_id: user.id, state: MergeRequestReviewer.states[:attention_requested]),
|
|
||||||
MergeRequestAssignee.select(:merge_request_id).where(user_id: user.id, state: MergeRequestAssignee.states[:attention_requested])
|
|
||||||
])
|
|
||||||
# rubocop: enable Gitlab/Union
|
|
||||||
|
|
||||||
with(Gitlab::SQL::CTE.new(:reviewers_and_assignees, union).to_arel).where('merge_requests.id in (select merge_request_id from reviewers_and_assignees)')
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.total_time_to_merge
|
def self.total_time_to_merge
|
||||||
join_metrics
|
join_metrics
|
||||||
.merge(MergeRequest::Metrics.with_valid_time_to_merge)
|
.merge(MergeRequest::Metrics.with_valid_time_to_merge)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class MergeRequestAssignee < ApplicationRecord
|
class MergeRequestAssignee < ApplicationRecord
|
||||||
include MergeRequestReviewerState
|
|
||||||
|
|
||||||
belongs_to :merge_request, touch: true
|
belongs_to :merge_request, touch: true
|
||||||
belongs_to :assignee, class_name: "User", foreign_key: :user_id, inverse_of: :merge_request_assignees
|
belongs_to :assignee, class_name: "User", foreign_key: :user_id, inverse_of: :merge_request_assignees
|
||||||
|
|
||||||
|
@ -11,6 +9,6 @@ class MergeRequestAssignee < ApplicationRecord
|
||||||
scope :in_projects, ->(project_ids) { joins(:merge_request).where(merge_requests: { target_project_id: project_ids }) }
|
scope :in_projects, ->(project_ids) { joins(:merge_request).where(merge_requests: { target_project_id: project_ids }) }
|
||||||
|
|
||||||
def cache_key
|
def cache_key
|
||||||
[model_name.cache_key, id, state, assignee.cache_key]
|
[model_name.cache_key, id, assignee.cache_key]
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -2152,10 +2152,6 @@ class User < ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def mr_attention_requests_enabled?
|
|
||||||
Feature.enabled?(:mr_attention_requests, self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def account_age_in_days
|
def account_age_in_days
|
||||||
(Date.current - created_at.to_date).to_i
|
(Date.current - created_at.to_date).to_i
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,8 +47,7 @@ module Users
|
||||||
storage_enforcement_banner_second_enforcement_threshold: 44,
|
storage_enforcement_banner_second_enforcement_threshold: 44,
|
||||||
storage_enforcement_banner_third_enforcement_threshold: 45,
|
storage_enforcement_banner_third_enforcement_threshold: 45,
|
||||||
storage_enforcement_banner_fourth_enforcement_threshold: 46,
|
storage_enforcement_banner_fourth_enforcement_threshold: 46,
|
||||||
attention_requests_top_nav: 47,
|
# 47 and 48 were removed with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/95446
|
||||||
attention_requests_side_nav: 48,
|
|
||||||
# 49 was removed with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91533
|
# 49 was removed with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/91533
|
||||||
# because the banner was no longer relevant.
|
# because the banner was no longer relevant.
|
||||||
# Records will be migrated with https://gitlab.com/gitlab-org/gitlab/-/issues/367293
|
# Records will be migrated with https://gitlab.com/gitlab-org/gitlab/-/issues/367293
|
||||||
|
|
|
@ -17,7 +17,7 @@ class MergeRequestUserEntity < ::API::Entities::UserBasic
|
||||||
end
|
end
|
||||||
|
|
||||||
expose :reviewed, if: satisfies(:present?, :allows_reviewers?) do |user, options|
|
expose :reviewed, if: satisfies(:present?, :allows_reviewers?) do |user, options|
|
||||||
find_reviewer_or_assignee(user, options)&.reviewed?
|
options[:merge_request].find_reviewer(user)&.reviewed?
|
||||||
end
|
end
|
||||||
|
|
||||||
expose :approved, if: satisfies(:present?) do |user, options|
|
expose :approved, if: satisfies(:present?) do |user, options|
|
||||||
|
@ -25,16 +25,6 @@ class MergeRequestUserEntity < ::API::Entities::UserBasic
|
||||||
# makes one query per merge request, whereas #approved_by? makes one per user
|
# makes one query per merge request, whereas #approved_by? makes one per user
|
||||||
options[:merge_request].approvals.any? { |app| app.user_id == user.id }
|
options[:merge_request].approvals.any? { |app| app.user_id == user.id }
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def find_reviewer_or_assignee(user, options)
|
|
||||||
if options[:type] == :reviewers
|
|
||||||
options[:merge_request].find_reviewer(user)
|
|
||||||
else
|
|
||||||
options[:merge_request].find_assignee(user)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
MergeRequestUserEntity.prepend_mod_with('MergeRequestUserEntity')
|
MergeRequestUserEntity.prepend_mod_with('MergeRequestUserEntity')
|
||||||
|
|
|
@ -43,8 +43,6 @@ module MergeRequests
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle_assignees_change(merge_request, old_assignees)
|
def handle_assignees_change(merge_request, old_assignees)
|
||||||
bulk_update_assignees_state(merge_request, merge_request.assignees - old_assignees)
|
|
||||||
|
|
||||||
MergeRequests::HandleAssigneesChangeService
|
MergeRequests::HandleAssigneesChangeService
|
||||||
.new(project: project, current_user: current_user)
|
.new(project: project, current_user: current_user)
|
||||||
.async_execute(merge_request, old_assignees)
|
.async_execute(merge_request, old_assignees)
|
||||||
|
@ -60,7 +58,6 @@ module MergeRequests
|
||||||
new_reviewers = merge_request.reviewers - old_reviewers
|
new_reviewers = merge_request.reviewers - old_reviewers
|
||||||
merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
|
merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
|
||||||
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
|
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
|
||||||
bulk_update_reviewers_state(merge_request, new_reviewers)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def cleanup_environments(merge_request)
|
def cleanup_environments(merge_request)
|
||||||
|
@ -247,46 +244,6 @@ module MergeRequests
|
||||||
|
|
||||||
Milestones::MergeRequestsCountService.new(milestone).delete_cache
|
Milestones::MergeRequestsCountService.new(milestone).delete_cache
|
||||||
end
|
end
|
||||||
|
|
||||||
def bulk_update_assignees_state(merge_request, new_assignees)
|
|
||||||
return unless current_user.mr_attention_requests_enabled?
|
|
||||||
return if new_assignees.empty?
|
|
||||||
|
|
||||||
assignees_map = merge_request.merge_request_assignees_with(new_assignees).to_h do |assignee|
|
|
||||||
state = if assignee.user_id == current_user&.id
|
|
||||||
:unreviewed
|
|
||||||
else
|
|
||||||
merge_request.find_reviewer(assignee.assignee)&.state || :attention_requested
|
|
||||||
end
|
|
||||||
|
|
||||||
[
|
|
||||||
assignee,
|
|
||||||
{ state: MergeRequestAssignee.states[state], updated_state_by_user_id: current_user.id }
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
::Gitlab::Database::BulkUpdate.execute(%i[state updated_state_by_user_id], assignees_map)
|
|
||||||
end
|
|
||||||
|
|
||||||
def bulk_update_reviewers_state(merge_request, new_reviewers)
|
|
||||||
return unless current_user.mr_attention_requests_enabled?
|
|
||||||
return if new_reviewers.empty?
|
|
||||||
|
|
||||||
reviewers_map = merge_request.merge_request_reviewers_with(new_reviewers).to_h do |reviewer|
|
|
||||||
state = if reviewer.user_id == current_user&.id
|
|
||||||
:unreviewed
|
|
||||||
else
|
|
||||||
merge_request.find_assignee(reviewer.reviewer)&.state || :attention_requested
|
|
||||||
end
|
|
||||||
|
|
||||||
[
|
|
||||||
reviewer,
|
|
||||||
{ state: MergeRequestReviewer.states[state], updated_state_by_user_id: current_user.id }
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
::Gitlab::Database::BulkUpdate.execute(%i[state updated_state_by_user_id], reviewers_map)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,6 @@ module MergeRequests
|
||||||
attrs = update_attrs.merge(assignee_ids: new_ids)
|
attrs = update_attrs.merge(assignee_ids: new_ids)
|
||||||
merge_request.update!(**attrs)
|
merge_request.update!(**attrs)
|
||||||
|
|
||||||
bulk_update_assignees_state(merge_request, merge_request.assignees - old_assignees)
|
|
||||||
|
|
||||||
# Defer the more expensive operations (handle_assignee_changes) to the background
|
# Defer the more expensive operations (handle_assignee_changes) to the background
|
||||||
MergeRequests::HandleAssigneesChangeService
|
MergeRequests::HandleAssigneesChangeService
|
||||||
.new(project: project, current_user: current_user)
|
.new(project: project, current_user: current_user)
|
||||||
|
|
|
@ -5,4 +5,4 @@
|
||||||
= content_for :after_content do
|
= content_for :after_content do
|
||||||
#js-crm-form-portal
|
#js-crm-form-portal
|
||||||
|
|
||||||
#js-crm-organizations-app{ data: { base_path: group_crm_organizations_path(@group), can_admin_crm_organization: can?(current_user, :admin_crm_organization, @group).to_s, group_full_path: @group.full_path, group_id: @group.id, group_issues_path: issues_group_path(@group) } }
|
#js-crm-organizations-app{ data: { base_path: group_crm_organizations_path(@group), can_admin_crm_organization: can?(current_user, :admin_crm_organization, @group).to_s, group_full_path: @group.full_path, group_id: @group.id, group_issues_path: issues_group_path(@group), text_query: params[:search] } }
|
||||||
|
|
|
@ -2415,6 +2415,15 @@
|
||||||
:weight: 1
|
:weight: 1
|
||||||
:idempotent: true
|
:idempotent: true
|
||||||
:tags: []
|
:tags: []
|
||||||
|
- :name: groups_update_two_factor_requirement_for_members
|
||||||
|
:worker_name: Groups::UpdateTwoFactorRequirementForMembersWorker
|
||||||
|
:feature_category: :authentication_and_authorization
|
||||||
|
:has_external_dependencies: false
|
||||||
|
:urgency: :low
|
||||||
|
:resource_boundary: :unknown
|
||||||
|
:weight: 1
|
||||||
|
:idempotent: true
|
||||||
|
:tags: []
|
||||||
- :name: import_issues_csv
|
- :name: import_issues_csv
|
||||||
:worker_name: ImportIssuesCsvWorker
|
:worker_name: ImportIssuesCsvWorker
|
||||||
:feature_category: :team_planning
|
:feature_category: :team_planning
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# Worker for updating two factor requirement for all group members
|
||||||
|
module Groups
|
||||||
|
class UpdateTwoFactorRequirementForMembersWorker
|
||||||
|
include ApplicationWorker
|
||||||
|
|
||||||
|
data_consistency :always
|
||||||
|
|
||||||
|
idempotent!
|
||||||
|
|
||||||
|
feature_category :authentication_and_authorization
|
||||||
|
|
||||||
|
def perform(group_id)
|
||||||
|
group = Group.find_by_id(group_id)
|
||||||
|
|
||||||
|
return unless group
|
||||||
|
|
||||||
|
group.update_two_factor_requirement_for_members
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -1,8 +0,0 @@
|
||||||
---
|
|
||||||
name: mr_attention_requests
|
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/72773
|
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343528
|
|
||||||
milestone: '14.4'
|
|
||||||
type: development
|
|
||||||
group: group::code review
|
|
||||||
default_enabled: false
|
|
|
@ -221,6 +221,8 @@
|
||||||
- 1
|
- 1
|
||||||
- - groups_update_statistics
|
- - groups_update_statistics
|
||||||
- 1
|
- 1
|
||||||
|
- - groups_update_two_factor_requirement_for_members
|
||||||
|
- 1
|
||||||
- - hashed_storage
|
- - hashed_storage
|
||||||
- 1
|
- 1
|
||||||
- - import_issues_csv
|
- - import_issues_csv
|
||||||
|
|
|
@ -20190,7 +20190,6 @@ State of a review of a GitLab merge request.
|
||||||
|
|
||||||
| Value | Description |
|
| Value | Description |
|
||||||
| ----- | ----------- |
|
| ----- | ----------- |
|
||||||
| <a id="mergerequestreviewstateattention_requested"></a>`ATTENTION_REQUESTED` | The merge request is attention_requested. |
|
|
||||||
| <a id="mergerequestreviewstatereviewed"></a>`REVIEWED` | The merge request is reviewed. |
|
| <a id="mergerequestreviewstatereviewed"></a>`REVIEWED` | The merge request is reviewed. |
|
||||||
| <a id="mergerequestreviewstateunreviewed"></a>`UNREVIEWED` | The merge request is unreviewed. |
|
| <a id="mergerequestreviewstateunreviewed"></a>`UNREVIEWED` | The merge request is unreviewed. |
|
||||||
|
|
||||||
|
@ -20864,8 +20863,6 @@ Name of the feature that the callout is for.
|
||||||
| Value | Description |
|
| Value | Description |
|
||||||
| ----- | ----------- |
|
| ----- | ----------- |
|
||||||
| <a id="usercalloutfeaturenameenumactive_user_count_threshold"></a>`ACTIVE_USER_COUNT_THRESHOLD` | Callout feature name for active_user_count_threshold. |
|
| <a id="usercalloutfeaturenameenumactive_user_count_threshold"></a>`ACTIVE_USER_COUNT_THRESHOLD` | Callout feature name for active_user_count_threshold. |
|
||||||
| <a id="usercalloutfeaturenameenumattention_requests_side_nav"></a>`ATTENTION_REQUESTS_SIDE_NAV` | Callout feature name for attention_requests_side_nav. |
|
|
||||||
| <a id="usercalloutfeaturenameenumattention_requests_top_nav"></a>`ATTENTION_REQUESTS_TOP_NAV` | Callout feature name for attention_requests_top_nav. |
|
|
||||||
| <a id="usercalloutfeaturenameenumbuy_pipeline_minutes_notification_dot"></a>`BUY_PIPELINE_MINUTES_NOTIFICATION_DOT` | Callout feature name for buy_pipeline_minutes_notification_dot. |
|
| <a id="usercalloutfeaturenameenumbuy_pipeline_minutes_notification_dot"></a>`BUY_PIPELINE_MINUTES_NOTIFICATION_DOT` | Callout feature name for buy_pipeline_minutes_notification_dot. |
|
||||||
| <a id="usercalloutfeaturenameenumcanary_deployment"></a>`CANARY_DEPLOYMENT` | Callout feature name for canary_deployment. |
|
| <a id="usercalloutfeaturenameenumcanary_deployment"></a>`CANARY_DEPLOYMENT` | Callout feature name for canary_deployment. |
|
||||||
| <a id="usercalloutfeaturenameenumci_deprecation_warning_for_types_keyword"></a>`CI_DEPRECATION_WARNING_FOR_TYPES_KEYWORD` | Callout feature name for ci_deprecation_warning_for_types_keyword. |
|
| <a id="usercalloutfeaturenameenumci_deprecation_warning_for_types_keyword"></a>`CI_DEPRECATION_WARNING_FOR_TYPES_KEYWORD` | Callout feature name for ci_deprecation_warning_for_types_keyword. |
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue