delete/archive implemented
This commit is contained in:
1 parent
89b8687431
commit
9ca05f5ea1
13 files changed
+680
-163
No files matched your search
@@ -5,7 +5,13 @@ import { lastValueFrom } from 'rxjs';
|
||||
import { ArticlesService } from './articles.service';
|
||||
import { LiveBlogService } from './live-blog.service';
|
||||
import { CreateArticleDto, CreateLiveBlogDto } from './articles.dto';
|
||||
import { ArticleStatus, LiveBlogStatus, ImagePosition, ImageSize, VideoPosition } from './entities';
|
||||
import {
|
||||
ArticleStatus,
|
||||
LiveBlogStatus,
|
||||
ImagePosition,
|
||||
ImageSize,
|
||||
VideoPosition,
|
||||
} from './entities';
|
||||
|
||||
interface StrapiArticle {
|
||||
id: number;
|
||||
@@ -88,18 +94,18 @@ export class StrapiService {
|
||||
private extractImageUrl(strapiArticle: StrapiArticle): string | undefined {
|
||||
// Try to get image from img field first (single image)
|
||||
let imageUrl: string | undefined;
|
||||
|
||||
|
||||
if (strapiArticle.img?.url) {
|
||||
imageUrl = strapiArticle.img.url;
|
||||
} else if (strapiArticle.media?.[0]?.url) {
|
||||
// Try to get first image from media field (multiple images)
|
||||
imageUrl = strapiArticle.media[0].url;
|
||||
}
|
||||
|
||||
|
||||
if (!imageUrl) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
// If URL is relative, prepend Strapi base URL
|
||||
if (imageUrl.startsWith('/')) {
|
||||
// Convert Docker service URL to localhost for frontend access
|
||||
@@ -107,25 +113,27 @@ export class StrapiService {
|
||||
const frontendStrapiUrl = this.strapiUrl.replace('cms:', 'localhost:');
|
||||
return `${frontendStrapiUrl}${imageUrl}`;
|
||||
}
|
||||
|
||||
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
private extractLiveBlogImageUrl(strapiLiveBlog: StrapiLiveBlog): string | undefined {
|
||||
private extractLiveBlogImageUrl(
|
||||
strapiLiveBlog: StrapiLiveBlog,
|
||||
): string | undefined {
|
||||
// Try to get image from img field first (single image)
|
||||
let imageUrl: string | undefined;
|
||||
|
||||
|
||||
if (strapiLiveBlog.img?.url) {
|
||||
imageUrl = strapiLiveBlog.img.url;
|
||||
} else if (strapiLiveBlog.media?.[0]?.url) {
|
||||
// Try to get first image from media field (multiple images)
|
||||
imageUrl = strapiLiveBlog.media[0].url;
|
||||
}
|
||||
|
||||
|
||||
if (!imageUrl) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
|
||||
// If URL is relative, prepend Strapi base URL
|
||||
if (imageUrl.startsWith('/')) {
|
||||
// Convert Docker service URL to localhost for frontend access
|
||||
@@ -133,7 +141,7 @@ export class StrapiService {
|
||||
const frontendStrapiUrl = this.strapiUrl.replace('cms:', 'localhost:');
|
||||
return `${frontendStrapiUrl}${imageUrl}`;
|
||||
}
|
||||
|
||||
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
@@ -141,7 +149,7 @@ export class StrapiService {
|
||||
try {
|
||||
this.logger.log('Starting articles sync from Strapi...');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
const response = await lastValueFrom(
|
||||
this.httpService.get<StrapiResponse<StrapiArticle[]>>(
|
||||
`${this.strapiUrl}/api/articles?populate=*`,
|
||||
{
|
||||
@@ -155,7 +163,7 @@ export class StrapiService {
|
||||
|
||||
for (const strapiArticle of strapiArticles) {
|
||||
const imageUrl = this.extractImageUrl(strapiArticle);
|
||||
|
||||
|
||||
const articleData: Partial<CreateArticleDto> = {
|
||||
title: strapiArticle.title,
|
||||
excerpt: strapiArticle.description,
|
||||
@@ -166,10 +174,12 @@ export class StrapiService {
|
||||
: ArticleStatus.DRAFT,
|
||||
tags: [],
|
||||
featuredImage: imageUrl,
|
||||
imagePosition: (strapiArticle.imagePosition || 'top') as ImagePosition,
|
||||
imagePosition: (strapiArticle.imagePosition ||
|
||||
'top') as ImagePosition,
|
||||
imageSize: (strapiArticle.imageSize || 'medium') as ImageSize,
|
||||
videoUrl: strapiArticle.videoUrl || '',
|
||||
videoPosition: (strapiArticle.videoPosition || 'inline') as VideoPosition,
|
||||
videoPosition: (strapiArticle.videoPosition ||
|
||||
'inline') as VideoPosition,
|
||||
videoCaption: strapiArticle.videoCaption || '',
|
||||
};
|
||||
|
||||
@@ -191,12 +201,19 @@ export class StrapiService {
|
||||
|
||||
async syncSingleArticle(
|
||||
strapiId: string,
|
||||
event?: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish' | 'entry.unpublish',
|
||||
event?:
|
||||
| 'entry.create'
|
||||
| 'entry.update'
|
||||
| 'entry.delete'
|
||||
| 'entry.publish'
|
||||
| 'entry.unpublish',
|
||||
): Promise<void> {
|
||||
try {
|
||||
this.logger.log(`Syncing single article from Strapi: ${strapiId}, event: ${event}`);
|
||||
this.logger.log(
|
||||
`Syncing single article from Strapi: ${strapiId}, event: ${event}`,
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(
|
||||
const response = await lastValueFrom(
|
||||
this.httpService.get<StrapiResponse<StrapiArticle>>(
|
||||
`${this.strapiUrl}/api/articles/${strapiId}?populate=*`,
|
||||
{
|
||||
@@ -206,7 +223,7 @@ export class StrapiService {
|
||||
);
|
||||
|
||||
const strapiArticle = response.data.data;
|
||||
|
||||
|
||||
// Determine status based on publishedAt and event type
|
||||
let status: ArticleStatus;
|
||||
if (event === 'entry.unpublish') {
|
||||
@@ -221,7 +238,7 @@ export class StrapiService {
|
||||
}
|
||||
|
||||
const imageUrl = this.extractImageUrl(strapiArticle);
|
||||
|
||||
|
||||
const articleData: Partial<CreateArticleDto> = {
|
||||
title: strapiArticle.title,
|
||||
excerpt: strapiArticle.description,
|
||||
@@ -233,7 +250,8 @@ export class StrapiService {
|
||||
imagePosition: (strapiArticle.imagePosition || 'top') as ImagePosition,
|
||||
imageSize: (strapiArticle.imageSize || 'medium') as ImageSize,
|
||||
videoUrl: strapiArticle.videoUrl || '',
|
||||
videoPosition: (strapiArticle.videoPosition || 'inline') as VideoPosition,
|
||||
videoPosition: (strapiArticle.videoPosition ||
|
||||
'inline') as VideoPosition,
|
||||
videoCaption: strapiArticle.videoCaption || '',
|
||||
};
|
||||
|
||||
@@ -241,20 +259,26 @@ export class StrapiService {
|
||||
strapiArticle.documentId,
|
||||
articleData,
|
||||
);
|
||||
this.logger.log(`Successfully synced article: ${strapiArticle.title} with status: ${status}`);
|
||||
this.logger.log(
|
||||
`Successfully synced article: ${strapiArticle.title} with status: ${status}`,
|
||||
);
|
||||
} catch (error: any) {
|
||||
// If we get a 404 and it's an unpublish event, we can still mark it as draft
|
||||
if (event === 'entry.unpublish' && error.response?.status === 404) {
|
||||
this.logger.log(`Article ${strapiId} not found in Strapi, marking as draft based on unpublish event`);
|
||||
|
||||
this.logger.log(
|
||||
`Article ${strapiId} not found in Strapi, marking as draft based on unpublish event`,
|
||||
);
|
||||
|
||||
// Try to update the article status to draft directly
|
||||
try {
|
||||
const articleData: Partial<CreateArticleDto> = {
|
||||
status: ArticleStatus.DRAFT,
|
||||
};
|
||||
|
||||
|
||||
await this.articlesService.syncFromStrapi(strapiId, articleData);
|
||||
this.logger.log(`Marked article ${strapiId} as draft based on unpublish event`);
|
||||
this.logger.log(
|
||||
`Marked article ${strapiId} as draft based on unpublish event`,
|
||||
);
|
||||
} catch (syncError) {
|
||||
this.logger.error(
|
||||
`Failed to mark article ${strapiId} as draft:`,
|
||||
@@ -276,7 +300,7 @@ export class StrapiService {
|
||||
try {
|
||||
this.logger.log('Starting live blogs sync from Strapi...');
|
||||
|
||||
const response = await lastValueFrom(
|
||||
const response = await lastValueFrom(
|
||||
this.httpService.get<StrapiResponse<StrapiLiveBlog[]>>(
|
||||
`${this.strapiUrl}/api/live-blogs?populate=*`,
|
||||
{
|
||||
@@ -290,17 +314,19 @@ export class StrapiService {
|
||||
|
||||
for (const strapiLiveBlog of strapiLiveBlogs) {
|
||||
const imageUrl = this.extractLiveBlogImageUrl(strapiLiveBlog);
|
||||
|
||||
|
||||
const liveBlogData: Partial<CreateLiveBlogDto> = {
|
||||
title: strapiLiveBlog.title,
|
||||
description: strapiLiveBlog.description,
|
||||
slug: strapiLiveBlog.slug,
|
||||
status: this.mapStrapiStatusToLiveBlogStatus(strapiLiveBlog.status),
|
||||
featuredImage: imageUrl,
|
||||
imagePosition: (strapiLiveBlog.imagePosition || 'top') as ImagePosition,
|
||||
imagePosition: (strapiLiveBlog.imagePosition ||
|
||||
'top') as ImagePosition,
|
||||
imageSize: (strapiLiveBlog.imageSize || 'medium') as ImageSize,
|
||||
videoUrl: strapiLiveBlog.videoUrl || '',
|
||||
videoPosition: (strapiLiveBlog.videoPosition || 'inline') as VideoPosition,
|
||||
videoPosition: (strapiLiveBlog.videoPosition ||
|
||||
'inline') as VideoPosition,
|
||||
videoCaption: strapiLiveBlog.videoCaption || '',
|
||||
};
|
||||
|
||||
@@ -322,12 +348,19 @@ export class StrapiService {
|
||||
|
||||
async syncSingleLiveBlog(
|
||||
strapiId: string,
|
||||
event?: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish' | 'entry.unpublish',
|
||||
event?:
|
||||
| 'entry.create'
|
||||
| 'entry.update'
|
||||
| 'entry.delete'
|
||||
| 'entry.publish'
|
||||
| 'entry.unpublish',
|
||||
): Promise<void> {
|
||||
try {
|
||||
this.logger.log(`Syncing single live blog from Strapi: ${strapiId}, event: ${event}`);
|
||||
this.logger.log(
|
||||
`Syncing single live blog from Strapi: ${strapiId}, event: ${event}`,
|
||||
);
|
||||
|
||||
const response = await lastValueFrom(
|
||||
const response = await lastValueFrom(
|
||||
this.httpService.get<StrapiResponse<StrapiLiveBlog>>(
|
||||
`${this.strapiUrl}/api/live-blogs/${strapiId}?populate=*`,
|
||||
{
|
||||
@@ -337,18 +370,18 @@ export class StrapiService {
|
||||
);
|
||||
|
||||
const strapiLiveBlog = response.data.data;
|
||||
|
||||
|
||||
// For live blogs, we use the status from Strapi directly
|
||||
// but we might want to handle unpublish events differently
|
||||
let status = this.mapStrapiStatusToLiveBlogStatus(strapiLiveBlog.status);
|
||||
|
||||
|
||||
// If it's an unpublish event, set to draft
|
||||
if (event === 'entry.unpublish') {
|
||||
status = LiveBlogStatus.DRAFT;
|
||||
}
|
||||
|
||||
const imageUrl = this.extractLiveBlogImageUrl(strapiLiveBlog);
|
||||
|
||||
|
||||
const liveBlogData: Partial<CreateLiveBlogDto> = {
|
||||
title: strapiLiveBlog.title,
|
||||
description: strapiLiveBlog.description,
|
||||
@@ -358,7 +391,8 @@ export class StrapiService {
|
||||
imagePosition: (strapiLiveBlog.imagePosition || 'top') as ImagePosition,
|
||||
imageSize: (strapiLiveBlog.imageSize || 'medium') as ImageSize,
|
||||
videoUrl: strapiLiveBlog.videoUrl || '',
|
||||
videoPosition: (strapiLiveBlog.videoPosition || 'inline') as VideoPosition,
|
||||
videoPosition: (strapiLiveBlog.videoPosition ||
|
||||
'inline') as VideoPosition,
|
||||
videoCaption: strapiLiveBlog.videoCaption || '',
|
||||
};
|
||||
|
||||
@@ -366,20 +400,26 @@ export class StrapiService {
|
||||
strapiLiveBlog.documentId,
|
||||
liveBlogData,
|
||||
);
|
||||
this.logger.log(`Successfully synced live blog: ${strapiLiveBlog.title} with status: ${status}`);
|
||||
this.logger.log(
|
||||
`Successfully synced live blog: ${strapiLiveBlog.title} with status: ${status}`,
|
||||
);
|
||||
} catch (error: any) {
|
||||
// If we get a 404 and it's an unpublish event, we can still mark it as draft
|
||||
if (event === 'entry.unpublish' && error.response?.status === 404) {
|
||||
this.logger.log(`Live blog ${strapiId} not found in Strapi, marking as draft based on unpublish event`);
|
||||
|
||||
this.logger.log(
|
||||
`Live blog ${strapiId} not found in Strapi, marking as draft based on unpublish event`,
|
||||
);
|
||||
|
||||
// Try to update the live blog status to draft directly
|
||||
try {
|
||||
const liveBlogData: Partial<CreateLiveBlogDto> = {
|
||||
status: LiveBlogStatus.DRAFT,
|
||||
};
|
||||
|
||||
|
||||
await this.liveBlogService.syncFromStrapi(strapiId, liveBlogData);
|
||||
this.logger.log(`Marked live blog ${strapiId} as draft based on unpublish event`);
|
||||
this.logger.log(
|
||||
`Marked live blog ${strapiId} as draft based on unpublish event`,
|
||||
);
|
||||
} catch (syncError) {
|
||||
this.logger.error(
|
||||
`Failed to mark live blog ${strapiId} as draft:`,
|
||||
@@ -413,7 +453,12 @@ export class StrapiService {
|
||||
}
|
||||
|
||||
async handleWebhook(
|
||||
event: 'entry.create' | 'entry.update' | 'entry.delete' | 'entry.publish' | 'entry.unpublish',
|
||||
event:
|
||||
| 'entry.create'
|
||||
| 'entry.update'
|
||||
| 'entry.delete'
|
||||
| 'entry.publish'
|
||||
| 'entry.unpublish',
|
||||
data: { documentId: string; model?: string },
|
||||
): Promise<void> {
|
||||
this.logger.log(
|
||||
@@ -421,8 +466,10 @@ export class StrapiService {
|
||||
);
|
||||
|
||||
if (event === 'entry.delete') {
|
||||
this.logger.log(`Handling delete for document: ${data.documentId}, model: ${data.model}`);
|
||||
|
||||
this.logger.log(
|
||||
`Handling delete for document: ${data.documentId}, model: ${data.model}`,
|
||||
);
|
||||
|
||||
if (data.model === 'article') {
|
||||
await this.articlesService.removeByStrapiId(data.documentId);
|
||||
} else if (data.model === 'live-blog') {
|
||||
|
||||
Reference in new issue
Block a user