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
path: root/app
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2022-12-28 18:07:23 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2022-12-28 18:07:23 +0300
commit20d52aa39ef79bc199e1459e385387baeb04d99f (patch)
treee13dc3aec8c70ad4c522452068b96fd98f2b3fa5 /app
parentd30b2ead9a6606035a5d650216b9b5630b010421 (diff)
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app')
-rw-r--r--app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue78
-rw-r--r--app/assets/javascripts/work_items/components/work_item_detail.vue2
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue1
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue54
-rw-r--r--app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue13
-rw-r--r--app/assets/javascripts/work_items/constants.js9
-rw-r--r--app/assets/javascripts/work_items/graphql/work_item_links.query.graphql1
-rw-r--r--app/assets/stylesheets/utilities.scss6
-rw-r--r--app/controllers/groups/usage_quotas_controller.rb3
-rw-r--r--app/models/group.rb4
10 files changed, 111 insertions, 60 deletions
diff --git a/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue b/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue
index 00e0649deed..5e0c5735bc0 100644
--- a/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue
+++ b/app/assets/javascripts/pages/projects/forks/new/components/project_namespace.vue
@@ -1,14 +1,5 @@
<script>
-import {
- GlButton,
- GlButtonGroup,
- GlDropdown,
- GlDropdownItem,
- GlDropdownText,
- GlDropdownSectionHeader,
- GlSearchBoxByType,
- GlTruncate,
-} from '@gitlab/ui';
+import { GlButton, GlButtonGroup, GlCollapsibleListbox } from '@gitlab/ui';
import { createAlert } from '~/flash';
import { MINIMUM_SEARCH_LENGTH } from '~/graphql_shared/constants';
import { s__ } from '~/locale';
@@ -20,12 +11,7 @@ export default {
components: {
GlButton,
GlButtonGroup,
- GlDropdown,
- GlDropdownItem,
- GlDropdownText,
- GlDropdownSectionHeader,
- GlSearchBoxByType,
- GlTruncate,
+ GlCollapsibleListbox,
},
apollo: {
project: {
@@ -61,24 +47,25 @@ export default {
};
},
computed: {
+ loading() {
+ return this.$apollo.queries.project.loading;
+ },
rootUrl() {
return `${gon.gitlab_url}/`;
},
namespaces() {
return this.project.forkTargets?.nodes || [];
},
- hasMatches() {
- return this.namespaces.length;
- },
dropdownText() {
return this.selectedNamespace?.fullPath || s__('ForkProject|Select a namespace');
},
+ namespaceItems() {
+ return this.namespaces?.map(({ id, fullPath }) => ({ value: id, text: fullPath }));
+ },
},
methods: {
- handleDropdownShown() {
- this.$refs.search.focusInput();
- },
- setNamespace(namespace) {
+ setNamespace(namespaceId) {
+ const namespace = this.namespaces.find(({ id }) => id === namespaceId);
const id = getIdFromGraphQLId(namespace.id);
this.$emit('select', {
@@ -89,6 +76,9 @@ export default {
this.selectedNamespace = { id, fullPath: namespace.fullPath };
},
+ searchNamespaces(search) {
+ this.search = search;
+ },
},
};
</script>
@@ -98,39 +88,19 @@ export default {
<gl-button class="gl-text-truncate gl-flex-grow-0! gl-max-w-34" label :title="rootUrl">{{
rootUrl
}}</gl-button>
-
- <gl-dropdown
+ <gl-collapsible-listbox
class="gl-flex-grow-1"
- toggle-class="gl-rounded-top-right-base! gl-rounded-bottom-right-base! gl-w-20"
data-qa-selector="select_namespace_dropdown"
data-testid="select_namespace_dropdown"
- no-flip
- @shown="handleDropdownShown"
- >
- <template #button-text>
- <gl-truncate :text="dropdownText" position="start" with-tooltip />
- </template>
- <gl-search-box-by-type
- ref="search"
- v-model.trim="search"
- :is-loading="$apollo.queries.project.loading"
- data-qa-selector="select_namespace_dropdown_search_field"
- data-testid="select_namespace_dropdown_search_field"
- />
- <template v-if="!$apollo.queries.project.loading">
- <template v-if="hasMatches">
- <gl-dropdown-section-header>{{ __('Namespaces') }}</gl-dropdown-section-header>
- <gl-dropdown-item
- v-for="namespace of namespaces"
- :key="namespace.id"
- data-qa-selector="select_namespace_dropdown_item"
- @click="setNamespace(namespace)"
- >
- {{ namespace.fullPath }}
- </gl-dropdown-item>
- </template>
- <gl-dropdown-text v-else>{{ __('No matches found') }}</gl-dropdown-text>
- </template>
- </gl-dropdown>
+ :items="namespaceItems"
+ :header-text="__('Namespaces')"
+ :no-results-text="__('No matches found')"
+ :searchable="true"
+ :searching="loading"
+ toggle-class="gl-flex-direction-column gl-align-items-stretch!"
+ :toggle-text="dropdownText"
+ @search="searchNamespaces"
+ @select="setNamespace"
+ />
</gl-button-group>
</template>
diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue
index 1efbc226ca2..94fe67fdcf7 100644
--- a/app/assets/javascripts/work_items/components/work_item_detail.vue
+++ b/app/assets/javascripts/work_items/components/work_item_detail.vue
@@ -623,10 +623,12 @@ export default {
<work-item-tree
v-if="workItemType === $options.WORK_ITEM_TYPE_VALUE_OBJECTIVE"
:work-item-type="workItemType"
+ :parent-work-item-type="workItem.workItemType.name"
:work-item-id="workItem.id"
:children="children"
:can-update="canUpdate"
:project-path="fullPath"
+ :confidential="workItem.confidential"
@addWorkItemChild="addChild"
@removeChild="removeChild"
/>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
index faadb5fa6fa..b078711ec5d 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links.vue
@@ -399,6 +399,7 @@ export default {
:parent-iteration="issuableIteration"
:parent-milestone="issuableMilestone"
:form-type="formType"
+ :parent-work-item-type="workItem.workItemType.name"
@cancel="hideAddForm"
@addWorkItemChild="addChild"
/>
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
index 5cf0c4154bb..34f7e659600 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_links_form.vue
@@ -1,5 +1,14 @@
<script>
-import { GlAlert, GlFormGroup, GlForm, GlTokenSelector, GlButton, GlFormInput } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlFormGroup,
+ GlForm,
+ GlTokenSelector,
+ GlButton,
+ GlFormInput,
+ GlFormCheckbox,
+ GlTooltip,
+} from '@gitlab/ui';
import { debounce } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { DEFAULT_DEBOUNCE_AND_THROTTLE_MS } from '~/lib/utils/constants';
@@ -17,6 +26,8 @@ import {
I18N_WORK_ITEM_SEARCH_INPUT_PLACEHOLDER,
I18N_WORK_ITEM_ADD_BUTTON_LABEL,
I18N_WORK_ITEM_ADD_MULTIPLE_BUTTON_LABEL,
+ I18N_WORK_ITEM_CONFIDENTIALITY_CHECKBOX_LABEL,
+ I18N_WORK_ITEM_CONFIDENTIALITY_CHECKBOX_TOOLTIP,
sprintfWorkItem,
} from '../../constants';
@@ -28,6 +39,8 @@ export default {
GlButton,
GlFormGroup,
GlFormInput,
+ GlFormCheckbox,
+ GlTooltip,
},
mixins: [glFeatureFlagMixin()],
inject: ['projectPath', 'hasIterationsFeature'],
@@ -61,6 +74,11 @@ export default {
type: String,
required: true,
},
+ parentWorkItemType: {
+ type: String,
+ required: false,
+ default: '',
+ },
childrenType: {
type: String,
required: false,
@@ -108,6 +126,7 @@ export default {
error: null,
childToCreateTitle: null,
workItemsToAdd: [],
+ confidential: this.parentConfidential,
};
},
computed: {
@@ -119,7 +138,7 @@ export default {
hierarchyWidget: {
parentId: this.issuableGid,
},
- confidential: this.parentConfidential,
+ confidential: this.parentConfidential || this.confidential,
};
if (this.parentMilestoneId) {
@@ -162,6 +181,16 @@ export default {
}
return sprintfWorkItem(I18N_WORK_ITEM_ADD_BUTTON_LABEL, this.childrenTypeName);
},
+ confidentialityCheckboxLabel() {
+ return sprintfWorkItem(I18N_WORK_ITEM_CONFIDENTIALITY_CHECKBOX_LABEL, this.childrenTypeName);
+ },
+ confidentialityCheckboxTooltip() {
+ return sprintfWorkItem(
+ I18N_WORK_ITEM_CONFIDENTIALITY_CHECKBOX_TOOLTIP,
+ this.childrenTypeName,
+ this.parentWorkItemType,
+ );
+ },
addOrCreateMethod() {
return this.isCreateForm ? this.createChild : this.addChild;
},
@@ -192,6 +221,11 @@ export default {
},
methods: {
getIdFromGraphQLId,
+ getConfidentialityTooltipTarget() {
+ // We want tooltip to be anchored to `input` within checkbox component
+ // but `$el.querySelector('input')` doesn't work. 🤷‍♂️
+ return this.$refs.confidentialityCheckbox?.$el;
+ },
unsetError() {
this.error = null;
},
@@ -299,8 +333,22 @@ export default {
autofocus
/>
</gl-form-group>
+ <gl-form-checkbox
+ ref="confidentialityCheckbox"
+ v-model="confidential"
+ name="isConfidential"
+ class="gl-md-mt-5 gl-mb-5 gl-md-mb-3!"
+ :disabled="parentConfidential"
+ >{{ confidentialityCheckboxLabel }}</gl-form-checkbox
+ >
+ <gl-tooltip
+ v-if="parentConfidential"
+ :target="getConfidentialityTooltipTarget"
+ triggers="hover"
+ >{{ confidentialityCheckboxTooltip }}</gl-tooltip
+ >
<gl-token-selector
- v-else
+ v-if="!isCreateForm"
v-model="workItemsToAdd"
:dropdown-items="availableWorkItems"
:loading="isLoading"
diff --git a/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue b/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue
index f06de2ca048..532a3b4aa18 100644
--- a/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue
+++ b/app/assets/javascripts/work_items/components/work_item_links/work_item_tree.vue
@@ -40,10 +40,20 @@ export default {
type: String,
required: true,
},
+ parentWorkItemType: {
+ type: String,
+ required: false,
+ default: '',
+ },
workItemId: {
type: String,
required: true,
},
+ confidential: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
children: {
type: Array,
required: false,
@@ -221,8 +231,10 @@ export default {
data-testid="add-tree-form"
:issuable-gid="workItemId"
:form-type="formType"
+ :parent-work-item-type="parentWorkItemType"
:children-type="childType"
:children-ids="childrenIds"
+ :parent-confidential="confidential"
@addWorkItemChild="$emit('addWorkItemChild', $event)"
@cancel="hideAddForm"
/>
@@ -233,6 +245,7 @@ export default {
:can-update="canUpdate"
:issuable-gid="workItemId"
:child-item="child"
+ :confidential="child.confidential"
:work-item-type="workItemType"
:has-indirect-children="hasIndirectChildren"
@mouseover="prefetchWorkItem(child)"
diff --git a/app/assets/javascripts/work_items/constants.js b/app/assets/javascripts/work_items/constants.js
index 7e4fd1d547d..21af1449e50 100644
--- a/app/assets/javascripts/work_items/constants.js
+++ b/app/assets/javascripts/work_items/constants.js
@@ -73,12 +73,19 @@ export const I18N_WORK_ITEM_ADD_MULTIPLE_BUTTON_LABEL = s__('WorkItem|Add %{work
export const I18N_WORK_ITEM_SEARCH_INPUT_PLACEHOLDER = s__(
'WorkItem|Search existing %{workItemType}s',
);
+export const I18N_WORK_ITEM_CONFIDENTIALITY_CHECKBOX_LABEL = s__(
+ 'WorkItem|This %{workItemType} is confidential and should only be visible to team members with at least Reporter access',
+);
+export const I18N_WORK_ITEM_CONFIDENTIALITY_CHECKBOX_TOOLTIP = s__(
+ 'WorkItem|A non-confidential %{workItemType} cannot be assigned to a confidential parent %{parentWorkItemType}.',
+);
-export const sprintfWorkItem = (msg, workItemTypeArg) => {
+export const sprintfWorkItem = (msg, workItemTypeArg, parentWorkItemType = '') => {
const workItemType = workItemTypeArg || s__('WorkItem|Work item');
return capitalizeFirstCharacter(
sprintf(msg, {
workItemType: workItemType.toLocaleLowerCase(),
+ parentWorkItemType: parentWorkItemType.toLocaleLowerCase(),
}),
);
};
diff --git a/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql b/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql
index 7fcf622cdb2..7d7bb9c7fc5 100644
--- a/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql
+++ b/app/assets/javascripts/work_items/graphql/work_item_links.query.graphql
@@ -3,6 +3,7 @@ query workItemLinksQuery($id: WorkItemID!) {
id
workItemType {
id
+ name
}
title
userPermissions {
diff --git a/app/assets/stylesheets/utilities.scss b/app/assets/stylesheets/utilities.scss
index 36e6f7941f6..5eb76be4bbf 100644
--- a/app/assets/stylesheets/utilities.scss
+++ b/app/assets/stylesheets/utilities.scss
@@ -255,6 +255,12 @@ to @gitlab/ui by https://gitlab.com/gitlab-org/gitlab-ui/-/issues/1709
}
}
+.gl-md-mb-3\! {
+ @include gl-media-breakpoint-up(md) {
+ margin-bottom: $gl-spacing-scale-3 !important;
+ }
+}
+
.gl-gap-2 {
gap: $gl-spacing-scale-2;
diff --git a/app/controllers/groups/usage_quotas_controller.rb b/app/controllers/groups/usage_quotas_controller.rb
index 29878f0001d..b660eb3af99 100644
--- a/app/controllers/groups/usage_quotas_controller.rb
+++ b/app/controllers/groups/usage_quotas_controller.rb
@@ -16,8 +16,7 @@ module Groups
private
def verify_usage_quotas_enabled!
- render_404 unless Feature.enabled?(:usage_quotas_for_all_editions, group)
- render_404 if group.has_parent?
+ render_404 unless group.usage_quotas_enabled?
end
# To be overriden in ee/app/controllers/ee/groups/usage_quotas_controller.rb
diff --git a/app/models/group.rb b/app/models/group.rb
index 2067eed9989..37dcbf95e63 100644
--- a/app/models/group.rb
+++ b/app/models/group.rb
@@ -915,6 +915,10 @@ class Group < Namespace
feature_flag_enabled_for_self_or_ancestor?(:work_items_create_from_markdown)
end
+ def usage_quotas_enabled?
+ ::Feature.enabled?(:usage_quotas_for_all_editions, self) && root?
+ end
+
# Check for enabled features, similar to `Project#feature_available?`
# NOTE: We still want to keep this after removing `Namespace#feature_available?`.
override :feature_available?