Skip to content

Commit a1db2ce

Browse files
authored
feat(graphql): add subject topics (#718)
1 parent 1e681f9 commit a1db2ce

File tree

9 files changed

+146
-61
lines changed

9 files changed

+146
-61
lines changed

lib/graphql/schema.gen.graphql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ type Subject {
132132
series_entry: Int!
133133
summary: String!
134134
tags(limit: Int = 0): [SubjectTag!]
135+
topics(limit: Int! = 10, offset: Int! = 0): [SubjectTopic!]
135136
type: Int!
136137
volumes: Int!
137138
}
@@ -195,6 +196,17 @@ type SubjectTag {
195196
name: String!
196197
}
197198

199+
type SubjectTopic {
200+
created_at: Int!
201+
creator: User!
202+
display: Int!
203+
id: Int!
204+
replies: Int!
205+
state: Int!
206+
title: String!
207+
updated_at: Int!
208+
}
209+
198210
type User {
199211
avatar: Avatar!
200212
id: Int!

lib/graphql/types/subject.ts

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@ import {
1010
PersonSubjectsRepo,
1111
SubjectRelationRepo,
1212
SubjectRepo,
13+
SubjectTopicRepo,
1314
} from '@app/lib/orm/index.ts';
1415
import { subjectCover } from '@app/lib/response.ts';
1516
import { platforms } from '@app/lib/subject/index.ts';
17+
import { ListTopicDisplays } from '@app/lib/topic/display.ts';
1618

1719
import { convertCharacter } from './character.ts';
1820
import { InfoboxItem } from './common.ts';
1921
import { convertPerson } from './person.ts';
22+
import { convertUser } from './user.ts';
2023

2124
const Episode = objectType({
2225
name: 'Episode',
@@ -127,6 +130,22 @@ const SubjectAirtime = objectType({
127130
},
128131
});
129132

133+
const SubjectTopic = objectType({
134+
name: 'SubjectTopic',
135+
definition(t) {
136+
t.nonNull.int('id');
137+
t.nonNull.field('creator', {
138+
type: 'User',
139+
});
140+
t.nonNull.string('title');
141+
t.nonNull.int('created_at');
142+
t.nonNull.int('updated_at');
143+
t.nonNull.int('replies');
144+
t.nonNull.int('state');
145+
t.nonNull.int('display');
146+
},
147+
});
148+
130149
const Subject = objectType({
131150
name: 'Subject',
132151
definition(t) {
@@ -321,6 +340,34 @@ const Subject = objectType({
321340
});
322341
},
323342
});
343+
t.list.nonNull.field('topics', {
344+
type: SubjectTopic,
345+
args: {
346+
limit: nonNull(intArg({ default: 10 })),
347+
offset: nonNull(intArg({ default: 0 })),
348+
},
349+
async resolve(
350+
parent: { id: number },
351+
{ limit, offset }: { limit: number; offset: number },
352+
{ auth: u }: Context,
353+
) {
354+
let query = SubjectTopicRepo.createQueryBuilder('t')
355+
.innerJoinAndMapOne('t.creator', entity.User, 'u', 'u.id = t.creatorID')
356+
.where('t.parentID = :id', { id: parent.id });
357+
const displays = ListTopicDisplays(u);
358+
if (displays.length > 0) {
359+
query = query.andWhere('t.display IN (:...displays)', { displays });
360+
}
361+
const topics = await query
362+
.orderBy('t.createdAt', 'DESC')
363+
.skip(offset)
364+
.take(limit)
365+
.getMany();
366+
return topics.map((t) => {
367+
return convertTopic(t);
368+
});
369+
},
370+
});
324371
},
325372
});
326373

@@ -410,6 +457,19 @@ export function convertSubject(subject: entity.Subject) {
410457
};
411458
}
412459

