Slave/blog #9

Merged
nobswebdev merged 14 commits from slave/blog into master 2026-09-16 20:15:08 +00:00
8 changed files with 50 additions and 3 deletions
Showing only changes of commit 73f7ffed00 - Show all commits
@@ -13,6 +13,7 @@ import { JwtGuard } from '../../../guards/JwtGuard';
import { shopFaviconFilePipe, shopFaviconUploadOptions } from '../config/shopFaviconUpload'; import { shopFaviconFilePipe, shopFaviconUploadOptions } from '../config/shopFaviconUpload';
import { shopLogoFilePipe, shopLogoUploadOptions } from '../config/shopLogoUpload'; import { shopLogoFilePipe, shopLogoUploadOptions } from '../config/shopLogoUpload';
import { ConnectSimplexNotificationsDto } from '../dto/ConnectSimplexNotificationsDto'; import { ConnectSimplexNotificationsDto } from '../dto/ConnectSimplexNotificationsDto';
import { UpdateBlogEnabledDto } from '../dto/UpdateBlogEnabledDto';
import { UpdateNotificationsDto } from '../dto/UpdateNotificationsDto'; import { UpdateNotificationsDto } from '../dto/UpdateNotificationsDto';
import { UpdateShippingNoteDto } from '../dto/UpdateShippingNoteDto'; import { UpdateShippingNoteDto } from '../dto/UpdateShippingNoteDto';
import { UpdateSimplexLinkDto } from '../dto/UpdateSimplexLinkDto'; import { UpdateSimplexLinkDto } from '../dto/UpdateSimplexLinkDto';
@@ -43,6 +44,11 @@ export class ShopSettingsController {
return this.shopSettingsService.updateNotifications(dto); return this.shopSettingsService.updateNotifications(dto);
} }
@Patch('/blog-enabled')
updateBlogEnabled(@Body() dto: UpdateBlogEnabledDto) {
return this.shopSettingsService.updateBlogEnabled(dto);
}
@Post('/simplex-connect') @Post('/simplex-connect')
connectSimplexNotifications(@Body() dto: ConnectSimplexNotificationsDto) { connectSimplexNotifications(@Body() dto: ConnectSimplexNotificationsDto) {
return this.shopSettingsService.connectSimplexNotifications(dto.simplexNotificationLink); return this.shopSettingsService.connectSimplexNotifications(dto.simplexNotificationLink);
@@ -0,0 +1,7 @@
import { IsBoolean, IsNotEmpty } from 'class-validator';
export class UpdateBlogEnabledDto {
@IsNotEmpty()
@IsBoolean()
blogEnabled: boolean;
}
@@ -25,6 +25,7 @@ describe('ShopSettingsService', () => {
notifyOnNewOrder: false, notifyOnNewOrder: false,
notifyOnOrderMessage: false, notifyOnOrderMessage: false,
simplexNotificationContactId: null, simplexNotificationContactId: null,
blogEnabled: false,
createdAt: new Date('2026-01-01T00:00:00.000Z'), createdAt: new Date('2026-01-01T00:00:00.000Z'),
updatedAt: new Date('2026-01-01T00:00:00.000Z') updatedAt: new Date('2026-01-01T00:00:00.000Z')
} as ShopSettings; } as ShopSettings;
@@ -67,10 +68,27 @@ describe('ShopSettingsService', () => {
logoUrl: '/uploads/public/shop/logo.png', logoUrl: '/uploads/public/shop/logo.png',
faviconUrl: null, faviconUrl: null,
simplexLink: 'https://simplex.example', simplexLink: 'https://simplex.example',
shippingNote: 'Ships in 3 days' shippingNote: 'Ships in 3 days',
blogEnabled: false
}); });
}); });
it('updates blog enabled flag', async () => {
await service.updateBlogEnabled({ blogEnabled: true });
expect(shopSettingsRepo.update).toHaveBeenCalledWith('settings-1', { blogEnabled: true });
});
it('includes blog enabled in shop settings view', async () => {
shopSettingsRepo.find.mockResolvedValue([{ ...settings, blogEnabled: true }]);
await expect(service.getView()).resolves.toEqual(
expect.objectContaining({
blogEnabled: true
})
);
});
it('trims simplex links on update', async () => { it('trims simplex links on update', async () => {
await service.updateSimplexLink({ simplexLink: ' https://simplex.example/new ' }); await service.updateSimplexLink({ simplexLink: ' https://simplex.example/new ' });
@@ -6,6 +6,7 @@ import { getShopBrandingPublicUrl, resolveShopBrandingPath } from '../../../conf
import { Config } from '../../../types/Config'; import { Config } from '../../../types/Config';
import { removeFileFromDisk } from '../../../utils/removeFileFromDisk'; import { removeFileFromDisk } from '../../../utils/removeFileFromDisk';
import { SimplexChatClient } from '../../simplex/services/SimplexChatClient'; import { SimplexChatClient } from '../../simplex/services/SimplexChatClient';
import { UpdateBlogEnabledDto } from '../dto/UpdateBlogEnabledDto';
import { UpdateNotificationsDto } from '../dto/UpdateNotificationsDto'; import { UpdateNotificationsDto } from '../dto/UpdateNotificationsDto';
import { UpdateShippingNoteDto } from '../dto/UpdateShippingNoteDto'; import { UpdateShippingNoteDto } from '../dto/UpdateShippingNoteDto';
import { UpdateSimplexLinkDto } from '../dto/UpdateSimplexLinkDto'; import { UpdateSimplexLinkDto } from '../dto/UpdateSimplexLinkDto';
@@ -43,7 +44,8 @@ export class ShopSettingsService {
logoUrl, logoUrl,
faviconUrl, faviconUrl,
simplexLink: settings.simplexLink, simplexLink: settings.simplexLink,
shippingNote: settings.shippingNote shippingNote: settings.shippingNote,
blogEnabled: settings.blogEnabled
}; };
} }
@@ -93,6 +95,14 @@ export class ShopSettingsService {
return this.getView(); return this.getView();
} }
async updateBlogEnabled({ blogEnabled }: UpdateBlogEnabledDto): Promise<ShopSettingsView> {
const settings = await this.findSettings();
await this.shopSettingsRepo.update(settings.id, { blogEnabled });
return this.getView();
}
async uploadLogo(filename: string): Promise<ShopSettingsView> { async uploadLogo(filename: string): Promise<ShopSettingsView> {
const settings = await this.findSettings(); const settings = await this.findSettings();
@@ -191,6 +201,7 @@ export class ShopSettingsService {
notifyOnNewOrder, notifyOnNewOrder,
notifyOnOrderMessage, notifyOnOrderMessage,
simplexNotificationContactId, simplexNotificationContactId,
blogEnabled,
createdAt, createdAt,
updatedAt updatedAt
}: ShopSettings): ShopSettingsView { }: ShopSettings): ShopSettingsView {
@@ -220,6 +231,7 @@ export class ShopSettingsService {
notifyOnNewOrder, notifyOnNewOrder,
notifyOnOrderMessage, notifyOnOrderMessage,
simplexNotificationConnected: simplexNotificationContactId !== null, simplexNotificationConnected: simplexNotificationContactId !== null,
blogEnabled,
isSetupComplete, isSetupComplete,
setupChecklist, setupChecklist,
createdAt, createdAt,
@@ -18,6 +18,7 @@ export interface ShopSettingsView {
notifyOnNewOrder: boolean; notifyOnNewOrder: boolean;
notifyOnOrderMessage: boolean; notifyOnOrderMessage: boolean;
simplexNotificationConnected: boolean; simplexNotificationConnected: boolean;
blogEnabled: boolean;
isSetupComplete: boolean; isSetupComplete: boolean;
setupChecklist: SetupChecklist; setupChecklist: SetupChecklist;
createdAt: Date | null; createdAt: Date | null;
@@ -3,4 +3,5 @@ export interface StorefrontBranding {
faviconUrl: string | null; faviconUrl: string | null;
simplexLink: string | null; simplexLink: string | null;
shippingNote: string | null; shippingNote: string | null;
blogEnabled: boolean;
} }
@@ -29,7 +29,8 @@ describe('StorefrontShopViewService', () => {
logoUrl: null, logoUrl: null,
faviconUrl: null, faviconUrl: null,
simplexLink: null, simplexLink: null,
shippingNote: null shippingNote: null,
blogEnabled: false
}, },
shopSettings = { shopSettings = {
shopName: 'Demo Shop', shopName: 'Demo Shop',
@@ -13,6 +13,7 @@ export type StorefrontShopViewServiceOverrides = {
faviconUrl: string | null; faviconUrl: string | null;
simplexLink: string | null; simplexLink: string | null;
shippingNote: string | null; shippingNote: string | null;
blogEnabled: boolean;
}; };
shopSettings?: { shopName: string; shopFiatCurrency: string; enabledPaymentMethods?: PaymentMethod[] }; shopSettings?: { shopName: string; shopFiatCurrency: string; enabledPaymentMethods?: PaymentMethod[] };
fiatPerXmr?: number; fiatPerXmr?: number;