diff --git a/apps/backend/src/api/routes/posts.controller.ts b/apps/backend/src/api/routes/posts.controller.ts
index 790df94f..14756ce2 100644
--- a/apps/backend/src/api/routes/posts.controller.ts
+++ b/apps/backend/src/api/routes/posts.controller.ts
@@ -175,7 +175,7 @@ export class PostsController {
) {
console.log(JSON.stringify(rawBody, null, 2));
const body = await this._postsService.mapTypeToPost(rawBody, org.id);
- return this._postsService.createPost(org.id, body);
+ return this._postsService.createPost(org.id, body, 'WEB');
}
@Post('/generator/draft')
diff --git a/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts b/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts
index 38ce060b..0b6d8338 100644
--- a/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts
+++ b/apps/backend/src/public-api/routes/v1/public.integrations.controller.ts
@@ -188,8 +188,15 @@ export class PublicIntegrationsController {
);
}
+ const allowedCreationMethods = ['CLI', 'API'] as const;
+ const creationMethod = allowedCreationMethods.includes(
+ rawBody.creationMethod
+ )
+ ? (rawBody.creationMethod as 'CLI' | 'API')
+ : 'API';
+
console.log(JSON.stringify(body, null, 2));
- return this._postsService.createPost(org.id, body);
+ return this._postsService.createPost(org.id, body, creationMethod);
}
@Delete('/posts/:id')
diff --git a/apps/frontend/src/app/(app)/(preview)/p/[id]/page.tsx b/apps/frontend/src/app/(app)/(preview)/p/[id]/page.tsx
index fb12181d..f5dc7b46 100644
--- a/apps/frontend/src/app/(app)/(preview)/p/[id]/page.tsx
+++ b/apps/frontend/src/app/(app)/(preview)/p/[id]/page.tsx
@@ -12,6 +12,7 @@ import { VideoOrImage } from '@gitroom/react/helpers/video.or.image';
import { CopyClient } from '@gitroom/frontend/components/preview/copy.client';
import { getT } from '@gitroom/react/translation/get.translation.service.backend';
import { RenderPreviewDateClient } from '@gitroom/frontend/components/preview/render.preview.date.client';
+import { CreationMethodBadge } from '@gitroom/frontend/components/launches/creation.method.badge';
dayjs.extend(utc);
export const metadata: Metadata = {
@@ -142,6 +143,12 @@ export default async function Auth(
@{post[0].integration.profile}
+ {index === 0 && (
+
+ )}
{
window.open(`/p/` + post.id + '?share=true', '_blank');
}, [post]);
@@ -1044,6 +1050,14 @@ const CalendarItem: FC<{
!
)}
+ {showCreationMethodBadge && (
+
+
+
+ )}
+ m === 'AUTOPOST' ? 'Auto-posted by system' : `Created via ${m}`;
+
+export const CreationMethodBadge: FC
= ({
+ creationMethod,
+ size = 'xs',
+ className,
+ ringColor,
+}) => {
+ if (!creationMethod || creationMethod === 'UNKNOWN') return null;
+
+ const sizeClasses =
+ size === 'xs'
+ ? 'h-[12px] px-[4px] text-[7px]'
+ : size === 'md'
+ ? 'h-[22px] px-[10px] text-[12px]'
+ : 'h-[18px] px-[8px] text-[10px]';
+
+ return (
+
+ {creationMethod}
+
+ );
+};
diff --git a/apps/frontend/src/components/new-launch/manage.modal.tsx b/apps/frontend/src/components/new-launch/manage.modal.tsx
index f8edb218..3b4cd464 100644
--- a/apps/frontend/src/components/new-launch/manage.modal.tsx
+++ b/apps/frontend/src/components/new-launch/manage.modal.tsx
@@ -33,6 +33,7 @@ import { SelectCustomer } from '@gitroom/frontend/components/launches/select.cus
import { CopilotPopup } from '@copilotkit/react-ui';
import { DummyCodeComponent } from '@gitroom/frontend/components/new-launch/dummy.code.component';
import { stripHtmlValidation } from '@gitroom/helpers/utils/strip.html.validation';
+import { CreationMethodBadge } from '@gitroom/frontend/components/launches/creation.method.badge';
import {
SettingsIcon,
ChevronDownIcon,
@@ -450,8 +451,12 @@ export const ManageModal: FC = (props) => {
-
+
{t('create_post_title', 'Create Post')}
+
{
const fetch = useFetch();
const { backendUrl } = useVariables();
@@ -30,6 +31,7 @@ export const PreviewWrapper = ({ children }: { children: ReactNode }) => {
>
+
{children}
diff --git a/libraries/helpers/src/utils/posts.list.minify.ts b/libraries/helpers/src/utils/posts.list.minify.ts
index cebe1497..f5847b9d 100644
--- a/libraries/helpers/src/utils/posts.list.minify.ts
+++ b/libraries/helpers/src/utils/posts.list.minify.ts
@@ -25,6 +25,7 @@ const POST_ITEM_KEYS: Record
= {
integration: 'n',
intervalInDays: 'iv',
actualDate: 'ad',
+ creationMethod: 'cm',
};
const INTEGRATION_KEYS: Record = {
diff --git a/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts b/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts
index dc3c3f52..b2983de7 100644
--- a/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts
+++ b/libraries/nestjs-libraries/src/chat/tools/integration.schedule.post.ts
@@ -223,7 +223,7 @@ If the tools return errors, you would need to rerun it with the right parameters
})),
},
],
- });
+ }, 'MCP');
finalOutput.push(...output);
}
diff --git a/libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts b/libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts
index 5964983a..c8132847 100644
--- a/libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/autopost/autopost.service.ts
@@ -303,7 +303,7 @@ export class AutopostService {
},
],
})),
- });
+ }, 'AUTOPOST');
}
async updateUrl(state: WorkflowChannelsState) {
diff --git a/libraries/nestjs-libraries/src/database/prisma/posts/posts.repository.ts b/libraries/nestjs-libraries/src/database/prisma/posts/posts.repository.ts
index 261f2628..84767937 100644
--- a/libraries/nestjs-libraries/src/database/prisma/posts/posts.repository.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/posts/posts.repository.ts
@@ -1,7 +1,12 @@
import { PrismaRepository } from '@gitroom/nestjs-libraries/database/prisma/prisma.service';
import { Injectable } from '@nestjs/common';
import { Post as PostBody } from '@gitroom/nestjs-libraries/dtos/posts/create.post.dto';
-import { APPROVED_SUBMIT_FOR_ORDER, Post, State } from '@prisma/client';
+import {
+ APPROVED_SUBMIT_FOR_ORDER,
+ CreationMethod,
+ Post,
+ State,
+} from '@prisma/client';
import { GetPostsDto } from '@gitroom/nestjs-libraries/dtos/posts/get.posts.dto';
import { GetPostsListDto } from '@gitroom/nestjs-libraries/dtos/posts/get.posts.list.dto';
import dayjs from 'dayjs';
@@ -174,6 +179,7 @@ export class PostsRepository {
state: true,
intervalInDays: true,
group: true,
+ creationMethod: true,
tags: {
select: {
tag: true,
@@ -261,6 +267,7 @@ export class PostsRepository {
releaseId: true,
state: true,
group: true,
+ creationMethod: true,
tags: {
select: {
tag: true,
@@ -484,6 +491,7 @@ export class PostsRepository {
date: string,
body: PostBody,
tags: { value: string; label: string }[],
+ creationMethod: CreationMethod,
inter?: number
) {
const posts: Post[] = [];
@@ -518,6 +526,7 @@ export class PostsRepository {
group: uuid,
intervalInDays: inter ? +inter : null,
approvedSubmitForOrder: APPROVED_SUBMIT_FOR_ORDER.NO,
+ ...(type === 'create' ? { creationMethod } : {}),
...(state === 'update'
? {}
: {
diff --git a/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts b/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts
index 5f4694ba..0e8100ef 100644
--- a/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts
+++ b/libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts
@@ -7,7 +7,14 @@ import { PostsRepository } from '@gitroom/nestjs-libraries/database/prisma/posts
import { CreatePostDto } from '@gitroom/nestjs-libraries/dtos/posts/create.post.dto';
import dayjs from 'dayjs';
import { IntegrationManager } from '@gitroom/nestjs-libraries/integrations/integration.manager';
-import { Integration, Post, Media, From, State } from '@prisma/client';
+import {
+ Integration,
+ Post,
+ Media,
+ From,
+ CreationMethod,
+ State,
+} from '@prisma/client';
import { GetPostsDto } from '@gitroom/nestjs-libraries/dtos/posts/get.posts.dto';
import { GetPostsListDto } from '@gitroom/nestjs-libraries/dtos/posts/get.posts.list.dto';
import { shuffle } from 'lodash';
@@ -740,7 +747,11 @@ export class PostsService {
} catch (err) {}
}
- async createPost(orgId: string, body: CreatePostDto): Promise {
+ async createPost(
+ orgId: string,
+ body: CreatePostDto,
+ creationMethod: CreationMethod
+ ): Promise {
const postList = [];
for (const post of body.posts) {
const provider = this._integrationManager.getSocialIntegration(
@@ -769,6 +780,7 @@ export class PostsService {
body.type === 'now' ? dayjs().format('YYYY-MM-DDTHH:mm:00') : body.date,
post,
body.tags,
+ creationMethod,
body.inter
);
@@ -902,43 +914,47 @@ export class PostsService {
const group = makeId(10);
const randomDate = findTime();
- await this.createPost(orgId, {
- type: 'draft',
- date: randomDate,
- order: '',
- shortLink: false,
- tags: [],
- posts: [
- {
- group,
- integration: {
- id: integration.id,
- },
- settings: {
- __type: integration.providerIdentifier as any,
- title: '',
- tags: [],
- subreddit: [],
- },
- value: [
- ...toPost.list.map((l) => ({
- id: '',
- content: l.post,
- delay: 0,
- image: [],
- })),
- {
- id: '',
- delay: 0,
- content: `Check out the full story here:\n${
- body.postId || body.url
- }`,
- image: [],
+ await this.createPost(
+ orgId,
+ {
+ type: 'draft',
+ date: randomDate,
+ order: '',
+ shortLink: false,
+ tags: [],
+ posts: [
+ {
+ group,
+ integration: {
+ id: integration.id,
},
- ],
- },
- ],
- });
+ settings: {
+ __type: integration.providerIdentifier as any,
+ title: '',
+ tags: [],
+ subreddit: [],
+ },
+ value: [
+ ...toPost.list.map((l) => ({
+ id: '',
+ content: l.post,
+ delay: 0,
+ image: [],
+ })),
+ {
+ id: '',
+ delay: 0,
+ content: `Check out the full story here:\n${
+ body.postId || body.url
+ }`,
+ image: [],
+ },
+ ],
+ },
+ ],
+ },
+ 'WEB'
+ );
}
}
}
diff --git a/libraries/nestjs-libraries/src/database/prisma/schema.prisma b/libraries/nestjs-libraries/src/database/prisma/schema.prisma
index a005ed80..7f48b7bf 100644
--- a/libraries/nestjs-libraries/src/database/prisma/schema.prisma
+++ b/libraries/nestjs-libraries/src/database/prisma/schema.prisma
@@ -409,6 +409,7 @@ model Post {
submittedForOrderId String?
submittedForOrganizationId String?
approvedSubmitForOrder APPROVED_SUBMIT_FOR_ORDER @default(NO)
+ creationMethod CreationMethod @default(UNKNOWN)
lastMessageId String?
intervalInDays Int?
error String?
@@ -436,6 +437,7 @@ model Post {
@@index([submittedForOrderId])
@@index([intervalInDays])
@@index([approvedSubmitForOrder])
+ @@index([creationMethod])
@@index([lastMessageId])
@@index([createdAt])
@@index([updatedAt])
@@ -938,6 +940,15 @@ enum APPROVED_SUBMIT_FOR_ORDER {
YES
}
+enum CreationMethod {
+ UNKNOWN
+ WEB
+ MCP
+ API
+ AUTOPOST
+ CLI
+}
+
enum ShortLinkPreference {
ASK
YES