Skip to content

Commit

Permalink
Move GShootListRowActions from GShootListRow to GShootList component (#…
Browse files Browse the repository at this point in the history
…2148)

* Move GShootListRowActions from GShootListRow to GShootList component

* Use shared composable instead of event propagation to distribute state (#2155)

* Uniform handling of action and menu events on ShootList

* fixed lint errors

* Added License

* Improved `useShootAction` composable

* License header format

* Do not unset shootItem when menu closes

* Update frontend/src/components/GShootListActions.vue

Co-authored-by: Peter Sutter <[email protected]>

---------

Co-authored-by: Peter Sutter <[email protected]>

* Update frontend/src/views/GShootList.vue

Co-authored-by: Peter Sutter <[email protected]>

---------

Co-authored-by: Holger Koser <[email protected]>
Co-authored-by: Peter Sutter <[email protected]>
  • Loading branch information
3 people authored Nov 6, 2024
1 parent 218d7ea commit ec8b341
Show file tree
Hide file tree
Showing 4 changed files with 141 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,45 @@ SPDX-License-Identifier: Apache-2.0
-->

<template>
<v-dialog
v-if="!!shootUid"
v-model="accessDialog"
persistent
max-width="850"
>
<v-card>
<g-toolbar>
Cluster Access
<code class="text-toolbar-title">
{{ shootName }}
</code>
<template #append>
<v-btn
variant="text"
density="comfortable"
icon="mdi-close"
color="toolbar-title"
@click="accessDialog = false"
/>
</template>
</g-toolbar>
<g-shoot-access-card
ref="clusterAccess"
:selected-shoot="shootActionItem"
:hide-terminal-shortcuts="true"
/>
</v-card>
</v-dialog>
<v-menu
v-model="menu"
v-model="actionMenu"
location="left"
:close-on-content-click="false"
eager
:target="shootActionTarget"
>
<template #activator="{ props }">
<g-action-button
v-bind="props"
icon="mdi-dots-vertical"
tooltip="Cluster Actions"
/>
</template>
<v-list
dense
@click.capture="menu = false"
@click.capture="actionMenu = false"
>
<v-list-item>
<g-shoot-action-change-hibernation
Expand All @@ -39,7 +62,7 @@ SPDX-License-Identifier: Apache-2.0
</v-list-item>
<v-list-item>
<g-shoot-action-rotate-credentials
:type="rotationType"
type="ALL_CREDENTIALS"
text
/>
</v-list-item>
Expand All @@ -64,9 +87,9 @@ SPDX-License-Identifier: Apache-2.0
</template>

<script setup>
import { ref } from 'vue'
import { watch } from 'vue'

import GActionButton from '@/components/GActionButton.vue'
import GShootAccessCard from '@/components/ShootDetails/GShootAccessCard.vue'
import GShootActionChangeHibernation from '@/components/ShootHibernation/GShootActionChangeHibernation.vue'
import GShootActionMaintenanceStart from '@/components/ShootMaintenance/GShootActionMaintenanceStart.vue'
import GShootActionReconcileStart from '@/components/GShootActionReconcileStart.vue'
Expand All @@ -75,13 +98,28 @@ import GShootActionDeleteCluster from '@/components/GShootActionDeleteCluster.vu
import GShootActionForceDelete from '@/components/GShootActionForceDelete.vue'
import GShootVersionConfiguration from '@/components/ShootVersion/GShootVersionConfiguration.vue'

import { useShootItem } from '@/composables/useShootItem'
import { useProvideShootItem } from '@/composables/useShootItem'
import { useShootAction } from '@/composables/useShootAction'

const {
shootActionItem,
shootActionTarget,
createShootActionFlag,
unsetShootAction,
} = useShootAction()

const {
shootName,
shootUid,
canForceDeleteShoot,
} = useShootItem()
} = useProvideShootItem(shootActionItem)

