mirror of
https://github.com/documenso/documenso.git
synced 2026-07-26 01:45:08 +10:00
feat: initial tags
This commit is contained in:
@@ -36,6 +36,8 @@ export type FindDocumentsOptions = {
|
||||
senderIds?: number[];
|
||||
query?: string;
|
||||
folderId?: string;
|
||||
includeAllFolders?: boolean;
|
||||
tagIds?: string[];
|
||||
/**
|
||||
* When true (default), use a windowed count that caps early for faster pagination.
|
||||
* When false, use a full COUNT(*) for exact totals — preferred for external API consumers.
|
||||
@@ -102,6 +104,22 @@ const senderEmailIs = (eb: EnvelopeExpressionBuilder, email: string) =>
|
||||
.select(sql.lit(1).as('one')),
|
||||
);
|
||||
|
||||
export const applyEnvelopeTagFilter = (qb: EnvelopeQueryBuilder, tagIds?: string[]) => {
|
||||
if (!tagIds || tagIds.length === 0) {
|
||||
return qb;
|
||||
}
|
||||
|
||||
return qb.where((eb) =>
|
||||
eb.exists(
|
||||
eb
|
||||
.selectFrom('EnvelopeTag')
|
||||
.whereRef('EnvelopeTag.envelopeId', '=', 'Envelope.id')
|
||||
.where('EnvelopeTag.tagId', 'in', tagIds)
|
||||
.select(sql.lit(1).as('one')),
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
export const findDocuments = async ({
|
||||
userId,
|
||||
teamId,
|
||||
@@ -115,6 +133,8 @@ export const findDocuments = async ({
|
||||
senderIds,
|
||||
query = '',
|
||||
folderId,
|
||||
includeAllFolders = false,
|
||||
tagIds,
|
||||
useWindowedCount = true,
|
||||
}: FindDocumentsOptions) => {
|
||||
const user = await prisma.user.findFirstOrThrow({
|
||||
@@ -147,8 +167,12 @@ export const findDocuments = async ({
|
||||
qb = qb.where('Envelope.type', '=', sql.lit(EnvelopeType.DOCUMENT));
|
||||
|
||||
// Folder filter
|
||||
qb =
|
||||
folderId !== undefined ? qb.where('Envelope.folderId', '=', folderId) : qb.where('Envelope.folderId', 'is', null);
|
||||
if (!includeAllFolders) {
|
||||
qb =
|
||||
folderId !== undefined
|
||||
? qb.where('Envelope.folderId', '=', folderId)
|
||||
: qb.where('Envelope.folderId', 'is', null);
|
||||
}
|
||||
|
||||
// Period filter
|
||||
if (period) {
|
||||
@@ -199,6 +223,9 @@ export const findDocuments = async ({
|
||||
);
|
||||
}
|
||||
|
||||
// Tag filter (OR semantics — envelope must have at least one of the selected tags)
|
||||
qb = applyEnvelopeTagFilter(qb, tagIds);
|
||||
|
||||
return qb;
|
||||
};
|
||||
|
||||
@@ -520,6 +547,7 @@ export const findDocuments = async ({
|
||||
envelopeItems: {
|
||||
select: { id: true, envelopeId: true, title: true, order: true },
|
||||
},
|
||||
tags: { include: { tag: true } },
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { PeriodSelectorValue } from '@documenso/lib/server-only/document/find-documents';
|
||||
import { applyEnvelopeTagFilter, type PeriodSelectorValue } from '@documenso/lib/server-only/document/find-documents';
|
||||
import { kyselyPrisma, prisma, sql } from '@documenso/prisma';
|
||||
import type { DB } from '@documenso/prisma/generated/types';
|
||||
import { ExtendedDocumentStatus } from '@documenso/prisma/types/extended-document-status';
|
||||
@@ -57,7 +57,9 @@ export type GetStatsInput = {
|
||||
period?: PeriodSelectorValue;
|
||||
search?: string;
|
||||
folderId?: string;
|
||||
includeAllFolders?: boolean;
|
||||
senderIds?: number[];
|
||||
tagIds?: string[];
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -80,7 +82,16 @@ const cappedCount = async (qb: EnvelopeQueryBuilder): Promise<number> => {
|
||||
return Math.min(Number(result.total ?? 0), STATS_COUNT_CAP);
|
||||
};
|
||||
|
||||
export const getStats = async ({ userId, teamId, period, search = '', folderId, senderIds }: GetStatsInput) => {
|
||||
export const getStats = async ({
|
||||
userId,
|
||||
teamId,
|
||||
period,
|
||||
search = '',
|
||||
folderId,
|
||||
includeAllFolders = false,
|
||||
senderIds,
|
||||
tagIds,
|
||||
}: GetStatsInput) => {
|
||||
const user = await prisma.user.findFirstOrThrow({
|
||||
where: { id: userId },
|
||||
select: { id: true, email: true },
|
||||
@@ -105,8 +116,12 @@ export const getStats = async ({ userId, teamId, period, search = '', folderId,
|
||||
qb = qb.where('Envelope.type', '=', sql.lit(EnvelopeType.DOCUMENT));
|
||||
|
||||
// Folder filter
|
||||
qb =
|
||||
folderId !== undefined ? qb.where('Envelope.folderId', '=', folderId) : qb.where('Envelope.folderId', 'is', null);
|
||||
if (!includeAllFolders) {
|
||||
qb =
|
||||
folderId !== undefined
|
||||
? qb.where('Envelope.folderId', '=', folderId)
|
||||
: qb.where('Envelope.folderId', 'is', null);
|
||||
}
|
||||
|
||||
// Period filter
|
||||
if (period) {
|
||||
@@ -121,6 +136,9 @@ export const getStats = async ({ userId, teamId, period, search = '', folderId,
|
||||
qb = qb.where('Envelope.userId', 'in', senderIds);
|
||||
}
|
||||
|
||||
// Tag filter (OR semantics — envelope must have at least one of the selected tags)
|
||||
qb = applyEnvelopeTagFilter(qb, tagIds);
|
||||
|
||||
// Search filter
|
||||
if (hasSearch) {
|
||||
qb = qb.where(({ or, eb }) =>
|
||||
|
||||
Reference in New Issue
Block a user