feat: add RichTextEditor component for rich text editing in articles
feat: create SanitizeBlogBodiesCommand to clean existing blog bodies according to current HTML sanitization policies test: add AppointmentTreatmentSessionLinkTest to ensure appointment booking functionality works correctly with treatment session links
This commit is contained in:
@@ -4,8 +4,9 @@ import userEvent from '@testing-library/user-event';
|
||||
import { Routes, Route } from 'react-router';
|
||||
import { renderWithProviders } from '@/test/utils';
|
||||
|
||||
vi.mock('@ckeditor/ckeditor5-react', () => ({ CKEditor: () => null }));
|
||||
vi.mock('@ckeditor/ckeditor5-build-classic', () => ({ default: {} }));
|
||||
// ادیتور در jsdom بالا نمیآید و به این تست ربطی ندارد؛ کلِ wrapper mock میشود
|
||||
// تا mockهای پکیجهای داخلیاش با هر مهاجرت CKEditor عوض نشوند.
|
||||
vi.mock('../components/RichTextEditor', () => ({ default: () => null }));
|
||||
vi.mock('sonner', () => ({ toast: { success: vi.fn(), error: vi.fn() } }));
|
||||
vi.mock('@/components/ui/SearchableSelect', () => ({ default: () => null }));
|
||||
vi.mock('@/lib/api', () => ({
|
||||
|
||||
@@ -4,8 +4,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { toast } from 'sonner';
|
||||
import { CKEditor } from '@ckeditor/ckeditor5-react';
|
||||
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
||||
import RichTextEditor from '../components/RichTextEditor';
|
||||
import { api } from '../lib/api';
|
||||
import type { ApiResponse } from '../lib/api';
|
||||
import type { Blog, City } from '../types';
|
||||
@@ -174,18 +173,7 @@ export default function BlogFormPage() {
|
||||
control={control}
|
||||
name="body"
|
||||
render={({ field }) => (
|
||||
<div dir="rtl" className="ck-rtl">
|
||||
<CKEditor
|
||||
editor={ClassicEditor as never}
|
||||
data={field.value ?? ''}
|
||||
onChange={(_evt: unknown, editor: { getData: () => string }) => field.onChange(editor.getData())}
|
||||
config={{
|
||||
licenseKey: 'GPL',
|
||||
language: 'fa',
|
||||
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|', 'blockQuote', 'insertTable', '|', 'undo', 'redo'],
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<RichTextEditor value={field.value ?? ''} onChange={field.onChange} />
|
||||
)}
|
||||
/>
|
||||
{errors.body && <p className="text-[var(--danger)] text-xs mt-1">{errors.body.message}</p>}
|
||||
|
||||
@@ -3,8 +3,7 @@ import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { useForm, Controller } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { toast } from 'sonner';
|
||||
import { CKEditor } from '@ckeditor/ckeditor5-react';
|
||||
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
|
||||
import RichTextEditor from '../components/RichTextEditor';
|
||||
import { api } from '../lib/api';
|
||||
import type { ApiResponse } from '../lib/api';
|
||||
import type { Blog } from '../types';
|
||||
@@ -117,14 +116,7 @@ export default function RepresentationBlogFormPage() {
|
||||
control={control}
|
||||
name="body"
|
||||
render={({ field }) => (
|
||||
<div dir="rtl" className="ck-rtl">
|
||||
<CKEditor
|
||||
editor={ClassicEditor as never}
|
||||
data={field.value ?? ''}
|
||||
onChange={(_e: unknown, editor: { getData: () => string }) => field.onChange(editor.getData())}
|
||||
config={{ licenseKey: 'GPL', language: 'fa', toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', '|', 'blockQuote', 'insertTable', '|', 'undo', 'redo'] }}
|
||||
/>
|
||||
</div>
|
||||
<RichTextEditor value={field.value ?? ''} onChange={field.onChange} />
|
||||
)}
|
||||
/>
|
||||
{errors.body && <p className="text-[var(--danger)] text-xs mt-1">{errors.body.message}</p>}
|
||||
|
||||
Reference in New Issue
Block a user