Skip to content

Commit

Permalink
Collapse ShootList Columns (#1991)
Browse files Browse the repository at this point in the history
* Collapse worker groups on cluster list

* - fixed worker group margins
- adjusted tooltip delay
- make button only visible on mouseover
- worker group chip not clickable

* Changed auto-hide activation

* use v-hover to show / hide collapse button

* Reset expanded state when component gets reused

* Store expansion state in provided object

* Allow to toggle all worker groups using shift-click
Some cleanup

* Refactored collapse logic into re-usable component

* Use collapsable items component for access restrictions and ticket labels

* Collapse Readiness Tags

* Cleanup

* React to shift press

* Further cleanup
Hide collapse buttons via css

* Expand Items in Table Header

* Removed expanded readiness condition state

* inject expanded items

* Use custom table header for all VDataTables to align headers

* Use collapsable items only where we actually want to collapse

* Fixed wrong param

* PR Feedback

* - Removed all unused functionality from GCollapsibleItems
- Removed GDataTableHeader
- Show number only for collapsed items
- Use VChipGroup for ticket labels
- Fixed sorting for numeric values

* PR Feedback
- Removed expand button / expand only by clicking on chip
- Added hover effect for expandable chips
- Close using close icon
- removed g-collapsible-items-button as we don't need that re-use component anymore
- Removed multi-expand logic (shift)
- Use v-chips for ticket labels
- Do not use v-chip-group as this makes the group selectable which we do not want

* fixed unknown color

* PR Feedback

* PR Feedback

* fixed unused import

* PR Feedback: minor renaming

---------

Co-authored-by: Holger Koser <[email protected]>
  • Loading branch information
grolu and holgerkoser authored Sep 28, 2024
1 parent 2721499 commit e7e5b5f
Show file tree
Hide file tree
Showing 17 changed files with 336 additions and 177 deletions.
9 changes: 7 additions & 2 deletions frontend/src/components/GCodeBlock.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ SPDX-License-Identifier: Apache-2.0
>
<div
class="code-block-wrapper"
:style="{ 'max-height': height }"
:style="{ 'max-height': maxHeight, 'min-width': minWidth }"
>
<pre><code
ref="block"
Expand Down Expand Up @@ -62,10 +62,15 @@ export default {
},
props: {
lang: String,
height: {
maxHeight: {
type: [Number, String],
default: '450px',
},
minWidth: {
type: [Number, String],
default: '100%',
},
content: {
type: String,
default: '',
Expand Down
108 changes: 108 additions & 0 deletions frontend/src/components/GCollapsibleItems.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
<!--
SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors
SPDX-License-Identifier: Apache-2.0
-->

<template>
<div
v-if="items.length"
class="d-flex"
>
<div
class="d-flex align-center"
>
<template v-if="!expanded">
<v-hover v-slot="{ props: hoverProps, isHovering }">
<v-chip
v-bind="hoverProps"
:variant="isHovering ? 'flat' : 'outlined'"
size="small"
:color="chipColor"
label
class="pointer"
@click="expanded = true"
>
{{ itemCount }}
<v-tooltip
location="top"
activator="parent"
>
Expand items
</v-tooltip>
</v-chip>
</v-hover>
</template>
<template v-else>
<div
class="d-flex flex-wrap"
>
<div
v-for="(item, i) in items"
:key="i"
class="d-flex align-center"
>
<slot
name="item"
:item="item"
/>
</div>
</div>
</template>
</div>
<div>
<v-btn
v-if="expanded"
icon="mdi-close"
variant="plain"
size="small"
@click="expanded = false"
/>
</div>
</div>
</template>

<script setup>
import {
toRefs,
computed,
inject,
} from 'vue'
const props = defineProps({
items: {
type: Array,
default: () => [],
},
uid: {
type: String,
required: false,
},
injectKey: {
type: String,
required: false,
},
chipColor: {
type: String,
default: 'primary',
},
})
const { items } = toRefs(props)
const expandedItems = inject(props.injectKey, undefined)
const itemCount = computed(() => {
return props.items.length
})
const expanded = computed({
get () {
return expandedItems[props.uid] ?? expandedItems.default
},
set (value) {
expandedItems[props.uid] = value
},
})
</script>
61 changes: 53 additions & 8 deletions frontend/src/components/GShootListRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,21 @@ SPDX-License-Identifier: Apache-2.0
</g-auto-hide>
</template>
<template v-if="cell.header.key === 'workers'">
<g-worker-groups />
<div class="d-flex justify-center">
<g-collapsible-items
:items="shootWorkerGroups"
:uid="shootUid"
:chip-color="hasShootWorkerGroupWarning ? 'warning' : 'primary'"
inject-key="expandedWorkerGroups"
>
<template #item="{ item }">
<g-worker-group
:worker-group="item"
class="ma-1"
/>
</template>
</g-collapsible-items>
</div>
</template>
<template v-if="cell.header.key === 'createdBy'">
<g-account-avatar :account-name="shootCreatedBy" />
Expand Down Expand Up @@ -115,7 +129,21 @@ SPDX-License-Identifier: Apache-2.0
/>
</template>
<template v-if="cell.header.key === 'accessRestrictions'">
<g-access-restriction-chips :access-restrictions="shootAccessRestrictions" />
<g-collapsible-items
:items="shootAccessRestrictions"
:uid="shootUid"
inject-key="expandedAccessRestrictions"
>
<template #item="{ item }">
<g-access-restriction-chip
:id="item.key"
:key="item.key"
:title="item.title"
:description="item.description"
:options="item.options"
/>
</template>
</g-collapsible-items>
</template>
<template v-if="cell.header.key === 'ticket'">
<g-external-link
Expand All @@ -134,11 +162,11 @@ SPDX-License-Identifier: Apache-2.0
</template>
<div
v-else
class="labels"
class="d-flex flex-wrap ticket-labels"
>
<g-ticket-label
v-for="label in shootTicketLabels"
:key="label.id"
:key="label.name"
:label="label"
/>
</div>
Expand Down Expand Up @@ -214,7 +242,7 @@ import { useProjectStore } from '@/store/project'
import { useSeedStore } from '@/store/seed'
import { useGardenerExtensionStore } from '@/store/gardenerExtension'
import GAccessRestrictionChips from '@/components/ShootAccessRestrictions/GAccessRestrictionChips.vue'
import GAccessRestrictionChip from '@/components/ShootAccessRestrictions/GAccessRestrictionChip.vue'
import GAccountAvatar from '@/components/GAccountAvatar.vue'
import GActionButton from '@/components/GActionButton.vue'
import GCopyBtn from '@/components/GCopyBtn.vue'
Expand All @@ -231,8 +259,9 @@ 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 GWorkerGroups from '@/components/ShootWorkers/GWorkerGroups'
import GWorkerGroup from '@/components/ShootWorkers/GWorkerGroup'
import GTextRouterLink from '@/components/GTextRouterLink.vue'
import GCollapsibleItems from '@/components/GCollapsibleItems'
import { useProvideShootItem } from '@/composables/useShootItem'
import { useProvideShootHelper } from '@/composables/useShootHelper'
Expand All @@ -244,6 +273,8 @@ import {
includes,
get,
map,
some,
find,
} from '@/lodash'
const props = defineProps({
Expand Down Expand Up @@ -293,6 +324,9 @@ const {
shootTechnicalId,
shootSeedName,
shootAccessRestrictions,
shootWorkerGroups,
shootUid,
shootCloudProfileName,
} = useProvideShootItem(shootItem, {
cloudProfileStore,
projectStore,
Expand Down Expand Up @@ -399,11 +433,22 @@ function showDialog (action) {
})
}
const hasShootWorkerGroupWarning = computed(() => {
const machineImages = cloudProfileStore.machineImagesByCloudProfileName(shootCloudProfileName.value)
return some(shootWorkerGroups.value, workerGroup => {
const { name, version } = get(workerGroup, 'machine.image', {})
const machineImage = find(machineImages, { name, version })
return machineImage?.isDeprecated
})
})
</script>
<style lang="scss" scoped>
.labels {
line-height: 10px;
.ticket-labels {
overflow-y: scroll;
max-height: 30px;
max-width: 300px;
}
.position-relative {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/GShootStatus.vue
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ export default {
},
color () {
if (this.isAborted || this.isStaleShoot) {
return 'grey'
return 'unknown'
} else if (this.isError) {
return 'error'
} else {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/GVendor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ SPDX-License-Identifier: Apache-2.0
<v-tooltip
v-else
location="top"
:open-delay="50"
:open-delay="200"
>
<template #activator="{ props }">
<div
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/Secrets/GSecretDialogAlicloud.vue
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ SPDX-License-Identifier: Apache-2.0
user: AliyunECSFullAccess, AliyunSLBFullAccess, AliyunVPCFullAccess, AliyunEIPFullAccess, AliyunNATGatewayFullAccess.
</p>
<g-code-block
height="100%"
max-height="100%"
lang="json"
:content="JSON.stringify(template, undefined, 2)"
/>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/Secrets/GSecretDialogAws.vue
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,14 @@ SPDX-License-Identifier: Apache-2.0
</p>
<g-code-block
v-if="vendor==='aws'"
height="100%"
max-height="100%"
lang="json"
:content="JSON.stringify(templateAws, undefined, 2)"
/>
<div v-if="vendor==='aws-route53'">
<p>In this example, the placeholder for the hosted zone is Z2XXXXXXXXXXXX</p>
<g-code-block
height="100%"
max-height="100%"
lang="json"
:content="JSON.stringify(templateAwsRoute53, undefined, 2)"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@ SPDX-License-Identifier: Apache-2.0
-->

<template>
<div
v-for="{ key, title, description, options: optionsList } in props.accessRestrictions"
:key="key"
class="d-flex"
>
<div class="d-flex">
<v-chip
size="small"
variant="tonal"
Expand All @@ -24,27 +20,27 @@ SPDX-License-Identifier: Apache-2.0
max-width="600px"
>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="transformHtml(description) " />
<div v-html="transformHtml(description)" />
</v-tooltip>
</v-chip>

<v-chip
v-for="options in optionsList "
:key="`${key}_${options.key}`"
v-for="option in options"
:key="`${id}_${option.key}`"
size="small"
variant="tonal"
color="primary"
class="mr-2"
>
{{ options.title }}
{{ option.title }}
<v-tooltip
activator="parent"
location="top"
:disabled="!options.description"
:disabled="!option.description"
max-width="600px"
>
<!-- eslint-disable-next-line vue/no-v-html -->
<div v-html="transformHtml(options.description) " />
<div v-html="transformHtml(option.description)" />
</v-tooltip>
</v-chip>
</div>
Expand All @@ -53,9 +49,22 @@ SPDX-License-Identifier: Apache-2.0
<script setup>
import { transformHtml } from '@/utils'
const props = defineProps({
accessRestrictions: {
defineProps({
id: {
type: String,
required: true,
},
title: {
type: String,
required: true,
},
description: {
type: String,
required: false,
},
options: {
type: Array,
required: true,
},
})
</script>
Expand Down
Loading

0 comments on commit e7e5b5f

Please sign in to comment.