[AAE-32978] Move ADF "RichTextEditorComponent" to HxP monorepo (#10967)

This commit is contained in:
dominikiwanekhyland
2025-07-17 12:11:56 +02:00
committed by GitHub
parent 89380f2905
commit b28479b92b
16 changed files with 2239 additions and 1321 deletions

View File

@@ -28,19 +28,6 @@
},
"allowedNonPeerDependencies": [
"@apollo/client",
"apollo-angular",
"@editorjs/editorjs",
"@editorjs/code",
"@editorjs/header",
"@editorjs/inline-code",
"@editorjs/list",
"@editorjs/marker",
"@editorjs/paragraph",
"@editorjs/underline",
"@valano/change-font-size",
"editorjs-text-color-plugin",
"editorjs-html",
"editorjs-paragraph-with-alignment",
"editorjs-text-alignment-blocktune"
"apollo-angular"
]
}

View File

@@ -10,21 +10,6 @@
"bugs": {
"url": "https://github.com/Alfresco/alfresco-ng2-components/issues"
},
"dependencies": {
"@editorjs/code": "2.9.0",
"@editorjs/editorjs": "^2.28.2",
"@editorjs/header": "2.8.1",
"@editorjs/inline-code": "1.5.0",
"@editorjs/list": "1.9.0",
"@editorjs/marker": "1.4.0",
"@editorjs/paragraph": "^2.11.6",
"@editorjs/underline": "1.1.0",
"editorjs-html": "4.0.5",
"editorjs-paragraph-with-alignment": "3.0.0",
"editorjs-text-alignment-blocktune": "^1.0.3",
"editorjs-text-color-plugin": "1.13.1",
"@valano/change-font-size": "1.0.0"
},
"peerDependencies": {
"@angular/animations": ">=14.1.3",
"@angular/cdk": ">=14.1.2",

View File

@@ -29,11 +29,9 @@ import { RadioButtonsCloudWidgetComponent } from './components/widgets/radio-but
import { FilePropertiesTableCloudComponent } from './components/widgets/attach-file/file-properties-table/file-properties-table-cloud.component';
import { FileViewerWidgetComponent } from './components/widgets/file-viewer/file-viewer.widget';
import { DisplayRichTextWidgetComponent } from './components/widgets/display-rich-text/display-rich-text.widget';
import { RichTextEditorComponent } from '../rich-text-editor';
import { FormSpinnerComponent } from './components/spinner/form-spinner.component';
export const FORM_CLOUD_DIRECTIVES = [
RichTextEditorComponent,
FormSpinnerComponent,
PropertiesViewerWrapperComponent,
PropertiesViewerWidgetComponent,

View File

@@ -23,7 +23,6 @@ import { ProcessCloudModule } from './process/process-cloud.module';
import { FORM_CLOUD_DIRECTIVES } from './form/form-cloud.module';
import { TASK_FORM_CLOUD_DIRECTIVES } from './task/task-form/task-form.module';
import { PreferenceCloudServiceInterface, TASK_LIST_CLOUD_TOKEN } from './services/public-api';
import { RichTextEditorComponent } from './rich-text-editor';
import { GroupCloudComponent } from './group/components/group-cloud.component';
import { PeopleCloudComponent } from './people/components/people-cloud.component';
import { provideCloudFormRenderer, provideCloudPreferences } from './providers';
@@ -33,8 +32,7 @@ export const PROCESS_SERVICES_CLOUD_DIRECTIVES = [
...APP_LIST_CLOUD_DIRECTIVES,
...FORM_CLOUD_DIRECTIVES,
...TASK_FORM_CLOUD_DIRECTIVES,
PeopleCloudComponent,
RichTextEditorComponent
PeopleCloudComponent
] as const;
/**

View File

@@ -1,102 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/** Plugin import */
import CodeTool from '@editorjs/code';
import Header from '@editorjs/header';
import Paragraph from '@editorjs/paragraph';
import InlineCode from '@editorjs/inline-code';
import List from '@editorjs/list';
import Marker from '@editorjs/marker';
import Underline from '@editorjs/underline';
import ChangeFontSize from '@valano/change-font-size';
import ColorPlugin from 'editorjs-text-color-plugin';
import AlignmentTuneTool from 'editorjs-text-alignment-blocktune';
export const editorJsConfig = {
autofocus: true,
logLevel: 'ERROR',
tools: {
underline: {
class: Underline,
shortcut: 'CMD+U'
},
header: {
class: Header,
inlineToolbar: true,
tunes: ['anyTuneName']
},
paragraph: {
class: Paragraph,
inlineToolbar: true,
tunes: ['anyTuneName']
},
list: {
class: List,
inlineToolbar: true,
config: {
defaultStyle: 'unordered'
}
},
Color: {
class: ColorPlugin,
config: {
customPicker: true,
colorCollections: [
'#FF1300',
'#ffa500',
'#9C27B0',
'#673AB7',
'#3F51B5',
'#0070FF',
'#03A9F4',
'#00BCD4',
'#5f9ea0',
'#4CAF50',
'#8BC34A',
'#CDDC39',
'#FFF',
'#000',
'#c0c0c0',
'#808080',
'#800000'
],
defaultColor: '#FF1300',
type: 'text'
}
},
Marker: {
class: Marker,
shortcut: 'CMD+M'
},
'Increase/Decrease font size': {
class: ChangeFontSize,
config: {
cssClass: 'plus20pc',
buttonIcon: '<span class="material-icons">format_size</span>'
}
},
inlineCode: {
class: InlineCode,
shortcut: 'CMD+SHIFT+M'
},
anyTuneName: {
class: AlignmentTuneTool
},
code: CodeTool
}
};

View File

@@ -1,18 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './public-api';

View File

@@ -1,19 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './rich-text-editor.component';
export * from './rich-text-editor.module';

View File

@@ -1,3 +0,0 @@
<div class="adf-rich-text-editor-container">
<div class="editorjs" id="{{dynamicId}}"></div>
</div>

View File

@@ -1,32 +0,0 @@
/* stylelint-disable selector-class-pattern */
.adf-rich-text-editor-container {
color: var(--theme-text-fg-color, rgba(0, 0, 0, 0.87));
.editorjs {
&.readonly {
.codex-editor__redactor {
/* stylelint-disable declaration-no-important */
padding-bottom: 0 !important;
}
}
}
.ce-inline-toolbar {
transform: scale(1);
.ce-popover__items {
overflow: hidden;
}
.ce-inline-tool .material-icons {
font-size: 20px;
}
}
}
xy-color-picker {
position: relative;
background-color: transparent;
margin: 0;
overflow: hidden;
}

View File

@@ -1,105 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { DebugElement } from '@angular/core';
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { RichTextEditorComponent } from './rich-text-editor.component';
describe('RichTextEditorComponent', () => {
let component: RichTextEditorComponent;
let fixture: ComponentFixture<RichTextEditorComponent>;
let debugElement: DebugElement;
const cssSelectors = {
editorContent: '.codex-editor',
editorJsElement: '.editorjs'
};
const mockEditorData = {
time: 1658154611110,
blocks: [
{
id: '1',
type: 'header',
data: {
text: 'Editor.js',
level: 2
}
}
],
version: 1
};
const whenEditorIsReady = async () => {
fixture.detectChanges();
await component.editorInstance.isReady;
await fixture.whenStable();
};
beforeEach(() => {
TestBed.configureTestingModule({
imports: [RichTextEditorComponent]
});
fixture = TestBed.createComponent(RichTextEditorComponent);
component = fixture.componentInstance;
debugElement = fixture.debugElement;
});
it('should render rich text editor', async () => {
await whenEditorIsReady();
const editor = debugElement.query(By.css(cssSelectors.editorContent));
expect(editor).toBeTruthy();
});
it('should generate dynamic id', async () => {
await whenEditorIsReady();
expect(component.dynamicId).toContain('editorjs');
});
it('should get editorjs data by calling getEditorContent', async () => {
await whenEditorIsReady();
spyOn(component.editorInstance, 'save').and.returnValue(Promise.resolve(mockEditorData) as any);
const savedEditorData = await component.getEditorContent();
expect(savedEditorData).toEqual(mockEditorData);
});
it('should destroy editor instance on ngOnDestroy', async () => {
await whenEditorIsReady();
const destroyEditorSpy = spyOn(component.editorInstance, 'destroy');
component.ngOnDestroy();
expect(destroyEditorSpy).toHaveBeenCalledTimes(1);
expect(destroyEditorSpy).toHaveBeenCalled();
});
it('should not destroy editor instance on ngOnDestroy if editor is not ready', async () => {
await whenEditorIsReady();
const destroyEditorSpy = spyOn(component.editorInstance, 'destroy');
component.isReady = false;
component.ngOnDestroy();
expect(destroyEditorSpy).not.toHaveBeenCalled();
});
});

View File

@@ -1,99 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { applicationConfig, Meta, moduleMetadata, StoryFn } from '@storybook/angular';
import { ProcessServicesCloudStoryModule } from '../testing/process-services-cloud-story.module';
import { RichTextEditorComponent } from './rich-text-editor.component';
import { importProvidersFrom } from '@angular/core';
export default {
component: RichTextEditorComponent,
title: 'Process Services Cloud/Rich Text Editor',
decorators: [
moduleMetadata({
imports: [RichTextEditorComponent]
}),
applicationConfig({
providers: [importProvidersFrom(ProcessServicesCloudStoryModule)]
})
],
argTypes: {
data: {
control: 'object',
description: 'Output data.',
table: {
type: { summary: 'OutputData' }
}
},
placeholder: {
control: 'text',
description: 'Placeholder text.',
table: {
type: { summary: 'string' }
}
},
autoFocus: {
control: 'boolean',
description: 'Focus on the editor when it is loaded.',
table: {
type: { summary: 'boolean' }
}
}
}
} as Meta<RichTextEditorComponent>;
const template: StoryFn<RichTextEditorComponent> = (args) => ({
props: args,
template: `
<adf-cloud-rich-text-editor [data]=data [placeholder]=placeholder [autofocus]=autofocus #editor>
</adf-cloud-rich-text-editor>
<hr/>
<h3>Output data from editor:</h3>
<pre>{{editor.outputData$ | async | json}}</pre>
`
});
export const DefaultRichTextEditor = template.bind({});
DefaultRichTextEditor.args = {
data: {
time: 1550476186479,
blocks: [
{
type: 'paragraph',
data: {
text: 'The example of text that was written in <b>one of popular</b> text editors.'
}
},
{
type: 'header',
data: {
text: 'With the header of course',
level: 2
}
},
{
type: 'paragraph',
data: {
text: 'So what do we have?'
}
}
],
version: '2.29.0'
},
placeholder: 'Type something here...',
autoFocus: true
};

View File

@@ -1,89 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AfterViewInit, Component, Input, OnDestroy, OnInit, ViewEncapsulation } from '@angular/core';
import EditorJS, { OutputData } from '@editorjs/editorjs';
import { Subject } from 'rxjs';
import { editorJsConfig } from './editorjs-config';
@Component({
selector: 'adf-cloud-rich-text-editor',
templateUrl: './rich-text-editor.component.html',
styleUrls: ['./rich-text-editor.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class RichTextEditorComponent implements OnInit, OnDestroy, AfterViewInit {
@Input()
data: OutputData;
@Input()
placeholder = '';
@Input()
autoFocus = false;
private _outputData = new Subject<OutputData>();
outputData$ = this._outputData.asObservable();
editorInstance: EditorJS;
dynamicId: string;
isReady = false;
ngOnInit(): void {
this.dynamicId = `editorjs-${crypto.getRandomValues(new Uint32Array(1))}`;
}
ngAfterViewInit(): void {
this.editorInstance = new EditorJS({
holder: this.dynamicId,
placeholder: this.placeholder,
autofocus: this.autoFocus,
...editorJsConfig,
data: this.data,
onChange: () => {
this.sendEditorOutputData();
},
onReady: () => {
this.isReady = true;
this.sendEditorOutputData();
}
} as any);
}
private sendEditorOutputData() {
this.editorInstance
.save()
.then((outputData) => {
this._outputData.next(outputData);
})
.catch((error) => {
console.error('Saving failed: ', error);
});
}
getEditorContent() {
return this.editorInstance.save();
}
ngOnDestroy(): void {
if (this.isReady) {
this.editorInstance.destroy();
}
}
}

View File

@@ -1,26 +0,0 @@
/*!
* @license
* Copyright © 2005-2025 Hyland Software, Inc. and its affiliates. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { NgModule } from '@angular/core';
import { RichTextEditorComponent } from './rich-text-editor.component';
/** @deprecated use `RichTextEditorComponent` instead */
@NgModule({
imports: [RichTextEditorComponent],
exports: [RichTextEditorComponent]
})
export class RichTextEditorModule {}

View File

@@ -23,7 +23,6 @@ export * from './lib/group/public-api';
export * from './lib/people/public-api';
export * from './lib/form/public-api';
export * from './lib/services/public-api';
export * from './lib/rich-text-editor/public-api';
export * from './lib/screen/public-api';
export * from './lib/types';

3018
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -78,14 +78,6 @@
"@angular/cli": "19.2.14",
"@angular/compiler-cli": "19.2.6",
"@chromatic-com/storybook": "1.7.0",
"@editorjs/code": "2.9.3",
"@editorjs/editorjs": "2.30.8",
"@editorjs/header": "2.8.8",
"@editorjs/inline-code": "1.5.1",
"@editorjs/list": "2.0.4",
"@editorjs/marker": "1.4.0",
"@editorjs/paragraph": "^2.11.7",
"@editorjs/underline": "1.2.1",
"@nx/angular": "21.2.2",
"@nx/eslint-plugin": "20.8.0",
"@nx/js": "20.8.0",
@@ -116,14 +108,10 @@
"@typescript-eslint/parser": "6.21.0",
"@typescript-eslint/typescript-estree": "8.35.1",
"@typescript-eslint/utils": "^8.8.1",
"@valano/change-font-size": "^1.0.1",
"ajv": "^8.12.0",
"commander": "12.0.0",
"dotenv": "16.4.7",
"editorjs-html": "4.0.5",
"editorjs-paragraph-with-alignment": "3.0.0",
"editorjs-text-alignment-blocktune": "1.0.3",
"editorjs-text-color-plugin": "2.0.4",
"ejs": "^3.1.10",
"eslint": "^8.47.0",
"eslint-config-prettier": "10.1.2",