feat: sets
This commit is contained in:
parent
3cf3a4b8bb
commit
35625b281b
|
|
@ -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],
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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')}
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
onClick={schedule('draft')}
|
||||
className="rounded-[4px] border-2 border-customColor21"
|
||||
secondary={true}
|
||||
disabled={selectedIntegrations.length === 0}
|
||||
>
|
||||
{t('save_as_draft', 'Save as draft')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={schedule('schedule')}
|
||||
className="rounded-[4px] relative group"
|
||||
disabled={
|
||||
selectedIntegrations.length === 0 ||
|
||||
loading ||
|
||||
!canSendForPublication
|
||||
}
|
||||
>
|
||||
<div className="flex justify-center items-center gap-[5px] h-full">
|
||||
<div className="h-full flex items-center text-white">
|
||||
{!canSendForPublication
|
||||
? t('not_matching_order', 'Not matching order')
|
||||
: postFor
|
||||
? t('submit_for_order', 'Submit for order')
|
||||
: !existingData.integration
|
||||
? selectedIntegrations.length === 0
|
||||
? t(
|
||||
'select_channels_from_circles',
|
||||
'Select channels from the circles above'
|
||||
)
|
||||
: t('add_to_calendar', 'Add to calendar')
|
||||
: // @ts-ignore
|
||||
existingData?.posts?.[0]?.state === 'DRAFT'
|
||||
? t('schedule', 'Schedule')
|
||||
: t('update', 'Update')}
|
||||
</div>
|
||||
{!postFor && (
|
||||
<div className="h-full flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M15.0233 7.14804L9.39828 12.773C9.34604 12.8253 9.284 12.8668 9.21572 12.8951C9.14743 12.9234 9.07423 12.938 9.00031 12.938C8.92639 12.938 8.8532 12.9234 8.78491 12.8951C8.71662 12.8668 8.65458 12.8253 8.60234 12.773L2.97734 7.14804C2.8718 7.04249 2.8125 6.89934 2.8125 6.75007C2.8125 6.6008 2.8718 6.45765 2.97734 6.3521C3.08289 6.24655 3.22605 6.18726 3.37531 6.18726C3.52458 6.18726 3.66773 6.24655 3.77328 6.3521L9.00031 11.5798L14.2273 6.3521C14.2796 6.29984 14.3417 6.25838 14.4099 6.2301C14.4782 6.20181 14.5514 6.18726 14.6253 6.18726C14.6992 6.18726 14.7724 6.20181 14.8407 6.2301C14.909 6.25838 14.971 6.29984 15.0233 6.3521C15.0755 6.40436 15.117 6.46641 15.1453 6.53469C15.1736 6.60297 15.1881 6.67616 15.1881 6.75007C15.1881 6.82398 15.1736 6.89716 15.1453 6.96545C15.117 7.03373 15.0755 7.09578 15.0233 7.14804Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
<div
|
||||
onClick={postNow}
|
||||
className={clsx(
|
||||
'hidden group-hover:flex hover:flex flex-col justify-center absolute start-0 top-[100%] w-full h-[40px] bg-customColor22 border border-tableBorder',
|
||||
loading &&
|
||||
'cursor-not-allowed pointer-events-none opacity-50'
|
||||
)}
|
||||
>
|
||||
{t('post_now', 'Post now')}
|
||||
</div>
|
||||
{addEditSets && (
|
||||
<Button
|
||||
onClick={schedule('draft')}
|
||||
className="rounded-[4px] relative group"
|
||||
>
|
||||
{t('save_set', 'Save Set')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{!addEditSets && (
|
||||
<Button
|
||||
onClick={schedule('draft')}
|
||||
className="rounded-[4px] border-2 border-customColor21"
|
||||
secondary={true}
|
||||
disabled={selectedIntegrations.length === 0}
|
||||
>
|
||||
{t('save_as_draft', 'Save as draft')}
|
||||
</Button>
|
||||
)}
|
||||
|
||||
{!addEditSets && (
|
||||
<Button
|
||||
onClick={schedule('schedule')}
|
||||
className="rounded-[4px] relative group"
|
||||
disabled={
|
||||
selectedIntegrations.length === 0 ||
|
||||
loading ||
|
||||
!canSendForPublication
|
||||
}
|
||||
>
|
||||
<div className="flex justify-center items-center gap-[5px] h-full">
|
||||
<div className="h-full flex items-center text-white">
|
||||
{!canSendForPublication
|
||||
? t('not_matching_order', 'Not matching order')
|
||||
: postFor
|
||||
? t('submit_for_order', 'Submit for order')
|
||||
: !existingData.integration
|
||||
? selectedIntegrations.length === 0
|
||||
? t(
|
||||
'select_channels_from_circles',
|
||||
'Select channels from the circles above'
|
||||
)
|
||||
: t('add_to_calendar', 'Add to calendar')
|
||||
: // @ts-ignore
|
||||
existingData?.posts?.[0]?.state === 'DRAFT'
|
||||
? t('schedule', 'Schedule')
|
||||
: t('update', 'Update')}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Button>
|
||||
{!postFor && (
|
||||
<div className="h-full flex items-center">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="18"
|
||||
height="18"
|
||||
viewBox="0 0 18 18"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M15.0233 7.14804L9.39828 12.773C9.34604 12.8253 9.284 12.8668 9.21572 12.8951C9.14743 12.9234 9.07423 12.938 9.00031 12.938C8.92639 12.938 8.8532 12.9234 8.78491 12.8951C8.71662 12.8668 8.65458 12.8253 8.60234 12.773L2.97734 7.14804C2.8718 7.04249 2.8125 6.89934 2.8125 6.75007C2.8125 6.6008 2.8718 6.45765 2.97734 6.3521C3.08289 6.24655 3.22605 6.18726 3.37531 6.18726C3.52458 6.18726 3.66773 6.24655 3.77328 6.3521L9.00031 11.5798L14.2273 6.3521C14.2796 6.29984 14.3417 6.25838 14.4099 6.2301C14.4782 6.20181 14.5514 6.18726 14.6253 6.18726C14.6992 6.18726 14.7724 6.20181 14.8407 6.2301C14.909 6.25838 14.971 6.29984 15.0233 6.3521C15.0755 6.40436 15.117 6.46641 15.1453 6.53469C15.1736 6.60297 15.1881 6.67616 15.1881 6.75007C15.1881 6.82398 15.1736 6.89716 15.1453 6.96545C15.117 7.03373 15.0755 7.09578 15.0233 7.14804Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
<div
|
||||
onClick={postNow}
|
||||
className={clsx(
|
||||
'hidden group-hover:flex hover:flex flex-col justify-center absolute start-0 top-[100%] w-full h-[40px] bg-customColor22 border border-tableBorder',
|
||||
loading &&
|
||||
'cursor-not-allowed pointer-events-none opacity-50'
|
||||
)}
|
||||
>
|
||||
{t('post_now', 'Post now')}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Button>
|
||||
)}
|
||||
</Submitted>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -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')}
|
||||
</Tabs.Tab>
|
||||
)}
|
||||
<Tabs.Tab value="sets">{t('sets', 'Sets')}</Tabs.Tab>
|
||||
{user?.tier.current !== 'FREE' && (
|
||||
<Tabs.Tab value="signatures">
|
||||
{t('signatures', 'Signatures')}
|
||||
|
|
@ -141,88 +140,6 @@ export const SettingsPopup: FC<{
|
|||
)}
|
||||
</Tabs.List>
|
||||
|
||||
{/* <Tabs.Panel value="profile" pt="md">
|
||||
<div className="flex flex-col gap-[4px]">
|
||||
<div className="text-[20px] font-[500]">Profile</div>
|
||||
<div className="text-[14px] text-customColor18 font-[400]">
|
||||
Add profile information
|
||||
</div>
|
||||
</div>
|
||||
<div className="rounded-[4px] border border-customColor6 p-[24px] flex flex-col">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="w-[455px]">
|
||||
<Input label="Full Name" translationKey="label_full_name" name="fullname" />
|
||||
</div>
|
||||
<div className="flex gap-[8px] mb-[10px]">
|
||||
<div className="w-[48px] h-[48px] rounded-full bg-customColor38">
|
||||
{!!picture?.path && (
|
||||
<img
|
||||
src={picture?.path}
|
||||
alt="profile"
|
||||
className="w-full h-full rounded-full"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex flex-col gap-[2px]">
|
||||
<div className="text-[14px]">Profile Picture</div>
|
||||
<div className="flex gap-[8px]">
|
||||
<button
|
||||
className="h-[24px] w-[120px] bg-forth rounded-[4px] flex justify-center gap-[4px] items-center cursor-pointer"
|
||||
type="button"
|
||||
>
|
||||
<div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 14 14"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M12.25 8.3126V11.3751C12.25 11.6072 12.1578 11.8297 11.9937 11.9938C11.8296 12.1579 11.6071 12.2501 11.375 12.2501H2.625C2.39294 12.2501 2.17038 12.1579 2.00628 11.9938C1.84219 11.8297 1.75 11.6072 1.75 11.3751V8.3126C1.75 8.19657 1.79609 8.08529 1.87814 8.00324C1.96019 7.92119 2.07147 7.8751 2.1875 7.8751C2.30353 7.8751 2.41481 7.92119 2.49686 8.00324C2.57891 8.08529 2.625 8.19657 2.625 8.3126V11.3751H11.375V8.3126C11.375 8.19657 11.4211 8.08529 11.5031 8.00324C11.5852 7.92119 11.6965 7.8751 11.8125 7.8751C11.9285 7.8751 12.0398 7.92119 12.1219 8.00324C12.2039 8.08529 12.25 8.19657 12.25 8.3126ZM5.12203 4.68463L6.5625 3.24362V8.3126C6.5625 8.42863 6.60859 8.53991 6.69064 8.62196C6.77269 8.70401 6.88397 8.7501 7 8.7501C7.11603 8.7501 7.22731 8.70401 7.30936 8.62196C7.39141 8.53991 7.4375 8.42863 7.4375 8.3126V3.24362L8.87797 4.68463C8.96006 4.76672 9.0714 4.81284 9.1875 4.81284C9.3036 4.81284 9.41494 4.76672 9.49703 4.68463C9.57912 4.60254 9.62524 4.4912 9.62524 4.3751C9.62524 4.259 9.57912 4.14766 9.49703 4.06557L7.30953 1.87807C7.2689 1.83739 7.22065 1.80512 7.16754 1.78311C7.11442 1.76109 7.05749 1.74976 7 1.74976C6.94251 1.74976 6.88558 1.76109 6.83246 1.78311C6.77935 1.80512 6.7311 1.83739 6.69047 1.87807L4.50297 4.06557C4.42088 4.14766 4.37476 4.259 4.37476 4.3751C4.37476 4.4912 4.42088 4.60254 4.50297 4.68463C4.58506 4.76672 4.6964 4.81284 4.8125 4.81284C4.9286 4.81284 5.03994 4.76672 5.12203 4.68463Z"
|
||||
fill="white"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
className="text-[12px] text-white"
|
||||
onClick={openMedia}
|
||||
>
|
||||
Upload image
|
||||
</div>
|
||||
</button>
|
||||
<button
|
||||
className="h-[24px] w-[88px] rounded-[4px] border-2 border-customColor21 hover:text-red-600 flex justify-center items-center gap-[4px]"
|
||||
type="button"
|
||||
>
|
||||
<div>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14"
|
||||
height="14"
|
||||
viewBox="0 0 14 14"
|
||||
fill="none"
|
||||
>
|
||||
<path
|
||||
d="M11.8125 2.625H9.625V2.1875C9.625 1.8394 9.48672 1.50556 9.24058 1.25942C8.99444 1.01328 8.6606 0.875 8.3125 0.875H5.6875C5.3394 0.875 5.00556 1.01328 4.75942 1.25942C4.51328 1.50556 4.375 1.8394 4.375 2.1875V2.625H2.1875C2.07147 2.625 1.96019 2.67109 1.87814 2.75314C1.79609 2.83519 1.75 2.94647 1.75 3.0625C1.75 3.17853 1.79609 3.28981 1.87814 3.37186C1.96019 3.45391 2.07147 3.5 2.1875 3.5H2.625V11.375C2.625 11.6071 2.71719 11.8296 2.88128 11.9937C3.04538 12.1578 3.26794 12.25 3.5 12.25H10.5C10.7321 12.25 10.9546 12.1578 11.1187 11.9937C11.2828 11.8296 11.375 11.6071 11.375 11.375V3.5H11.8125C11.9285 3.5 12.0398 3.45391 12.1219 3.37186C12.2039 3.28981 12.25 3.17853 12.25 3.0625C12.25 2.94647 12.2039 2.83519 12.1219 2.75314C12.0398 2.67109 11.9285 2.625 11.8125 2.625ZM5.25 2.1875C5.25 2.07147 5.29609 1.96019 5.37814 1.87814C5.46019 1.79609 5.57147 1.75 5.6875 1.75H8.3125C8.42853 1.75 8.53981 1.79609 8.62186 1.87814C8.70391 1.96019 8.75 2.07147 8.75 2.1875V2.625H5.25V2.1875ZM10.5 11.375H3.5V3.5H10.5V11.375ZM6.125 5.6875V9.1875C6.125 9.30353 6.07891 9.41481 5.99686 9.49686C5.91481 9.57891 5.80353 9.625 5.6875 9.625C5.57147 9.625 5.46019 9.57891 5.37814 9.49686C5.29609 9.41481 5.25 9.30353 5.25 9.1875V5.6875C5.25 5.57147 5.29609 5.46019 5.37814 5.37814C5.46019 5.29609 5.57147 5.25 5.6875 5.25C5.80353 5.25 5.91481 5.29609 5.99686 5.37814C6.07891 5.46019 6.125 5.57147 6.125 5.6875ZM8.75 5.6875V9.1875C8.75 9.30353 8.70391 9.41481 8.62186 9.49686C8.53981 9.57891 8.42853 9.625 8.3125 9.625C8.19647 9.625 8.08519 9.57891 8.00314 9.49686C7.92109 9.41481 7.875 9.30353 7.875 9.1875V5.6875C7.875 5.57147 7.92109 5.46019 8.00314 5.37814C8.08519 5.29609 8.19647 5.25 8.3125 5.25C8.42853 5.25 8.53981 5.29609 8.62186 5.37814C8.70391 5.46019 8.75 5.57147 8.75 5.6875Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div className="text-[12px] " onClick={remove}>
|
||||
Remove
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Textarea label="Bio" translationKey="label_bio" name="bio" className="resize-none" />
|
||||
</div>
|
||||
</div>
|
||||
</Tabs.Panel> */}
|
||||
|
||||
{!!user?.tier?.team_members && isGeneral && (
|
||||
<Tabs.Panel value="teams" pt="md">
|
||||
<TeamsComponent />
|
||||
|
|
@ -241,6 +158,12 @@ export const SettingsPopup: FC<{
|
|||
</Tabs.Panel>
|
||||
)}
|
||||
|
||||
{user?.tier.current !== 'FREE' && (
|
||||
<Tabs.Panel value="sets" pt="md">
|
||||
<Sets />
|
||||
</Tabs.Panel>
|
||||
)}
|
||||
|
||||
{user?.tier.current !== 'FREE' && (
|
||||
<Tabs.Panel value="signatures" pt="md">
|
||||
<SignaturesComponent />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,219 @@
|
|||
'use client';
|
||||
import 'reflect-metadata';
|
||||
|
||||
import React, { FC, Fragment, useCallback, useMemo, useState } from 'react';
|
||||
import { useFetch } from '@gitroom/helpers/utils/custom.fetch';
|
||||
import useSWR from 'swr';
|
||||
import { useUser } from '@gitroom/frontend/components/layout/user.context';
|
||||
import { Button } from '@gitroom/react/form/button';
|
||||
import { useModals } from '@mantine/modals';
|
||||
import { TopTitle } from '@gitroom/frontend/components/launches/helpers/top.title.component';
|
||||
import { Input } from '@gitroom/react/form/input';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import { object, string } from 'yup';
|
||||
import { yupResolver } from '@hookform/resolvers/yup';
|
||||
import { Textarea } from '@gitroom/react/form/textarea';
|
||||
import { useToaster } from '@gitroom/react/toaster/toaster';
|
||||
import clsx from 'clsx';
|
||||
import { deleteDialog } from '@gitroom/react/helpers/delete.dialog';
|
||||
import { useT } from '@gitroom/react/translation/get.transation.service.client';
|
||||
import { AddEditModal } from '@gitroom/frontend/components/launches/add.edit.model';
|
||||
import dayjs from 'dayjs';
|
||||
|
||||
export const Sets: FC = () => {
|
||||
const fetch = useFetch();
|
||||
const user = useUser();
|
||||
const modal = useModals();
|
||||
const toaster = useToaster();
|
||||
|
||||
const load = useCallback(async (path: string) => {
|
||||
return (await (await fetch(path)).json()).integrations;
|
||||
}, []);
|
||||
|
||||
const { isLoading, data: integrations } = useSWR('/integrations/list', load, {
|
||||
fallbackData: [],
|
||||
});
|
||||
|
||||
const list = useCallback(async () => {
|
||||
return (await fetch('/sets')).json();
|
||||
}, []);
|
||||
|
||||
const { data, mutate } = useSWR('sets', list);
|
||||
|
||||
const addSet = useCallback(
|
||||
(data?: any) => () => {
|
||||
modal.openModal({
|
||||
closeOnClickOutside: false,
|
||||
closeOnEscape: false,
|
||||
withCloseButton: false,
|
||||
classNames: {
|
||||
modal: 'w-[100%] max-w-[1400px] bg-transparent text-textColor',
|
||||
},
|
||||
children: (
|
||||
<AddEditModal
|
||||
allIntegrations={integrations.map((p: any) => ({
|
||||
...p,
|
||||
}))}
|
||||
addEditSets={(data) => {
|
||||
console.log('save', data);
|
||||
}}
|
||||
reopenModal={() => {}}
|
||||
mutate={() => {}}
|
||||
integrations={integrations}
|
||||
date={dayjs()}
|
||||
/>
|
||||
),
|
||||
size: '80%',
|
||||
title: ``,
|
||||
});
|
||||
},
|
||||
[integrations]
|
||||
);
|
||||
|
||||
const deleteSet = useCallback(
|
||||
(data: any) => async () => {
|
||||
if (await deleteDialog(`Are you sure you want to delete ${data.name}?`)) {
|
||||
await fetch(`/sets/${data.id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
mutate();
|
||||
toaster.show('Set deleted successfully', 'success');
|
||||
}
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const t = useT();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<h3 className="text-[20px]">Sets ({data?.length || 0})</h3>
|
||||
<div className="text-customColor18 mt-[4px]">
|
||||
Manage your content sets for easy reuse across posts.
|
||||
</div>
|
||||
<div className="my-[16px] mt-[16px] bg-sixth border-fifth items-center border rounded-[4px] p-[24px] flex gap-[24px]">
|
||||
<div className="flex flex-col w-full">
|
||||
{!!data?.length && (
|
||||
<div className="grid grid-cols-[2fr,1fr,1fr] w-full gap-y-[10px]">
|
||||
<div>{t('name', 'Name')}</div>
|
||||
<div>{t('edit', 'Edit')}</div>
|
||||
<div>{t('delete', 'Delete')}</div>
|
||||
{data?.map((p: any) => (
|
||||
<Fragment key={p.id}>
|
||||
<div className="flex flex-col justify-center">{p.name}</div>
|
||||
<div className="flex flex-col justify-center">
|
||||
<div>
|
||||
<Button onClick={addSet(p)}>{t('edit', 'Edit')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col justify-center">
|
||||
<div>
|
||||
<Button onClick={deleteSet(p)}>
|
||||
{t('delete', 'Delete')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<Button
|
||||
onClick={addSet()}
|
||||
className={clsx((data?.length || 0) > 0 && 'my-[16px]')}
|
||||
>
|
||||
Add a set
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const details = object().shape({
|
||||
name: string().required(),
|
||||
content: string().required(),
|
||||
});
|
||||
|
||||
export const AddOrEditSet: FC<{
|
||||
data?: any;
|
||||
reload: () => void;
|
||||
}> = (props) => {
|
||||
const { data, reload } = props;
|
||||
const fetch = useFetch();
|
||||
const modal = useModals();
|
||||
const toast = useToaster();
|
||||
|
||||
const form = useForm({
|
||||
resolver: yupResolver(details),
|
||||
values: {
|
||||
name: data?.name || '',
|
||||
content: data?.content || '',
|
||||
},
|
||||
});
|
||||
|
||||
const callBack = useCallback(
|
||||
async (values: any) => {
|
||||
// TODO: Implement save functionality
|
||||
console.log('Save set functionality to be implemented', values);
|
||||
modal.closeAll();
|
||||
reload();
|
||||
},
|
||||
[data]
|
||||
);
|
||||
|
||||
const t = useT();
|
||||
|
||||
return (
|
||||
<FormProvider {...form}>
|
||||
<form onSubmit={form.handleSubmit(callBack)}>
|
||||
<div className="relative flex gap-[20px] flex-col flex-1 rounded-[4px] border border-customColor6 bg-sixth p-[16px] pt-0 w-[500px]">
|
||||
<TopTitle title={data ? 'Edit set' : 'Add set'} />
|
||||
<button
|
||||
className="outline-none absolute end-[20px] top-[15px] mantine-UnstyledButton-root mantine-ActionIcon-root hover:bg-tableBorder cursor-pointer mantine-Modal-close mantine-1dcetaa"
|
||||
type="button"
|
||||
onClick={modal.closeAll}
|
||||
>
|
||||
<svg
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="16"
|
||||
height="16"
|
||||
>
|
||||
<path
|
||||
d="M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z"
|
||||
fill="currentColor"
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div>
|
||||
<Input
|
||||
label="Name"
|
||||
translationKey="label_name"
|
||||
{...form.register('name')}
|
||||
/>
|
||||
<Textarea
|
||||
label="Content"
|
||||
translationKey="label_content"
|
||||
{...form.register('content')}
|
||||
/>
|
||||
<div className="flex gap-[10px]">
|
||||
<Button
|
||||
type="submit"
|
||||
className="mt-[24px]"
|
||||
disabled={!form.formState.isValid}
|
||||
>
|
||||
{t('save', 'Save')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</FormProvider>
|
||||
);
|
||||
};
|
||||
|
|
@ -35,6 +35,8 @@ import { SignatureRepository } from '@gitroom/nestjs-libraries/database/prisma/s
|
|||
import { SignatureService } from '@gitroom/nestjs-libraries/database/prisma/signatures/signature.service';
|
||||
import { AutopostRepository } from '@gitroom/nestjs-libraries/database/prisma/autopost/autopost.repository';
|
||||
import { AutopostService } from '@gitroom/nestjs-libraries/database/prisma/autopost/autopost.service';
|
||||
import { SetsService } from '@gitroom/nestjs-libraries/database/prisma/sets/sets.service';
|
||||
import { SetsRepository } from '@gitroom/nestjs-libraries/database/prisma/sets/sets.repository';
|
||||
|
||||
@Global()
|
||||
@Module({
|
||||
|
|
@ -78,6 +80,8 @@ import { AutopostService } from '@gitroom/nestjs-libraries/database/prisma/autop
|
|||
EmailService,
|
||||
TrackService,
|
||||
ShortLinkService,
|
||||
SetsService,
|
||||
SetsRepository,
|
||||
],
|
||||
get exports() {
|
||||
return this.providers;
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ model Organization {
|
|||
github GitHub[]
|
||||
subscription Subscription?
|
||||
Integration Integration[]
|
||||
post Post[] @relation("organization")
|
||||
submittedPost Post[] @relation("submittedForOrg")
|
||||
post Post[] @relation("organization")
|
||||
submittedPost Post[] @relation("submittedForOrg")
|
||||
allowTrial Boolean @default(false)
|
||||
Comments Comments[]
|
||||
notifications Notifications[]
|
||||
|
|
@ -37,18 +37,19 @@ model Organization {
|
|||
tags Tags[]
|
||||
signatures Signatures[]
|
||||
autoPost AutoPost[]
|
||||
sets Sets[]
|
||||
}
|
||||
|
||||
model Tags {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
color String
|
||||
orgId String
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
color String
|
||||
orgId String
|
||||
organization Organization @relation(fields: [orgId], references: [id])
|
||||
posts TagsPosts[]
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
posts TagsPosts[]
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([orgId])
|
||||
@@index([deletedAt])
|
||||
|
|
@ -56,9 +57,9 @@ model Tags {
|
|||
|
||||
model TagsPosts {
|
||||
postId String
|
||||
post Post @relation(fields: [postId], references: [id])
|
||||
post Post @relation(fields: [postId], references: [id])
|
||||
tagId String
|
||||
tag Tags @relation(fields: [tagId], references: [id])
|
||||
tag Tags @relation(fields: [tagId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
|
|
@ -67,39 +68,39 @@ model TagsPosts {
|
|||
}
|
||||
|
||||
model User {
|
||||
id String @id @default(uuid())
|
||||
email String
|
||||
password String?
|
||||
providerName Provider
|
||||
name String?
|
||||
lastName String?
|
||||
isSuperAdmin Boolean @default(false)
|
||||
bio String?
|
||||
audience Int @default(0)
|
||||
pictureId String?
|
||||
picture Media? @relation(fields: [pictureId], references: [id])
|
||||
providerId String?
|
||||
organizations UserOrganization[]
|
||||
timezone Int
|
||||
comments Comments[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
lastReadNotifications DateTime @default(now())
|
||||
inviteId String?
|
||||
activated Boolean @default(true)
|
||||
items ItemUser[]
|
||||
marketplace Boolean @default(true)
|
||||
account String?
|
||||
connectedAccount Boolean @default(false)
|
||||
groupBuyer MessagesGroup[] @relation("groupBuyer")
|
||||
groupSeller MessagesGroup[] @relation("groupSeller")
|
||||
orderBuyer Orders[] @relation("orderBuyer")
|
||||
orderSeller Orders[] @relation("orderSeller")
|
||||
payoutProblems PayoutProblems[]
|
||||
lastOnline DateTime @default(now())
|
||||
agencies SocialMediaAgency[]
|
||||
ip String?
|
||||
agent String?
|
||||
id String @id @default(uuid())
|
||||
email String
|
||||
password String?
|
||||
providerName Provider
|
||||
name String?
|
||||
lastName String?
|
||||
isSuperAdmin Boolean @default(false)
|
||||
bio String?
|
||||
audience Int @default(0)
|
||||
pictureId String?
|
||||
picture Media? @relation(fields: [pictureId], references: [id])
|
||||
providerId String?
|
||||
organizations UserOrganization[]
|
||||
timezone Int
|
||||
comments Comments[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
lastReadNotifications DateTime @default(now())
|
||||
inviteId String?
|
||||
activated Boolean @default(true)
|
||||
items ItemUser[]
|
||||
marketplace Boolean @default(true)
|
||||
account String?
|
||||
connectedAccount Boolean @default(false)
|
||||
groupBuyer MessagesGroup[] @relation("groupBuyer")
|
||||
groupSeller MessagesGroup[] @relation("groupSeller")
|
||||
orderBuyer Orders[] @relation("orderBuyer")
|
||||
orderSeller Orders[] @relation("orderSeller")
|
||||
payoutProblems PayoutProblems[]
|
||||
lastOnline DateTime @default(now())
|
||||
agencies SocialMediaAgency[]
|
||||
ip String?
|
||||
agent String?
|
||||
|
||||
@@unique([email, providerName])
|
||||
@@index([lastReadNotifications])
|
||||
|
|
@ -110,12 +111,12 @@ model User {
|
|||
}
|
||||
|
||||
model UsedCodes {
|
||||
id String @id @default(uuid())
|
||||
code String
|
||||
orgId String
|
||||
id String @id @default(uuid())
|
||||
code String
|
||||
orgId String
|
||||
organization Organization @relation(fields: [orgId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([code])
|
||||
}
|
||||
|
|
@ -164,16 +165,16 @@ model Trending {
|
|||
}
|
||||
|
||||
model TrendingLog {
|
||||
id String @id @default(uuid())
|
||||
language String?
|
||||
date DateTime
|
||||
id String @id @default(uuid())
|
||||
language String?
|
||||
date DateTime
|
||||
}
|
||||
|
||||
model ItemUser {
|
||||
id String @id @default(uuid())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
key String
|
||||
id String @id @default(uuid())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String
|
||||
key String
|
||||
|
||||
@@index([userId])
|
||||
@@index([key])
|
||||
|
|
@ -195,13 +196,13 @@ model Star {
|
|||
}
|
||||
|
||||
model Media {
|
||||
id String @id @default(uuid())
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
path String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
organizationId String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
userPicture User[]
|
||||
agencies SocialMediaAgency[]
|
||||
deletedAt DateTime?
|
||||
|
|
@ -210,31 +211,31 @@ model Media {
|
|||
}
|
||||
|
||||
model SocialMediaAgency {
|
||||
id String @id @default(uuid())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String @unique()
|
||||
name String
|
||||
logoId String?
|
||||
logo Media? @relation(fields: [logoId], references: [id])
|
||||
website String?
|
||||
slug String?
|
||||
id String @id @default(uuid())
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
userId String @unique()
|
||||
name String
|
||||
logoId String?
|
||||
logo Media? @relation(fields: [logoId], references: [id])
|
||||
website String?
|
||||
slug String?
|
||||
|
||||
facebook String?
|
||||
instagram String?
|
||||
twitter String?
|
||||
linkedIn String?
|
||||
youtube String?
|
||||
tiktok String?
|
||||
otherSocialMedia String?
|
||||
facebook String?
|
||||
instagram String?
|
||||
twitter String?
|
||||
linkedIn String?
|
||||
youtube String?
|
||||
tiktok String?
|
||||
otherSocialMedia String?
|
||||
|
||||
shortDescription String
|
||||
description String
|
||||
niches SocialMediaAgencyNiche[]
|
||||
approved Boolean @default(false)
|
||||
shortDescription String
|
||||
description String
|
||||
niches SocialMediaAgencyNiche[]
|
||||
approved Boolean @default(false)
|
||||
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@index([userId])
|
||||
@@index([deletedAt])
|
||||
|
|
@ -242,85 +243,85 @@ model SocialMediaAgency {
|
|||
}
|
||||
|
||||
model SocialMediaAgencyNiche {
|
||||
agencyId String
|
||||
agency SocialMediaAgency @relation(fields: [agencyId], references: [id])
|
||||
niche String
|
||||
agencyId String
|
||||
agency SocialMediaAgency @relation(fields: [agencyId], references: [id])
|
||||
niche String
|
||||
|
||||
@@id([agencyId, niche])
|
||||
}
|
||||
|
||||
model Credits {
|
||||
id String @id @default(uuid())
|
||||
id String @id @default(uuid())
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
organizationId String
|
||||
credits Int
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId])
|
||||
@@index([createdAt])
|
||||
}
|
||||
|
||||
model Subscription {
|
||||
id String @id @default(cuid())
|
||||
organizationId String @unique
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
subscriptionTier SubscriptionTier
|
||||
identifier String?
|
||||
cancelAt DateTime?
|
||||
period Period
|
||||
totalChannels Int
|
||||
isLifetime Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
id String @id @default(cuid())
|
||||
organizationId String @unique
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
subscriptionTier SubscriptionTier
|
||||
identifier String?
|
||||
cancelAt DateTime?
|
||||
period Period
|
||||
totalChannels Int
|
||||
isLifetime Boolean @default(false)
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@index([organizationId])
|
||||
@@index([deletedAt])
|
||||
}
|
||||
|
||||
model Customer {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
orgId String
|
||||
organization Organization @relation(fields: [orgId], references: [id])
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
orgId String
|
||||
organization Organization @relation(fields: [orgId], references: [id])
|
||||
integrations Integration[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@unique([orgId, name, deletedAt])
|
||||
}
|
||||
|
||||
model Integration {
|
||||
id String @id @default(cuid())
|
||||
id String @id @default(cuid())
|
||||
internalId String
|
||||
organizationId String
|
||||
name String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
picture String?
|
||||
providerIdentifier String
|
||||
type String
|
||||
token String
|
||||
disabled Boolean @default(false)
|
||||
disabled Boolean @default(false)
|
||||
tokenExpiration DateTime?
|
||||
refreshToken String?
|
||||
posts Post[]
|
||||
profile String?
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime? @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime? @updatedAt
|
||||
orderItems OrderItems[]
|
||||
inBetweenSteps Boolean @default(false)
|
||||
refreshNeeded Boolean @default(false)
|
||||
postingTimes String @default("[{\"time\":120}, {\"time\":400}, {\"time\":700}]")
|
||||
inBetweenSteps Boolean @default(false)
|
||||
refreshNeeded Boolean @default(false)
|
||||
postingTimes String @default("[{\"time\":120}, {\"time\":400}, {\"time\":700}]")
|
||||
customInstanceDetails String?
|
||||
customerId String?
|
||||
customer Customer? @relation(fields: [customerId], references: [id])
|
||||
customer Customer? @relation(fields: [customerId], references: [id])
|
||||
plugs Plugs[]
|
||||
exisingPlugData ExisingPlugData[]
|
||||
rootInternalId String?
|
||||
additionalSettings String? @default("[]")
|
||||
additionalSettings String? @default("[]")
|
||||
webhooks IntegrationsWebhooks[]
|
||||
|
||||
@@index([rootInternalId])
|
||||
|
|
@ -331,14 +332,14 @@ model Integration {
|
|||
}
|
||||
|
||||
model Signatures {
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
content String
|
||||
autoAdd Boolean
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
content String
|
||||
autoAdd Boolean
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([organizationId])
|
||||
|
|
@ -346,17 +347,17 @@ model Signatures {
|
|||
}
|
||||
|
||||
model Comments {
|
||||
id String @id @default(uuid())
|
||||
content String
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
postId String
|
||||
post Post @relation(fields: [postId], references: [id])
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
id String @id @default(uuid())
|
||||
content String
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
postId String
|
||||
post Post @relation(fields: [postId], references: [id])
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([organizationId])
|
||||
|
|
@ -366,39 +367,39 @@ model Comments {
|
|||
}
|
||||
|
||||
model Post {
|
||||
id String @id @default(cuid())
|
||||
state State @default(QUEUE)
|
||||
publishDate DateTime
|
||||
organizationId String
|
||||
integrationId String
|
||||
content String
|
||||
group String
|
||||
organization Organization @relation("organization", fields: [organizationId], references: [id])
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
title String?
|
||||
description String?
|
||||
parentPostId String?
|
||||
releaseId String?
|
||||
releaseURL String?
|
||||
settings String?
|
||||
parentPost Post? @relation("parentPostId", fields: [parentPostId], references: [id])
|
||||
childrenPost Post[] @relation("parentPostId")
|
||||
image String?
|
||||
submittedForOrderId String?
|
||||
submittedForOrder Orders? @relation(fields: [submittedForOrderId], references: [id])
|
||||
id String @id @default(cuid())
|
||||
state State @default(QUEUE)
|
||||
publishDate DateTime
|
||||
organizationId String
|
||||
integrationId String
|
||||
content String
|
||||
group String
|
||||
organization Organization @relation("organization", fields: [organizationId], references: [id])
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
title String?
|
||||
description String?
|
||||
parentPostId String?
|
||||
releaseId String?
|
||||
releaseURL String?
|
||||
settings String?
|
||||
parentPost Post? @relation("parentPostId", fields: [parentPostId], references: [id])
|
||||
childrenPost Post[] @relation("parentPostId")
|
||||
image String?
|
||||
submittedForOrderId String?
|
||||
submittedForOrder Orders? @relation(fields: [submittedForOrderId], references: [id])
|
||||
submittedForOrganizationId String?
|
||||
submittedForOrganization Organization? @relation("submittedForOrg", fields: [submittedForOrganizationId], references: [id])
|
||||
approvedSubmitForOrder APPROVED_SUBMIT_FOR_ORDER @default(NO)
|
||||
lastMessageId String?
|
||||
lastMessage Messages? @relation(fields: [lastMessageId], references: [id])
|
||||
intervalInDays Int?
|
||||
payoutProblems PayoutProblems[]
|
||||
comments Comments[]
|
||||
tags TagsPosts[]
|
||||
error String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
submittedForOrganization Organization? @relation("submittedForOrg", fields: [submittedForOrganizationId], references: [id])
|
||||
approvedSubmitForOrder APPROVED_SUBMIT_FOR_ORDER @default(NO)
|
||||
lastMessageId String?
|
||||
lastMessage Messages? @relation(fields: [lastMessageId], references: [id])
|
||||
intervalInDays Int?
|
||||
payoutProblems PayoutProblems[]
|
||||
comments Comments[]
|
||||
tags TagsPosts[]
|
||||
error String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@index([group])
|
||||
@@index([deletedAt])
|
||||
|
|
@ -417,14 +418,14 @@ model Post {
|
|||
}
|
||||
|
||||
model Notifications {
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
content String
|
||||
link String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
content String
|
||||
link String?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@index([createdAt])
|
||||
@@index([organizationId])
|
||||
|
|
@ -432,17 +433,17 @@ model Notifications {
|
|||
}
|
||||
|
||||
model MessagesGroup {
|
||||
id String @id @default(uuid())
|
||||
id String @id @default(uuid())
|
||||
buyerOrganizationId String
|
||||
buyerOrganization Organization @relation(fields: [buyerOrganizationId], references: [id])
|
||||
buyerId String
|
||||
buyer User @relation("groupBuyer", fields: [buyerId], references: [id])
|
||||
buyer User @relation("groupBuyer", fields: [buyerId], references: [id])
|
||||
sellerId String
|
||||
seller User @relation("groupSeller", fields: [sellerId], references: [id])
|
||||
seller User @relation("groupSeller", fields: [sellerId], references: [id])
|
||||
messages Messages[]
|
||||
orders Orders[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@unique([buyerId, sellerId])
|
||||
@@index([createdAt])
|
||||
|
|
@ -451,34 +452,34 @@ model MessagesGroup {
|
|||
}
|
||||
|
||||
model PayoutProblems {
|
||||
id String @id @default(uuid())
|
||||
status String
|
||||
orderId String
|
||||
order Orders @relation(fields: [orderId], references: [id])
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
postId String?
|
||||
post Post? @relation(fields: [postId], references: [id])
|
||||
amount Int
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id String @id @default(uuid())
|
||||
status String
|
||||
orderId String
|
||||
order Orders @relation(fields: [orderId], references: [id])
|
||||
userId String
|
||||
user User @relation(fields: [userId], references: [id])
|
||||
postId String?
|
||||
post Post? @relation(fields: [postId], references: [id])
|
||||
amount Int
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model Orders {
|
||||
id String @id @default(uuid())
|
||||
buyerId String
|
||||
sellerId String
|
||||
posts Post[]
|
||||
buyer User @relation("orderBuyer", fields: [buyerId], references: [id])
|
||||
seller User @relation("orderSeller", fields: [sellerId], references: [id])
|
||||
status OrderStatus
|
||||
ordersItems OrderItems[]
|
||||
messageGroupId String
|
||||
messageGroup MessagesGroup @relation(fields: [messageGroupId], references: [id])
|
||||
captureId String?
|
||||
payoutProblems PayoutProblems[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id String @id @default(uuid())
|
||||
buyerId String
|
||||
sellerId String
|
||||
posts Post[]
|
||||
buyer User @relation("orderBuyer", fields: [buyerId], references: [id])
|
||||
seller User @relation("orderSeller", fields: [sellerId], references: [id])
|
||||
status OrderStatus
|
||||
ordersItems OrderItems[]
|
||||
messageGroupId String
|
||||
messageGroup MessagesGroup @relation(fields: [messageGroupId], references: [id])
|
||||
captureId String?
|
||||
payoutProblems PayoutProblems[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([buyerId])
|
||||
@@index([sellerId])
|
||||
|
|
@ -488,29 +489,29 @@ model Orders {
|
|||
}
|
||||
|
||||
model OrderItems {
|
||||
id String @id @default(uuid())
|
||||
orderId String
|
||||
order Orders @relation(fields: [orderId], references: [id])
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
quantity Int
|
||||
price Int
|
||||
id String @id @default(uuid())
|
||||
orderId String
|
||||
order Orders @relation(fields: [orderId], references: [id])
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
quantity Int
|
||||
price Int
|
||||
|
||||
@@index([orderId])
|
||||
@@index([integrationId])
|
||||
}
|
||||
|
||||
model Messages {
|
||||
id String @id @default(uuid())
|
||||
from From
|
||||
content String?
|
||||
groupId String
|
||||
group MessagesGroup @relation(fields: [groupId], references: [id])
|
||||
special String?
|
||||
posts Post[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
id String @id @default(uuid())
|
||||
from From
|
||||
content String?
|
||||
groupId String
|
||||
group MessagesGroup @relation(fields: [groupId], references: [id])
|
||||
special String?
|
||||
posts Post[]
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
deletedAt DateTime?
|
||||
|
||||
@@index([groupId])
|
||||
@@index([createdAt])
|
||||
|
|
@ -518,44 +519,44 @@ model Messages {
|
|||
}
|
||||
|
||||
model Plugs {
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
plugFunction String
|
||||
data String
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
activated Boolean @default(true)
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
plugFunction String
|
||||
data String
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
activated Boolean @default(true)
|
||||
|
||||
@@unique([plugFunction, integrationId])
|
||||
@@index([organizationId])
|
||||
}
|
||||
|
||||
model ExisingPlugData {
|
||||
id String @id @default(uuid())
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
methodName String
|
||||
value String
|
||||
id String @id @default(uuid())
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
methodName String
|
||||
value String
|
||||
|
||||
@@unique([integrationId, methodName, value])
|
||||
}
|
||||
|
||||
model PopularPosts {
|
||||
id String @id @default(uuid())
|
||||
category String
|
||||
topic String
|
||||
content String
|
||||
hook String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
id String @id @default(uuid())
|
||||
category String
|
||||
topic String
|
||||
content String
|
||||
hook String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
}
|
||||
|
||||
model IntegrationsWebhooks {
|
||||
integrationId String
|
||||
integration Integration @relation(fields: [integrationId], references: [id])
|
||||
webhookId String
|
||||
webhook Webhooks @relation(fields: [webhookId], references: [id])
|
||||
webhook Webhooks @relation(fields: [webhookId], references: [id])
|
||||
|
||||
@@unique([integrationId, webhookId])
|
||||
@@id([integrationId, webhookId])
|
||||
|
|
@ -564,22 +565,22 @@ model IntegrationsWebhooks {
|
|||
}
|
||||
|
||||
model Webhooks {
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
id String @id @default(uuid())
|
||||
name String
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
integrations IntegrationsWebhooks[]
|
||||
url String
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
integrations IntegrationsWebhooks[]
|
||||
url String
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId])
|
||||
@@index([deletedAt])
|
||||
}
|
||||
|
||||
model AutoPost {
|
||||
id String @id @default(uuid())
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
title String
|
||||
|
|
@ -593,12 +594,24 @@ model AutoPost {
|
|||
generateContent Boolean
|
||||
integrations String
|
||||
deletedAt DateTime?
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([deletedAt])
|
||||
}
|
||||
|
||||
model Sets {
|
||||
id String @id @default(uuid())
|
||||
organizationId String
|
||||
organization Organization @relation(fields: [organizationId], references: [id])
|
||||
name String
|
||||
content String
|
||||
createdAt DateTime @default(now())
|
||||
updatedAt DateTime @updatedAt
|
||||
|
||||
@@index([organizationId])
|
||||
}
|
||||
|
||||
enum OrderStatus {
|
||||
PENDING
|
||||
ACCEPTED
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
import { PrismaRepository } from '@gitroom/nestjs-libraries/database/prisma/prisma.service';
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { SetsDto } from '@gitroom/nestjs-libraries/dtos/sets/sets.dto';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
@Injectable()
|
||||
export class SetsRepository {
|
||||
constructor(private _sets: PrismaRepository<'sets'>) {}
|
||||
|
||||
getTotal(orgId: string) {
|
||||
return this._sets.model.sets.count({
|
||||
where: {
|
||||
organizationId: orgId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
getSets(orgId: string) {
|
||||
return this._sets.model.sets.findMany({
|
||||
where: {
|
||||
organizationId: orgId,
|
||||
},
|
||||
orderBy: {
|
||||
createdAt: 'desc',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
deleteSet(orgId: string, id: string) {
|
||||
return this._sets.model.sets.delete({
|
||||
where: {
|
||||
id,
|
||||
organizationId: orgId,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async createSet(orgId: string, body: SetsDto) {
|
||||
const { id } = await this._sets.model.sets.upsert({
|
||||
where: {
|
||||
id: body.id || uuidv4(),
|
||||
organizationId: orgId,
|
||||
},
|
||||
create: {
|
||||
id: body.id || uuidv4(),
|
||||
organizationId: orgId,
|
||||
name: body.name,
|
||||
content: body.content,
|
||||
},
|
||||
update: {
|
||||
name: body.name,
|
||||
content: body.content,
|
||||
},
|
||||
});
|
||||
|
||||
return { id };
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
import { Injectable } from '@nestjs/common';
|
||||
import { SetsRepository } from '@gitroom/nestjs-libraries/database/prisma/sets/sets.repository';
|
||||
import { SetsDto } from '@gitroom/nestjs-libraries/dtos/sets/sets.dto';
|
||||
|
||||
@Injectable()
|
||||
export class SetsService {
|
||||
constructor(private _setsRepository: SetsRepository) {}
|
||||
|
||||
getTotal(orgId: string) {
|
||||
return this._setsRepository.getTotal(orgId);
|
||||
}
|
||||
|
||||
getSets(orgId: string) {
|
||||
return this._setsRepository.getSets(orgId);
|
||||
}
|
||||
|
||||
createSet(orgId: string, body: SetsDto) {
|
||||
return this._setsRepository.createSet(orgId, body);
|
||||
}
|
||||
|
||||
deleteSet(orgId: string, id: string) {
|
||||
return this._setsRepository.deleteSet(orgId, id);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
import { IsDefined, IsOptional, IsString } from 'class-validator';
|
||||
|
||||
export class SetsDto {
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
id?: string;
|
||||
|
||||
@IsString()
|
||||
@IsDefined()
|
||||
name: string;
|
||||
|
||||
@IsString()
|
||||
@IsDefined()
|
||||
content: string;
|
||||
}
|
||||
|
||||
export class UpdateSetsDto {
|
||||
@IsString()
|
||||
@IsDefined()
|
||||
id: string;
|
||||
|
||||
@IsString()
|
||||
@IsDefined()
|
||||
name: string;
|
||||
|
||||
@IsString()
|
||||
@IsDefined()
|
||||
content: string;
|
||||
}
|
||||
|
|
@ -483,5 +483,6 @@
|
|||
"start_7_days_free_trial": "Start 7 days free trial",
|
||||
"change_language": "Change Language",
|
||||
"that_a_wrap": "That's a wrap!\n\nIf you enjoyed this thread:\n\n1. Follow me @{{username}} for more of these\n2. RT the tweet below to share this thread with your audience\n",
|
||||
"post_as_images_carousel": "Post as images carousel"
|
||||
"post_as_images_carousel": "Post as images carousel",
|
||||
"save_set": "Save Set"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue