From 35625b281b6032eeb433f43042136536086c337e Mon Sep 17 00:00:00 2001 From: Nevo David Date: Mon, 9 Jun 2025 17:49:51 +0700 Subject: [PATCH 1/4] feat: sets --- apps/backend/src/api/api.module.ts | 2 + .../backend/src/api/routes/sets.controller.ts | 57 ++ .../components/launches/add.edit.model.tsx | 189 ++++--- .../components/layout/settings.component.tsx | 95 +--- apps/frontend/src/components/sets/sets.tsx | 219 ++++++++ .../src/database/prisma/database.module.ts | 4 + .../src/database/prisma/schema.prisma | 525 +++++++++--------- .../database/prisma/sets/sets.repository.ts | 58 ++ .../src/database/prisma/sets/sets.service.ts | 24 + .../src/dtos/sets/sets.dto.ts | 29 + .../translation/locales/en/translation.json | 3 +- 11 files changed, 779 insertions(+), 426 deletions(-) create mode 100644 apps/backend/src/api/routes/sets.controller.ts create mode 100644 apps/frontend/src/components/sets/sets.tsx create mode 100644 libraries/nestjs-libraries/src/database/prisma/sets/sets.repository.ts create mode 100644 libraries/nestjs-libraries/src/database/prisma/sets/sets.service.ts create mode 100644 libraries/nestjs-libraries/src/dtos/sets/sets.dto.ts diff --git a/apps/backend/src/api/api.module.ts b/apps/backend/src/api/api.module.ts index 54b8382a..aef9a805 100644 --- a/apps/backend/src/api/api.module.ts +++ b/apps/backend/src/api/api.module.ts @@ -33,6 +33,7 @@ import { SignatureController } from '@gitroom/backend/api/routes/signature.contr import { AutopostController } from '@gitroom/backend/api/routes/autopost.controller'; import { McpService } from '@gitroom/nestjs-libraries/mcp/mcp.service'; import { McpController } from '@gitroom/backend/api/routes/mcp.controller'; +import { SetsController } from '@gitroom/backend/api/routes/sets.controller'; const authenticatedController = [ UsersController, @@ -50,6 +51,7 @@ const authenticatedController = [ WebhookController, SignatureController, AutopostController, + SetsController, ]; @Module({ imports: [UploadModule], diff --git a/apps/backend/src/api/routes/sets.controller.ts b/apps/backend/src/api/routes/sets.controller.ts new file mode 100644 index 00000000..df10a344 --- /dev/null +++ b/apps/backend/src/api/routes/sets.controller.ts @@ -0,0 +1,57 @@ +import { + Body, + Controller, + Delete, + Get, + Param, + Post, + Put, +} from '@nestjs/common'; +import { GetOrgFromRequest } from '@gitroom/nestjs-libraries/user/org.from.request'; +import { Organization } from '@prisma/client'; +import { ApiTags } from '@nestjs/swagger'; +import { SetsService } from '@gitroom/nestjs-libraries/database/prisma/sets/sets.service'; +import { CheckPolicies } from '@gitroom/backend/services/auth/permissions/permissions.ability'; +import { + AuthorizationActions, + Sections, +} from '@gitroom/backend/services/auth/permissions/permissions.service'; +import { + UpdateSetsDto, + SetsDto, +} from '@gitroom/nestjs-libraries/dtos/sets/sets.dto'; + +@ApiTags('Sets') +@Controller('/sets') +export class SetsController { + constructor(private _setsService: SetsService) {} + + @Get('/') + async getSets(@GetOrgFromRequest() org: Organization) { + return this._setsService.getSets(org.id); + } + + @Post('/') + async createASet( + @GetOrgFromRequest() org: Organization, + @Body() body: SetsDto + ) { + return this._setsService.createSet(org.id, body); + } + + @Put('/') + async updateSet( + @GetOrgFromRequest() org: Organization, + @Body() body: UpdateSetsDto + ) { + return this._setsService.createSet(org.id, body); + } + + @Delete('/:id') + async deleteSet( + @GetOrgFromRequest() org: Organization, + @Param('id') id: string + ) { + return this._setsService.deleteSet(org.id, id); + } +} \ No newline at end of file diff --git a/apps/frontend/src/components/launches/add.edit.model.tsx b/apps/frontend/src/components/launches/add.edit.model.tsx index 002a055e..299b50a5 100644 --- a/apps/frontend/src/components/launches/add.edit.model.tsx +++ b/apps/frontend/src/components/launches/add.edit.model.tsx @@ -71,6 +71,8 @@ export const AddEditModal: FC<{ date: dayjs.Dayjs; integrations: Integrations[]; allIntegrations?: Integrations[]; + setId?: string; + addEditSets?: (data: any) => void; reopenModal: () => void; mutate: () => void; padding?: string; @@ -92,6 +94,7 @@ export const AddEditModal: FC<{ onlyValues, padding, customClose, + addEditSets, } = props; const [customer, setCustomer] = useState(''); const [loading, setLoading] = useState(false); @@ -436,28 +439,33 @@ export const AddEditModal: FC<{ 'Yes, shortlink it!' ); setLoading(true); - await fetch('/posts', { - method: 'POST', - body: JSON.stringify({ - ...(postFor - ? { - order: postFor.id, - } - : {}), - type, - inter, - tags, - shortLink, - date: dateState.utc().format('YYYY-MM-DDTHH:mm:ss'), - posts: allKeys.map((p) => ({ - ...p, - value: p.value.map((a) => ({ - ...a, - content: a.content.slice(0, p.maximumCharacters || 1000000), - })), + + const data = { + ...(postFor + ? { + order: postFor.id, + } + : {}), + type, + inter, + tags, + shortLink, + date: dateState.utc().format('YYYY-MM-DDTHH:mm:ss'), + posts: allKeys.map((p) => ({ + ...p, + value: p.value.map((a) => ({ + ...a, + content: a.content.slice(0, p.maximumCharacters || 1000000), })), - }), - }); + })), + }; + + addEditSets + ? addEditSets(data) + : await fetch('/posts', { + method: 'POST', + body: JSON.stringify(data), + }); existingData.group = makeId(10); mutate(); toaster.show( @@ -481,6 +489,7 @@ export const AddEditModal: FC<{ existingData, selectedIntegrations, tags, + addEditSets, ] ); const uppy = useUppyUploader({ @@ -811,70 +820,84 @@ Here are the things you can do: {t('delete_post', 'Delete Post')} )} - - + )} + + {!addEditSets && ( + + )} + + {!addEditSets && ( + + {!postFor && ( +
+ + + +
+ {t('post_now', 'Post now')} +
+
+ )} + + + )} diff --git a/apps/frontend/src/components/layout/settings.component.tsx b/apps/frontend/src/components/layout/settings.component.tsx index 0fad51f2..0850f213 100644 --- a/apps/frontend/src/components/layout/settings.component.tsx +++ b/apps/frontend/src/components/layout/settings.component.tsx @@ -21,6 +21,7 @@ import { useVariables } from '@gitroom/react/helpers/variable.context'; import { PublicComponent } from '@gitroom/frontend/components/public-api/public.component'; import Link from 'next/link'; import { Webhooks } from '@gitroom/frontend/components/webhooks/webhooks'; +import { Sets } from '@gitroom/frontend/components/sets/sets'; import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component'; import { Tabs } from '@mantine/core'; import { SignaturesComponent } from '@gitroom/frontend/components/settings/signatures.component'; @@ -84,10 +85,7 @@ export const SettingsPopup: FC<{ if (user?.tier?.autoPost) { return 'autopost'; } - if (user?.tier?.public_api && isGeneral) { - return 'api'; - } - return 'signatures'; + return 'sets'; }, [user?.tier, isGeneral]); const t = useT(); @@ -131,6 +129,7 @@ export const SettingsPopup: FC<{ {t('auto_post', 'Auto Post')} )} + {t('sets', 'Sets')} {user?.tier.current !== 'FREE' && ( {t('signatures', 'Signatures')} @@ -141,88 +140,6 @@ export const SettingsPopup: FC<{ )} - {/* -
-
Profile
-
- Add profile information -
-
-
-
-
- -
-
-
- {!!picture?.path && ( - profile - )} -
-
-
Profile Picture
-
- - -
-
-
-
-
-