Compare commits

...

8 Commits

Author SHA1 Message Date
Mythie
42e39f7ef1 v1.9.1-rc.4 2025-02-26 15:28:51 +11:00
Mythie
838e399c73 fix: handle empty field meta for checkboxes 2025-02-26 15:27:44 +11:00
Catalin Pit
b6a891acc8 docs: add the v2 api staging base url (#1671) 2025-02-25 14:02:12 +02:00
Samuel Huber
84b4d58856 chore: update readme (#1664)
Resolve external link issue
2025-02-25 16:59:20 +11:00
Mythie
c51c32fdc6 feat: search by externalId 2025-02-25 09:44:40 +11:00
Mythie
59c1e55233 v1.9.1-rc.3 2025-02-25 08:03:13 +11:00
Mythie
2fbaf56c06 fix: early adopters can use platform features 2025-02-25 07:54:28 +11:00
David Nguyen
70320cd24b chore: update API documentation 2025-02-25 02:35:11 +11:00
13 changed files with 128 additions and 20 deletions

View File

@@ -1,4 +1,4 @@
> 🚨 We are live on Product Hunt 🎉 Check out our latest launch: <a href="documen.so/sign-everywhere">The Platform Plan</a>!
> 🚨 We are live on Product Hunt 🎉 Check out our latest launch: <a href="https://documen.so/sign-everywhere">The Platform Plan</a>!
<a href="https://www.producthunt.com/posts/documenso-platform-plan?embed=true&utm_source=badge-featured&utm_medium=badge&utm_souce=badge-documenso&#0045;platform&#0045;plan" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=670576&theme=light" alt="Documenso&#0032;Platform&#0032;Plan - Whitelabeled&#0032;signing&#0032;flows&#0032;in&#0032;your&#0032;product | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>

View File

@@ -21,14 +21,25 @@ Check out the [API V1 documentation](https://app.documenso.com/api/v1/openapi) f
## API V2 - Beta
Our new API V2 is currently in Beta. The new API features typed SDKs for TypeScript, Python and Go and example code for many more.
<Callout type="warning">API V2 is currently beta, and will be subject to breaking changes</Callout>
<Callout type="warning">
NOW IN BETA: [API V2 Documentation](https://documen.so/api-v2-docs)
Check out the [API V2 documentation](https://documen.so/api-v2-docs) for details about the API endpoints, request parameters, response formats, and authentication methods.
Our new API V2 supports the following typed SDKs:
- [TypeScript](https://github.com/documenso/sdk-typescript)
- [Python](https://github.com/documenso/sdk-python)
- [Go](https://github.com/documenso/sdk-go)
<Callout type="info">
For the staging API, please use the following base URL:
`https://stg-app.documenso.dev/api/v2-beta/`
</Callout>
🚀 [V2 Announcement](https://documen.so/sdk-blog)
📖 [Documentation](https://documen.so/api-v2-docs)
💬 [Leave Feedback](https://documen.so/sdk-feedback)
🔔 [Breaking Changes](https://documen.so/sdk-breaking)

View File

@@ -1,6 +1,6 @@
{
"name": "@documenso/web",
"version": "1.9.1-rc.2",
"version": "1.9.1-rc.4",
"private": true,
"license": "AGPL-3.0",
"scripts": {

View File

@@ -44,7 +44,12 @@ export const CheckboxField = ({ field, onSignField, onUnsignField }: CheckboxFie
const [isPending, startTransition] = useTransition();
const { executeActionAuthProcedure } = useRequiredDocumentAuthContext();
const parsedFieldMeta = ZCheckboxFieldMeta.parse(field.fieldMeta);
const parsedFieldMeta = ZCheckboxFieldMeta.parse(
field.fieldMeta ?? {
type: 'checkbox',
values: [{ id: 1, checked: false, value: '' }],
},
);
const values = parsedFieldMeta.values?.map((item) => ({
...item,

View File

@@ -49,7 +49,7 @@ export type EmbedDirectTemplateClientPageProps = {
fields: Field[];
metadata?: DocumentMeta | TemplateMeta | null;
hidePoweredBy?: boolean;
isPlatformOrEnterprise?: boolean;
allowWhiteLabelling?: boolean;
};
export const EmbedDirectTemplateClientPage = ({
@@ -60,7 +60,7 @@ export const EmbedDirectTemplateClientPage = ({
fields,
metadata,
hidePoweredBy = false,
isPlatformOrEnterprise = false,
allowWhiteLabelling = false,
}: EmbedDirectTemplateClientPageProps) => {
const { _ } = useLingui();
const { toast } = useToast();
@@ -288,7 +288,7 @@ export const EmbedDirectTemplateClientPage = ({
document.documentElement.classList.add('dark-mode-disabled');
}
if (isPlatformOrEnterprise) {
if (allowWhiteLabelling) {
injectCss({
css: data.css,
cssVars: data.cssVars,

View File

@@ -2,6 +2,7 @@ import { notFound } from 'next/navigation';
import { match } from 'ts-pattern';
import { isCommunityPlan as isUserCommunityPlan } from '@documenso/ee/server-only/util/is-community-plan';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
import { isDocumentPlatform } from '@documenso/ee/server-only/util/is-document-platform';
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
@@ -55,12 +56,16 @@ export default async function EmbedDirectTemplatePage({ params }: EmbedDirectTem
documentAuth: template.authOptions,
});
const [isPlatformDocument, isEnterpriseDocument] = await Promise.all([
const [isPlatformDocument, isEnterpriseDocument, isCommunityPlan] = await Promise.all([
isDocumentPlatform(template),
isUserEnterprise({
userId: template.userId,
teamId: template.teamId ?? undefined,
}),
isUserCommunityPlan({
userId: template.userId,
teamId: template.teamId ?? undefined,
}),
]);
const isAccessAuthValid = match(derivedRecipientAccessAuth)
@@ -106,7 +111,7 @@ export default async function EmbedDirectTemplatePage({ params }: EmbedDirectTem
fields={fields}
metadata={template.templateMeta}
hidePoweredBy={isPlatformDocument || isEnterpriseDocument || hidePoweredBy}
isPlatformOrEnterprise={isPlatformDocument || isEnterpriseDocument}
allowWhiteLabelling={isCommunityPlan || isPlatformDocument || isEnterpriseDocument}
/>
</RecipientProvider>
</DocumentAuthProvider>

View File

@@ -51,7 +51,7 @@ export type EmbedSignDocumentClientPageProps = {
metadata?: DocumentMeta | TemplateMeta | null;
isCompleted?: boolean;
hidePoweredBy?: boolean;
isPlatformOrEnterprise?: boolean;
allowWhitelabelling?: boolean;
allRecipients?: RecipientWithFields[];
};
@@ -64,7 +64,7 @@ export const EmbedSignDocumentClientPage = ({
metadata,
isCompleted,
hidePoweredBy = false,
isPlatformOrEnterprise = false,
allowWhitelabelling = false,
allRecipients = [],
}: EmbedSignDocumentClientPageProps) => {
const { _ } = useLingui();
@@ -212,7 +212,7 @@ export const EmbedSignDocumentClientPage = ({
document.documentElement.classList.add('dark-mode-disabled');
}
if (isPlatformOrEnterprise) {
if (allowWhitelabelling) {
injectCss({
css: data.css,
cssVars: data.cssVars,

View File

@@ -2,6 +2,7 @@ import { notFound } from 'next/navigation';
import { match } from 'ts-pattern';
import { isCommunityPlan as isUserCommunityPlan } from '@documenso/ee/server-only/util/is-community-plan';
import { isUserEnterprise } from '@documenso/ee/server-only/util/is-document-enterprise';
import { isDocumentPlatform } from '@documenso/ee/server-only/util/is-document-platform';
import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app';
@@ -62,12 +63,16 @@ export default async function EmbedSignDocumentPage({ params }: EmbedSignDocumen
return <EmbedPaywall />;
}
const [isPlatformDocument, isEnterpriseDocument] = await Promise.all([
const [isPlatformDocument, isEnterpriseDocument, isCommunityPlan] = await Promise.all([
isDocumentPlatform(document),
isUserEnterprise({
userId: document.userId,
teamId: document.teamId ?? undefined,
}),
isUserCommunityPlan({
userId: document.userId,
teamId: document.teamId ?? undefined,
}),
]);
const { derivedRecipientAccessAuth } = extractDocumentAuthMethods({
@@ -127,7 +132,7 @@ export default async function EmbedSignDocumentPage({ params }: EmbedSignDocumen
metadata={document.documentMeta}
isCompleted={document.status === DocumentStatus.COMPLETED}
hidePoweredBy={isPlatformDocument || isEnterpriseDocument || hidePoweredBy}
isPlatformOrEnterprise={isPlatformDocument || isEnterpriseDocument}
allowWhitelabelling={isCommunityPlan || isPlatformDocument || isEnterpriseDocument}
allRecipients={allRecipients}
/>
</DocumentAuthProvider>

6
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "@documenso/root",
"version": "1.9.1-rc.2",
"version": "1.9.1-rc.4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@documenso/root",
"version": "1.9.1-rc.2",
"version": "1.9.1-rc.4",
"workspaces": [
"apps/*",
"packages/*"
@@ -106,7 +106,7 @@
},
"apps/web": {
"name": "@documenso/web",
"version": "1.9.1-rc.2",
"version": "1.9.1-rc.4",
"license": "AGPL-3.0",
"dependencies": {
"@documenso/api": "*",

View File

@@ -1,6 +1,6 @@
{
"private": true,
"version": "1.9.1-rc.2",
"version": "1.9.1-rc.4",
"scripts": {
"build": "turbo run build",
"build:web": "turbo run build --filter=@documenso/web",

View File

@@ -0,0 +1,56 @@
import { subscriptionsContainsActivePlan } from '@documenso/lib/utils/billing';
import { prisma } from '@documenso/prisma';
import type { Subscription } from '@documenso/prisma/client';
import { getCommunityPlanPriceIds } from '../stripe/get-community-plan-prices';
export type IsCommunityPlanOptions = {
userId: number;
teamId?: number;
};
/**
* Whether the user or team is on the community plan.
*/
export const isCommunityPlan = async ({
userId,
teamId,
}: IsCommunityPlanOptions): Promise<boolean> => {
let subscriptions: Subscription[] = [];
if (teamId) {
subscriptions = await prisma.team
.findFirstOrThrow({
where: {
id: teamId,
},
select: {
owner: {
include: {
subscriptions: true,
},
},
},
})
.then((team) => team.owner.subscriptions);
} else {
subscriptions = await prisma.user
.findFirstOrThrow({
where: {
id: userId,
},
select: {
subscriptions: true,
},
})
.then((user) => user.subscriptions);
}
if (subscriptions.length === 0) {
return false;
}
const communityPlanPriceIds = await getCommunityPlanPriceIds();
return subscriptionsContainsActivePlan(subscriptions, communityPlanPriceIds);
};

View File

@@ -88,6 +88,7 @@ export const findDocuments = async ({
const searchFilter: Prisma.DocumentWhereInput = {
OR: [
{ title: { contains: query, mode: 'insensitive' } },
{ externalId: { contains: query, mode: 'insensitive' } },
{ recipients: { some: { name: { contains: query, mode: 'insensitive' } } } },
{ recipients: { some: { email: { contains: query, mode: 'insensitive' } } } },
],

View File

@@ -34,6 +34,14 @@ export const searchDocumentsWithKeyword = async ({
userId: userId,
deletedAt: null,
},
{
externalId: {
contains: query,
mode: 'insensitive',
},
userId: userId,
deletedAt: null,
},
{
recipients: {
some: {
@@ -88,6 +96,23 @@ export const searchDocumentsWithKeyword = async ({
},
deletedAt: null,
},
{
externalId: {
contains: query,
mode: 'insensitive',
},
teamId: {
not: null,
},
team: {
members: {
some: {
userId: userId,
},
},
},
deletedAt: null,
},
],
},
include: {