feat(server): add doc meta for ignored docs (#12021)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

- **New Features**
  - Ignored documents in workspace embedding now display additional metadata, including document title, creation and update timestamps, and the names and avatars of users who created or updated the document.
- **Enhancements**
  - The list of ignored documents provides richer information for easier identification and management within the workspace.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
darkskygit
2025-04-28 11:56:09 +00:00
parent 9d21d13a5e
commit 21dc550b9d
8 changed files with 111 additions and 4 deletions

View File

@@ -120,3 +120,15 @@ export type CopilotWorkspaceFile = CopilotWorkspaceFileMetadata & {
fileId: string; fileId: string;
createdAt: Date; createdAt: Date;
}; };
export type IgnoredDoc = {
docId: string;
createdAt: Date;
// metadata
docCreatedAt: Date | undefined;
docUpdatedAt: Date | undefined;
title: string | undefined;
createdBy: string | undefined;
createdByAvatar: string | undefined;
updatedBy: string | undefined;
};

View File

@@ -11,6 +11,7 @@ import type {
CopilotWorkspaceFileMetadata, CopilotWorkspaceFileMetadata,
Embedding, Embedding,
FileChunkSimilarity, FileChunkSimilarity,
IgnoredDoc,
} from './common'; } from './common';
@Injectable() @Injectable()
@@ -50,12 +51,13 @@ export class CopilotWorkspaceConfigModel extends BaseModel {
return added.length + ignored.size; return added.length + ignored.size;
} }
@Transactional()
async listIgnoredDocs( async listIgnoredDocs(
workspaceId: string, workspaceId: string,
options?: { options?: {
includeRead?: boolean; includeRead?: boolean;
} & PaginationInput } & PaginationInput
): Promise<{ docId: string; createdAt: Date }[]> { ): Promise<IgnoredDoc[]> {
const row = await this.db.aiWorkspaceIgnoredDocs.findMany({ const row = await this.db.aiWorkspaceIgnoredDocs.findMany({
where: { where: {
workspaceId, workspaceId,
@@ -68,7 +70,29 @@ export class CopilotWorkspaceConfigModel extends BaseModel {
skip: options?.offset, skip: options?.offset,
take: options?.first, take: options?.first,
}); });
return row; const ids = row.map(r => ({ workspaceId, docId: r.docId }));
const docs = await this.models.doc.findMetas(ids);
const docsMap = new Map(
docs.filter(r => !!r).map(r => [`${r.workspaceId}-${r.docId}`, r])
);
const authors = await this.models.doc.findAuthors(ids);
const authorsMap = new Map(
authors.filter(r => !!r).map(r => [`${r.workspaceId}-${r.id}`, r])
);
return row.map(r => {
const docMeta = docsMap.get(`${workspaceId}-${r.docId}`);
const docAuthor = authorsMap.get(`${workspaceId}-${r.docId}`);
return {
...r,
docCreatedAt: docAuthor?.createdAt,
docUpdatedAt: docAuthor?.updatedAt,
title: docMeta?.title || undefined,
createdBy: docAuthor?.createdByUser?.name,
createdByAvatar: docAuthor?.createdByUser?.avatarUrl || undefined,
updatedBy: docAuthor?.updatedByUser?.name,
};
});
} }
async countIgnoredDocs(workspaceId: string): Promise<number> { async countIgnoredDocs(workspaceId: string): Promise<number> {

View File

@@ -373,6 +373,29 @@ export class DocModel extends BaseModel {
}); });
} }
async findAuthors(ids: { workspaceId: string; docId: string }[]) {
const rows = await this.db.snapshot.findMany({
where: {
workspaceId: { in: ids.map(id => id.workspaceId) },
id: { in: ids.map(id => id.docId) },
},
select: {
workspaceId: true,
id: true,
createdAt: true,
updatedAt: true,
createdByUser: { select: publicUserSelect },
updatedByUser: { select: publicUserSelect },
},
});
const resultMap = new Map(
rows.map(row => [`${row.workspaceId}-${row.id}`, row])
);
return ids.map(
id => resultMap.get(`${id.workspaceId}-${id.docId}`) ?? null
);
}
async findMetas(ids: { workspaceId: string; docId: string }[]) { async findMetas(ids: { workspaceId: string; docId: string }[]) {
const rows = await this.db.workspaceDoc.findMany({ const rows = await this.db.workspaceDoc.findMany({
where: { where: {

View File

@@ -2,7 +2,7 @@ import { Field, ObjectType } from '@nestjs/graphql';
import { SafeIntResolver } from 'graphql-scalars'; import { SafeIntResolver } from 'graphql-scalars';
import { Paginated } from '../../../base'; import { Paginated } from '../../../base';
import { CopilotWorkspaceFile } from '../../../models'; import { CopilotWorkspaceFile, IgnoredDoc } from '../../../models';
declare global { declare global {
interface Events { interface Events {
@@ -16,12 +16,30 @@ declare global {
} }
@ObjectType('CopilotWorkspaceIgnoredDoc') @ObjectType('CopilotWorkspaceIgnoredDoc')
export class CopilotWorkspaceIgnoredDocType { export class CopilotWorkspaceIgnoredDocType implements IgnoredDoc {
@Field(() => String) @Field(() => String)
docId!: string; docId!: string;
@Field(() => Date) @Field(() => Date)
createdAt!: Date; createdAt!: Date;
@Field(() => Date, { nullable: true })
docCreatedAt!: Date | undefined;
@Field(() => Date, { nullable: true })
docUpdatedAt!: Date | undefined;
@Field(() => String, { nullable: true })
title!: string | undefined;
@Field(() => String, { nullable: true })
createdBy!: string | undefined;
@Field(() => String, { nullable: true })
createdByAvatar!: string | undefined;
@Field(() => String, { nullable: true })
updatedBy!: string | undefined;
} }
@ObjectType() @ObjectType()

View File

@@ -295,7 +295,13 @@ type CopilotWorkspaceFileTypeEdge {
type CopilotWorkspaceIgnoredDoc { type CopilotWorkspaceIgnoredDoc {
createdAt: DateTime! createdAt: DateTime!
createdBy: String
createdByAvatar: String
docCreatedAt: DateTime
docId: String! docId: String!
docUpdatedAt: DateTime
title: String
updatedBy: String
} }
type CopilotWorkspaceIgnoredDocTypeEdge { type CopilotWorkspaceIgnoredDocTypeEdge {

View File

@@ -11,6 +11,12 @@ query getWorkspaceEmbeddingIgnoredDocs($workspaceId: String!, $pagination: Pagin
node { node {
docId docId
createdAt createdAt
docCreatedAt
docUpdatedAt
title
createdBy
createdByAvatar
updatedBy
} }
} }
} }

View File

@@ -830,6 +830,12 @@ export const getWorkspaceEmbeddingIgnoredDocsQuery = {
node { node {
docId docId
createdAt createdAt
docCreatedAt
docUpdatedAt
title
createdBy
createdByAvatar
updatedBy
} }
} }
} }

View File

@@ -399,7 +399,13 @@ export interface CopilotWorkspaceFileTypeEdge {
export interface CopilotWorkspaceIgnoredDoc { export interface CopilotWorkspaceIgnoredDoc {
__typename?: 'CopilotWorkspaceIgnoredDoc'; __typename?: 'CopilotWorkspaceIgnoredDoc';
createdAt: Scalars['DateTime']['output']; createdAt: Scalars['DateTime']['output'];
createdBy: Maybe<Scalars['String']['output']>;
createdByAvatar: Maybe<Scalars['String']['output']>;
docCreatedAt: Maybe<Scalars['DateTime']['output']>;
docId: Scalars['String']['output']; docId: Scalars['String']['output'];
docUpdatedAt: Maybe<Scalars['DateTime']['output']>;
title: Maybe<Scalars['String']['output']>;
updatedBy: Maybe<Scalars['String']['output']>;
} }
export interface CopilotWorkspaceIgnoredDocTypeEdge { export interface CopilotWorkspaceIgnoredDocTypeEdge {
@@ -3374,6 +3380,12 @@ export type GetWorkspaceEmbeddingIgnoredDocsQuery = {
__typename?: 'CopilotWorkspaceIgnoredDoc'; __typename?: 'CopilotWorkspaceIgnoredDoc';
docId: string; docId: string;
createdAt: string; createdAt: string;
docCreatedAt: string | null;
docUpdatedAt: string | null;
title: string | null;
createdBy: string | null;
createdByAvatar: string | null;
updatedBy: string | null;
}; };
}>; }>;
}; };