commit: 2b6de423d5a02413924f18910b1ce3538a5a1625
parent 49ec95b8f66ff3a60e86b0a6027956d71fb6abf5
Author: marcin mikołajczak <git@mkljczk.pl>
Date: Tue, 24 Sep 2024 18:15:49 +0200
Bookmark folder editing
Signed-off-by: marcin mikołajczak <git@mkljczk.pl>
Diffstat:
10 files changed, 269 insertions(+), 11 deletions(-)
diff --git a/src/boot/routes.js b/src/boot/routes.js
@@ -27,6 +27,7 @@ import NavPanel from 'src/components/nav_panel/nav_panel.vue'
import AnnouncementsPage from 'components/announcements_page/announcements_page.vue'
import QuotesTimeline from '../components/quotes_timeline/quotes_timeline.vue'
import BookmarkFolders from '../components/bookmark_folders/bookmark_folders.vue'
+import BookmarkFolderEdit from '../components/bookmark_folder_edit/bookmark_folder_edit.vue'
export default (store) => {
const validateAuthenticatedRoute = (to, from, next) => {
@@ -89,7 +90,9 @@ export default (store) => {
{ name: 'lists-new', path: '/lists/new', component: ListsEdit },
{ name: 'edit-navigation', path: '/nav-edit', component: NavPanel, props: () => ({ forceExpand: true, forceEditMode: true }), beforeEnter: validateAuthenticatedRoute },
{ name: 'bookmark-folders', path: '/bookmark_folders', component: BookmarkFolders },
- { name: 'bookmark-folder', path: '/bookmarks/:id', component: BookmarkTimeline }
+ { name: 'bookmark-folder-new', path: '/bookmarks/new-folder', component: BookmarkFolderEdit },
+ { name: 'bookmark-folder', path: '/bookmarks/:id', component: BookmarkTimeline },
+ { name: 'bookmark-folder-edit', path: '/bookmarks/:id/edit', component: BookmarkFolderEdit }
]
if (store.state.instance.pleromaChatMessagesAvailable) {
diff --git a/src/components/bookmark_folder_card/bookmark_folder_card.js b/src/components/bookmark_folder_card/bookmark_folder_card.js
@@ -10,7 +10,12 @@ library.add(
const BookmarkFolderCard = {
props: [
'folder'
- ]
+ ],
+ computed: {
+ firstLetter () {
+ return this.folder.name[0]
+ }
+ }
}
export default BookmarkFolderCard
diff --git a/src/components/bookmark_folder_card/bookmark_folder_card.vue b/src/components/bookmark_folder_card/bookmark_folder_card.vue
@@ -4,10 +4,28 @@
:to="{ name: 'bookmark-folder', params: { id: folder.id } }"
class="bookmark-folder-name"
>
- {{ folder.name }}
+ <img
+ v-if="folder.emoji_url"
+ class="iconEmoji iconEmoji-image"
+ :src="folder.emoji_url"
+ :alt="folder.emoji"
+ :title="folder.emoji"
+ >
+ <span
+ v-else-if="folder.emoji"
+ class="iconEmoji"
+ >
+ <span>
+ {{ folder.emoji }}
+ </span>
+ </span>
+ <span
+ v-else-if="firstLetter"
+ class="icon iconLetter fa-scale-110"
+ >{{ firstLetter }}</span>{{ folder.name }}
</router-link>
<router-link
- :to="{ name: 'bookmark-folder' /* -edit' */, params: { id: folder.id } }"
+ :to="{ name: 'bookmark-folder-edit', params: { id: folder.id } }"
class="button-folder-edit"
>
<FAIcon
@@ -27,6 +45,35 @@
.bookmark-folder-name {
flex-grow: 1;
+
+ .iconLetter, .iconEmoji {
+ margin-right: 0.5em;
+ }
+
+ .iconLetter {
+ height: 2.5rem;
+ width: 2.5rem;
+ font-size: 1.5rem;
+ }
+
+ .iconEmoji {
+ display: inline-block;
+ text-align: center;
+ object-fit: contain;
+ vertical-align: middle;
+ height: 2.5em;
+ width: 2.5em;
+
+ > span {
+ font-size: 1.5rem;
+ line-height: 2.5rem;
+ }
+ }
+
+ img.iconEmoji {
+ padding: 0.25em;
+ box-sizing: border-box;
+ }
}
.bookmark-folder-name,
diff --git a/src/components/bookmark_folder_edit/bookmark_folder_edit.js b/src/components/bookmark_folder_edit/bookmark_folder_edit.js
@@ -0,0 +1,65 @@
+import apiService from '../../services/api/api.service'
+
+const BookmarkFolderEdit = {
+ data () {
+ return {
+ name: '',
+ nameDraft: '',
+ emoji: '',
+ emojiUrl: null,
+ emojiDraft: '',
+ emojiUrlDraft: null,
+ reallyDelete: false
+ }
+ },
+ created () {
+ if (!this.id) return
+ const credentials = this.$store.state.users.currentUser.credentials
+ apiService.fetchBookmarkFolders({ credentials })
+ .then((folders) => {
+ const folder = folders.find(folder => folder.id === this.id)
+ if (!folder) return
+
+ this.nameDraft = this.name = folder.name
+ this.emojiDraft = this.emoji = folder.emoji
+ this.emojiUrlDraft = this.emojiUrl = folder.emoji_url
+ })
+ },
+ computed: {
+ id () {
+ return this.$route.params.id
+ }
+ },
+ methods: {
+ updateFolder () {
+ this.$store.dispatch('setBookmarkFolder', { folderId: this.id, name: this.nameDraft, emoji: this.emojiDraft })
+ .then((folder) => {
+ this.nameDraft = this.name = folder.name
+ this.emojiDraft = this.emoji = folder.emoji
+ this.emojiUrlDraft = this.emojiUrl = folder.emoji_url
+ })
+ },
+ createFolder () {
+ this.$store.dispatch('createBookmarkFolder', { name: this.nameDraft, emoji: this.emojiDraft })
+ .then((folder) => {
+ return folder.id
+ })
+ .then((folderId) => {
+ this.$router.push({ name: 'bookmark-folders' })
+ })
+ .catch((e) => {
+ this.$store.dispatch('pushGlobalNotice', {
+ messageKey: 'bookmark_folders.error',
+ messageArgs: [e.message],
+ level: 'error'
+ })
+ })
+ },
+ deleteFolder () {
+ this.$store.dispatch('deleteBookmarkFolder', { folderId: this.id })
+ this.$router.push({ name: 'bookmark-folders' })
+ }
+ }
+}
+
+export default BookmarkFolderEdit
diff --git a/src/components/bookmark_folder_edit/bookmark_folder_edit.vue b/src/components/bookmark_folder_edit/bookmark_folder_edit.vue
@@ -0,0 +1,125 @@
+<template>
+ <div class="panel-default panel BookmarkFolderEdit">
+ <div
+ ref="header"
+ class="panel-heading folder-edit-heading"
+ >
+ <button
+ class="button-unstyled go-back-button"
+ @click="$router.back"
+ >
+ <FAIcon
+ size="lg"
+ icon="chevron-left"
+ />
+ </button>
+ <div class="title">
+ <i18n-t
+ v-if="id"
+ keypath="bookmark_folders.editing_folder"
+ >
+ <template #folderName>
+ {{ name }}
+ </template>
+ </i18n-t>
+ <i18n-t
+ v-else
+ keypath="bookmark_folders.creating_folder"
+ />
+ </div>
+ </div>
+ <div class="panel-body">
+ <div class="input-wrap">
+ <label for="folder-edit-title">{{ $t('bookmark_folders.name') }}</label>
+ {{ ' ' }}
+ <input
+ id="folder-edit-title"
+ ref="name"
+ v-model="nameDraft"
+ class="input"
+ >
+ <button
+ v-if="id"
+ class="btn button-default follow-button"
+ @click="updateFolder"
+ >
+ {{ $t('bookmark_folders.update_folder') }}
+ </button>
+ </div>
+ </div>
+ <div class="panel-footer">
+ <span class="spacer" />
+ <button
+ v-if="!id"
+ class="btn button-default footer-button"
+ @click="createFolder"
+ >
+ {{ $t('bookmark_folders.create') }}
+ </button>
+ <button
+ v-else-if="!reallyDelete"
+ class="btn button-default footer-button"
+ @click="reallyDelete = true"
+ >
+ {{ $t('bookmark_folders.delete') }}
+ </button>
+ <template v-else>
+ {{ $t('bookmark_folders.really_delete') }}
+ <button
+ class="btn button-default footer-button"
+ @click="deleteFolder"
+ >
+ {{ $t('general.yes') }}
+ </button>
+ <button
+ class="btn button-default footer-button"
+ @click="reallyDelete = false"
+ >
+ {{ $t('general.no') }}
+ </button>
+ </template>
+ </div>
+ </div>
+</template>
+
+<script src="./bookmark_folder_edit.js"></script>
+
+<style lang="scss">
+.BookmarkFolderEdit {
+ --panel-body-padding: 0.5em;
+
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+
+ .folder-edit-heading {
+ grid-template-columns: auto minmax(50%, 1fr);
+ }
+
+ .panel-body {
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+ }
+
+ .go-back-button {
+ text-align: center;
+ line-height: 1;
+ height: 100%;
+ align-self: start;
+ width: var(--__panel-heading-height-inner);
+ }
+
+ .btn {
+ margin: 0 0.5em;
+ }
+
+ .panel-footer {
+ grid-template-columns: minmax(10%, 1fr);
+
+ .footer-button {
+ min-width: 9em;
+ }
+ }
+}
+</style>
diff --git a/src/components/bookmark_folders/bookmark_folders.vue b/src/components/bookmark_folders/bookmark_folders.vue
@@ -5,7 +5,7 @@
{{ $t('nav.bookmark_folders') }}
</div>
<router-link
- :to="{ name: 'bookmark-folders' /* 'new' */ }"
+ :to="{ name: 'bookmark-folder-new' }"
class="button-default btn new-folder-button"
>
{{ $t("bookmark_folders.new") }}
diff --git a/src/components/navigation/navigation_entry.vue b/src/components/navigation/navigation_entry.vue
@@ -137,5 +137,10 @@
font-size: 1.5rem;
}
}
+
+ img.iconEmoji {
+ padding: 0.25rem;
+ box-sizing: border-box;
+ }
}
</style>
diff --git a/src/i18n/en.json b/src/i18n/en.json
@@ -1409,7 +1409,15 @@
"tooltip": "This domain contains non-ascii characters."
},
"bookmark_folders": {
+ "create": "Create folder",
+ "creating_folder": "Creating bookmark folder",
+ "delete": "Delete folder",
+ "editing_folder": "Editing folder {folderName}",
+ "error": "Error manipulating bookmark folders: {0}",
+ "name": "Folder name",
"new": "New Folder",
- "select_folder": "Select bookmark folder"
+ "really_delete": "Do you really want to delete the folder?",
+ "select_folder": "Select bookmark folder",
+ "update_folder": "Save changes"
}
}
diff --git a/src/modules/bookmark_folders.js b/src/modules/bookmark_folders.js
@@ -8,10 +8,10 @@ export const mutations = {
setBookmarkFolders (state, value) {
state.allFolders = value
},
- setBookmarkFolder (state, { folderId, name, emoji, emojiUrl }) {
- const entry = find(state.allFolders, { id: name })
+ setBookmarkFolder (state, { id, name, emoji, emojiUrl }) {
+ const entry = find(state.allFolders, { id })
if (!entry) {
- state.allFolders.push({ id: folderId, name, emoji, emojiUrl })
+ state.allFolders.push({ id, name, emoji, emojiUrl })
} else {
entry.name = name
entry.emoji = emoji
diff --git a/src/services/api/api.service.js b/src/services/api/api.service.js
@@ -1927,9 +1927,9 @@ const updateBookmarkFolder = ({ folderId, name, emoji, credentials }) => {
return fetch(url, {
headers,
- method: 'PUT',
+ method: 'PATCH',
body: JSON.stringify({ name, emoji })
- })
+ }).then((data) => data.json())
}
const deleteBookmarkFolder = ({ folderId, credentials }) => {