Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how to install autosave in React, TypeScript project #454

Open
surzioarmani opened this issue Feb 13, 2024 · 1 comment
Open

how to install autosave in React, TypeScript project #454

surzioarmani opened this issue Feb 13, 2024 · 1 comment
Labels
pending:feedback This issue is blocked by necessary feedback.

Comments

@surzioarmani
Copy link

surzioarmani commented Feb 13, 2024

import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic';
import { CKEditor } from '@ckeditor/ckeditor5-react';

import { apiPostUploadFile } from '@/api/common/apiComfunc';
import { Alignment } from '@ckeditor/ckeditor5-alignment';
import { Autosave } from '@ckeditor/ckeditor5-autosave';
import { Bold, Code, Italic, Strikethrough, Subscript, Superscript, Underline } from '@ckeditor/ckeditor5-basic-styles';
import { BlockQuote } from '@ckeditor/ckeditor5-block-quote';
import viewToPlainText from '@ckeditor/ckeditor5-clipboard/src/utils/viewtoplaintext';
import { Essentials } from '@ckeditor/ckeditor5-essentials';
import { FindAndReplace } from '@ckeditor/ckeditor5-find-and-replace';
import { Font, FontFamily } from '@ckeditor/ckeditor5-font';
import Heading from '@ckeditor/ckeditor5-heading/src/heading';
import { HorizontalLine } from '@ckeditor/ckeditor5-horizontal-line';
import {
	Image,
	ImageInsert,
	ImageInsertViaUrl,
	ImageResizeEditing,
	ImageResizeHandles,
	ImageUpload,
} from '@ckeditor/ckeditor5-image';
import { Indent } from '@ckeditor/ckeditor5-indent';
import { AutoLink, Link } from '@ckeditor/ckeditor5-link';
import { ListProperties } from '@ckeditor/ckeditor5-list';
import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed';
import { Paragraph } from '@ckeditor/ckeditor5-paragraph';
import { RemoveFormat } from '@ckeditor/ckeditor5-remove-format';
import { SourceEditing } from '@ckeditor/ckeditor5-source-editing';
import { SpecialCharacters, SpecialCharactersEssentials } from '@ckeditor/ckeditor5-special-characters';
import { Table, TableCaption, TableCellProperties, TableProperties, TableToolbar } from '@ckeditor/ckeditor5-table';
// import { Base64UploadAdapter } from '@ckeditor/ckeditor5-upload';
import { Button, Row } from 'antd';
import DOMPurify from 'dompurify';
interface PropsType {
	data?: any;
	offImage?: any;
	setData?: React.Dispatch<React.SetStateAction<any>>;
	setPlainText?: React.Dispatch<React.SetStateAction<any>>;
}

