Skip to content

Commit

Permalink
TimeString / ExternalLink improvements (gardener#1241)
Browse files Browse the repository at this point in the history
* Move tooltip logic to TimeString component

* use ExternalLink component where applicable

* Added an option to show a custom phrase instead of "in a few seconds" for invalid timestamps in future mode.
We could enhance this by providing slots where we define the whole phrases for valid / invalid case. However this would require more refactoring and would maybe be over-engineered.

* Update frontend/src/views/Administration.vue

Co-authored-by: Holger Koser <[email protected]>

* PR Feedback

Co-authored-by: Holger Koser <[email protected]>
  • Loading branch information
grolu and holgerkoser authored Jun 28, 2022
1 parent b3de362 commit 86190b0
Show file tree
Hide file tree
Showing 14 changed files with 79 additions and 92 deletions.
16 changes: 5 additions & 11 deletions frontend/src/components/ExternalLink.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ SPDX-License-Identifier: Apache-2.0
-->

<template>
<a :href="sanitizeUrl(url)" target="_blank" rel="noopener">
<slot>{{url}}</slot> <v-icon :size="12">mdi-open-in-new</v-icon>
<a :href="sanitizeUrl(url)" target="_blank" rel="noopener" class="text-decoration-none text-no-wrap">
<span class="text-decoration-underline">
<slot>{{url}}</slot>
</span>
<v-icon :size="12" class="inherit-color ml-1">mdi-open-in-new</v-icon>
</a>
</template>

Expand All @@ -24,12 +27,3 @@ export default {
}
}
</script>

<style scoped>
a {
text-decoration: none;
}
a > span {
text-decoration-line: underline;
}
</style>
8 changes: 5 additions & 3 deletions frontend/src/components/LinkListTile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ SPDX-License-Identifier: Apache-2.0
</template>
{{appTitle}} is not running for hibernated clusters
</v-tooltip>
<a v-else :href="sanitizeUrl(url)" target="_blank" rel="noopener">{{urlText}}</a>
<external-link v-else :url="url"></external-link>
</v-list-item-title>
</v-list-item-content>
</v-list-item>
</template>

<script>
import sanitizeUrl from '@/mixins/sanitizeUrl'
import ExternalLink from '@/components/ExternalLink.vue'

