diff --git a/src/client/pages/gallery/edit.vue b/src/client/pages/gallery/edit.vue new file mode 100644 index 0000000000..cd6a0defdd --- /dev/null +++ b/src/client/pages/gallery/edit.vue @@ -0,0 +1,168 @@ + + + + + diff --git a/src/client/pages/gallery/new.vue b/src/client/pages/gallery/new.vue deleted file mode 100644 index 3f9756df8e..0000000000 --- a/src/client/pages/gallery/new.vue +++ /dev/null @@ -1,110 +0,0 @@ - - - - - diff --git a/src/client/pages/gallery/post.vue b/src/client/pages/gallery/post.vue index 9bd102cee2..703506a78d 100644 --- a/src/client/pages/gallery/post.vue +++ b/src/client/pages/gallery/post.vue @@ -19,6 +19,7 @@ {{ post.likedCount }}
+
@@ -84,6 +85,11 @@ export default defineComponent({ title: this.post.title, text: this.post.description, }, + actions: [{ + icon: 'fas fa-pencil-alt', + text: this.$ts.edit, + handler: this.edit + }] } : null), otherPostsPagination: { endpoint: 'users/gallery/posts', @@ -154,6 +160,10 @@ export default defineComponent({ this.post.likedCount--; }); }, + + edit() { + this.$router.push(`/gallery/${this.post.id}/edit`); + } } }); diff --git a/src/client/router.ts b/src/client/router.ts index 5371bf17d9..8dcc1d1eb4 100644 --- a/src/client/router.ts +++ b/src/client/router.ts @@ -38,7 +38,8 @@ export const router = createRouter({ { path: '/pages/new', component: page('page-editor/page-editor') }, { path: '/pages/edit/:pageId', component: page('page-editor/page-editor'), props: route => ({ initPageId: route.params.pageId }) }, { path: '/gallery', component: page('gallery/index') }, - { path: '/gallery/new', component: page('gallery/new') }, + { path: '/gallery/new', component: page('gallery/edit') }, + { path: '/gallery/:postId/edit', component: page('gallery/edit'), props: route => ({ postId: route.params.postId }) }, { path: '/gallery/:postId', component: page('gallery/post'), props: route => ({ postId: route.params.postId }) }, { path: '/channels', component: page('channels') }, { path: '/channels/new', component: page('channel-editor') }, diff --git a/src/server/api/endpoints/gallery/posts/delete.ts b/src/server/api/endpoints/gallery/posts/delete.ts new file mode 100644 index 0000000000..8b54828b20 --- /dev/null +++ b/src/server/api/endpoints/gallery/posts/delete.ts @@ -0,0 +1,40 @@ +import $ from 'cafy'; +import define from '../../../define'; +import { ApiError } from '../../../error'; +import { GalleryPosts } from '../../../../../models'; +import { ID } from '@/misc/cafy-id'; + +export const meta = { + tags: ['gallery'], + + requireCredential: true as const, + + kind: 'write:gallery', + + params: { + postId: { + validator: $.type(ID), + }, + }, + + errors: { + noSuchPost: { + message: 'No such post.', + code: 'NO_SUCH_POST', + id: 'ae52f367-4bd7-4ecd-afc6-5672fff427f5' + }, + } +}; + +export default define(meta, async (ps, user) => { + const post = await GalleryPosts.findOne({ + id: ps.postId, + userId: user.id, + }); + + if (post == null) { + throw new ApiError(meta.errors.noSuchPost); + } + + await GalleryPosts.delete(post.id); +}); diff --git a/src/server/api/endpoints/gallery/posts/update.ts b/src/server/api/endpoints/gallery/posts/update.ts new file mode 100644 index 0000000000..c8bb8d48c9 --- /dev/null +++ b/src/server/api/endpoints/gallery/posts/update.ts @@ -0,0 +1,81 @@ +import $ from 'cafy'; +import * as ms from 'ms'; +import define from '../../../define'; +import { ID } from '../../../../../misc/cafy-id'; +import { DriveFiles, GalleryPosts } from '../../../../../models'; +import { GalleryPost } from '../../../../../models/entities/gallery-post'; +import { ApiError } from '../../../error'; + +export const meta = { + tags: ['gallery'], + + requireCredential: true as const, + + kind: 'write:gallery', + + limit: { + duration: ms('1hour'), + max: 300 + }, + + params: { + postId: { + validator: $.type(ID), + }, + + title: { + validator: $.str.min(1), + }, + + description: { + validator: $.optional.nullable.str, + }, + + fileIds: { + validator: $.arr($.type(ID)).unique().range(1, 32), + }, + + isSensitive: { + validator: $.optional.bool, + default: false, + }, + }, + + res: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'GalleryPost', + }, + + errors: { + + } +}; + +export default define(meta, async (ps, user) => { + const files = (await Promise.all(ps.fileIds.map(fileId => + DriveFiles.findOne({ + id: fileId, + userId: user.id + }) + ))).filter(file => file != null); + + if (files.length === 0) { + throw new Error(); + } + + await GalleryPosts.update({ + id: ps.postId, + userId: user.id, + }, { + updatedAt: new Date(), + title: ps.title, + description: ps.description, + isSensitive: ps.isSensitive, + fileIds: files.map(file => file.id) + }); + + const post = await GalleryPosts.findOneOrFail(ps.postId); + + return await GalleryPosts.pack(post, user); +});