const Ckeditor = (props: PropsType) => {
	const { setData, offImage, setPlainText, data } = props; // html whole text
	// const [editor, setEditor] = useState<ClassicEditor | null>(null);
	const [isPreview, setIsPreview] = useState(false);
	const [num, setNum] = useState(0); //only text
	const [fileList, setFileList] = useState([]);
	// const autosavePlugin: PluginConstructor<Editor> = Autosave;
	// 다국어
	const { t } = useTranslation();

	const customColorPalette = [
		{
			color: 'hsl(4, 90%, 58%)',
			label: 'Red',
		},
		{
			color: 'hsl(340, 82%, 52%)',
			label: 'Pink',
		},
		{
			color: 'hsl(291, 64%, 42%)',
			label: 'Purple',
		},
		{
			color: 'hsl(262, 52%, 47%)',
			label: 'Deep Purple',
		},
		{
			color: 'hsl(231, 48%, 48%)',
			label: 'Indigo',
		},
		{
			color: 'hsl(207, 90%, 54%)',
			label: 'Blue',
		},
	];

	/**
	 *
	 * @param {any} editor editor
	 * @param {any} editor.plugins editor.plugins
	 * @param {any} editor.plugins.get editor.plugins.get
	 */
	function uploadPlugin(editor: {
		plugins: {
			get: (arg0: string) => {
				(): any;
				new (): any;
				createUploadAdapter: (loader: any) => { upload(): Promise<unknown> };
			};
		};
	}) {
		editor.plugins.get('FileRepository').createUploadAdapter = (loader: any) => {
			return customUploadAdapter(loader);
		};
	}

	const customUploadAdapter = (loader: { file: Promise<any> }) => {
		setNum(num + 1);
		return {
			upload() {
				return new Promise((resolve, reject) => {
					const formData = new FormData();
					loader.file.then((file: string | Blob) => {
						formData.append('file', file);
						setFileList(prevList => [...prevList, file]);
						apiPostUploadFile(formData).then(res => {
							console.log(res.data);
							// showAlert('', t('com.msg.confirmSaved'), () => {});
							resolve({
								default: '' + res.data,
							});
						});
					});
				});
			},
		};
	};
	const saveData = (value: any) => {
		return new Promise<void>(resolve => {
			// Fake HTTP server's lag.
			setTimeout(() => {
				updateServerDataConsole(data);

				resolve();
			}, 500);
		});
	};
	/**
	 *
	 * @param msg
	 */
	let consoleUpdates = 0;
	/**
	 *
	 * @param msg
	 */
	function updateServerDataConsole(msg: string) {
		const console = document.querySelector('#snippet-autosave-console');

		consoleUpdates++;
		console.classList.add('updated');
		console.textContent = msg;

		setTimeout(() => {
			if (--consoleUpdates == 0) {
				console.classList.remove('updated');
			}
		}, 500);
	}

	const onClickPreview = () => {
		if (isPreview) {
			setIsPreview(false);
		} else {
			setIsPreview(true);
		}
	};

	// useEffect(() => {
	// 	if (editor) {
	// 		const toolbarElement = editor.ui.view.toolbar.element;
	// 		if (!isEdit) {
	// 			toolbarElement.style.display = 'none';
	// 		} else {
	// 			toolbarElement.style.display = 'flex';
	// 		}
	// 	}
	// }, [isEdit, editor]);

	return (
		<>
			{!isPreview ? (
				<CKEditor
					// ref={ref}
					editor={ClassicEditor}
					config={{
						plugins: [
							AutoLink,
							Autosave,
							FindAndReplace,
							// Base64UploadAdapter,
							Link,
							AutoLink,
							RemoveFormat,
							BlockQuote,
							Alignment,
							ListProperties,
							Strikethrough,
							Code,
							SourceEditing,
							HorizontalLine,
							Underline,
							MediaEmbed,
							Table,
							TableToolbar,
							Essentials,
							TableCellProperties,
							TableProperties,
							TableCaption,
							Paragraph,
							Bold,
							Italic,
							Heading,
							Font,
							SpecialCharacters,
							SpecialCharactersEssentials,
							Indent,
							SpecialCharacters,
							FontFamily,
							Image,
							ImageUpload,
							ImageInsertViaUrl,
							ImageInsert,
							Subscript,
							Superscript,
							ImageResizeEditing,
							ImageResizeHandles,
						],
						toolbar: {
							items: [
								'sourceEditing',
								'findAndReplace',
								'undo',
								'redo',
								'|',
								'heading',
								'|',
								'fontSize',
								'fontFamily',
								'fontColor',
								'fontBackgroundColor',
								'horizontalLine',
								'|',
								'bold',
								'italic',
								'alignment',
								'underline',
								'strikethrough',
								'subscript',
								'superscript',
								'removeFormat',
								'-',
								'bulletedList',
								'numberedList',
								'|',
								'link',
								offImage ? null : 'insertImage', // props로  onoff 가능
								'insertTable',
								'blockQuote',
								'mediaEmbed',
								'|',
								'outdent',
								'indent',
								'code',
								'specialCharacters',
							],
							shouldNotGroupWhenFull: true,
						},
						autosave: {
							waitingTime: 5000, // in ms
							save(editor: ClassicEditor) {
								// The saveData() function must return a promise
								// which should be resolved when the data is successfully saved.
								console.log(editor.getData());
								return saveData(editor.getData());
							},
						},
						list: {
							properties: {
								styles: true,
								startIndex: true,
								reversed: true,
							},
						},

						// head: {
						// 	options: [
						// 		{
						// 			model: 'paragraph',
						// 			view: 'p',
						// 			title: '본문',
						// 			class: 'ck-heading_paragraph',
						// 		},
						// 		{
						// 			model: 'heading1',
						// 			view: 'h1',
						// 			title: '헤더1',
						// 			class: 'ck-heading_heading1',
						// 		},
						// 		{
						// 			model: 'heading2',
						// 			view: 'h2',
						// 			title: '헤더2',
						// 			class: 'ck-heading_heading2',
						// 		},
						// 		{
						// 			model: 'heading3',
						// 			view: 'h3',
						// 			title: '헤더3',
						// 			class: 'ck-heading_heading3',
						// 		},
						// 	],
						// },
						image: {
							insert: {
								integrations: ['upload', 'url'],
								type: 'auto',
							},
							resizeOptions: [
								{
									name: 'resizeImage:original',
									value: null,
									label: 'Original',
								},
								{
									name: 'resizeImage:40',
									value: '40',
									label: '40%',
								},
								{
									name: 'resizeImage:60',
									value: '60',
									label: '60%',
								},
							],
							toolbar: ['resizeImage' /* ... */],
						},
						placeholder: '여기에 양식 데이터를 넣어주세요 ',
						language: 'ko',

						alignment: {
							options: ['justify', 'left', 'center', 'right'],
						},
						fontSize: {
							options: [9, 11, 13, 'default', 17, 19, 21],
						},
						fontFamily: {
							options: [
								'default',
								'궁서체',
								'바탕',
								'돋움',
								'Arial',
								'Courier New',
								'Georgia',
								'Lucida Sans Unicode',
								'Tahoma',
								'Times New Roman',
								'Trebuchet MS',
								'Verdana',
							],
							supportAllValues: true,
						},
						table: {
							contentToolbar: ['tableColumn', 'tableRow', 'mergeTableCells', 'tableProperties', 'tableCellProperties'],
							tableProperties: {
								borderColors: customColorPalette,
								backgroundColors: customColorPalette,
							},
							tableCellProperties: {
								borderColors: customColorPalette,
								backgroundColors: customColorPalette,
							},
						},
						extraPlugins: [uploadPlugin],
					}}
					data={data}
					// onReady={neweditor => {
					// setEditor(neweditor);
					// }}
					onChange={(event, neweditor) => {
						setData(DOMPurify.sanitize(neweditor.getData()));
						if (setPlainText) {
							setPlainText(viewToPlainText(neweditor.editing.view.document.getRoot()).replace(/\n/g, ''));
						}
					}}
				/>
			) : (
				<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(data) }} />
			)}
			<Row>
				<Button type="primary" onClick={onClickPreview}>
					{!isPreview ? t('comfunc.bbs.search.preview') : t('comfunc.bbs.search.nopreview')}
				</Button>
			</Row>
		</>
	);
};

export default Ckeditor;


I followed the guide
but i have some error (Autosave)

i want to know how to using autosave function

@Witoso
Copy link
Member

Witoso commented Feb 15, 2024

Hi! Please provide the information about the error, or best, provide some reproducible sample for us (zip/repo). We not always have the time to set up the whole project and debug it.

@Witoso Witoso added the pending:feedback This issue is blocked by necessary feedback. label Feb 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
pending:feedback This issue is blocked by necessary feedback.
Projects
None yet
Development

No branches or pull requests

2 participants