Skip to content

Commit

Permalink
[frontend] Migrate CK Editor to 9.3 (#8151)
Browse files Browse the repository at this point in the history
Co-authored-by: Landry Trebon <landry.trebon@filigran.io>
  • Loading branch information
Archidoit and lndrtrbn authored Oct 17, 2024
1 parent ef0f0c3 commit 6953bad
Show file tree
Hide file tree
Showing 11 changed files with 1,109 additions and 63 deletions.
4 changes: 2 additions & 2 deletions opencti-platform/opencti-front/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "src/front.tsx",
"dependencies": {
"@analytics/google-analytics": "1.0.7",
"@ckeditor/ckeditor5-react": "6.2.0",
"@ckeditor/ckeditor5-react": "9.3.0",
"@date-fns/upgrade": "1.0.3",
"@date-io/date-fns": "3.0.0",
"@emotion/react": "11.13.0",
Expand All @@ -26,7 +26,7 @@
"apexcharts": "3.54.0",
"axios": "1.7.7",
"buffer": "6.0.3",
"ckeditor5-custom-build": "0.0.1",
"ckeditor5": "43.1.1",
"classnames": "2.5.1",
"convert": "5.4.0",
"d3-hierarchy": "3.1.2",
Expand Down
217 changes: 217 additions & 0 deletions opencti-platform/opencti-front/src/components/CKEditor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,217 @@
import { CKEditor as ReactCKEditor } from '@ckeditor/ckeditor5-react';
import {
Editor,
Alignment,
Autoformat,
AutoImage,
AutoLink,
Base64UploadAdapter,
BlockQuote,
Bold,
ClassicEditor,
Code,
CodeBlock,
Essentials,
FontBackgroundColor,
FontColor,
FontFamily,
FontSize,
Heading,
Highlight,
HorizontalLine,
ImageCaption,
ImageInsert,
ImageResize,
ImageStyle,
ImageToolbar,
Indent,
IndentBlock,
Italic,
Link,
LinkImage,
ListProperties,
Mention,
Paragraph,
PasteFromOffice,
RemoveFormat,
SourceEditing,
SpecialCharacters,
SpecialCharactersCurrency,
SpecialCharactersEssentials,
Strikethrough,
Subscript,
Superscript,
List,
Table,
TodoList,
TableCaption,
TableColumnResize,
TableToolbar,
Underline,
ImageEditing,
ImageBlockEditing,
EditorConfig,
ImageTextAlternative,
} from 'ckeditor5';
import React from 'react';
import { useIntl } from 'react-intl';

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import de from 'ckeditor5/translations/de.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import en from 'ckeditor5/translations/en.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import es from 'ckeditor5/translations/es.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import fr from 'ckeditor5/translations/fr.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import ja from 'ckeditor5/translations/ja.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import ko from 'ckeditor5/translations/ko.js';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
// eslint-disable-next-line import/extensions
import zh from 'ckeditor5/translations/zh.js';

const CKEDITOR_DEFAULT_CONFIG: EditorConfig = {
translations: [de, en, es, fr, ja, ko, zh],
plugins: [
Alignment,
AutoImage,
Autoformat,
AutoLink,
Base64UploadAdapter,
BlockQuote,
Bold,
Code,
CodeBlock,
Essentials,
FontBackgroundColor,
FontColor,
FontFamily,
FontSize,
Heading,
Highlight,
HorizontalLine,
ImageBlockEditing,
ImageCaption,
ImageEditing,
ImageInsert,
ImageResize,
ImageStyle,
ImageToolbar,
ImageTextAlternative,
Indent,
IndentBlock,
Italic,
Link,
LinkImage,
List,
ListProperties,
Mention,
Paragraph,
PasteFromOffice,
RemoveFormat,
SourceEditing,
SpecialCharacters,
SpecialCharactersCurrency,
SpecialCharactersEssentials,
Strikethrough,
Subscript,
Superscript,
Table,
TableCaption,
TableColumnResize,
TableToolbar,
TodoList,
Underline,
],
toolbar: {
items: [
'heading',
'fontFamily',
'fontSize',
'alignment',
'|',
'bold',
'italic',
'underline',
'strikethrough',
'link',
'fontColor',
'fontBackgroundColor',
'highlight',
'|',
'bulletedList',
'numberedList',
'outdent',
'indent',
'todoList',
'|',
'imageInsert',
'blockQuote',
'code',
'codeBlock',
'insertTable',
'specialCharacters',
'subscript',
'superscript',
'horizontalLine',
'|',
'sourceEditing',
'removeFormat',
'undo',
'redo',
],
},
image: {
resizeUnit: 'px',
toolbar: [
'imageTextAlternative',
'toggleImageCaption',
'imageStyle:block',
'imageStyle:side',
'linkImage',
],
},
table: {
contentToolbar: [
'tableColumn',
'tableRow',
'mergeTableCells',
],
},
};

type CKEditorProps<T extends Editor> = Omit<ReactCKEditor<T>['props'], 'editor' | 'config'>;

const CKEditor = (props: CKEditorProps<ClassicEditor>) => {
const { locale } = useIntl();

const config: EditorConfig = {
...CKEDITOR_DEFAULT_CONFIG,
language: locale.slice(0, 2),
};

return (
<ReactCKEditor
editor={ClassicEditor}
config={config}
{...props}
/>
);
};

export default CKEditor;
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,6 @@ import InputLabel from '@mui/material/InputLabel';
import FormHelperText from '@mui/material/FormHelperText';
import { CloseOutlined, FullscreenOutlined } from '@mui/icons-material';
import * as R from 'ramda';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import Editor from 'ckeditor5-custom-build/build/ckeditor';
import 'ckeditor5-custom-build/build/translations/fr';
import 'ckeditor5-custom-build/build/translations/zh-cn';
import IconButton from '@mui/material/IconButton';
import DialogActions from '@mui/material/DialogActions';
import Button from '@mui/material/Button';
Expand All @@ -17,6 +13,7 @@ import Tooltip from '@mui/material/Tooltip';
import { FilePdfBox } from 'mdi-material-ui';
import TextFieldAskAI from '../../private/components/common/form/TextFieldAskAI';
import { useFormatter } from '../i18n';
import CKEditor from '../CKEditor';

// Deprecated - https://mui.com/system/styles/basics/
// Do not use it for new code.
Expand Down Expand Up @@ -88,21 +85,13 @@ const RichTextField = (props) => {

const CKEditorInstance = (
<CKEditor
editor={Editor}
onReady={(editor) => {
editorReference.current = editor;
editorReference.current.model.document.selection.on(
'change',
internalOnSelect,
);
}}
config={{
width: '100%',
language: 'en',
image: {
resizeUnit: 'px',
},
}}
data={value || ''}
onChange={(_, editor) => {
setFieldValue(name, editor.getData());
Expand Down
1 change: 1 addition & 0 deletions opencti-platform/opencti-front/src/front.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import makeStyles from '@mui/styles/makeStyles';
import { RelayEnvironmentProvider } from 'react-relay/hooks';
import './static/css/index.css';
import './static/css/leaflet.css';
import 'ckeditor5/ckeditor5.css';
import './static/css/CKEditorDark.css';
import './static/css/CKEditorLight.css';
import 'react-grid-layout/css/styles.css';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import withTheme from '@mui/styles/withTheme';
import TextField from '@mui/material/TextField';
import htmlToPdfmake from 'html-to-pdfmake';
import pdfMake from 'pdfmake';
import { CKEditor } from '@ckeditor/ckeditor5-react';
import Editor from 'ckeditor5-custom-build/build/ckeditor';
import 'ckeditor5-custom-build/build/translations/fr';
import 'ckeditor5-custom-build/build/translations/zh-cn';
import { Document, Page, pdfjs } from 'react-pdf';
import 'react-pdf/dist/esm/Page/TextLayer.css';
import 'react-pdf/dist/esm/Page/AnnotationLayer.css';
Expand All @@ -32,6 +28,7 @@ import { isEmptyField } from '../../../../utils/utils';
import MarkdownDisplay from '../../../../components/MarkdownDisplay';
import { FIVE_SECONDS } from '../../../../utils/Time';
import withRouter from '../../../../utils/compat_router/withRouter';
import CKEditor from '../../../../components/CKEditor';

pdfjs.GlobalWorkerOptions.workerSrc = `${APP_BASE_PATH}/static/ext/pdf.worker.mjs`;

Expand Down Expand Up @@ -621,11 +618,6 @@ class StixCoreObjectContentComponent extends Component {
style={{ minHeight: height, height }}
>
<CKEditor
editor={Editor}
config={{
language: 'en',
toolbar: { shouldNotGroupWhenFull: true },
}}
data={currentContent ?? ''}
onChange={() => {
this.setState({ changed: true });
Expand Down
11 changes: 1 addition & 10 deletions opencti-platform/opencti-front/src/utils/ai/ResponseDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ import DialogContent from '@mui/material/DialogContent';
import Alert from '@mui/material/Alert';
import { graphql, useSubscription } from 'react-relay';
import { GraphQLSubscriptionConfig } from 'relay-runtime';
import { CKEditor } from '@ckeditor/ckeditor5-react';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
import Editor from 'ckeditor5-custom-build/build/ckeditor';
import 'ckeditor5-custom-build/build/translations/fr';
import 'ckeditor5-custom-build/build/translations/zh-cn';
import ReactMde from 'react-mde';
import TextField from '@mui/material/TextField';
import Button from '@mui/material/Button';
Expand All @@ -24,6 +18,7 @@ import { ResponseDialogAskAISubscription, ResponseDialogAskAISubscription$data }
import { useFormatter } from '../../components/i18n';
import MarkdownDisplay from '../../components/MarkdownDisplay';
import { isNotEmptyField } from '../utils';
import CKEditor from '../../components/CKEditor';

// region types
interface ResponseDialogProps {
Expand Down Expand Up @@ -150,10 +145,6 @@ const ResponseDialog: FunctionComponent<ResponseDialogProps> = ({
{format === 'html' && (
<CKEditor
id="response-dialog-editor"
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
editor={Editor}
config={{ language: 'en', toolbar: { shouldNotGroupWhenFull: true } }}
data={content}
onChange={(_, editor) => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ export default class StixDomainObjectContentTabPage {

async selectMainContent() {
await this.page.getByRole('button', { name: 'Description & Main content' }).click();
return this.page.getByLabel('Editor editing area: main');
return this.page.getByLabel('Editing area: main');
}

async selectFile(name: string) {
await this.page.getByText(name, { exact: true }).click();
return this.page.getByLabel('Editor editing area: main');
return this.page.getByLabel('Editing area: main');
}

async editMainContent(input: string) {
Expand All @@ -23,7 +23,7 @@ export default class StixDomainObjectContentTabPage {
}

async editTextArea(input: string, isAutoSave = false) {
const element = this.page.getByLabel('Editor editing area: main');
const element = this.page.getByLabel('Editing area: main');
await element.click();
if (isAutoSave) {
await element.fill(input);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export default class TextFieldPageModel {
this.inputLocator = this.parentLocator.getByTestId('text-area');
} else if (type === 'rich-content') {
this.parentLocator = root.getByText(label).locator('..');
this.inputLocator = this.parentLocator.getByLabel('Editor editing area: main');
this.inputLocator = this.parentLocator.getByLabel('Editing area: main');
} else if (type === 'text-no-label') {
this.inputLocator = root.getByRole('textbox', { name: label });
this.parentLocator = root.getByText(label).locator('..');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ test('Testing content customization for Report', async ({ page }) => {
await page.getByRole('link', { name: 'Report' }).click();
await page.getByRole('button', { name: 'Content' }).click();
// Update the default value for content
await page.getByLabel('Editor editing area: main').fill('Content from customization');
await page.getByLabel('Editing area: main').fill('Content from customization');
await page.getByRole('button', { name: 'Update' }).click();

// Go back to the Report page
Expand All @@ -40,6 +40,6 @@ test('Testing content customization for Report', async ({ page }) => {
await leftBarPage.clickOnMenu('Settings', 'Customization');
await page.getByRole('link', { name: 'Report' }).click();
await page.getByRole('button', { name: 'Content' }).click();
await page.getByLabel('Editor editing area: main').fill('');
await page.getByLabel('Editing area: main').fill('');
await page.getByRole('button', { name: 'Update' }).click();
});
Loading

0 comments on commit 6953bad

Please sign in to comment.