mirror of https://github.com/nextcloud/bookmarks
345 lines
8.4 KiB
Vue
345 lines
8.4 KiB
Vue
<!--
|
|
- Copyright (c) 2020. The Nextcloud Bookmarks contributors.
|
|
-
|
|
- This file is licensed under the Affero General Public License version 3 or later. See the COPYING file.
|
|
-->
|
|
|
|
<template>
|
|
<Item :title="bookmark.title"
|
|
:tags="bookmark.tags"
|
|
:rename-placeholder="t('bookmarks', 'Enter new title')"
|
|
:select-label="t('bookmarks', 'Select bookmark')"
|
|
:active="isActive"
|
|
:editable="isEditable"
|
|
:selected="selected"
|
|
:draggable="isEditable"
|
|
:renaming="renaming"
|
|
:background="background"
|
|
:url="url"
|
|
:selectable="selectable"
|
|
@select="onSelect"
|
|
@rename="onRenameSubmit"
|
|
@rename-cancel="renaming = false"
|
|
@click="onClick">
|
|
<template #title>
|
|
<div class="bookmark__title">
|
|
<h3 :title="bookmark.title">
|
|
<span v-if="bookmark.preliminary" class="icon-loading-small bookmark__icon" />
|
|
<figure v-else
|
|
class="bookmark__icon"
|
|
:style="{ backgroundImage: 'url(' + iconUrl + ')' }" />
|
|
{{ bookmark.title }}
|
|
</h3>
|
|
<span v-if="bookmark.description"
|
|
v-tooltip="bookmark.description"
|
|
class="bookmark__description"><figure class="icon-file" />
|
|
{{ bookmark.description }}</span>
|
|
</div>
|
|
</template>
|
|
<template #actions>
|
|
<NcActionButton :close-after-click="true"
|
|
@click="onDetails">
|
|
<template #icon>
|
|
<InformationVariantIcon />
|
|
</template>
|
|
{{ t('bookmarks', 'Details') }}
|
|
</NcActionButton>
|
|
<NcActionCheckbox @change="onSelect">
|
|
{{ t('bookmarks', 'Select bookmark') }}
|
|
</NcActionCheckbox>
|
|
<NcActionButton :close-after-click="true"
|
|
@click="onRename">
|
|
<template #icon>
|
|
<PencilIcon />
|
|
</template>
|
|
{{ t('bookmarks', 'Rename') }}
|
|
</NcActionButton>
|
|
<NcActionButton :close-after-click="true"
|
|
@click="onCopyUrl">
|
|
<template #icon>
|
|
<ContentCopyIcon />
|
|
</template>
|
|
{{ t('bookmarks', 'Copy link') }}
|
|
</NcActionButton>
|
|
<NcActionButton :close-after-click="true" @click="onMove">
|
|
<template #icon>
|
|
<FolderMoveIcon />
|
|
</template>
|
|
{{ t('bookmarks', 'Move') }}
|
|
</NcActionButton>
|
|
<NcActionButton :close-after-click="true" @click="onCopy">
|
|
<template #icon>
|
|
<FolderPlusIcon />
|
|
</template>
|
|
{{ t('bookmarks', 'Add to folders') }}
|
|
</NcActionButton>
|
|
<NcActionButton :close-after-click="true"
|
|
@click="onDelete">
|
|
<template #icon>
|
|
<DeleteIcon />
|
|
</template>
|
|
{{ t('bookmarks', 'Delete') }}
|
|
</NcActionButton>
|
|
</template>
|
|
</Item>
|
|
</template>
|
|
<script>
|
|
import Item from './Item.vue'
|
|
import { NcActionButton, NcActionCheckbox } from '@nextcloud/vue'
|
|
import FolderPlusIcon from 'vue-material-design-icons/FolderPlus.vue'
|
|
import FolderMoveIcon from 'vue-material-design-icons/FolderMove.vue'
|
|
import ContentCopyIcon from 'vue-material-design-icons/ContentCopy.vue'
|
|
import PencilIcon from 'vue-material-design-icons/Pencil.vue'
|
|
import InformationVariantIcon from 'vue-material-design-icons/InformationVariant.vue'
|
|
import DeleteIcon from 'vue-material-design-icons/Delete.vue'
|
|
import { getCurrentUser } from '@nextcloud/auth'
|
|
import { generateUrl } from '@nextcloud/router'
|
|
import { actions, mutations } from '../store/index.js'
|
|
import copy from 'copy-text-to-clipboard'
|
|
import axios from '@nextcloud/axios'
|
|
|
|
export default {
|
|
name: 'Bookmark',
|
|
components: {
|
|
Item,
|
|
NcActionButton,
|
|
NcActionCheckbox,
|
|
FolderPlusIcon,
|
|
FolderMoveIcon,
|
|
ContentCopyIcon,
|
|
PencilIcon,
|
|
InformationVariantIcon,
|
|
DeleteIcon,
|
|
},
|
|
props: {
|
|
bookmark: {
|
|
type: Object,
|
|
required: true,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
title: this.bookmark.title,
|
|
renaming: false,
|
|
backgroundImage: undefined,
|
|
}
|
|
},
|
|
computed: {
|
|
apiUrl() {
|
|
if (this.isPublic) {
|
|
return generateUrl('/apps/bookmarks/public/rest/v2')
|
|
}
|
|
return generateUrl('/apps/bookmarks')
|
|
},
|
|
iconUrl() {
|
|
return (
|
|
this.apiUrl
|
|
+ '/bookmark/'
|
|
+ this.bookmark.id
|
|
+ '/favicon'
|
|
+ (this.$store.state.public
|
|
? '?token=' + this.$store.state.authToken
|
|
: '')
|
|
)
|
|
},
|
|
imageUrl() {
|
|
return (
|
|
this.apiUrl
|
|
+ '/bookmark/'
|
|
+ this.bookmark.id
|
|
+ '/image'
|
|
+ (this.$store.state.public
|
|
? '?token=' + this.$store.state.authToken
|
|
: '')
|
|
)
|
|
},
|
|
url() {
|
|
return this.bookmark.url
|
|
},
|
|
isOpen() {
|
|
return this.$store.state.sidebar
|
|
&& this.$store.state.sidebar.type === 'bookmark'
|
|
? this.$store.state.sidebar.id === this.bookmark.id
|
|
: false
|
|
},
|
|
viewMode() {
|
|
return this.$store.state.viewMode
|
|
},
|
|
isOwner() {
|
|
const currentUser = getCurrentUser()
|
|
return currentUser && this.bookmark.userId === currentUser.uid
|
|
},
|
|
permissions() {
|
|
return this.$store.getters.getPermissionsForBookmark(
|
|
this.bookmark.id
|
|
)
|
|
},
|
|
isEditable() {
|
|
return this.isOwner || (!this.isOwner && this.permissions.canWrite)
|
|
},
|
|
selectedBookmarks() {
|
|
return this.$store.state.selection.bookmarks
|
|
},
|
|
selectable() {
|
|
return Boolean(
|
|
this.$store.state.selection.bookmarks.length
|
|
|| this.$store.state.selection.folders.length
|
|
)
|
|
},
|
|
selected() {
|
|
return this.selectedBookmarks
|
|
.map(b => b.id)
|
|
.includes(this.bookmark.id)
|
|
},
|
|
isActive() {
|
|
return this.isOpen || this.selected
|
|
},
|
|
background() {
|
|
return this.viewMode === 'grid' ? this.backgroundImage : undefined
|
|
},
|
|
},
|
|
mounted() {
|
|
this.fetchBackgroundImage()
|
|
},
|
|
methods: {
|
|
onDelete() {
|
|
if (
|
|
!confirm(
|
|
t(
|
|
'bookmarks',
|
|
'Do you really want to delete this bookmark?'
|
|
)
|
|
)
|
|
) {
|
|
return
|
|
}
|
|
this.$store.dispatch(actions.DELETE_BOOKMARK, {
|
|
id: this.bookmark.id,
|
|
folder: this.$store.state.fetchState.query.folder,
|
|
})
|
|
},
|
|
onDetails() {
|
|
this.$store.dispatch(actions.OPEN_BOOKMARK, this.bookmark.id)
|
|
},
|
|
onMove() {
|
|
this.$store.commit(mutations.RESET_SELECTION)
|
|
this.$store.commit(mutations.ADD_SELECTION_BOOKMARK, this.bookmark)
|
|
this.$store.commit(mutations.DISPLAY_MOVE_DIALOG, true)
|
|
},
|
|
onCopy() {
|
|
this.$store.commit(mutations.RESET_SELECTION)
|
|
this.$store.commit(mutations.ADD_SELECTION_BOOKMARK, this.bookmark)
|
|
this.$store.commit(mutations.DISPLAY_COPY_DIALOG, true)
|
|
},
|
|
async onRename() {
|
|
this.renaming = true
|
|
},
|
|
async onRenameSubmit(title) {
|
|
// eslint-disable-next-line vue/no-mutating-props
|
|
this.bookmark.title = title
|
|
await this.$store.dispatch(actions.SAVE_BOOKMARK, this.bookmark.id)
|
|
this.renaming = false
|
|
},
|
|
onSelect() {
|
|
if (!this.selected) {
|
|
this.$store.commit(
|
|
mutations.ADD_SELECTION_BOOKMARK,
|
|
this.bookmark
|
|
)
|
|
} else {
|
|
this.$store.commit(
|
|
mutations.REMOVE_SELECTION_BOOKMARK,
|
|
this.bookmark
|
|
)
|
|
}
|
|
},
|
|
onClick() {
|
|
this.$store.dispatch(actions.CLICK_BOOKMARK, this.bookmark)
|
|
},
|
|
onCopyUrl() {
|
|
copy(this.bookmark.url)
|
|
this.$store.commit(mutations.SET_NOTIFICATION, this.t('bookmarks', 'Link copied to clipboard'))
|
|
},
|
|
async fetchBackgroundImage() {
|
|
if (this.colorMainBackground === '#ffffff') {
|
|
this.backgroundImage = 'var(--icon-link-000) no-repeat center 25% / 50% !important'
|
|
} else {
|
|
this.backgroundImage = 'var(--icon-link-fff) no-repeat center 25% / 50% !important'
|
|
}
|
|
try {
|
|
const response = await axios.get(this.imageUrl, { responseType: 'blob' })
|
|
const url = URL.createObjectURL(response.data)
|
|
this.backgroundImage = `linear-gradient(0deg, var(--color-main-background) 25%, rgba(0, 212, 255, 0) 50%), url('${url}')`
|
|
} catch (e) {
|
|
if (this.colorMainBackground === '#ffffff') {
|
|
this.backgroundImage = 'var(--icon-link-000) no-repeat center 25% / 50% !important'
|
|
} else {
|
|
this.backgroundImage = 'var(--icon-link-fff) no-repeat center 25% / 50% !important'
|
|
}
|
|
}
|
|
},
|
|
},
|
|
}
|
|
</script>
|
|
<style>
|
|
.bookmark__icon {
|
|
display: inline-block;
|
|
flex: 0;
|
|
height: 20px;
|
|
width: 20px;
|
|
background-size: cover;
|
|
margin: 0 15px;
|
|
position: relative;
|
|
top: 3px;
|
|
}
|
|
|
|
.bookmark__title {
|
|
display: flex;
|
|
min-width: calc(50px + 40%);
|
|
}
|
|
|
|
.bookmark__title,
|
|
.bookmark__title > h3 {
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.bookmark__title > h3 {
|
|
margin: 0;
|
|
}
|
|
|
|
.bookmark__description {
|
|
display: inline-block;
|
|
flex: 1;
|
|
margin: auto 10px;
|
|
height: 24px;
|
|
color: var(--color-text-lighter);
|
|
text-overflow: ellipsis;
|
|
overflow: hidden;
|
|
min-width: 15px;
|
|
}
|
|
|
|
.bookmark__description figure {
|
|
display: none !important;
|
|
}
|
|
|
|
.item--gridview .bookmark__title {
|
|
min-width: auto;
|
|
}
|
|
|
|
.item--gridview .bookmark__description {
|
|
flex: 0;
|
|
}
|
|
|
|
.item--gridview .bookmark__description figure {
|
|
display: inline-block !important;
|
|
position: relative;
|
|
top: 5px;
|
|
}
|
|
|
|
.item--gridview .bookmark__icon {
|
|
margin: 0 5px 0 8px;
|
|
}
|
|
</style>
|