Redesign notes list and editor to match Keep-style mockups.
Add checklist, activity link, location, analyze flag, and audio attachments with a real API-backed masonry UI. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,21 @@
|
|||||||
|
-- AlterTable
|
||||||
|
ALTER TABLE "Note" ADD COLUMN IF NOT EXISTS "checklist" JSONB;
|
||||||
|
ALTER TABLE "Note" ADD COLUMN IF NOT EXISTS "activityId" TEXT;
|
||||||
|
ALTER TABLE "Note" ADD COLUMN IF NOT EXISTS "locationText" TEXT;
|
||||||
|
ALTER TABLE "Note" ADD COLUMN IF NOT EXISTS "analyzeEnabled" BOOLEAN NOT NULL DEFAULT true;
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX IF NOT EXISTS "Note_activityId_idx" ON "Note"("activityId");
|
||||||
|
|
||||||
|
-- AddForeignKey
|
||||||
|
DO $$
|
||||||
|
BEGIN
|
||||||
|
IF NOT EXISTS (
|
||||||
|
SELECT 1 FROM pg_constraint WHERE conname = 'Note_activityId_fkey'
|
||||||
|
) THEN
|
||||||
|
ALTER TABLE "Note"
|
||||||
|
ADD CONSTRAINT "Note_activityId_fkey"
|
||||||
|
FOREIGN KEY ("activityId") REFERENCES "Activity"("id")
|
||||||
|
ON DELETE SET NULL ON UPDATE CASCADE;
|
||||||
|
END IF;
|
||||||
|
END $$;
|
||||||
@@ -383,6 +383,7 @@ model Activity {
|
|||||||
assignee User? @relation("ActivityAssignee", fields: [assigneeId], references: [id], onDelete: SetNull)
|
assignee User? @relation("ActivityAssignee", fields: [assigneeId], references: [id], onDelete: SetNull)
|
||||||
createdById String?
|
createdById String?
|
||||||
createdBy User? @relation("ActivityCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
createdBy User? @relation("ActivityCreator", fields: [createdById], references: [id], onDelete: SetNull)
|
||||||
|
notes Note[]
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
updatedAt DateTime @updatedAt
|
updatedAt DateTime @updatedAt
|
||||||
|
|
||||||
@@ -405,12 +406,18 @@ model Note {
|
|||||||
color String? @default("default")
|
color String? @default("default")
|
||||||
tags String[] @default([])
|
tags String[] @default([])
|
||||||
reminderAt DateTime?
|
reminderAt DateTime?
|
||||||
|
/// [{ id: string, text: string, done: boolean }]
|
||||||
|
checklist Json?
|
||||||
|
locationText String?
|
||||||
|
analyzeEnabled Boolean @default(true)
|
||||||
personId String?
|
personId String?
|
||||||
person Person? @relation(fields: [personId], references: [id], onDelete: SetNull)
|
person Person? @relation(fields: [personId], references: [id], onDelete: SetNull)
|
||||||
companyId String?
|
companyId String?
|
||||||
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
|
company Company? @relation(fields: [companyId], references: [id], onDelete: SetNull)
|
||||||
dealId String?
|
dealId String?
|
||||||
deal Deal? @relation(fields: [dealId], references: [id], onDelete: SetNull)
|
deal Deal? @relation(fields: [dealId], references: [id], onDelete: SetNull)
|
||||||
|
activityId String?
|
||||||
|
activity Activity? @relation(fields: [activityId], references: [id], onDelete: SetNull)
|
||||||
authorId String?
|
authorId String?
|
||||||
author User? @relation("NoteAuthor", fields: [authorId], references: [id], onDelete: SetNull)
|
author User? @relation("NoteAuthor", fields: [authorId], references: [id], onDelete: SetNull)
|
||||||
attachments NoteAttachment[]
|
attachments NoteAttachment[]
|
||||||
@@ -424,6 +431,7 @@ model Note {
|
|||||||
@@index([personId])
|
@@index([personId])
|
||||||
@@index([companyId])
|
@@index([companyId])
|
||||||
@@index([dealId])
|
@@index([dealId])
|
||||||
|
@@index([activityId])
|
||||||
@@index([authorId])
|
@@index([authorId])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import {
|
|||||||
Min,
|
Min,
|
||||||
MinLength,
|
MinLength,
|
||||||
ValidateIf,
|
ValidateIf,
|
||||||
|
ValidateNested,
|
||||||
} from 'class-validator';
|
} from 'class-validator';
|
||||||
|
|
||||||
const NOTE_TYPES = [
|
const NOTE_TYPES = [
|
||||||
@@ -21,8 +22,28 @@ const NOTE_TYPES = [
|
|||||||
'important',
|
'important',
|
||||||
'warning',
|
'warning',
|
||||||
'next_action',
|
'next_action',
|
||||||
|
'follow_up',
|
||||||
|
'idea',
|
||||||
|
'suggestion',
|
||||||
|
'personal',
|
||||||
] as const;
|
] as const;
|
||||||
|
|
||||||
|
const NOTE_SORTS = ['updatedAt', 'createdAt', 'reminderAt'] as const;
|
||||||
|
|
||||||
|
export class NoteChecklistItemDto {
|
||||||
|
@IsString()
|
||||||
|
@MinLength(1)
|
||||||
|
@MaxLength(64)
|
||||||
|
id!: string;
|
||||||
|
|
||||||
|
@IsString()
|
||||||
|
@MaxLength(500)
|
||||||
|
text!: string;
|
||||||
|
|
||||||
|
@IsBoolean()
|
||||||
|
done!: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export class ListNotesQueryDto {
|
export class ListNotesQueryDto {
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@IsString()
|
@IsString()
|
||||||
@@ -53,6 +74,10 @@ export class ListNotesQueryDto {
|
|||||||
@IsIn(NOTE_TYPES)
|
@IsIn(NOTE_TYPES)
|
||||||
noteType?: (typeof NOTE_TYPES)[number];
|
noteType?: (typeof NOTE_TYPES)[number];
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsIn(NOTE_SORTS)
|
||||||
|
sort?: (typeof NOTE_SORTS)[number];
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@Type(() => Number)
|
@Type(() => Number)
|
||||||
@IsInt()
|
@IsInt()
|
||||||
@@ -101,6 +126,22 @@ export class CreateNoteDto {
|
|||||||
@IsDateString()
|
@IsDateString()
|
||||||
reminderAt?: string | null;
|
reminderAt?: string | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => NoteChecklistItemDto)
|
||||||
|
checklist?: NoteChecklistItemDto[];
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
|
@IsString()
|
||||||
|
@MaxLength(500)
|
||||||
|
locationText?: string | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
analyzeEnabled?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateIf((_, v) => v !== '' && v != null)
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
@IsString()
|
@IsString()
|
||||||
@@ -115,6 +156,11 @@ export class CreateNoteDto {
|
|||||||
@ValidateIf((_, v) => v !== '' && v != null)
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
@IsString()
|
@IsString()
|
||||||
dealId?: string | null;
|
dealId?: string | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
|
@IsString()
|
||||||
|
activityId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class UpdateNoteDto {
|
export class UpdateNoteDto {
|
||||||
@@ -153,6 +199,22 @@ export class UpdateNoteDto {
|
|||||||
@IsDateString()
|
@IsDateString()
|
||||||
reminderAt?: string | null;
|
reminderAt?: string | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsArray()
|
||||||
|
@ValidateNested({ each: true })
|
||||||
|
@Type(() => NoteChecklistItemDto)
|
||||||
|
checklist?: NoteChecklistItemDto[];
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
|
@IsString()
|
||||||
|
@MaxLength(500)
|
||||||
|
locationText?: string | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@IsBoolean()
|
||||||
|
analyzeEnabled?: boolean;
|
||||||
|
|
||||||
@IsOptional()
|
@IsOptional()
|
||||||
@ValidateIf((_, v) => v !== '' && v != null)
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
@IsString()
|
@IsString()
|
||||||
@@ -167,6 +229,11 @@ export class UpdateNoteDto {
|
|||||||
@ValidateIf((_, v) => v !== '' && v != null)
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
@IsString()
|
@IsString()
|
||||||
dealId?: string | null;
|
dealId?: string | null;
|
||||||
|
|
||||||
|
@IsOptional()
|
||||||
|
@ValidateIf((_, v) => v !== '' && v != null)
|
||||||
|
@IsString()
|
||||||
|
activityId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
class NoteAiNextActionDtoClass {
|
class NoteAiNextActionDtoClass {
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export class NotesController {
|
|||||||
dealId: query.dealId,
|
dealId: query.dealId,
|
||||||
tag: query.tag,
|
tag: query.tag,
|
||||||
noteType: query.noteType,
|
noteType: query.noteType,
|
||||||
|
sort: query.sort,
|
||||||
page: query.page ?? 1,
|
page: query.page ?? 1,
|
||||||
limit: query.limit ?? 50,
|
limit: query.limit ?? 50,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
import type {
|
import type {
|
||||||
CreateNoteRequest,
|
CreateNoteRequest,
|
||||||
NoteAttachmentDto,
|
NoteAttachmentDto,
|
||||||
|
NoteChecklistItemDto,
|
||||||
NoteDto,
|
NoteDto,
|
||||||
PaginatedResponse,
|
PaginatedResponse,
|
||||||
UpdateNoteRequest,
|
UpdateNoteRequest,
|
||||||
@@ -32,11 +33,15 @@ type NoteRow = {
|
|||||||
color: string | null;
|
color: string | null;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
reminderAt: Date | null;
|
reminderAt: Date | null;
|
||||||
|
checklist: Prisma.JsonValue | null;
|
||||||
|
locationText: string | null;
|
||||||
|
analyzeEnabled: boolean;
|
||||||
createdAt: Date;
|
createdAt: Date;
|
||||||
updatedAt: Date;
|
updatedAt: Date;
|
||||||
person: { id: string; firstName: string; lastName: string } | null;
|
person: { id: string; firstName: string; lastName: string } | null;
|
||||||
company: { id: string; name: string } | null;
|
company: { id: string; name: string } | null;
|
||||||
deal: { id: string; title: string } | null;
|
deal: { id: string; title: string } | null;
|
||||||
|
activity: { id: string; title: string } | null;
|
||||||
author: { id: string; fullName: string } | null;
|
author: { id: string; fullName: string } | null;
|
||||||
attachments: Array<{
|
attachments: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
@@ -51,6 +56,7 @@ const include = {
|
|||||||
person: { select: { id: true, firstName: true, lastName: true } },
|
person: { select: { id: true, firstName: true, lastName: true } },
|
||||||
company: { select: { id: true, name: true } },
|
company: { select: { id: true, name: true } },
|
||||||
deal: { select: { id: true, title: true } },
|
deal: { select: { id: true, title: true } },
|
||||||
|
activity: { select: { id: true, title: true } },
|
||||||
author: { select: { id: true, fullName: true } },
|
author: { select: { id: true, fullName: true } },
|
||||||
attachments: {
|
attachments: {
|
||||||
select: {
|
select: {
|
||||||
@@ -81,6 +87,12 @@ const ALLOWED_MIME = new Set([
|
|||||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
'application/zip',
|
'application/zip',
|
||||||
'application/x-zip-compressed',
|
'application/x-zip-compressed',
|
||||||
|
'audio/webm',
|
||||||
|
'audio/wav',
|
||||||
|
'audio/mpeg',
|
||||||
|
'audio/mp4',
|
||||||
|
'audio/ogg',
|
||||||
|
'audio/x-m4a',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
@@ -101,6 +113,7 @@ export class NotesService {
|
|||||||
dealId?: string;
|
dealId?: string;
|
||||||
tag?: string;
|
tag?: string;
|
||||||
noteType?: string;
|
noteType?: string;
|
||||||
|
sort?: 'updatedAt' | 'createdAt' | 'reminderAt';
|
||||||
page?: number;
|
page?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
},
|
},
|
||||||
@@ -131,11 +144,17 @@ export class NotesService {
|
|||||||
: access),
|
: access),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const sortField = opts.sort ?? 'updatedAt';
|
||||||
|
const orderBy: Prisma.NoteOrderByWithRelationInput[] = [
|
||||||
|
{ pinned: 'desc' },
|
||||||
|
{ [sortField]: 'desc' },
|
||||||
|
];
|
||||||
|
|
||||||
const [rows, total] = await this.prisma.$transaction([
|
const [rows, total] = await this.prisma.$transaction([
|
||||||
this.prisma.note.findMany({
|
this.prisma.note.findMany({
|
||||||
where,
|
where,
|
||||||
include,
|
include,
|
||||||
orderBy: [{ pinned: 'desc' }, { updatedAt: 'desc' }],
|
orderBy,
|
||||||
skip: (page - 1) * limit,
|
skip: (page - 1) * limit,
|
||||||
take: limit,
|
take: limit,
|
||||||
}),
|
}),
|
||||||
@@ -174,6 +193,8 @@ export class NotesService {
|
|||||||
actor ?? { userId, role: 'owner' },
|
actor ?? { userId, role: 'owner' },
|
||||||
dto,
|
dto,
|
||||||
);
|
);
|
||||||
|
const analyzeEnabled = dto.analyzeEnabled !== false;
|
||||||
|
const checklist = parseChecklist(dto.checklist);
|
||||||
const row = await this.prisma.note.create({
|
const row = await this.prisma.note.create({
|
||||||
data: {
|
data: {
|
||||||
organizationId,
|
organizationId,
|
||||||
@@ -185,9 +206,15 @@ export class NotesService {
|
|||||||
color: emptyToNull(dto.color) ?? 'default',
|
color: emptyToNull(dto.color) ?? 'default',
|
||||||
tags: normalizeTags(dto.tags),
|
tags: normalizeTags(dto.tags),
|
||||||
reminderAt: dto.reminderAt ? new Date(dto.reminderAt) : null,
|
reminderAt: dto.reminderAt ? new Date(dto.reminderAt) : null,
|
||||||
|
checklist: checklist.length
|
||||||
|
? (checklist as unknown as Prisma.InputJsonValue)
|
||||||
|
: Prisma.JsonNull,
|
||||||
|
locationText: emptyToNull(dto.locationText ?? null),
|
||||||
|
analyzeEnabled,
|
||||||
personId: emptyToNull(dto.personId ?? null),
|
personId: emptyToNull(dto.personId ?? null),
|
||||||
companyId: emptyToNull(dto.companyId ?? null),
|
companyId: emptyToNull(dto.companyId ?? null),
|
||||||
dealId: emptyToNull(dto.dealId ?? null),
|
dealId: emptyToNull(dto.dealId ?? null),
|
||||||
|
activityId: emptyToNull(dto.activityId ?? null),
|
||||||
},
|
},
|
||||||
include,
|
include,
|
||||||
});
|
});
|
||||||
@@ -213,9 +240,24 @@ export class NotesService {
|
|||||||
if ('reminderAt' in dto) {
|
if ('reminderAt' in dto) {
|
||||||
data.reminderAt = dto.reminderAt ? new Date(dto.reminderAt) : null;
|
data.reminderAt = dto.reminderAt ? new Date(dto.reminderAt) : null;
|
||||||
}
|
}
|
||||||
|
if (dto.checklist !== undefined) {
|
||||||
|
const checklist = parseChecklist(dto.checklist);
|
||||||
|
data.checklist = checklist.length
|
||||||
|
? (checklist as unknown as Prisma.InputJsonValue)
|
||||||
|
: Prisma.JsonNull;
|
||||||
|
}
|
||||||
|
if ('locationText' in dto) {
|
||||||
|
data.locationText = emptyToNull(dto.locationText ?? null);
|
||||||
|
}
|
||||||
|
if (dto.analyzeEnabled !== undefined) {
|
||||||
|
data.analyzeEnabled = dto.analyzeEnabled;
|
||||||
|
}
|
||||||
if ('personId' in dto) data.personId = emptyToNull(dto.personId ?? null);
|
if ('personId' in dto) data.personId = emptyToNull(dto.personId ?? null);
|
||||||
if ('companyId' in dto) data.companyId = emptyToNull(dto.companyId ?? null);
|
if ('companyId' in dto) data.companyId = emptyToNull(dto.companyId ?? null);
|
||||||
if ('dealId' in dto) data.dealId = emptyToNull(dto.dealId ?? null);
|
if ('dealId' in dto) data.dealId = emptyToNull(dto.dealId ?? null);
|
||||||
|
if ('activityId' in dto) {
|
||||||
|
data.activityId = emptyToNull(dto.activityId ?? null);
|
||||||
|
}
|
||||||
|
|
||||||
const row = await this.prisma.note.update({
|
const row = await this.prisma.note.update({
|
||||||
where: { id },
|
where: { id },
|
||||||
@@ -308,7 +350,7 @@ export class NotesService {
|
|||||||
const mimeType = (file.mimetype || '').toLowerCase();
|
const mimeType = (file.mimetype || '').toLowerCase();
|
||||||
if (!ALLOWED_MIME.has(mimeType)) {
|
if (!ALLOWED_MIME.has(mimeType)) {
|
||||||
throw new BadRequestException(
|
throw new BadRequestException(
|
||||||
'نوع فایل مجاز نیست. تصویر، PDF، Word، Excel، متن یا ZIP بفرستید.',
|
'نوع فایل مجاز نیست. تصویر، PDF، Word، Excel، متن، ZIP یا صوت بفرستید.',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -404,11 +446,13 @@ export class NotesService {
|
|||||||
personId?: string | null;
|
personId?: string | null;
|
||||||
companyId?: string | null;
|
companyId?: string | null;
|
||||||
dealId?: string | null;
|
dealId?: string | null;
|
||||||
|
activityId?: string | null;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
const personId = emptyToNull(dto.personId ?? null);
|
const personId = emptyToNull(dto.personId ?? null);
|
||||||
const companyId = emptyToNull(dto.companyId ?? null);
|
const companyId = emptyToNull(dto.companyId ?? null);
|
||||||
const dealId = emptyToNull(dto.dealId ?? null);
|
const dealId = emptyToNull(dto.dealId ?? null);
|
||||||
|
const activityId = emptyToNull(dto.activityId ?? null);
|
||||||
const scope = ownerWhere(actor);
|
const scope = ownerWhere(actor);
|
||||||
|
|
||||||
if (personId) {
|
if (personId) {
|
||||||
@@ -432,6 +476,13 @@ export class NotesService {
|
|||||||
});
|
});
|
||||||
if (!deal) throw new BadRequestException('معامله انتخابشده معتبر نیست');
|
if (!deal) throw new BadRequestException('معامله انتخابشده معتبر نیست');
|
||||||
}
|
}
|
||||||
|
if (activityId) {
|
||||||
|
const activity = await this.prisma.activity.findFirst({
|
||||||
|
where: { id: activityId, organizationId },
|
||||||
|
select: { id: true },
|
||||||
|
});
|
||||||
|
if (!activity) throw new BadRequestException('فعالیت انتخابشده معتبر نیست');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private toDto(row: NoteRow): NoteDto {
|
private toDto(row: NoteRow): NoteDto {
|
||||||
@@ -444,6 +495,9 @@ export class NotesService {
|
|||||||
color: row.color,
|
color: row.color,
|
||||||
tags: row.tags,
|
tags: row.tags,
|
||||||
reminderAt: row.reminderAt?.toISOString() ?? null,
|
reminderAt: row.reminderAt?.toISOString() ?? null,
|
||||||
|
checklist: parseChecklist(row.checklist),
|
||||||
|
locationText: row.locationText ?? null,
|
||||||
|
analyzeEnabled: row.analyzeEnabled ?? true,
|
||||||
person: row.person
|
person: row.person
|
||||||
? {
|
? {
|
||||||
id: row.person.id,
|
id: row.person.id,
|
||||||
@@ -452,6 +506,7 @@ export class NotesService {
|
|||||||
: null,
|
: null,
|
||||||
company: row.company,
|
company: row.company,
|
||||||
deal: row.deal,
|
deal: row.deal,
|
||||||
|
activity: row.activity,
|
||||||
author: row.author,
|
author: row.author,
|
||||||
attachments: (row.attachments ?? []).map((a) => this.toAttachmentDto(a)),
|
attachments: (row.attachments ?? []).map((a) => this.toAttachmentDto(a)),
|
||||||
createdAt: row.createdAt.toISOString(),
|
createdAt: row.createdAt.toISOString(),
|
||||||
@@ -500,3 +555,21 @@ function sanitizeFileName(raw: string): string {
|
|||||||
const trimmed = base.trim() || 'file';
|
const trimmed = base.trim() || 'file';
|
||||||
return trimmed.slice(0, 180);
|
return trimmed.slice(0, 180);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseChecklist(raw: unknown): NoteChecklistItemDto[] {
|
||||||
|
if (!Array.isArray(raw)) return [];
|
||||||
|
const items: NoteChecklistItemDto[] = [];
|
||||||
|
for (const entry of raw) {
|
||||||
|
if (!entry || typeof entry !== 'object') continue;
|
||||||
|
const rec = entry as Record<string, unknown>;
|
||||||
|
const id = typeof rec.id === 'string' ? rec.id.trim() : '';
|
||||||
|
const text = typeof rec.text === 'string' ? rec.text.trim() : '';
|
||||||
|
if (!id && !text) continue;
|
||||||
|
items.push({
|
||||||
|
id: id || randomUUID(),
|
||||||
|
text: text.slice(0, 500),
|
||||||
|
done: Boolean(rec.done),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return items.slice(0, 50);
|
||||||
|
}
|
||||||
|
|||||||
+1820
-801
File diff suppressed because it is too large
Load Diff
@@ -548,7 +548,11 @@ export type NoteType =
|
|||||||
| "meeting"
|
| "meeting"
|
||||||
| "important"
|
| "important"
|
||||||
| "warning"
|
| "warning"
|
||||||
| "next_action";
|
| "next_action"
|
||||||
|
| "follow_up"
|
||||||
|
| "idea"
|
||||||
|
| "suggestion"
|
||||||
|
| "personal";
|
||||||
|
|
||||||
export interface NoteAttachmentDto {
|
export interface NoteAttachmentDto {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -558,6 +562,12 @@ export interface NoteAttachmentDto {
|
|||||||
createdAt: string;
|
createdAt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface NoteChecklistItemDto {
|
||||||
|
id: string;
|
||||||
|
text: string;
|
||||||
|
done: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export interface NoteDto {
|
export interface NoteDto {
|
||||||
id: string;
|
id: string;
|
||||||
title: string | null;
|
title: string | null;
|
||||||
@@ -567,9 +577,13 @@ export interface NoteDto {
|
|||||||
color: string | null;
|
color: string | null;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
reminderAt: string | null;
|
reminderAt: string | null;
|
||||||
|
checklist: NoteChecklistItemDto[];
|
||||||
|
locationText: string | null;
|
||||||
|
analyzeEnabled: boolean;
|
||||||
person: PersonSummaryDto | null;
|
person: PersonSummaryDto | null;
|
||||||
company: CompanySummaryDto | null;
|
company: CompanySummaryDto | null;
|
||||||
deal: DealSummaryDto | null;
|
deal: DealSummaryDto | null;
|
||||||
|
activity: { id: string; title: string } | null;
|
||||||
author: UserSummaryDto | null;
|
author: UserSummaryDto | null;
|
||||||
attachments: NoteAttachmentDto[];
|
attachments: NoteAttachmentDto[];
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -584,9 +598,13 @@ export interface CreateNoteRequest {
|
|||||||
color?: string;
|
color?: string;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
reminderAt?: string | null;
|
reminderAt?: string | null;
|
||||||
|
checklist?: NoteChecklistItemDto[];
|
||||||
|
locationText?: string | null;
|
||||||
|
analyzeEnabled?: boolean;
|
||||||
personId?: string | null;
|
personId?: string | null;
|
||||||
companyId?: string | null;
|
companyId?: string | null;
|
||||||
dealId?: string | null;
|
dealId?: string | null;
|
||||||
|
activityId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UpdateNoteRequest {
|
export interface UpdateNoteRequest {
|
||||||
@@ -597,9 +615,13 @@ export interface UpdateNoteRequest {
|
|||||||
color?: string | null;
|
color?: string | null;
|
||||||
tags?: string[];
|
tags?: string[];
|
||||||
reminderAt?: string | null;
|
reminderAt?: string | null;
|
||||||
|
checklist?: NoteChecklistItemDto[];
|
||||||
|
locationText?: string | null;
|
||||||
|
analyzeEnabled?: boolean;
|
||||||
personId?: string | null;
|
personId?: string | null;
|
||||||
companyId?: string | null;
|
companyId?: string | null;
|
||||||
dealId?: string | null;
|
dealId?: string | null;
|
||||||
|
activityId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type NoteAiSuggestionStatus =
|
export type NoteAiSuggestionStatus =
|
||||||
|
|||||||
Reference in New Issue
Block a user