const menu = ref(false)
const accessDialog = createShootActionFlag('access')
const actionMenu = createShootActionFlag('menu')

const rotationType = ref('ALL_CREDENTIALS')
watch(accessDialog, value => {
if (!value) {
unsetShootAction()
}
})
</script>
20 changes: 7 additions & 13 deletions frontend/src/components/GShootListRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -202,10 +202,13 @@ SPDX-License-Identifier: Apache-2.0
icon="mdi-key"
:disabled="isClusterAccessDialogDisabled"
:tooltip="showClusterAccessActionTitle"
@click="showDialog('access')"
@click="setShootAction('access', shootItem)"
/>
<g-shoot-list-row-actions
<g-action-button
v-if="canPatchShoots"
icon="mdi-dots-vertical"
tooltip="Cluster Actions"
@click="setShootAction('menu', shootItem, $event.target)"
/>
</v-row>
</template>
Expand Down Expand Up @@ -255,14 +258,14 @@ import GShootVersionChip from '@/components/ShootVersion/GShootVersionChip.vue'
import GTicketLabel from '@/components/ShootTickets/GTicketLabel.vue'
import GShootSeedName from '@/components/GShootSeedName.vue'
import GShootMessages from '@/components/ShootMessages/GShootMessages.vue'
import GShootListRowActions from '@/components/GShootListRowActions.vue'
import GAutoHide from '@/components/GAutoHide.vue'
import GExternalLink from '@/components/GExternalLink.vue'
import GControlPlaneHighAvailabilityTag from '@/components/ControlPlaneHighAvailability/GControlPlaneHighAvailabilityTag.vue'
import GWorkerGroup from '@/components/ShootWorkers/GWorkerGroup'
import GTextRouterLink from '@/components/GTextRouterLink.vue'
import GCollapsibleItems from '@/components/GCollapsibleItems'

import { useShootAction } from '@/composables/useShootAction'
import { useProvideShootItem } from '@/composables/useShootItem'
import { useProvideShootHelper } from '@/composables/useShootHelper'
import { formatValue } from '@/composables/useProjectShootCustomFields/helper'
Expand All @@ -289,9 +292,7 @@ const props = defineProps({
})
const shootItem = toRef(props, 'modelValue')

const emit = defineEmits([
'showDialog',
])
const { setShootAction } = useShootAction()

const shootStore = useShootStore()
const ticketStore = useTicketStore()
Expand Down Expand Up @@ -426,13 +427,6 @@ const cells = computed(() => {
})
})

function showDialog (action) {
emit('showDialog', {
action,
shootItem: shootItem.value,
})
}