460+
export function convertTopic(topic: entity.SubjectTopic) {
461+
return {
462+
id: topic.id,
463+
creator: convertUser(topic.creator),
464+
title: topic.title,
465+
created_at: topic.createdAt,
466+
updated_at: topic.updatedAt,
467+
replies: topic.replies,
468+
state: topic.state,
469+
display: topic.display,
470+
};
471+
}
472+
413473
const SubjectByIDQuery = extendType({
414474
type: 'Query',
415475
definition(t) {

lib/graphql/types/user.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { extendType, objectType } from 'nexus';
22

33
import { imageDomain } from '@app/lib/config.ts';
44
import type { Context } from '@app/lib/graphql/context.ts';
5+
import type * as entity from '@app/lib/orm/entity/index.ts';
56
import type { IUser } from '@app/lib/orm/index.ts';
67
import { fetchUser } from '@app/lib/orm/index.ts';
78
import { avatar } from '@app/lib/response.ts';
@@ -37,6 +38,15 @@ const User = objectType({
3738
},
3839
});
3940

41+
export function convertUser(user: entity.User) {
42+
return {
43+
id: user.id,
44+
username: user.username,
45+
nickname: user.nickname,
46+
avatar: avatar(user.avatar),
47+
};
48+
}
49+
4050
const GetCurrentUser = extendType({
4151
type: 'Query',
4252
definition(t) {

lib/orm/entity/group.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Column, Entity, Index, PrimaryGeneratedColumn } from 'typeorm';
22

33
import { BooleanTransformer, htmlEscapedString } from '@app/lib/orm/transformer.ts';
44

5+
import type { User } from './user';
6+
57
@Entity('chii_groups', { schema: 'bangumi' })
68
export class Group {
79
@PrimaryGeneratedColumn({ type: 'smallint', name: 'grp_id', unsigned: true })
@@ -139,6 +141,8 @@ export class GroupTopic {
139141
default: () => "'1'",
140142
})
141143
display!: number;
144+
145+
creator!: User;
142146
}
143147

144148
@Index('pss_topic_id', ['topicID'], {})
@@ -179,4 +183,6 @@ export class GroupPost {
179183
default: () => "'0'",
180184
})
181185
dateline!: number;
186+
187+
creator!: User;
182188
}

lib/orm/entity/subject.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { Column, Entity, Index, PrimaryColumn, PrimaryGeneratedColumn } from 'ty
22

33
import { BooleanTransformer, htmlEscapedString, UnixTimestamp } from '@app/lib/orm/transformer.ts';
44

5+
import type { User } from './user.ts';
6+
57
@Index('subject_name_cn', ['nameCN'], {})
68
@Index('subject_platform', ['platform'], {})
79
@Index('subject_creator', ['subjectCreator'], {})
@@ -428,6 +430,8 @@ export class SubjectTopic {
428430
default: () => "'1'",
429431
})
430432
display!: number;
433+
434+
creator!: User;
431435
}
432436

433437
@Index('pss_topic_id', ['topicID'], {})
@@ -455,6 +459,8 @@ export class SubjectPost {
455459

456460
@Column('int', { name: 'sbj_pst_dateline', unsigned: true, default: 0 })
457461
dateline!: number;
462+
463+
creator!: User;
458464
}
459465

460466
@Index('interest_collect_dateline', ['collectDateline'], {})

lib/orm/unused/ChiiSubjectTopics.ts.tmp

Lines changed: 0 additions & 59 deletions
This file was deleted.

lib/server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ export async function createServer(
116116
schema,
117117
path: '/v0/graphql',
118118
graphiql: false,
119-
queryDepth: 4,
119+
queryDepth: 5,
120120
allowBatchedQueries: true,
121121
context: async (request: FastifyRequest): Promise<Context> => {
122122
const a = await auth.byHeader(request.headers.authorization);

tests/graphql/__snapshots__/subject.test.ts.snap

Lines changed: 26 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/graphql/subject.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,29 @@ describe('subject', () => {
221221

222222
expect(res).toMatchSnapshot();
223223
});
224+
225+
test('should subject topics', async () => {
226+
const res = await testClient.query(gql`
227+
query {
228+
subject(id: 12) {
229+
topics(limit: 1) {
230+
id
231+
creator {
232+
id
233+
username
234+
nickname
235+
}
236+
created_at
237+
updated_at
238+
title
239+
replies
240+
state
241+
display
242+
}
243+
}
244+
}
245+
`);
246+
247+
expect(res).toMatchSnapshot();
248+
});
224249
});

0 commit comments

Comments
 (0)