diff --git a/.gitlab/CODEOWNERS b/.gitlab/CODEOWNERS index 52ffc3e24aa..2526ddc1b02 100644 --- a/.gitlab/CODEOWNERS +++ b/.gitlab/CODEOWNERS @@ -582,7 +582,6 @@ lib/gitlab/checks/** /doc/administration/application_settings_cache.md @jglassman1 /doc/administration/auditor_users.md @idurham /doc/administration/auth/ @idurham -/doc/administration/backup_restore/ @axil /doc/administration/broadcast_messages.md @sselhorn /doc/administration/cells.md @emily.sahlani /doc/administration/cicd/ @lyspin @@ -606,7 +605,7 @@ lib/gitlab/checks/** /doc/administration/file_hooks.md @ashrafkhamis /doc/administration/geo/ @axil /doc/administration/geo_sites.md @axil -/doc/administration/get_started.md @kpaizee +/doc/administration/get_started.md @gl-docsteam /doc/administration/git_protocol.md @brendan777 /doc/administration/gitaly/ @eread /doc/administration/gitlab_duo_self_hosted/ @jglassman1 @@ -632,7 +631,7 @@ lib/gitlab/checks/** /doc/administration/logs/ @axil /doc/administration/logs/_index.md @lciutacu /doc/administration/maintenance_mode/ @axil -/doc/administration/merge_request_diffs.md @brendan777 +/doc/administration/merge_request_diffs.md @aqualls /doc/administration/merge_requests_approvals.md @brendan777 /doc/administration/moderate_users.md @lciutacu /doc/administration/monitoring/_index.md @lciutacu @@ -655,7 +654,6 @@ lib/gitlab/checks/** /doc/administration/packages/_index.md @z_painter /doc/administration/pages/ @msedlakjakubowski /doc/administration/polling.md @axil -/doc/administration/postgresql/ @emily.sahlani /doc/administration/raketasks/ @axil /doc/administration/raketasks/ldap.md @idurham /doc/administration/raketasks/praefect.md @eread @@ -710,6 +708,7 @@ lib/gitlab/checks/** /doc/administration/settings/terraform_limits.md @z_painter /doc/administration/settings/third_party_offers.md @emily.sahlani /doc/administration/settings/visibility_and_access_controls.md @brendan777 +/doc/administration/settings/vscode_extension_marketplace.md @brendan777 /doc/administration/sidekiq/ @axil /doc/administration/sidekiq/sidekiq_memory_killer.md @jglassman1 /doc/administration/silent_mode/ @axil @@ -795,6 +794,7 @@ lib/gitlab/checks/** /doc/api/group_level_variables.md @marcel.amirault /doc/api/group_markdown_uploads.md @msedlakjakubowski /doc/api/group_milestones.md @msedlakjakubowski +/doc/api/group_placeholder_reassignments.md @ashrafkhamis /doc/api/group_protected_branches.md @brendan777 /doc/api/group_protected_environments.md @z_painter /doc/api/group_push_rules.md @brendan777 @@ -831,7 +831,7 @@ lib/gitlab/checks/** /doc/api/merge_trains.md @lyspin /doc/api/metadata.md @z_painter /doc/api/milestones.md @msedlakjakubowski -/doc/api/namespaces.md @idurham +/doc/api/namespaces.md @emily.sahlani /doc/api/notes.md @msedlakjakubowski /doc/api/notification_settings.md @sselhorn /doc/api/oauth2.md @idurham @@ -934,6 +934,7 @@ lib/gitlab/checks/** /doc/ci/examples/deployment/ @z_painter /doc/ci/examples/semantic-release.md @z_painter /doc/ci/gitlab_google_cloud_integration/ @lyspin +/doc/ci/inputs/ @marcel.amirault /doc/ci/interactive_web_terminal/ @rsarangadharan /doc/ci/jobs/ @marcel.amirault /doc/ci/jobs/fine_grained_permissions.md @idurham @@ -977,7 +978,7 @@ lib/gitlab/checks/** /doc/development/audit_event_guide/ @gitlab-org/govern/security-policies-frontend @gitlab-org/govern/threat-insights-frontend-team @gitlab-org/govern/threat-insights-backend-team /doc/development/avoiding_required_stops.md @gitlab-org/distribution /doc/development/build_test_package.md @gitlab-org/distribution -/doc/development/cascading_settings.md @gitlab-org/foundations/personal-productivity/engineering +/doc/development/cascading_settings.md @gitlab-org/foundations/engineering /doc/development/cells/ @OmarQunsulGitlab @bmarjanovic /doc/development/cicd/ @gitlab-org/maintainers/cicd-verify /doc/development/contributing/verify/ @gitlab-org/maintainers/cicd-verify @@ -987,7 +988,7 @@ lib/gitlab/checks/** /doc/development/documentation/ @fneill @sselhorn /doc/development/duo_workflow/ @gitlab-org/ai-powered /doc/development/fe_guide/analytics_dashboards.md @gitlab-org/analytics-section/product-analytics/engineers/frontend -/doc/development/fe_guide/keyboard_shortcuts.md @gitlab-org/foundations/personal-productivity/engineering +/doc/development/fe_guide/keyboard_shortcuts.md @gitlab-org/foundations/engineering /doc/development/git_object_deduplication.md @proglottis @toon /doc/development/gitaly.md @proglottis @toon /doc/development/gitpod_internals.md @gl-dx/tooling-maintainers @@ -998,7 +999,7 @@ lib/gitlab/checks/** /doc/development/logging.md @gitlab-org/analytics-section/product-analytics/engineers/frontend /doc/development/logs.md @gitlab-org/analytics-section/product-analytics/engineers/frontend /doc/development/metrics.md @gitlab-org/analytics-section/product-analytics/engineers/frontend -/doc/development/navigation_sidebar.md @gitlab-org/foundations/personal-productivity/engineering +/doc/development/navigation_sidebar.md @gitlab-org/foundations/engineering /doc/development/observability/ @gitlab-org/analytics-section/product-analytics/engineers/frontend /doc/development/omnibus.md @gitlab-org/distribution /doc/development/organization/ @abdwdd @alexpooley @@ -1039,6 +1040,7 @@ lib/gitlab/checks/** /doc/operations/feature_flags.md @z_painter /doc/policy/ @axil /doc/security/ @idurham +/doc/security/asset_proxy.md @msedlakjakubowski /doc/security/hardening_nist_800_53.md @emily.sahlani /doc/solutions/ @jfullam @Darwinjs @sbrightwell /doc/solutions/integrations/servicenow.md @ashrafkhamis @@ -1052,7 +1054,7 @@ lib/gitlab/checks/** /doc/topics/git/project.md @emily.sahlani /doc/topics/offline/ @axil /doc/topics/runner_fleet_design_guides/ @rsarangadharan -/doc/tutorials/ @kpaizee +/doc/tutorials/ @gl-docsteam /doc/tutorials/boards_for_standups/ @msedlakjakubowski /doc/tutorials/boards_for_teams/ @msedlakjakubowski /doc/tutorials/compliance_pipeline/ @eread @@ -1067,6 +1069,7 @@ lib/gitlab/checks/** /doc/tutorials/idea_management/ @msedlakjakubowski /doc/tutorials/install_gitlab_single_node/ @axil /doc/tutorials/issue_triage/ @msedlakjakubowski +/doc/tutorials/issue_triage_group/ @msedlakjakubowski /doc/tutorials/kanban/ @msedlakjakubowski /doc/tutorials/left_sidebar/ @sselhorn /doc/tutorials/merge_requests/ @aqualls @@ -1098,6 +1101,7 @@ lib/gitlab/checks/** /doc/user/application_security/security_dashboard/ @rlehmann1 /doc/user/application_security/vulnerabilities/ @rlehmann1 /doc/user/application_security/vulnerabilities/risk_assessment_data.md @rdickenson +/doc/user/application_security/vulnerability_archival/ @rlehmann1 /doc/user/application_security/vulnerability_report/ @rlehmann1 /doc/user/asciidoc.md @brendan777 /doc/user/clusters/ @z_painter @@ -1105,7 +1109,6 @@ lib/gitlab/checks/** /doc/user/compliance/license_approval_policies.md @rlehmann1 /doc/user/compliance/license_scanning_of_cyclonedx_files/ @rdickenson /doc/user/crm/ @msedlakjakubowski -/doc/user/custom_roles.md @idurham /doc/user/custom_roles/ @idurham /doc/user/discussions/ @aqualls /doc/user/duo_amazon_q/ @sselhorn @@ -1119,6 +1122,7 @@ lib/gitlab/checks/** /doc/user/get_started/get_started_projects.md @emily.sahlani /doc/user/get_started/getting_started_gitlab_duo.md @sselhorn /doc/user/gitlab_duo/ @sselhorn +/doc/user/gitlab_duo/tutorials/ @gl-docsteam /doc/user/gitlab_duo_chat/ @jglassman1 /doc/user/glql/ @msedlakjakubowski /doc/user/group/_index.md @emily.sahlani @@ -1200,7 +1204,6 @@ lib/gitlab/checks/** /doc/user/project/merge_requests/ @aqualls /doc/user/project/merge_requests/approvals/ @brendan777 /doc/user/project/merge_requests/cherry_pick_changes.md @brendan777 -/doc/user/project/merge_requests/csv_export.md @eread /doc/user/project/merge_requests/methods/ @brendan777 /doc/user/project/merge_requests/squash_and_merge.md @brendan777 /doc/user/project/merge_requests/status_checks.md @rlehmann1 @@ -1245,6 +1248,7 @@ lib/gitlab/checks/** /doc/user/storage_usage_quotas.md @lciutacu /doc/user/tasks.md @msedlakjakubowski /doc/user/todos.md @sselhorn +/doc/user/work_items/ @msedlakjakubowski /doc/user/workspace/ @brendan777 # End rake-managed-docs-block diff --git a/app/assets/javascripts/api/groups_api.js b/app/assets/javascripts/api/groups_api.js index 5e39feb0f88..58b423f65b3 100644 --- a/app/assets/javascripts/api/groups_api.js +++ b/app/assets/javascripts/api/groups_api.js @@ -3,6 +3,7 @@ import axios from '../lib/utils/axios_utils'; import { buildApiUrl } from './api_utils'; const GROUP_PATH = '/api/:version/groups/:id'; +const GROUP_RESTORE_PATH = '/api/:version/groups/:id/restore'; const GROUPS_PATH = '/api/:version/groups.json'; const GROUP_MEMBERS_PATH = '/api/:version/groups/:id/members'; const GROUP_MEMBER_PATH = '/api/:version/groups/:id/members/:user_id'; @@ -59,6 +60,12 @@ export function deleteGroup(groupId) { return axios.delete(url); } +export function restoreGroup(groupId) { + const url = buildApiUrl(GROUP_RESTORE_PATH).replace(':id', groupId); + + return axios.post(url); +} + export const getGroupTransferLocations = (groupId, params = {}) => { const url = buildApiUrl(GROUP_TRANSFER_LOCATIONS_PATH).replace(':id', groupId); const defaultParams = { per_page: DEFAULT_PER_PAGE }; diff --git a/app/assets/javascripts/environments/constants.js b/app/assets/javascripts/environments/constants.js index 5c2734a0dab..8d9b72b359e 100644 --- a/app/assets/javascripts/environments/constants.js +++ b/app/assets/javascripts/environments/constants.js @@ -87,23 +87,32 @@ export const ENVIRONMENT_EDIT_HELP_TEXT = ENVIRONMENT_NEW_HELP_TEXT; export const SERVICES_LIMIT_PER_PAGE = 10; -export const CLUSTER_STATUS_HEALTHY_TEXT = s__('Environment|Healthy'); -export const CLUSTER_STATUS_UNHEALTHY_TEXT = s__('Environment|Unhealthy'); - export const CLUSTER_HEALTH_SUCCESS = 'success'; export const CLUSTER_HEALTH_ERROR = 'error'; +export const CLUSTER_HEALTH_NEEDS_ATTENTION = 'needs-attention'; +export const CLUSTER_HEALTH_UNKNOWN = 'unknown'; export const HEALTH_BADGES = { [CLUSTER_HEALTH_SUCCESS]: { variant: 'success', - text: CLUSTER_STATUS_HEALTHY_TEXT, + text: s__('Environment|Healthy'), icon: 'status-success', }, [CLUSTER_HEALTH_ERROR]: { variant: 'danger', - text: CLUSTER_STATUS_UNHEALTHY_TEXT, + text: s__('Environment|Unhealthy'), icon: 'status-alert', }, + [CLUSTER_HEALTH_NEEDS_ATTENTION]: { + variant: 'warning', + text: s__('Environment|Needs attention'), + icon: 'status-alert', + }, + [CLUSTER_HEALTH_UNKNOWN]: { + variant: 'muted', + text: s__('Environment|Unknown'), + icon: 'status-waiting', + }, }; export const SYNC_STATUS_BADGES = { diff --git a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_overview.vue b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_overview.vue index 1211cea3948..10c23c48a49 100644 --- a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_overview.vue +++ b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_overview.vue @@ -25,8 +25,6 @@ import { import fluxKustomizationQuery from '~/environments/graphql/queries/flux_kustomization.query.graphql'; import fluxHelmReleaseQueryStatus from '~/environments/graphql/queries/flux_helm_release.query.graphql'; import { - CLUSTER_HEALTH_SUCCESS, - CLUSTER_HEALTH_ERROR, HELM_RELEASES_RESOURCE_TYPE, KUSTOMIZATIONS_RESOURCE_TYPE, FLUX_RECONCILE_ACTION, @@ -128,9 +126,8 @@ export default { data() { return { error: null, - failedState: {}, - podsLoading: false, activeTab: k8sResourceType.k8sPods, + clusterHealthStatus: '', fluxApiError: '', podToDelete: {}, fluxHelmRelease: {}, @@ -147,15 +144,6 @@ export default { gitlabAgentId: this.gitlabAgentId, }); }, - clusterHealthStatus() { - if (this.podsLoading) { - return ''; - } - return this.hasFailedState ? CLUSTER_HEALTH_ERROR : CLUSTER_HEALTH_SUCCESS; - }, - hasFailedState() { - return Object.values(this.failedState).some((item) => item); - }, fluxResourceStatus() { const conditions = this.fluxKustomization.conditions || this.fluxHelmRelease.conditions || []; const spec = this.fluxKustomization.spec || this.fluxHelmRelease.spec || false; @@ -186,12 +174,6 @@ export default { }); this.error = message; }, - handleFailedState(event) { - this.failedState = { - ...this.failedState, - ...event, - }; - }, transformFluxResourceData(item) { return { name: item.metadata.name, @@ -347,8 +329,7 @@ export default { :flux-kustomization="fluxKustomization" class="gl-mb-5" @cluster-error="handleError" - @loading="podsLoading = $event" - @update-failed-state="handleFailedState" + @update-cluster-state="clusterHealthStatus = $event" @select-item="toggleDetailsDrawer" @remove-selection="closeDetailsDrawer" @delete-pod="onDeletePod" diff --git a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_pods.vue b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_pods.vue index ad7864bf01e..95b5c90ca9b 100644 --- a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_pods.vue +++ b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_pods.vue @@ -9,7 +9,13 @@ import { STATUS_LABELS, PODS_TABLE_FIELDS, } from '~/kubernetes_dashboard/constants'; -import { DELETE_POD_ACTION } from '~/environments/constants'; +import { + DELETE_POD_ACTION, + CLUSTER_HEALTH_SUCCESS, + CLUSTER_HEALTH_ERROR, + CLUSTER_HEALTH_NEEDS_ATTENTION, + CLUSTER_HEALTH_UNKNOWN, +} from '~/environments/constants'; import { getAge, getPodStatusText } from '~/kubernetes_dashboard/helpers/k8s_integration_helper'; import WorkloadStats from '~/kubernetes_dashboard/components/workload_stats.vue'; import WorkloadTable from '~/kubernetes_dashboard/components/workload_table.vue'; @@ -59,9 +65,6 @@ export default { this.error = error.message; this.$emit('cluster-error', this.error); }, - watchLoading(isLoading) { - this.$emit('loading', isLoading); - }, }, }, props: { @@ -88,19 +91,19 @@ export default { return [ { - value: this.countPodsByPhase(STATUS_RUNNING), + value: this.podsRunning, title: STATUS_LABELS[STATUS_RUNNING], }, { - value: this.countPodsByPhase(STATUS_PENDING), + value: this.podsPending, title: STATUS_LABELS[STATUS_PENDING], }, { - value: this.countPodsByPhase(STATUS_SUCCEEDED), + value: this.podsSucceeded, title: STATUS_LABELS[STATUS_SUCCEEDED], }, { - value: this.countPodsByPhase(STATUS_FAILED), + value: this.podsFailed, title: STATUS_LABELS[STATUS_FAILED], }, ]; @@ -108,6 +111,18 @@ export default { loading() { return this.$apollo?.queries?.k8sPods?.loading; }, + podsRunning() { + return this.countPodsByPhase(STATUS_RUNNING); + }, + podsPending() { + return this.countPodsByPhase(STATUS_PENDING); + }, + podsFailed() { + return this.countPodsByPhase(STATUS_FAILED); + }, + podsSucceeded() { + return this.countPodsByPhase(STATUS_SUCCEEDED); + }, podsCount() { return this.k8sPods?.length || 0; }, @@ -118,6 +133,30 @@ export default { return matchesStatus && matchesSearch; }); }, + podsHealthStatus() { + if (this.loading) { + return ''; + } + + if (!this.k8sPods.length) { + return CLUSTER_HEALTH_UNKNOWN; + } + + if (this.podsFailed > 0) { + return CLUSTER_HEALTH_ERROR; + } + + if (this.podsPending > 0) { + return CLUSTER_HEALTH_NEEDS_ATTENTION; + } + + return CLUSTER_HEALTH_SUCCESS; + }, + }, + watch: { + k8sPods() { + this.$emit('update-cluster-state', this.podsHealthStatus); + }, }, methods: { search(searchTerm, podName) { @@ -125,15 +164,13 @@ export default { }, countPodsByPhase(phase) { const pods = this.k8sPods || []; + const filteredPods = pods.filter((item) => { const matchesPhase = item.status === phase; if (!this.podsSearch) return matchesPhase; return matchesPhase && this.search(this.podsSearch, item.name); }); - const hasFailedState = Boolean(phase === STATUS_FAILED && filteredPods.length); - this.$emit('update-failed-state', { pods: hasFailedState }); - return filteredPods.length; }, onItemSelect(item) { diff --git a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_status_bar.vue b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_status_bar.vue index 1e98fce1a67..8b1a8739479 100644 --- a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_status_bar.vue +++ b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_status_bar.vue @@ -12,6 +12,8 @@ import { s__ } from '~/locale'; import { CLUSTER_HEALTH_SUCCESS, CLUSTER_HEALTH_ERROR, + CLUSTER_HEALTH_NEEDS_ATTENTION, + CLUSTER_HEALTH_UNKNOWN, HEALTH_BADGES, SYNC_STATUS_BADGES, HELM_RELEASES_RESOURCE_TYPE, @@ -46,7 +48,13 @@ export default { type: String, default: '', validator(val) { - return [CLUSTER_HEALTH_ERROR, CLUSTER_HEALTH_SUCCESS, ''].includes(val); + return [ + CLUSTER_HEALTH_ERROR, + CLUSTER_HEALTH_SUCCESS, + CLUSTER_HEALTH_UNKNOWN, + CLUSTER_HEALTH_NEEDS_ATTENTION, + '', + ].includes(val); }, }, configuration: { diff --git a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_tabs.vue b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_tabs.vue index 08b6b6371db..546b4009995 100644 --- a/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_tabs.vue +++ b/app/assets/javascripts/environments/environment_details/components/kubernetes/kubernetes_tabs.vue @@ -71,8 +71,7 @@ export default { ({ createdAt: group.created_at, updatedAt: group.updated_at, avatarUrl: group.avatar_url, + markedForDeletionOn: group.marked_for_deletion_on, userPermissions: { canLeave: group.can_leave, removeGroup: group.can_remove, @@ -36,7 +37,6 @@ export const formatGroup = (group) => ({ organizationEditPath: '', groupMembersCount: 0, isLinkedToSubscription: false, - markedForDeletionOn: null, isAdjournedDeletionEnabled: false, permanentDeletionDate: null, }); diff --git a/app/assets/javascripts/organizations/shared/utils.js b/app/assets/javascripts/organizations/shared/utils.js index 600c69c4961..1f3b9cd27a4 100644 --- a/app/assets/javascripts/organizations/shared/utils.js +++ b/app/assets/javascripts/organizations/shared/utils.js @@ -3,6 +3,7 @@ import { ACTION_EDIT, ACTION_DELETE, ACTION_LEAVE, + ACTION_RESTORE, } from '~/vue_shared/components/list_actions/constants'; import { TIMESTAMP_TYPE_CREATED_AT, @@ -11,13 +12,17 @@ import { import { formatGraphQLProjects } from '~/vue_shared/components/projects_list/formatter'; import { SORT_CREATED_AT, SORT_UPDATED_AT } from './constants'; -const availableGroupActions = (userPermissions) => { +const availableGroupActions = ({ userPermissions, markedForDeletionOn }) => { const baseActions = []; if (userPermissions.viewEditPage) { baseActions.push(ACTION_EDIT); } + if (userPermissions.removeGroup && markedForDeletionOn) { + baseActions.push(ACTION_RESTORE); + } + if (userPermissions.canLeave) { baseActions.push(ACTION_LEAVE); } @@ -36,6 +41,7 @@ export const formatGroups = (groups) => fullName, webUrl, parent, + markedForDeletionOn, maxAccessLevel: accessLevel, userPermissions, organizationEditPath: editPath, @@ -49,9 +55,10 @@ export const formatGroups = (groups) => fullName, webUrl, parent: parent?.id || null, + markedForDeletionOn, accessLevel, editPath, - availableActions: availableGroupActions(userPermissions), + availableActions: availableGroupActions({ userPermissions, markedForDeletionOn }), descendantGroupsCount, children: children?.length ? formatGroups(children) : [], childrenLoading: false, diff --git a/app/assets/javascripts/projects/components/project_delete_button.vue b/app/assets/javascripts/projects/components/project_delete_button.vue index eac83d094c7..4287a2a1a94 100644 --- a/app/assets/javascripts/projects/components/project_delete_button.vue +++ b/app/assets/javascripts/projects/components/project_delete_button.vue @@ -14,11 +14,6 @@ export default { type: String, required: true, }, - disabled: { - type: Boolean, - required: false, - default: false, - }, formPath: { type: String, required: true, @@ -55,7 +50,6 @@ export default { {{ buttonText }} diff --git a/app/assets/javascripts/projects/project_delete_button.js b/app/assets/javascripts/projects/project_delete_button.js index b3de3e6db9e..5ad618b102e 100644 --- a/app/assets/javascripts/projects/project_delete_button.js +++ b/app/assets/javascripts/projects/project_delete_button.js @@ -12,7 +12,6 @@ export default (selector = '#js-project-delete-button') => { nameWithNamespace, formPath, isFork, - isSecurityPolicyProject, issuesCount, mergeRequestsCount, forksCount, @@ -28,7 +27,6 @@ export default (selector = '#js-project-delete-button') => { props: { confirmPhrase, nameWithNamespace, - disabled: parseBoolean(isSecurityPolicyProject), formPath, isFork: parseBoolean(isFork), issuesCount: parseInt(issuesCount, 10), diff --git a/app/assets/javascripts/vue_shared/components/groups_list/group_list_item_actions.vue b/app/assets/javascripts/vue_shared/components/groups_list/group_list_item_actions.vue new file mode 100644 index 00000000000..bd99df1474a --- /dev/null +++ b/app/assets/javascripts/vue_shared/components/groups_list/group_list_item_actions.vue @@ -0,0 +1,85 @@ + + + diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue b/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue index 5798bb964b1..741f6252d13 100644 --- a/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue +++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue @@ -9,11 +9,7 @@ import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '~/visibility_level/ import { ACCESS_LEVEL_LABELS, ACCESS_LEVEL_NO_ACCESS_INTEGER } from '~/access_level/constants'; import { __ } from '~/locale'; import { numberToMetricPrefix } from '~/lib/utils/number_utils'; -import { - ACTION_EDIT, - ACTION_DELETE, - ACTION_LEAVE, -} from '~/vue_shared/components/list_actions/constants'; +import { ACTION_DELETE, ACTION_LEAVE } from '~/vue_shared/components/list_actions/constants'; import { TIMESTAMP_TYPES, TIMESTAMP_TYPE_CREATED_AT, @@ -22,7 +18,8 @@ import ListItem from '~/vue_shared/components/resource_lists/list_item.vue'; import ListItemStat from '~/vue_shared/components/resource_lists/list_item_stat.vue'; import { renderDeleteSuccessToast, deleteParams } from '~/vue_shared/components/groups_list/utils'; import GroupListItemLeaveModal from '~/vue_shared/components/groups_list/group_list_item_leave_modal.vue'; -import GroupListItemPreventDeleteModal from './group_list_item_prevent_delete_modal.vue'; +import GroupListItemPreventDeleteModal from '~/vue_shared/components/groups_list/group_list_item_prevent_delete_modal.vue'; +import GroupListItemActions from '~/vue_shared/components/groups_list/group_list_item_actions.vue'; import GroupListItemInactiveBadge from './group_list_item_inactive_badge.vue'; export default { @@ -39,6 +36,7 @@ export default { ListItemStat, GlIcon, GlBadge, + GroupListItemActions, GroupListItemLeaveModal, GroupListItemPreventDeleteModal, GroupListItemDeleteModal, @@ -110,25 +108,15 @@ export default { groupMembersCount() { return numberToMetricPrefix(this.group.groupMembersCount); }, - actions() { - return { - [ACTION_EDIT]: { - href: this.group.editPath, - }, - [ACTION_DELETE]: { - action: this.onActionDelete, - }, - [ACTION_LEAVE]: { - action: this.onActionLeave, - }, - }; - }, hasActionDelete() { return this.group.availableActions?.includes(ACTION_DELETE); }, hasActionLeave() { return this.group.availableActions?.includes(ACTION_LEAVE); }, + hasActions() { + return this.group.availableActions?.length; + }, hasFooterAction() { return this.hasActionDelete || this.hasActionLeave; }, @@ -170,7 +158,6 @@ export default { :resource="group" :show-icon="showGroupIcon" :icon-name="groupIconName" - :actions="actions" :list-item-class="listItemClass" :timestamp-type="timestampType" > @@ -211,6 +198,15 @@ export default { /> + +