const hasShootWorkerGroupWarning = computed(() => {
const machineImages = cloudProfileStore.machineImagesByCloudProfileName(shootCloudProfileName.value)
return some(shootWorkerGroups.value, workerGroup => {
Expand Down
73 changes: 73 additions & 0 deletions frontend/src/composables/useShootAction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//
// SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
//
// SPDX-License-Identifier: Apache-2.0
//

import {
reactive,
computed,
toRef,
inject,
provide,
} from 'vue'

import { useShootStore } from '@/store/shoot'

import { get } from '@/lodash'

export function createShootActionEventComposable (options = {}) {
const {
shootStore = useShootStore(),
} = options

const state = reactive({
name: '',
target: null,
})

const shootActionItem = toRef(shootStore, 'selectedShoot')
const shootActionTarget = computed(() => state.target)

function setShootAction (name, shootItem, target = null) {
const metadata = get(shootItem, ['metadata'], null)
shootStore.setSelection(metadata)
state.name = name
state.target = target
}

function unsetShootAction () {
setShootAction('', null, null)
}

function createShootActionFlag (name) {
return computed({
get () {
return state.name === name
},
set (value) {
if (!value) {
state.name = ''
}
},
})
}

return {
shootActionItem,
shootActionTarget,
setShootAction,
unsetShootAction,
createShootActionFlag,
}
}

export function useShootAction () {
return inject('shoot-action-event', null)
}

export function useProvideShootAction (options) {
const composable = createShootActionEventComposable(options)
provide('shoot-action-event', composable)
return composable
}
65 changes: 7 additions & 58 deletions frontend/src/views/GShootList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ SPDX-License-Identifier: Apache-2.0
<g-shoot-list-row
:model-value="item"
:visible-headers="visibleHeaders"
@show-dialog="showDialog"
/>
</template>
<template #bottom="{ pageCount }">
Expand All @@ -193,36 +192,8 @@ SPDX-License-Identifier: Apache-2.0
/>
</template>
</v-data-table>
<v-dialog
v-if="!isShootItemEmpty"
v-model="clusterAccessDialog"
persistent
max-width="850"
>
<v-card>
<g-toolbar>
Cluster Access
<code class="text-toolbar-title">
{{ currentName }}
</code>
<template #append>
<v-btn
variant="text"
density="comfortable"
icon="mdi-close"
color="toolbar-title"
@click.stop="hideDialog"
/>
</template>
</g-toolbar>
<g-shoot-access-card
ref="clusterAccess"
:selected-shoot="shootItem"
:hide-terminal-shortcuts="true"
/>
</v-card>
</v-dialog>
</v-card>
<g-shoot-list-actions />
</v-container>
</template>

Expand Down Expand Up @@ -256,10 +227,11 @@ import GTableColumnSelection from '@/components/GTableColumnSelection.vue'
import GIconBase from '@/components/icons/GIconBase.vue'
import GCertifiedKubernetes from '@/components/icons/GCertifiedKubernetes.vue'
import GDataTableFooter from '@/components/GDataTableFooter.vue'
import GShootAccessCard from '@/components/ShootDetails/GShootAccessCard.vue'
import GShootListActions from '@/components/GShootListActions.vue'

import { useProjectShootCustomFields } from '@/composables/useProjectShootCustomFields'
import { isCustomField } from '@/composables/useProjectShootCustomFields/helper'
import { useProvideShootAction } from '@/composables/useShootAction'

import { mapTableHeader } from '@/utils'

Expand All @@ -281,11 +253,11 @@ export default {
GToolbar,
GShootListRow,
GShootListProgress,
GShootAccessCard,
GIconBase,
GCertifiedKubernetes,
GTableColumnSelection,
GDataTableFooter,
GShootListActions,
},
inject: ['logger'],
beforeRouteEnter (to, from, next) {
Expand Down Expand Up @@ -314,6 +286,9 @@ export default {
},
setup () {
const projectStore = useProjectStore()
const shootStore = useShootStore()

useProvideShootAction({ shootStore })

const activePopoverKey = ref('')
const expandedWorkerGroups = reactive({ default: false })
Expand Down Expand Up @@ -428,16 +403,6 @@ export default {
defaultItemsPerPage () {
return 10
},
clusterAccessDialog: {
get () {
return this.dialog === 'access'
},
set (value) {
if (!value) {
this.hideDialog()
}
},
},
focusModeInternal: {
get () {
return this.focusMode
Expand Down Expand Up @@ -819,29 +784,13 @@ export default {
},
methods: {
...mapActions(useShootStore, [
'setSelection',
'toogleShootListFilter',
'subscribeShoots',
'sortItems',
'searchItems',
'setFocusMode',
'setSortBy',
]),
async showDialog (args) {
switch (args.action) {
case 'access':
try {
await this.setSelection(args.shootItem.metadata)
this.dialog = args.action
} catch (err) {
this.logger('Failed to select shoot: %s', err.message)
}
}
},
hideDialog () {
this.dialog = null
this.setSelection(null)
},
setSelectedHeader (header) {
this.selectedColumns[header.key] = !header.selected
this.saveSelectedColumns()
Expand Down

0 comments on commit ec8b341

Please sign in to comment.