feat(ui): modals close only via Esc/X/cancel; standard 3:1 form cover processing
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -106,7 +106,7 @@ export class LeadFormsController {
|
||||
const form = await this.leadFormsService.get(user.organizationId, id);
|
||||
const row = await this.leadFormsService.getByToken(form.publicToken);
|
||||
if (!row?.coverStorageKey) return { ok: false };
|
||||
res.set({ 'Content-Type': 'image/jpeg' });
|
||||
res.set({ 'Content-Type': this.leadFormsService.coverContentType(row.coverStorageKey) });
|
||||
return new StreamableFile(this.files.openReadStream(row.coverStorageKey));
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,13 @@ import {
|
||||
} from '../contacts/normalize';
|
||||
import { LeadStagesService } from '../leads/lead-stages.service';
|
||||
|
||||
const COVER_CONTENT_TYPES: Record<string, string> = {
|
||||
jpg: 'image/jpeg',
|
||||
jpeg: 'image/jpeg',
|
||||
png: 'image/png',
|
||||
webp: 'image/webp',
|
||||
};
|
||||
|
||||
const DEFAULT_FIELDS: LeadFormFieldInput[] = [
|
||||
{
|
||||
key: 'fullName',
|
||||
@@ -222,7 +229,7 @@ export class LeadFormsService {
|
||||
submitColor: row.submitColor || '#14b8a6',
|
||||
hasCover: Boolean(row.coverStorageKey),
|
||||
coverPath: row.coverStorageKey
|
||||
? `/api/public/forms/${row.publicToken}/cover`
|
||||
? `/api/public/forms/${row.publicToken}/cover?v=${row.updatedAt.getTime()}`
|
||||
: null,
|
||||
fields: row.fields.map((f) => ({
|
||||
key: f.key,
|
||||
@@ -806,7 +813,10 @@ export class LeadFormsService {
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9]/g, '')
|
||||
.slice(0, 6);
|
||||
const key = `lead-forms/${id}/cover.${ext || 'jpg'}`;
|
||||
if (!COVER_CONTENT_TYPES[ext]) {
|
||||
throw new BadRequestException('فرمت تصویر کاور باید PNG، JPG یا WEBP باشد');
|
||||
}
|
||||
const key = `lead-forms/${id}/cover.${ext}`;
|
||||
await this.files.save(key, file.buffer);
|
||||
if (row.coverStorageKey && row.coverStorageKey !== key) {
|
||||
await this.files.remove(row.coverStorageKey);
|
||||
@@ -832,6 +842,11 @@ export class LeadFormsService {
|
||||
return row.coverStorageKey;
|
||||
}
|
||||
|
||||
coverContentType(key: string) {
|
||||
const ext = key.split('.').pop()?.toLowerCase() ?? '';
|
||||
return COVER_CONTENT_TYPES[ext] ?? 'image/jpeg';
|
||||
}
|
||||
|
||||
async getByToken(token: string, onlyActive = false) {
|
||||
return this.prisma.leadForm.findFirst({
|
||||
where: { publicToken: token, ...(onlyActive ? { isActive: true } : {}) },
|
||||
|
||||
@@ -33,7 +33,10 @@ export class PublicLeadFormsController {
|
||||
) {
|
||||
const row = await this.leadFormsService.getByToken(token);
|
||||
if (!row?.coverStorageKey) throw new NotFoundException('کاور پیدا نشد');
|
||||
res.set({ 'Content-Type': 'image/jpeg', 'Cache-Control': 'public, max-age=3600' });
|
||||
res.set({
|
||||
'Content-Type': this.leadFormsService.coverContentType(row.coverStorageKey),
|
||||
'Cache-Control': 'public, max-age=3600',
|
||||
});
|
||||
return new StreamableFile(this.files.openReadStream(row.coverStorageKey));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user