feat: Implement reference resolving for cards that have a link in the title

Signed-off-by: Julius Härtl <jus@bitgrid.net>

fix: Enrich on update

Signed-off-by: Julius Knorr <jus@bitgrid.net>

fix: Enrich on create

Signed-off-by: Julius Knorr <jus@bitgrid.net>
This commit is contained in:
Julius Härtl
2024-09-01 11:58:08 +02:00
committed by Julius Knorr
parent 46c4c7d4fd
commit 75be929077
12 changed files with 155 additions and 49 deletions

View File

@@ -7,12 +7,12 @@
<NcAppSidebar v-if="currentBoard && currentCard"
ref="cardSidebar"
:active="tabId"
:name="title"
:name="displayTitle"
:subname="subtitle"
:subtitle="subtitleTooltip"
:name-editable="titleEditable"
@update:nameEditable="handleUpdateTitleEditable"
@update:name="handleUpdateTitle"
:name-editable.sync="isEditingTitle"
@update:name="(value) => titleEditing = value"
@dismiss-editing="titleEditing = currentCard.title"
@submit-name="handleSubmitTitle"
@opened="focusHeader"
@close="closeSidebar">
@@ -26,6 +26,11 @@
<CardMenuEntries :card="currentCard" :hide-details-entry="true" />
</template>
<template #description>
<NcReferenceList v-if="currentCard.referenceData"
:text="currentCard.title"
:interactive="false" />
</template>
<NcAppSidebarTab id="details"
:order="0"
@@ -68,6 +73,7 @@
<script>
import { NcActionButton, NcAppSidebar, NcAppSidebarTab } from '@nextcloud/vue'
import { NcReferenceList } from '@nextcloud/vue/dist/Components/NcRichText.js'
import { getCapabilities } from '@nextcloud/capabilities'
import { mapState, mapGetters } from 'vuex'
import CardSidebarTabDetails from './CardSidebarTabDetails.vue'
@@ -93,6 +99,7 @@ export default {
NcAppSidebar,
NcAppSidebarTab,
NcActionButton,
NcReferenceList,
CardSidebarTabAttachments,
CardSidebarTabComments,
CardSidebarTabActivity,
@@ -122,7 +129,7 @@ export default {
},
data() {
return {
titleEditable: false,
isEditingTitle: false,
titleEditing: '',
hasActivity: capabilities && capabilities.activity,
locale: getLocale(),
@@ -130,13 +137,10 @@ export default {
},
computed: {
...mapState({
isFullApp: state => state.isFullApp,
currentBoard: state => state.currentBoard,
isFullApp: (state) => state.isFullApp,
currentBoard: (state) => state.currentBoard,
}),
...mapGetters(['canEdit', 'assignables', 'cardActions', 'stackById']),
title() {
return this.titleEditable ? this.titleEditing : this.currentCard.title
},
currentCard() {
return this.$store.getters.cardById(this.id)
},
@@ -154,11 +158,26 @@ export default {
this.$store.dispatch('setConfig', { cardDetailsInModal: newValue })
},
},
displayTitle: {
get() {
if (this.isEditingTitle) {
return this.titleEditing
}
const reference = this.currentCard.referenceData
return reference ? reference.openGraphObject.name : this.currentCard.title
},
},
},
watch: {
currentCard() {
this.focusHeader()
},
'currentCard.title': {
immediate: true,
handler(newTitle) {
this.titleEditing = newTitle
},
},
},
methods: {
focusHeader() {
@@ -166,22 +185,16 @@ export default {
this.$refs?.cardSidebar.$el.querySelector('.app-sidebar-header__mainname')?.focus()
})
},
handleUpdateTitleEditable(value) {
this.titleEditable = value
if (value) {
this.titleEditing = this.currentCard.title
}
},
handleUpdateTitle(value) {
this.titleEditing = value
},
handleSubmitTitle(value) {
if (value.trim === '') {
handleSubmitTitle() {
if (this.titleEditing.trim() === '') {
showError(t('deck', 'The title cannot be empty.'))
return
}
this.titleEditable = false
this.$store.dispatch('updateCardTitle', { ...this.currentCard, title: this.titleEditing })
this.isEditingTitle = false
this.$store.dispatch('updateCardTitle', {
...this.currentCard,
title: this.titleEditing,
})
},
closeSidebar() {

View File

@@ -4,7 +4,10 @@
-->
<template>
<div v-if="cardId && ( attachments.length > 0 )" class="card-cover">
<div v-if="referencePreview" class="card-cover">
<div class="image-wrapper rounded-left rounded-right" :style="{ backgroundImage: `url(${referencePreview})`}" />
</div>
<div v-else-if="cardId && ( attachments.length > 0 )" class="card-cover">
<div v-for="(attachment, index) in attachments"
:key="attachment.id"
:class="['image-wrapper', { 'rounded-left': index === 0 }, { 'rounded-right': index === attachments.length - 1 }]"
@@ -43,6 +46,12 @@ export default {
attachment.extendedData.fileid ? generateUrl(`/core/preview?fileId=${attachment.extendedData.fileid}&x=${x}&y=${y}&a=1`) : null
)
},
card() {
return this.$store.getters.cardById(this.cardId)
},
referencePreview() {
return this.card?.referenceData?.richObject?.thumb
},
},
watch: {
cardId: {

View File

@@ -20,7 +20,7 @@
<CardCover v-if="showCardCover" :card-id="card.id" />
<div class="card-upper">
<h4 v-if="inlineEditingBlocked" dir="auto">
{{ card.title }}
{{ displayTitle }}
</h4>
<h4 v-else
dir="auto"
@@ -133,11 +133,15 @@ export default {
return board ? !board.archived && board.permissions.PERMISSION_EDIT : false
},
inlineEditingBlocked() {
return this.isArchived || this.showArchived || !this.canEdit || this.standalone
return this.card.referenceData || this.isArchived || this.showArchived || !this.canEdit || this.standalone
},
card() {
return this.item ? this.item : this.$store.getters.cardById(this.id)
},
displayTitle() {
const reference = this.card.referenceData
return reference ? reference.openGraphObject.name : this.card.title
},
currentCard() {
return this.card && this.$route && this.$route.params.cardId === this.card.id
},

View File

@@ -5,23 +5,35 @@
<template>
<div v-if="card" class="card-menu" @click.stop.prevent>
<NcButton v-if="card.referenceData" type="tertiary" @click="openLink">
<template #icon>
<LinkIcon :size="20" />
</template>
</NcButton>
<NcActions>
<CardMenuEntries :card="card" />
</NcActions>
</div>
</template>
<script>
import { NcActions } from '@nextcloud/vue'
import { NcActions, NcButton } from '@nextcloud/vue'
import LinkIcon from 'vue-material-design-icons/Link.vue'
import CardMenuEntries from './CardMenuEntries.vue'
export default {
name: 'CardMenu',
components: { NcActions, CardMenuEntries },
components: { NcActions, NcButton, LinkIcon, CardMenuEntries },
props: {
card: {
type: Object,
default: null,
},
},
methods: {
openLink() {
window.open(this.card?.referenceData?.openGraphObject?.link)
return false
},
},
}
</script>