Gallery (#7194)
* wip * wip * wip * wip * wip * wip * wip * wip * wip * wip * wip
This commit is contained in:
parent
ccf063709e
commit
fec3c70886
32 changed files with 1607 additions and 9 deletions
33
src/models/entities/gallery-like.ts
Normal file
33
src/models/entities/gallery-like.ts
Normal file
|
@ -0,0 +1,33 @@
|
|||
import { PrimaryColumn, Entity, Index, JoinColumn, Column, ManyToOne } from 'typeorm';
|
||||
import { User } from './user';
|
||||
import { id } from '../id';
|
||||
import { GalleryPost } from './gallery-post';
|
||||
|
||||
@Entity()
|
||||
@Index(['userId', 'postId'], { unique: true })
|
||||
export class GalleryLike {
|
||||
@PrimaryColumn(id())
|
||||
public id: string;
|
||||
|
||||
@Column('timestamp with time zone')
|
||||
public createdAt: Date;
|
||||
|
||||
@Index()
|
||||
@Column(id())
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
@JoinColumn()
|
||||
public user: User | null;
|
||||
|
||||
@Column(id())
|
||||
public postId: GalleryPost['id'];
|
||||
|
||||
@ManyToOne(type => GalleryPost, {
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
@JoinColumn()
|
||||
public post: GalleryPost | null;
|
||||
}
|
79
src/models/entities/gallery-post.ts
Normal file
79
src/models/entities/gallery-post.ts
Normal file
|
@ -0,0 +1,79 @@
|
|||
import { Entity, Index, JoinColumn, Column, PrimaryColumn, ManyToOne } from 'typeorm';
|
||||
import { User } from './user';
|
||||
import { id } from '../id';
|
||||
import { DriveFile } from './drive-file';
|
||||
|
||||
@Entity()
|
||||
export class GalleryPost {
|
||||
@PrimaryColumn(id())
|
||||
public id: string;
|
||||
|
||||
@Index()
|
||||
@Column('timestamp with time zone', {
|
||||
comment: 'The created date of the GalleryPost.'
|
||||
})
|
||||
public createdAt: Date;
|
||||
|
||||
@Index()
|
||||
@Column('timestamp with time zone', {
|
||||
comment: 'The updated date of the GalleryPost.'
|
||||
})
|
||||
public updatedAt: Date;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 256,
|
||||
})
|
||||
public title: string;
|
||||
|
||||
@Column('varchar', {
|
||||
length: 2048, nullable: true
|
||||
})
|
||||
public description: string | null;
|
||||
|
||||
@Index()
|
||||
@Column({
|
||||
...id(),
|
||||
comment: 'The ID of author.'
|
||||
})
|
||||
public userId: User['id'];
|
||||
|
||||
@ManyToOne(type => User, {
|
||||
onDelete: 'CASCADE'
|
||||
})
|
||||
@JoinColumn()
|
||||
public user: User | null;
|
||||
|
||||
@Index()
|
||||
@Column({
|
||||
...id(),
|
||||
array: true, default: '{}'
|
||||
})
|
||||
public fileIds: DriveFile['id'][];
|
||||
|
||||
@Index()
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
comment: 'Whether the post is sensitive.'
|
||||
})
|
||||
public isSensitive: boolean;
|
||||
|
||||
@Index()
|
||||
@Column('integer', {
|
||||
default: 0
|
||||
})
|
||||
public likedCount: number;
|
||||
|
||||
@Index()
|
||||
@Column('varchar', {
|
||||
length: 128, array: true, default: '{}'
|
||||
})
|
||||
public tags: string[];
|
||||
|
||||
constructor(data: Partial<GalleryPost>) {
|
||||
if (data == null) return;
|
||||
|
||||
for (const [k, v] of Object.entries(data)) {
|
||||
(this as any)[k] = v;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -43,6 +43,8 @@ import { UserSecurityKey } from './entities/user-security-key';
|
|||
import { HashtagRepository } from './repositories/hashtag';
|
||||
import { PageRepository } from './repositories/page';
|
||||
import { PageLikeRepository } from './repositories/page-like';
|
||||
import { GalleryPostRepository } from './repositories/gallery-post';
|
||||
import { GalleryLikeRepository } from './repositories/gallery-like';
|
||||
import { ModerationLogRepository } from './repositories/moderation-logs';
|
||||
import { UsedUsername } from './entities/used-username';
|
||||
import { ClipRepository } from './repositories/clip';
|
||||
|
@ -105,6 +107,8 @@ export const ReversiMatchings = getCustomRepository(ReversiMatchingRepository);
|
|||
export const Logs = getRepository(Log);
|
||||
export const Pages = getCustomRepository(PageRepository);
|
||||
export const PageLikes = getCustomRepository(PageLikeRepository);
|
||||
export const GalleryPosts = getCustomRepository(GalleryPostRepository);
|
||||
export const GalleryLikes = getCustomRepository(GalleryLikeRepository);
|
||||
export const ModerationLogs = getCustomRepository(ModerationLogRepository);
|
||||
export const Clips = getCustomRepository(ClipRepository);
|
||||
export const ClipNotes = getRepository(ClipNote);
|
||||
|
|
25
src/models/repositories/gallery-like.ts
Normal file
25
src/models/repositories/gallery-like.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { GalleryLike } from '../entities/gallery-like';
|
||||
import { GalleryPosts } from '..';
|
||||
|
||||
@EntityRepository(GalleryLike)
|
||||
export class GalleryLikeRepository extends Repository<GalleryLike> {
|
||||
public async pack(
|
||||
src: GalleryLike['id'] | GalleryLike,
|
||||
me?: any
|
||||
) {
|
||||
const like = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return {
|
||||
id: like.id,
|
||||
post: await GalleryPosts.pack(like.post || like.postId, me),
|
||||
};
|
||||
}
|
||||
|
||||
public packMany(
|
||||
likes: any[],
|
||||
me: any
|
||||
) {
|
||||
return Promise.all(likes.map(x => this.pack(x, me)));
|
||||
}
|
||||
}
|
113
src/models/repositories/gallery-post.ts
Normal file
113
src/models/repositories/gallery-post.ts
Normal file
|
@ -0,0 +1,113 @@
|
|||
import { EntityRepository, Repository } from 'typeorm';
|
||||
import { GalleryPost } from '../entities/gallery-post';
|
||||
import { SchemaType } from '../../misc/schema';
|
||||
import { Users, DriveFiles, GalleryLikes } from '..';
|
||||
import { awaitAll } from '../../prelude/await-all';
|
||||
import { User } from '../entities/user';
|
||||
|
||||
export type PackedGalleryPost = SchemaType<typeof packedGalleryPostSchema>;
|
||||
|
||||
@EntityRepository(GalleryPost)
|
||||
export class GalleryPostRepository extends Repository<GalleryPost> {
|
||||
public async pack(
|
||||
src: GalleryPost['id'] | GalleryPost,
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
): Promise<PackedGalleryPost> {
|
||||
const meId = me ? me.id : null;
|
||||
const post = typeof src === 'object' ? src : await this.findOneOrFail(src);
|
||||
|
||||
return await awaitAll({
|
||||
id: post.id,
|
||||
createdAt: post.createdAt.toISOString(),
|
||||
updatedAt: post.updatedAt.toISOString(),
|
||||
userId: post.userId,
|
||||
user: Users.pack(post.user || post.userId, me),
|
||||
title: post.title,
|
||||
description: post.description,
|
||||
fileIds: post.fileIds,
|
||||
files: DriveFiles.packMany(post.fileIds),
|
||||
tags: post.tags.length > 0 ? post.tags : undefined,
|
||||
isSensitive: post.isSensitive,
|
||||
likedCount: post.likedCount,
|
||||
isLiked: meId ? await GalleryLikes.findOne({ postId: post.id, userId: meId }).then(x => x != null) : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
public packMany(
|
||||
posts: GalleryPost[],
|
||||
me?: { id: User['id'] } | null | undefined,
|
||||
) {
|
||||
return Promise.all(posts.map(x => this.pack(x, me)));
|
||||
}
|
||||
}
|
||||
|
||||
export const packedGalleryPostSchema = {
|
||||
type: 'object' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
properties: {
|
||||
id: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
format: 'id',
|
||||
example: 'xxxxxxxxxx',
|
||||
},
|
||||
createdAt: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
format: 'date-time',
|
||||
},
|
||||
updatedAt: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
format: 'date-time',
|
||||
},
|
||||
title: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
},
|
||||
description: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: true as const,
|
||||
},
|
||||
userId: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
format: 'id',
|
||||
},
|
||||
user: {
|
||||
type: 'object' as const,
|
||||
ref: 'User',
|
||||
optional: false as const, nullable: false as const,
|
||||
},
|
||||
fileIds: {
|
||||
type: 'array' as const,
|
||||
optional: true as const, nullable: false as const,
|
||||
items: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
format: 'id'
|
||||
}
|
||||
},
|
||||
files: {
|
||||
type: 'array' as const,
|
||||
optional: true as const, nullable: false as const,
|
||||
items: {
|
||||
type: 'object' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
ref: 'DriveFile'
|
||||
}
|
||||
},
|
||||
tags: {
|
||||
type: 'array' as const,
|
||||
optional: true as const, nullable: false as const,
|
||||
items: {
|
||||
type: 'string' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
}
|
||||
},
|
||||
isSensitive: {
|
||||
type: 'boolean' as const,
|
||||
optional: false as const, nullable: false as const,
|
||||
},
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue