From 0417c70d546de860d41610a48eeee05761ddbf6a Mon Sep 17 00:00:00 2001 From: DarkSky Date: Wed, 21 Aug 2024 14:57:57 +0800 Subject: [PATCH] feat: add page meta api --- .../src/core/workspaces/resolvers/history.ts | 12 +--- .../core/workspaces/resolvers/workspace.ts | 57 +++++++++++++++++++ packages/backend/server/src/schema.gql | 10 ++++ .../src/graphql/get-workspace-page-meta.gql | 16 ++++++ .../frontend/graphql/src/graphql/index.ts | 24 ++++++++ packages/frontend/graphql/src/schema.ts | 46 +++++++++++++++ 6 files changed, 155 insertions(+), 10 deletions(-) create mode 100644 packages/frontend/graphql/src/graphql/get-workspace-page-meta.gql diff --git a/packages/backend/server/src/core/workspaces/resolvers/history.ts b/packages/backend/server/src/core/workspaces/resolvers/history.ts index de9ab71889..594bf2e767 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/history.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/history.ts @@ -12,19 +12,11 @@ import { import type { SnapshotHistory } from '@prisma/client'; import { CurrentUser } from '../../auth'; -import { type Editor, PgWorkspaceDocStorageAdapter } from '../../doc'; +import { PgWorkspaceDocStorageAdapter } from '../../doc'; import { Permission, PermissionService } from '../../permission'; import { DocID } from '../../utils/doc'; import { WorkspaceType } from '../types'; - -@ObjectType() -class EditorType implements Partial { - @Field() - name!: string; - - @Field(() => String, { nullable: true }) - avatarUrl!: string | null; -} +import { EditorType } from './workspace'; @ObjectType() class DocHistoryType implements Partial { diff --git a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts index 76c84407fa..0db1c89bae 100644 --- a/packages/backend/server/src/core/workspaces/resolvers/workspace.ts +++ b/packages/backend/server/src/core/workspaces/resolvers/workspace.ts @@ -1,8 +1,10 @@ import { Logger } from '@nestjs/common'; import { Args, + Field, Int, Mutation, + ObjectType, Parent, Query, ResolveField, @@ -16,6 +18,7 @@ import { applyUpdate, Doc } from 'yjs'; import type { FileUpload } from '../../../fundamentals'; import { CantChangeSpaceOwner, + DocNotFound, EventEmitter, InternalServerError, MailService, @@ -28,6 +31,7 @@ import { UserNotFound, } from '../../../fundamentals'; import { CurrentUser, Public } from '../../auth'; +import type { Editor } from '../../doc'; import { Permission, PermissionService } from '../../permission'; import { QuotaManagementService, QuotaQueryType } from '../../quota'; import { WorkspaceBlobStorage } from '../../storage'; @@ -40,6 +44,30 @@ import { } from '../types'; import { defaultWorkspaceAvatar } from '../utils'; +@ObjectType() +export class EditorType implements Partial { + @Field() + name!: string; + + @Field(() => String, { nullable: true }) + avatarUrl!: string | null; +} + +@ObjectType() +class WorkspacePageMeta { + @Field(() => Date) + createdAt!: Date; + + @Field(() => Date) + updatedAt!: Date; + + @Field(() => EditorType, { nullable: true }) + createdBy!: EditorType | null; + + @Field(() => EditorType, { nullable: true }) + updatedBy!: EditorType | null; +} + /** * Workspace resolver * Public apis rate limit: 10 req/m @@ -140,6 +168,35 @@ export class WorkspaceResolver { })); } + @ResolveField(() => WorkspacePageMeta, { + description: 'Cloud page metadata of workspace', + complexity: 2, + }) + async pageMeta( + @Parent() workspace: WorkspaceType, + @Args('pageId') pageId: string + ) { + const metadata = await this.prisma.snapshot.findFirst({ + where: { workspaceId: workspace.id, id: pageId }, + select: { + createdAt: true, + updatedAt: true, + createdByUser: { select: { name: true, avatarUrl: true } }, + updatedByUser: { select: { name: true, avatarUrl: true } }, + }, + }); + if (!metadata) { + throw new DocNotFound({ spaceId: workspace.id, docId: pageId }); + } + + return { + createdAt: metadata.createdAt, + updatedAt: metadata.updatedAt, + createdBy: metadata.createdByUser || null, + updatedBy: metadata.updatedByUser || null, + }; + } + @ResolveField(() => QuotaQueryType, { name: 'quota', description: 'quota of workspace', diff --git a/packages/backend/server/src/schema.gql b/packages/backend/server/src/schema.gql index 58c1bd0756..6b89d9da6e 100644 --- a/packages/backend/server/src/schema.gql +++ b/packages/backend/server/src/schema.gql @@ -881,6 +881,13 @@ type WorkspacePage { workspaceId: String! } +type WorkspacePageMeta { + createdAt: DateTime! + createdBy: EditorType + updatedAt: DateTime! + updatedBy: EditorType +} + type WorkspaceType { """Available features of workspace""" availableFeatures: [FeatureType!]! @@ -908,6 +915,9 @@ type WorkspaceType { """Owner of workspace""" owner: UserType! + """Cloud page metadata of workspace""" + pageMeta(pageId: String!): WorkspacePageMeta! + """Permission of current signed in user in workspace""" permission: Permission! diff --git a/packages/frontend/graphql/src/graphql/get-workspace-page-meta.gql b/packages/frontend/graphql/src/graphql/get-workspace-page-meta.gql new file mode 100644 index 0000000000..1c047d5521 --- /dev/null +++ b/packages/frontend/graphql/src/graphql/get-workspace-page-meta.gql @@ -0,0 +1,16 @@ +query getWorkspacePageMetaById($id: String!, $pageId: String!) { + workspace(id: $id) { + pageMeta(pageId: $pageId) { + createdAt + updatedAt + createdBy { + name + avatarUrl + } + updatedBy { + name + avatarUrl + } + } + } +} diff --git a/packages/frontend/graphql/src/graphql/index.ts b/packages/frontend/graphql/src/graphql/index.ts index d42036c06c..e9135394bb 100644 --- a/packages/frontend/graphql/src/graphql/index.ts +++ b/packages/frontend/graphql/src/graphql/index.ts @@ -610,6 +610,30 @@ query getWorkspaceFeatures($workspaceId: String!) { }`, }; +export const getWorkspacePageMetaByIdQuery = { + id: 'getWorkspacePageMetaByIdQuery' as const, + operationName: 'getWorkspacePageMetaById', + definitionName: 'workspace', + containsFile: false, + query: ` +query getWorkspacePageMetaById($id: String!, $pageId: String!) { + workspace(id: $id) { + pageMeta(pageId: $pageId) { + createdAt + updatedAt + createdBy { + name + avatarUrl + } + updatedBy { + name + avatarUrl + } + } + } +}`, +}; + export const getWorkspacePublicByIdQuery = { id: 'getWorkspacePublicByIdQuery' as const, operationName: 'getWorkspacePublicById', diff --git a/packages/frontend/graphql/src/schema.ts b/packages/frontend/graphql/src/schema.ts index 3d4cde1c41..94ae4f99c9 100644 --- a/packages/frontend/graphql/src/schema.ts +++ b/packages/frontend/graphql/src/schema.ts @@ -1196,6 +1196,14 @@ export interface WorkspacePage { workspaceId: Scalars['String']['output']; } +export interface WorkspacePageMeta { + __typename?: 'WorkspacePageMeta'; + createdAt: Scalars['DateTime']['output']; + createdBy: Maybe; + updatedAt: Scalars['DateTime']['output']; + updatedBy: Maybe; +} + export interface WorkspaceType { __typename?: 'WorkspaceType'; /** Available features of workspace */ @@ -1216,6 +1224,8 @@ export interface WorkspaceType { members: Array; /** Owner of workspace */ owner: UserType; + /** Cloud page metadata of workspace */ + pageMeta: WorkspacePageMeta; /** Permission of current signed in user in workspace */ permission: Permission; /** is Public workspace */ @@ -1244,6 +1254,10 @@ export interface WorkspaceTypeMembersArgs { take: InputMaybe; } +export interface WorkspaceTypePageMetaArgs { + pageId: Scalars['String']['input']; +} + export interface WorkspaceTypePublicPageArgs { pageId: Scalars['String']['input']; } @@ -1792,6 +1806,33 @@ export type GetWorkspaceFeaturesQuery = { workspace: { __typename?: 'WorkspaceType'; features: Array }; }; +export type GetWorkspacePageMetaByIdQueryVariables = Exact<{ + id: Scalars['String']['input']; + pageId: Scalars['String']['input']; +}>; + +export type GetWorkspacePageMetaByIdQuery = { + __typename?: 'Query'; + workspace: { + __typename?: 'WorkspaceType'; + pageMeta: { + __typename?: 'WorkspacePageMeta'; + createdAt: string; + updatedAt: string; + createdBy: { + __typename?: 'EditorType'; + name: string; + avatarUrl: string | null; + } | null; + updatedBy: { + __typename?: 'EditorType'; + name: string; + avatarUrl: string | null; + } | null; + }; + }; +}; + export type GetWorkspacePublicByIdQueryVariables = Exact<{ id: Scalars['String']['input']; }>; @@ -2496,6 +2537,11 @@ export type Queries = variables: GetWorkspaceFeaturesQueryVariables; response: GetWorkspaceFeaturesQuery; } + | { + name: 'getWorkspacePageMetaByIdQuery'; + variables: GetWorkspacePageMetaByIdQueryVariables; + response: GetWorkspacePageMetaByIdQuery; + } | { name: 'getWorkspacePublicByIdQuery'; variables: GetWorkspacePublicByIdQueryVariables;