Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/projects/settings')
-rw-r--r--app/assets/javascripts/projects/settings/access_dropdown.js2
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js1
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue40
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js9
-rw-r--r--app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql1
-rw-r--r--app/assets/javascripts/projects/settings/repository/branch_rules/app.vue11
-rw-r--r--app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue57
-rw-r--r--app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql24
-rw-r--r--app/assets/javascripts/projects/settings/utils.js17
9 files changed, 127 insertions, 35 deletions
diff --git a/app/assets/javascripts/projects/settings/access_dropdown.js b/app/assets/javascripts/projects/settings/access_dropdown.js
index 335545c802a..dcf7415a444 100644
--- a/app/assets/javascripts/projects/settings/access_dropdown.js
+++ b/app/assets/javascripts/projects/settings/access_dropdown.js
@@ -580,7 +580,7 @@ export default class AccessDropdown {
return `
<li>
<a href="#" class="${isActiveClass} item-${role.type}" data-role-id="${role.id}">
- ${role.text}
+ ${escape(role.text)}
</a>
</li>
`;
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
index 6da058ebc9c..61c37a2348a 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/constants.js
@@ -6,6 +6,7 @@ export const I18N = {
branchNameOrPattern: s__('BranchRules|Branch name or pattern'),
branch: s__('BranchRules|Target Branch'),
allBranches: s__('BranchRules|All branches'),
+ matchingBranchesLinkTitle: s__('BranchRules|%{total} matching %{subject}'),
protectBranchTitle: s__('BranchRules|Protect branch'),
protectBranchDescription: s__(
'BranchRules|Keep stable branches secure and force developers to use merge requests. %{linkStart}What are protected branches?%{linkEnd}',
diff --git a/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue b/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue
index eb11e17dd1b..626ed67c466 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue
+++ b/app/assets/javascripts/projects/settings/branch_rules/components/view/index.vue
@@ -1,9 +1,10 @@
<script>
import { GlSprintf, GlLink, GlLoadingIcon } from '@gitlab/ui';
-import { sprintf } from '~/locale';
-import { getParameterByName } from '~/lib/utils/url_utility';
+import { sprintf, n__ } from '~/locale';
+import { getParameterByName, mergeUrlParams } from '~/lib/utils/url_utility';
import { helpPagePath } from '~/helpers/help_page_helper';
import branchRulesQuery from '../../queries/branch_rules_details.query.graphql';
+import { getAccessLevels } from '../../../utils';
import Protection from './protection.vue';
import {
I18N,
@@ -41,6 +42,9 @@ export default {
statusChecksPath: {
default: '',
},
+ branchesPath: {
+ default: '',
+ },
},
apollo: {
project: {
@@ -55,6 +59,7 @@ export default {
this.branchProtection = branchRule?.branchProtection;
this.approvalRules = branchRule?.approvalRules;
this.statusChecks = branchRule?.externalStatusChecks?.nodes || [];
+ this.matchingBranchesCount = branchRule?.matchingBranchesCount;
},
},
},
@@ -64,6 +69,7 @@ export default {
branchProtection: {},
approvalRules: {},
statusChecks: [],
+ matchingBranchesCount: null,
};
},
computed: {
@@ -115,28 +121,20 @@ export default {
? this.$options.i18n.targetBranch
: this.$options.i18n.branchNameOrPattern;
},
+ matchingBranchesLinkHref() {
+ return mergeUrlParams({ state: 'all', search: this.branch }, this.branchesPath);
+ },
+ matchingBranchesLinkTitle() {
+ const total = this.matchingBranchesCount;
+ const subject = n__('branch', 'branches', total);
+ return sprintf(this.$options.i18n.matchingBranchesLinkTitle, { total, subject });
+ },
approvals() {
return this.approvalRules?.nodes || [];
},
},
methods: {
- getAccessLevels(accessLevels = {}) {
- const total = accessLevels.edges?.length;
- const accessLevelTypes = { total, users: [], groups: [], roles: [] };
-
- accessLevels.edges?.forEach(({ node }) => {
- if (node.user) {
- const src = node.user.avatarUrl;
- accessLevelTypes.users.push({ src, ...node.user });
- } else if (node.group) {
- accessLevelTypes.groups.push(node);
- } else {
- accessLevelTypes.roles.push(node);
- }
- });
-
- return accessLevelTypes;
- },
+ getAccessLevels,
},
};
</script>
@@ -161,6 +159,10 @@ export default {
</div>
<code v-else class="gl-mt-2" data-testid="branch">{{ branch }}</code>
+ <p v-if="matchingBranchesCount" class="gl-mt-3">
+ <gl-link :href="matchingBranchesLinkHref">{{ matchingBranchesLinkTitle }}</gl-link>
+ </p>
+
<h4 class="gl-mb-1 gl-mt-5">{{ $options.i18n.protectBranchTitle }}</h4>
<gl-sprintf :message="$options.i18n.protectBranchDescription">
<template #link="{ content }">
diff --git a/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
index 89cfb1e1c8e..7639acc1181 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
+++ b/app/assets/javascripts/projects/settings/branch_rules/mount_branch_rules.js
@@ -14,7 +14,13 @@ export default function mountBranchRules(el) {
defaultClient: createDefaultClient(),
});
- const { projectPath, protectedBranchesPath, approvalRulesPath, statusChecksPath } = el.dataset;
+ const {
+ projectPath,
+ protectedBranchesPath,
+ approvalRulesPath,
+ statusChecksPath,
+ branchesPath,
+ } = el.dataset;
return new Vue({
el,
@@ -24,6 +30,7 @@ export default function mountBranchRules(el) {
protectedBranchesPath,
approvalRulesPath,
statusChecksPath,
+ branchesPath,
},
render(h) {
return h(View);
diff --git a/app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql b/app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql
index aa1e4923aa8..a832e59aa67 100644
--- a/app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql
+++ b/app/assets/javascripts/projects/settings/branch_rules/queries/branch_rules_details.query.graphql
@@ -68,6 +68,7 @@ query getBranchRulesDetails($projectPath: ID!) {
externalUrl
}
}
+ matchingBranchesCount
}
}
}
diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue b/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue
index a9eb2a53fbf..9b669024a8b 100644
--- a/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue
+++ b/app/assets/javascripts/projects/settings/repository/branch_rules/app.vue
@@ -1,7 +1,7 @@
<script>
import { s__ } from '~/locale';
import { createAlert } from '~/flash';
-import branchRulesQuery from './graphql/queries/branch_rules.query.graphql';
+import branchRulesQuery from 'ee_else_ce/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql';
import BranchRule from './components/branch_rule.vue';
export const i18n = {
@@ -51,13 +51,14 @@ export default {
<template>
<div class="settings-content">
<branch-rule
- v-for="rule in branchRules"
- :key="rule.name"
+ v-for="(rule, index) in branchRules"
+ :key="`${rule.name}-${index}`"
:name="rule.name"
:is-default="rule.isDefault"
:branch-protection="rule.branchProtection"
- :status-checks-total="rule.externalStatusChecks.nodes.length"
- :approval-rules-total="rule.approvalRules.nodes.length"
+ :status-checks-total="rule.externalStatusChecks ? rule.externalStatusChecks.nodes.length : 0"
+ :approval-rules-total="rule.approvalRules ? rule.approvalRules.nodes.length : 0"
+ :matching-branches-count="rule.matchingBranchesCount"
/>
<span v-if="!branchRules.length" data-testid="empty">{{ $options.i18n.emptyState }}</span>
diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue
index 78c824c66d1..41947834bdb 100644
--- a/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue
+++ b/app/assets/javascripts/projects/settings/repository/branch_rules/components/branch_rule.vue
@@ -1,6 +1,7 @@
<script>
import { GlBadge, GlButton } from '@gitlab/ui';
import { s__, sprintf, n__ } from '~/locale';
+import { getAccessLevels } from '../../../utils';
export const i18n = {
defaultLabel: s__('BranchRules|default'),
@@ -9,6 +10,9 @@ export const i18n = {
codeOwnerApprovalRequired: s__('BranchRules|Requires CODEOWNERS approval'),
statusChecks: s__('BranchRules|%{total} status %{subject}'),
approvalRules: s__('BranchRules|%{total} approval %{subject}'),
+ matchingBranches: s__('BranchRules|%{total} matching %{subject}'),
+ pushAccessLevels: s__('BranchRules|Allowed to merge'),
+ mergeAccessLevels: s__('BranchRules|Allowed to push'),
};
export default {
@@ -48,8 +52,16 @@ export default {
required: false,
default: 0,
},
+ matchingBranchesCount: {
+ type: Number,
+ required: false,
+ default: 0,
+ },
},
computed: {
+ isWildcard() {
+ return this.name.includes('*');
+ },
hasApprovalDetails() {
return this.approvalDetails.length;
},
@@ -68,8 +80,31 @@ export default {
subject: n__('rule', 'rules', this.approvalRulesTotal),
});
},
+ matchingBranchesText() {
+ return sprintf(this.$options.i18n.matchingBranches, {
+ total: this.matchingBranchesCount,
+ subject: n__('branch', 'branches', this.matchingBranchesCount),
+ });
+ },
+ mergeAccessLevels() {
+ const { mergeAccessLevels } = this.branchProtection || {};
+ return this.getAccessLevels(mergeAccessLevels);
+ },
+ pushAccessLevels() {
+ const { pushAccessLevels } = this.branchProtection || {};
+ return this.getAccessLevels(pushAccessLevels);
+ },
+ pushAccessLevelsText() {
+ return this.getAccessLevelsText(this.$options.i18n.pushAccessLevels, this.pushAccessLevels);
+ },
+ mergeAccessLevelsText() {
+ return this.getAccessLevelsText(this.$options.i18n.mergeAccessLevels, this.mergeAccessLevels);
+ },
approvalDetails() {
const approvalDetails = [];
+ if (this.isWildcard) {
+ approvalDetails.push(this.matchingBranchesText);
+ }
if (this.branchProtection.allowForcePush) {
approvalDetails.push(this.$options.i18n.allowForcePush);
}
@@ -82,9 +117,31 @@ export default {
if (this.approvalRulesTotal) {
approvalDetails.push(this.approvalRulesText);
}
+ if (this.mergeAccessLevels.total > 0) {
+ approvalDetails.push(this.mergeAccessLevelsText);
+ }
+ if (this.pushAccessLevels.total > 0) {
+ approvalDetails.push(this.pushAccessLevelsText);
+ }
return approvalDetails;
},
},
+ methods: {
+ getAccessLevels,
+ getAccessLevelsText(beginString = '', accessLevels) {
+ const textParts = [];
+ if (accessLevels.roles.length) {
+ textParts.push(n__('1 role', '%d roles', accessLevels.roles.length));
+ }
+ if (accessLevels.groups.length) {
+ textParts.push(n__('1 group', '%d groups', accessLevels.groups.length));
+ }
+ if (accessLevels.users.length) {
+ textParts.push(n__('1 user', '%d users', accessLevels.users.length));
+ }
+ return `${beginString}: ${textParts.join(', ')}`;
+ },
+ },
};
</script>
diff --git a/app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql b/app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql
index 49e089e7805..a8cdda5505f 100644
--- a/app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql
+++ b/app/assets/javascripts/projects/settings/repository/branch_rules/graphql/queries/branch_rules.query.graphql
@@ -5,18 +5,24 @@ query getBranchRules($projectPath: ID!) {
nodes {
name
isDefault
+ matchingBranchesCount
branchProtection {
allowForcePush
- codeOwnerApprovalRequired
- }
- externalStatusChecks {
- nodes {
- id
+ mergeAccessLevels {
+ edges {
+ node {
+ accessLevel
+ accessLevelDescription
+ }
+ }
}
- }
- approvalRules {
- nodes {
- id
+ pushAccessLevels {
+ edges {
+ node {
+ accessLevel
+ accessLevelDescription
+ }
+ }
}
}
}
diff --git a/app/assets/javascripts/projects/settings/utils.js b/app/assets/javascripts/projects/settings/utils.js
new file mode 100644
index 00000000000..7bcfde39178
--- /dev/null
+++ b/app/assets/javascripts/projects/settings/utils.js
@@ -0,0 +1,17 @@
+export const getAccessLevels = (accessLevels = {}) => {
+ const total = accessLevels.edges?.length;
+ const accessLevelTypes = { total, users: [], groups: [], roles: [] };
+
+ accessLevels.edges?.forEach(({ node }) => {
+ if (node.user) {
+ const src = node.user.avatarUrl;
+ accessLevelTypes.users.push({ src, ...node.user });
+ } else if (node.group) {
+ accessLevelTypes.groups.push(node);
+ } else {
+ accessLevelTypes.roles.push(node);
+ }
+ });
+
+ return accessLevelTypes;
+};