Skip to content

Commit ed93eab

Browse files
authored
Merge pull request #603 from gitroomhq/feat/repeated-post
Add a repeated post
2 parents d51e560 + 83c7f75 commit ed93eab

File tree

7 files changed

+128
-24
lines changed

7 files changed

+128
-24
lines changed

apps/frontend/src/components/launches/add.edit.model.tsx

+6
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ import { LoadingComponent } from '@gitroom/frontend/components/layout/loading';
5858
import { DropFiles } from '@gitroom/frontend/components/layout/drop.files';
5959
import { SelectCustomer } from '@gitroom/frontend/components/launches/select.customer';
6060
import { TagsComponent } from './tags.component';
61+
import { RepeatComponent } from '@gitroom/frontend/components/launches/repeat.component';
6162

6263
function countCharacters(text: string, type: string): number {
6364
if (type !== 'x') {
@@ -140,6 +141,8 @@ export const AddEditModal: FC<{
140141
// are we in edit mode?
141142
const existingData = useExistingData();
142143

144+
const [inter, setInter] = useState(existingData?.posts?.[0]?.intervalInDays);
145+
143146
const [tags, setTags] = useState<any[]>(
144147
// @ts-ignore
145148
existingData?.posts?.[0]?.tags?.map((p: any) => ({
@@ -394,6 +397,7 @@ export const AddEditModal: FC<{
394397
body: JSON.stringify({
395398
...(postFor ? { order: postFor.id } : {}),
396399
type,
400+
inter,
397401
tags,
398402
shortLink,
399403
date: dateState.utc().format('YYYY-MM-DDTHH:mm:ss'),
@@ -418,6 +422,7 @@ export const AddEditModal: FC<{
418422
modal.closeAll();
419423
},
420424
[
425+
inter,
421426
postFor,
422427
dateState,
423428
value,
@@ -566,6 +571,7 @@ export const AddEditModal: FC<{
566571
setSelectedIntegrations([]);
567572
}}
568573
/>
574+
<RepeatComponent repeat={inter} onChange={setInter} />
569575
<DatePicker onChange={setDateState} date={dateState} />
570576
{!selectedIntegrations.length && (
571577
<svg

apps/frontend/src/components/launches/calendar.tsx

+6-1
Original file line numberDiff line numberDiff line change
@@ -420,8 +420,13 @@ export const CalendarColumn: FC<{
420420
);
421421

422422
const editPost = useCallback(
423-
(post: Post & { integration: Integration }, isDuplicate?: boolean) =>
423+
(loadPost: Post & { integration: Integration }, isDuplicate?: boolean) =>
424424
async () => {
425+
const post = {
426+
...loadPost,
427+
// @ts-ignore
428+
publishDate: loadPost.actualDate || loadPost.publishDate,
429+
};
425430
if (user?.orgId === post.submittedForOrganizationId) {
426431
return previewPublication(post);
427432
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { FC } from 'react';
2+
import { Select } from '@gitroom/react/form/select';
3+
4+
const list = [
5+
{ value: 1, label: 'Every Day' },
6+
{ value: 2, label: 'Every Two Days' },
7+
{ value: 3, label: 'Every Three Days' },
8+
{ value: 4, label: 'Every Four Days' },
9+
{ value: 5, label: 'Every Five Days' },
10+
{ value: 6, label: 'Every Six Days' },
11+
{ value: 7, label: 'Every Week' },
12+
{ value: 14, label: 'Every Two Weeks' },
13+
{ value: 30, label: 'Every Month' },
14+
];
15+
16+
export const RepeatComponent: FC<{ repeat: number|null, onChange: (newVal: number) => void }> = (props) => {
17+
const { repeat } = props;
18+
return (
19+
<Select
20+
disableForm={true}
21+
label=""
22+
hideErrors={true}
23+
name="repeat"
24+
value={repeat ? repeat : undefined}
25+
onChange={(e) => props.onChange(Number(e.target.value))}
26+
>
27+
<option>Repeat Post Every...</option>
28+
{list.map((item) => (
29+
<option key={item.value} value={item.value}>
30+
{item.label}
31+
</option>
32+
))}
33+
</Select>
34+
);
35+
};

libraries/nestjs-libraries/src/database/prisma/posts/posts.repository.ts

+54-10
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,15 @@ import { GetPostsDto } from '@gitroom/nestjs-libraries/dtos/posts/get.posts.dto'
66
import dayjs from 'dayjs';
77
import isoWeek from 'dayjs/plugin/isoWeek';
88
import weekOfYear from 'dayjs/plugin/weekOfYear';
9+
import isSameOrAfter from 'dayjs/plugin/isSameOrAfter';
10+
import utc from 'dayjs/plugin/utc';
911
import { v4 as uuidv4 } from 'uuid';
1012
import { CreateTagDto } from '@gitroom/nestjs-libraries/dtos/posts/create.tag.dto';
1113

1214
dayjs.extend(isoWeek);
1315
dayjs.extend(weekOfYear);
16+
dayjs.extend(isSameOrAfter);
17+
dayjs.extend(utc);
1418

1519
@Injectable()
1620
export class PostsRepository {
@@ -80,7 +84,7 @@ export class PostsRepository {
8084
});
8185
}
8286

83-
getPosts(orgId: string, query: GetPostsDto) {
87+
async getPosts(orgId: string, query: GetPostsDto) {
8488
const dateYear = dayjs().year(query.year);
8589
const date =
8690
query.display === 'day'
@@ -108,20 +112,35 @@ export class PostsRepository {
108112
.add(2, 'hours')
109113
.toDate();
110114

111-
return this._post.model.post.findMany({
115+
const list = await this._post.model.post.findMany({
112116
where: {
113-
OR: [
117+
AND: [
114118
{
115-
organizationId: orgId,
119+
OR: [
120+
{
121+
organizationId: orgId,
122+
},
123+
{
124+
submittedForOrganizationId: orgId,
125+
},
126+
],
116127
},
117128
{
118-
submittedForOrganizationId: orgId,
129+
OR: [
130+
{
131+
publishDate: {
132+
gte: startDate,
133+
lte: endDate,
134+
},
135+
},
136+
{
137+
intervalInDays: {
138+
not: null,
139+
},
140+
},
141+
],
119142
},
120143
],
121-
publishDate: {
122-
gte: startDate,
123-
lte: endDate,
124-
},
125144
deletedAt: null,
126145
parentPostId: null,
127146
...(query.customer
@@ -140,6 +159,7 @@ export class PostsRepository {
140159
submittedForOrganizationId: true,
141160
submittedForOrderId: true,
142161
state: true,
162+
intervalInDays: true,
143163
tags: {
144164
select: {
145165
tag: true,
@@ -155,6 +175,28 @@ export class PostsRepository {
155175
},
156176
},
157177
});
178+
179+
return list.reduce((all, post) => {
180+
if (!post.intervalInDays) {
181+
return [...all, post];
182+
}
183+
184+
const addMorePosts = [];
185+
let startingDate = dayjs.utc(post.publishDate);
186+
while (dayjs.utc(endDate).isSameOrAfter(startingDate)) {
187+
if (dayjs(startingDate).isSameOrAfter(dayjs.utc(post.publishDate))) {
188+
addMorePosts.push({
189+
...post,
190+
publishDate: startingDate.toDate(),
191+
actualDate: post.publishDate,
192+
});
193+
}
194+
195+
startingDate = startingDate.add(post.intervalInDays, 'days');
196+
}
197+
198+
return [...all, ...addMorePosts];
199+
}, [] as any[]);
158200
}
159201

160202
async deletePost(orgId: string, group: string) {
@@ -272,7 +314,8 @@ export class PostsRepository {
272314
orgId: string,
273315
date: string,
274316
body: PostBody,
275-
tags: { value: string; label: string }[]
317+
tags: { value: string; label: string }[],
318+
inter?: number,
276319
) {
277320
const posts: Post[] = [];
278321
const uuid = uuidv4();
@@ -303,6 +346,7 @@ export class PostsRepository {
303346
: {}),
304347
content: value.content,
305348
group: uuid,
349+
intervalInDays: inter ? +inter : null,
306350
approvedSubmitForOrder: APPROVED_SUBMIT_FOR_ORDER.NO,
307351
state: state === 'draft' ? ('DRAFT' as const) : ('QUEUE' as const),
308352
image: JSON.stringify(value.image),

libraries/nestjs-libraries/src/database/prisma/posts/posts.service.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export class PostsService {
8888
];
8989
}
9090

91-
getPosts(orgId: string, query: GetPostsDto) {
91+
async getPosts(orgId: string, query: GetPostsDto) {
9292
return this._postRepository.getPosts(orgId, query);
9393
}
9494

@@ -205,6 +205,18 @@ export class PostsService {
205205
return;
206206
}
207207

208+
if (firstPost?.intervalInDays) {
209+
this._workerServiceProducer.emit('post', {
210+
id,
211+
options: {
212+
delay: firstPost.intervalInDays * 86400000,
213+
},
214+
payload: {
215+
id: id,
216+
},
217+
});
218+
}
219+
208220
if (firstPost.submittedForOrderId) {
209221
this._workerServiceProducer.emit('submit', {
210222
payload: {
@@ -597,7 +609,8 @@ export class PostsService {
597609
? dayjs().format('YYYY-MM-DDTHH:mm:00')
598610
: body.date,
599611
post,
600-
body.tags
612+
body.tags,
613+
body.inter,
601614
);
602615

603616
if (!posts?.length) {
@@ -633,6 +646,10 @@ export class PostsService {
633646
},
634647
payload: {
635648
id: posts[0].id,
649+
delay:
650+
body.type === 'now'
651+
? 0
652+
: dayjs(posts[0].publishDate).diff(dayjs(), 'millisecond'),
636653
},
637654
});
638655
}
@@ -666,6 +683,7 @@ export class PostsService {
666683
},
667684
payload: {
668685
id: id,
686+
delay: dayjs(date).diff(dayjs(), 'millisecond'),
669687
},
670688
});
671689
}

libraries/nestjs-libraries/src/database/prisma/schema.prisma

+2
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ model Post {
374374
approvedSubmitForOrder APPROVED_SUBMIT_FOR_ORDER @default(NO)
375375
lastMessageId String?
376376
lastMessage Messages? @relation(fields: [lastMessageId], references: [id])
377+
intervalInDays Int?
377378
payoutProblems PayoutProblems[]
378379
comments Comments[]
379380
tags TagsPosts[]
@@ -389,6 +390,7 @@ model Post {
389390
@@index([organizationId])
390391
@@index([parentPostId])
391392
@@index([submittedForOrderId])
393+
@@index([intervalInDays])
392394
@@index([approvedSubmitForOrder])
393395
@@index([lastMessageId])
394396
@@index([createdAt])

libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts

+5-11
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,5 @@
11
import {
2-
ArrayMinSize,
3-
IsArray,
4-
IsBoolean,
5-
IsDateString,
6-
IsDefined,
7-
IsIn,
8-
IsOptional,
9-
IsString,
10-
MinLength,
11-
ValidateIf,
12-
ValidateNested,
2+
ArrayMinSize, IsArray, IsBoolean, IsDateString, IsDefined, IsIn, IsNumber, IsOptional, IsString, MinLength, ValidateIf, ValidateNested
133
} from 'class-validator';
144
import { Type } from 'class-transformer';
155
import { DevToSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/dev.to.settings.dto';
@@ -113,6 +103,10 @@ export class CreatePostDto {
113103
@IsBoolean()
114104
shortLink: boolean;
115105

106+
@IsOptional()
107+
@IsNumber()
108+
inter?: number;
109+
116110
@IsDefined()
117111
@IsDateString()
118112
date: string;

0 commit comments

Comments
 (0)