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 @@
+
+
+
+
+ {{ $ts.title }}
+
+
+
+ {{ $ts.description }}
+
+
+
+
+ {{ $ts.attachFile }}
+
+
+ {{ $ts.markAsSensitive }}
+
+ {{ $ts.save }}
+ {{ $ts.publish }}
+
+ {{ $ts.delete }}
+
+
+
+
+
+
+
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 @@
-
-
-
- {{ $ts.title }}
-
-
-
- {{ $ts.description }}
-
-
-
-
- {{ $ts.attachFile }}
-
-
- {{ $ts.markAsSensitive }}
-
- {{ $ts.publish }}
-
-
-
-
-
-
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);
+});