export default {
mixins: [sanitizeUrl],
components: {
ExternalLink
},
props: {
appTitle: {
type: String,
Expand Down
9 changes: 1 addition & 8 deletions frontend/src/components/ProjectServiceAccountRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,7 @@ SPDX-License-Identifier: Apache-2.0
</td>
<td v-if="selectedHeaders.creationTimestamp">
<div>
<v-tooltip top v-if="item.creationTimestamp">
<template v-slot:activator="{ on }">
<span v-on="on">
<time-string :date-time="item.creationTimestamp" mode="past"></time-string>
</span>
</template>
{{item.created}}
</v-tooltip>
<time-string v-if="item.creationTimestamp" :date-time="item.creationTimestamp" mode="past"></time-string>
<span v-else class="font-weight-light text--disabled">unknown</span>
</div>
</td>
Expand Down
7 changes: 1 addition & 6 deletions frontend/src/components/ShootDetails/ShootDetailsCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,7 @@ SPDX-License-Identifier: Apache-2.0
<v-list-item-content class="pt-0">
<v-list-item-subtitle>Created at</v-list-item-subtitle>
<v-list-item-title class="pt-1">
<v-tooltip top>
<template v-slot:activator="{ on }">
<span v-on="on">{{shootCreatedAt}}</span>
</template>
<time-string :date-time="shootMetadata.creationTimestamp" mode="past"></time-string>
</v-tooltip>
<time-string :date-time="shootMetadata.creationTimestamp" mode="past"></time-string>
</v-list-item-title>
</v-list-item-content>
</v-list-item>
Expand Down
28 changes: 5 additions & 23 deletions frontend/src/components/ShootListRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -52,14 +52,7 @@ SPDX-License-Identifier: Apache-2.0
<account-avatar :account-name="shootCreatedBy"></account-avatar>
</template>
<template v-if="cell.header.value === 'createdAt'">
<v-tooltip top>
<template v-slot:activator="{ on }">
<div v-on="on">
<time-string :date-time="shootCreationTimestamp" mode="past"></time-string>
</div>
</template>
{{ shootCreatedAt }}
</v-tooltip>
<time-string :date-time="shootCreationTimestamp" mode="past"></time-string>
</template>
<template v-if="cell.header.value === 'purpose'">
<div class="d-flex justify-center pr-4">
Expand Down Expand Up @@ -88,16 +81,9 @@ SPDX-License-Identifier: Apache-2.0
<access-restriction-chips :selected-access-restrictions="shootSelectedAccessRestrictions"></access-restriction-chips>
</template>
<template v-if="cell.header.value === 'ticket'">
<v-tooltip top>
<template v-slot:activator="{ on }">
<div v-on="on">
<router-link :to="{ name: 'ShootItem', params: { name: shootName, namespace: shootNamespace } }">
<time-string :date-time="shootLastUpdatedTicketTimestamp" mode="past"></time-string>
</router-link>
</div>
</template>
{{ shootLastUpdatedTicket }}
</v-tooltip>
<router-link :to="{ name: 'ShootItem', params: { name: shootName, namespace: shootNamespace } }">
<time-string :date-time="shootLastUpdatedTicketTimestamp" mode="past"></time-string>
</router-link>
</template>
<template v-if="cell.header.value === 'ticketLabels'">
<template v-if="shootLastUpdatedTicketTimestamp && !shootTicketsLabels.length">
Expand Down Expand Up @@ -163,8 +149,7 @@ import ShootListRowActions from '@/components/ShootListRowActions'
import AutoHide from '@/components/AutoHide'

import {
isTypeDelete,
getTimestampFormatted
isTypeDelete
} from '@/utils'

import { shootItem } from '@/mixins/shootItem'
Expand Down Expand Up @@ -236,9 +221,6 @@ export default {
shootLastUpdatedTicketTimestamp () {
return this.latestUpdatedTicketByNameAndNamespace(this.shootMetadata)
},
shootLastUpdatedTicket () {
return getTimestampFormatted(this.shootLastUpdatedTicketTimestamp)
},
shootTicketsLabels () {
return this.ticketsLabels(this.shootMetadata)
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ SPDX-License-Identifier: Apache-2.0

<template>
<div>
<span v-if="isValidTerminationDate">This cluster will self terminate <time-string :date-time="shootExpirationTimestamp" mode="future" class="font-weight-bold"></time-string></span>
<span v-if="isValidTerminationDate">This cluster will self terminate <time-string :date-time="shootExpirationTimestamp" mode="future" no-tooltip class="font-weight-bold"></time-string></span>
<span v-else>This cluster is about to self terminate</span>
</div>
</template>
Expand Down
15 changes: 3 additions & 12 deletions frontend/src/components/ShootMessages/K8sExpirationMessage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,9 @@ SPDX-License-Identifier: Apache-2.0
<template>
<div>
<span v-if="isValidTerminationDate">Kubernetes version of this cluster expires
<v-tooltip right>
<template v-slot:activator="{ on }">
<time-string v-on="on" :date-time="expirationDate" mode="future" class="font-weight-bold"></time-string>
</template>
{{getDateFormatted(expirationDate)}}
</v-tooltip>. </span>
<time-string :date-time="expirationDate" mode="future" date-tooltip content-class="font-weight-bold"></time-string>
<span>. </span>
</span>
<span v-else>Kubernetes version of this cluster is expired.</span>
<span v-if="severity === 'info'">Version will be updated in the next maintenance window</span>
<template v-else-if="severity === 'warning'">
Expand All @@ -25,7 +22,6 @@ SPDX-License-Identifier: Apache-2.0

<script>

import { getDateFormatted } from '@/utils'
import TimeString from '@/components/TimeString'

export default {
Expand All @@ -45,11 +41,6 @@ export default {
type: String,
required: true
}
},
methods: {
getDateFormatted (date) {
return getDateFormatted(date)
}
}
}
</script>
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,7 @@ SPDX-License-Identifier: Apache-2.0
<div>
Machine image <span class="font-weight-bold">{{name}} | Version: {{version}}</span> of worker group <span class="font-weight-bold">{{workerName}} </span>
<span v-if="isValidTerminationDate">expires
<v-tooltip right>
<template v-slot:activator="{ on }">
<span class="font-weight-bold" v-on="on"><time-string :date-time="expirationDate" mode="future"></time-string></span>
</template>
{{getDateFormatted(expirationDate)}}
</v-tooltip>
<time-string :date-time="expirationDate" mode="future" date-tooltip content-class="font-weight-bold"></time-string>
<span>. </span>
</span>
<span v-else>is expired. </span>
Expand Down
9 changes: 5 additions & 4 deletions frontend/src/components/ShootTickets/Ticket.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ SPDX-License-Identifier: Apache-2.0

<v-container>
<span class="font-weight-bold">{{login}}</span> created this
<a :href="sanitizeUrl(ticketHtmlUrl)" target="_blank" rel="noopener">ticket</a>
<a :href="sanitizeUrl(ticketHtmlUrl)" target="_blank" rel="noopener" class="link-icon"><v-icon color="anchor" class="link-icon">mdi-open-in-new</v-icon></a>
<time-string :date-time="ticket.metadata.created_at" mode="past"></time-string>
<external-link :url="ticketHtmlUrl">ticket</external-link>
<time-string :date-time="ticket.metadata.created_at" mode="past" content-class="ml-1"></time-string>
</v-container>
<v-list>
<ticket-comment :comment="ticket"></ticket-comment>
Expand All @@ -40,13 +39,15 @@ import { mapState, mapGetters } from 'vuex'
import TimeString from '@/components/TimeString'
import TicketLabel from '@/components/ShootTickets/TicketLabel'
import TicketComment from '@/components/ShootTickets/TicketComment'
import ExternalLink from '@/components/ExternalLink.vue'
import sanitizeUrl from '@/mixins/sanitizeUrl'

export default {
components: {
TimeString,
TicketLabel,
TicketComment
TicketComment,
ExternalLink
},
mixins: [sanitizeUrl],
props: {
Expand Down
8 changes: 4 additions & 4 deletions frontend/src/components/ShootTickets/TicketComment.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ SPDX-License-Identifier: Apache-2.0
</v-list-item-icon>
<v-list-item-content class="comment">
<v-list-item-title class="comment-header toolbar-background toolbar-title--text">
<span class="font-weight-bold">{{login}}</span> commented <a :href="sanitizeUrl(htmlUrl)" target="_blank" rel="noopener"><time-string :date-time="createdAt" mode="past" class="toolbar-title--text"></time-string></a>
<external-link :url="htmlUrl" class="inherit-color toolbar-title--text"><span class="font-weight-bold toolbar-title--text">{{login}}</span> commented <time-string :date-time="createdAt" mode="past" content-class="toolbar-title--text"></time-string></external-link>
</v-list-item-title>
<v-list-item-subtitle class="wrap-text comment-body" v-html="commentHtml"></v-list-item-subtitle>
</v-list-item-content>
Expand All @@ -27,8 +27,8 @@ SPDX-License-Identifier: Apache-2.0
import get from 'lodash/get'
import { gravatarUrlIdenticon, transformHtml } from '@/utils'
import TimeString from '@/components/TimeString'
import ExternalLink from '@/components/ExternalLink.vue'
import { mapState } from 'vuex'
import sanitizeUrl from '@/mixins/sanitizeUrl'

const AvatarEnum = {
GITHUB: 'github', // default
Expand All @@ -38,9 +38,9 @@ const AvatarEnum = {

export default {
components: {
TimeString
TimeString,
ExternalLink
},
mixins: [sanitizeUrl],
props: {
comment: {
type: Object,
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/StaleProjectWarning.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ SPDX-License-Identifier: Apache-2.0
<v-icon :small="small" v-on="on" :color="color" class="staleIcon" v-else>mdi-clock-alert-outline</v-icon>
</template>
<span v-if="staleAutoDeleteTimestamp">
This is a <span class="font-weight-bold">stale</span> project. Gardener will auto delete this project <span class="font-weight-bold"><time-string :date-time="staleAutoDeleteTimestamp" mode="future"></time-string></span>
This is a <span class="font-weight-bold">stale</span> project. Gardener will auto delete this project <time-string :date-time="staleAutoDeleteTimestamp" mode="future" no-tooltip content-class="font-weight-bold"></time-string>
</span>
<span v-else>
This project is considered <span class="font-weight-bold">stale</span> since <span class="font-weight-bold"><time-string :date-time="staleSinceTimestamp" withoutPrefixOrSuffix></time-string></span>
This project is considered <span class="font-weight-bold">stale</span> since <time-string :date-time="staleSinceTimestamp" without-prefix-or-suffix no-tooltip content-class="font-weight-bold"></time-string>
</span>
</v-tooltip>
</template>
Expand Down
52 changes: 44 additions & 8 deletions frontend/src/components/TimeString.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@ SPDX-License-Identifier: Apache-2.0
-->

<template>
<span>{{timeString}}</span>
<v-tooltip top :disabled="noTooltip">
<template v-slot:activator="{ on }">
<span v-on="on" :class="contentClass">{{relDateTimeString}}</span>
</template>
{{dateTimeString}}
</v-tooltip>
</template>

<script>
import { getTimeStringFrom, getTimeStringTo } from '@/utils'
import {
getTimeStringFrom,
getTimeStringTo,
getTimestampFormatted,
getDateFormatted,
isValidTerminationDate
} from '@/utils'
import Vue from 'vue'

class Clock {
Expand Down Expand Up @@ -47,6 +58,22 @@ export default {
withoutPrefixOrSuffix: {
type: Boolean,
default: false
},
noTooltip: {
type: Boolean,
default: false
},
dateTooltip: {
type: Boolean,
default: false
},
contentClass: {
type: String,
default: ''
},
expiredText: {
type: String,
default: 'soon'
}
},
data () {
Expand All @@ -57,18 +84,27 @@ export default {
}
},
computed: {
timeString () {
let timeString = ''
relDateTimeString () {
if (this.mode === 'future' && !isValidTerminationDate(this.dateTime)) {
return this.expiredText
}
let relDateTimeString = ''
if (this.dateTime && this.currentClockTimer) {
if (this.negativeRefDate) {
timeString = getTimeStringFrom(new Date(this.dateTime), new Date(Math.max(new Date(this.dateTime), this.currentClockTimer.dateObj)), this.withoutPrefixOrSuffix)
relDateTimeString = getTimeStringFrom(new Date(this.dateTime), new Date(Math.max(new Date(this.dateTime), this.currentClockTimer.dateObj)), this.withoutPrefixOrSuffix)
} else {
timeString = getTimeStringTo(new Date(Math.min(new Date(this.dateTime), this.currentClockTimer.dateObj)), new Date(this.dateTime), this.withoutPrefixOrSuffix)
relDateTimeString = getTimeStringTo(new Date(Math.min(new Date(this.dateTime), this.currentClockTimer.dateObj)), new Date(this.dateTime), this.withoutPrefixOrSuffix)
}
}

this.$emit('update:current-string', timeString)
return timeString
this.$emit('update:current-string', relDateTimeString)
return relDateTimeString
},
dateTimeString () {
if (this.dateTooltip) {
return getDateFormatted(this.dateTime)
}
return getTimestampFormatted(this.dateTime)
}
},
methods: {
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/views/Administration.vue
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ SPDX-License-Identifier: Apache-2.0
<template v-slot:activator="{ on }">
<span class="font-weight-bold" v-on="on">{{staleAutoDeleteDate}}</span>
</template>
<time-string :date-time="staleAutoDeleteTimestamp" mode="future"></time-string>
<time-string :date-time="staleAutoDeleteTimestamp" mode="future" no-tooltip></time-string>
</v-tooltip>
</span>
<span v-else>
This project is considered <span class="font-weight-bold">stale</span> since <span class="font-weight-bold"><time-string :date-time="staleSinceTimestamp" withoutPrefixOrSuffix></time-string></span>
This project is considered <span class="font-weight-bold">stale</span> since <time-string :date-time="staleSinceTimestamp" without-prefix-or-suffix content-class="font-weight-bold"></time-string>
</span>
</v-list-item-title>
</v-list-item-content>
Expand Down
2 changes: 0 additions & 2 deletions frontend/src/views/Members.vue
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,6 @@ import {
parseServiceAccountUsername,
isForeignServiceAccount,
isServiceAccountUsername,
getTimestampFormatted,
getProjectDetails,
sortedRoleDisplayNames,
mapTableHeader
Expand Down Expand Up @@ -355,7 +354,6 @@ export default {
...serviceAccount,
avatarUrl: gravatarUrlGeneric(username),
displayName: displayName(username),
created: getTimestampFormatted(serviceAccount.creationTimestamp),
roleDisplayNames: this.sortedRoleDisplayNames(serviceAccount.roles),
isCurrentUser: this.isCurrentUser(username)
}
Expand Down

0 comments on commit 86190b0

Please sign in to comment.