MD2 editor
This commit is contained in:
parent
cdceaab2fd
commit
ed90250876
@ -38,6 +38,7 @@
|
||||
"node_modules/nebular-icons/scss/nebular-icons.scss",
|
||||
"node_modules/pace-js/templates/pace-theme-flash.tmpl.css",
|
||||
"node_modules/leaflet/dist/leaflet.css",
|
||||
"node_modules/@progress/kendo-theme-default/dist/all.css",
|
||||
"src/app/@theme/styles/styles.scss",
|
||||
"src/assets/styles/site.scss"
|
||||
],
|
||||
|
||||
12987
package-lock.json
generated
12987
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -45,7 +45,13 @@
|
||||
"@nebular/eva-icons": "13.0.0",
|
||||
"@nebular/security": "13.0.0",
|
||||
"@nebular/theme": "13.0.0",
|
||||
"@progress/kendo-angular-buttons": "^20.1.1",
|
||||
"@progress/kendo-angular-dialog": "^20.1.1",
|
||||
"@progress/kendo-angular-editor": "^20.1.1",
|
||||
"@progress/kendo-angular-toolbar": "^20.1.1",
|
||||
"@progress/kendo-licensing": "^1.7.1",
|
||||
"@progress/kendo-svg-icons": "^4.5.0",
|
||||
"@progress/kendo-theme-default": "^12.2.0",
|
||||
"@tinymce/tinymce-angular": "^7.0.0",
|
||||
"angular2-chartjs": "0.4.1",
|
||||
"angular2-qrcode": "^2.0.3",
|
||||
|
||||
@ -35,6 +35,10 @@ import { MobStandInfoComponent } from './massive-darkness2/mobs/mob-stand-info/m
|
||||
import { HtmlEditorModule } from '../ui/html-editor/html-editor.module';
|
||||
import { EditorModule } from '@tinymce/tinymce-angular';
|
||||
import { MD2HtmlEditorComponent } from './massive-darkness2/md2-html-editor/md2-html-editor.component';
|
||||
import { MD2IconPickerDlgComponent } from './massive-darkness2/md2-html-editor/md2-icon-picker-dlg.component';
|
||||
import { EditorModule as KendoEditorModule } from '@progress/kendo-angular-editor';
|
||||
import { ToolBarModule } from '@progress/kendo-angular-toolbar';
|
||||
import { ButtonsModule } from '@progress/kendo-angular-buttons';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@ -63,7 +67,8 @@ import { MD2HtmlEditorComponent } from './massive-darkness2/md2-html-editor/md2-
|
||||
MobDefInfoComponent,
|
||||
MobCombatInfoComponent,
|
||||
MobStandInfoComponent,
|
||||
MD2HtmlEditorComponent
|
||||
MD2HtmlEditorComponent,
|
||||
MD2IconPickerDlgComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@ -95,7 +100,10 @@ import { MD2HtmlEditorComponent } from './massive-darkness2/md2-html-editor/md2-
|
||||
AlertDlgModule,
|
||||
DropDownListModule,
|
||||
HtmlEditorModule,
|
||||
EditorModule
|
||||
EditorModule,
|
||||
KendoEditorModule,
|
||||
ToolBarModule,
|
||||
ButtonsModule
|
||||
]
|
||||
})
|
||||
export class GamesModule { }
|
||||
|
||||
@ -1 +1,20 @@
|
||||
<!-- <editor [init]="htmlEditorSetting"></editor> -->
|
||||
<kendo-editor [value]="value" (valueChange)="onChange($event)" (blur)="onTouched()" [disabled]="disabled"
|
||||
[iframeCss]="{ content: customCssClass }">
|
||||
<kendo-toolbar>
|
||||
<!-- Standard editing tools -->
|
||||
<kendo-toolbar-button kendoEditorBold></kendo-toolbar-button>
|
||||
<kendo-toolbar-button kendoEditorItalic></kendo-toolbar-button>
|
||||
<kendo-toolbar-button kendoEditorUnderline></kendo-toolbar-button>
|
||||
<kendo-toolbar-separator></kendo-toolbar-separator>
|
||||
<kendo-toolbar-button kendoEditorUnorderedList></kendo-toolbar-button>
|
||||
<kendo-toolbar-button kendoEditorOrderedList></kendo-toolbar-button>
|
||||
<kendo-toolbar-separator></kendo-toolbar-separator>
|
||||
<kendo-toolbar-button kendoEditorUndo></kendo-toolbar-button>
|
||||
<kendo-toolbar-button kendoEditorRedo></kendo-toolbar-button>
|
||||
<kendo-toolbar-separator></kendo-toolbar-separator>
|
||||
<!-- Custom MD2 Icon button -->
|
||||
<kendo-toolbar-button (click)="showInsertMD2Icon()">
|
||||
Insert Icon
|
||||
</kendo-toolbar-button>
|
||||
</kendo-toolbar>
|
||||
</kendo-editor>
|
||||
@ -1,6 +1,6 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MD2HtmlEditorComponent } from './md2-html-editor.component';
|
||||
import { GamesModule } from '../../games.module';
|
||||
|
||||
describe('MD2HtmlEditorComponent', () => {
|
||||
let component: MD2HtmlEditorComponent;
|
||||
@ -8,7 +8,7 @@ describe('MD2HtmlEditorComponent', () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
imports: [MD2HtmlEditorComponent]
|
||||
imports: [GamesModule]
|
||||
})
|
||||
.compileComponents();
|
||||
|
||||
|
||||
@ -1,39 +1,112 @@
|
||||
import { Component, ElementRef, EventEmitter, Inject, Input, NgZone, Output, PLATFORM_ID, Renderer2 } from '@angular/core';
|
||||
import { Component, ElementRef, EventEmitter, Inject, Input, NgZone, Output, PLATFORM_ID, Renderer2, ViewChild } from '@angular/core';
|
||||
import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
|
||||
import { EditorComponent } from '@progress/kendo-angular-editor';
|
||||
|
||||
import { MsgBoxService } from '../../../services/msg-box.service';
|
||||
import { DropDownOption } from '../../../entity/dropDownOption';
|
||||
import { MD2Icon } from '../massive-darkness2.model';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||
import { MD2IconPickerDlgComponent } from './md2-icon-picker-dlg.component';
|
||||
import { NbDialogService } from '@nebular/theme';
|
||||
|
||||
@Component({
|
||||
selector: 'md2-html-editor',
|
||||
templateUrl: './md2-html-editor.component.html',
|
||||
styleUrl: './md2-html-editor.component.scss'
|
||||
})
|
||||
export class MD2HtmlEditorComponent implements ControlValueAccessor {
|
||||
@ViewChild(EditorComponent) editor: EditorComponent;
|
||||
|
||||
value: string = '';
|
||||
disabled: boolean = false;
|
||||
|
||||
customCssClass = '.MD2Icon{font-family: "Massive Darkness 2", sans-serif !important; font-size: 40px; margin-left:5px} body{font-size: 30px; }';
|
||||
|
||||
// ControlValueAccessor interface
|
||||
private onChangeFn = (value: string) => { };
|
||||
private onTouchedFn = () => { };
|
||||
|
||||
constructor(
|
||||
private msgBoxService: MsgBoxService,
|
||||
private md2StateService: MD2StateService,
|
||||
private dialogService: NbDialogService,
|
||||
elementRef: ElementRef, ngZone: NgZone, @Inject(PLATFORM_ID) platformId: Object) {
|
||||
|
||||
}
|
||||
|
||||
// ControlValueAccessor implementation
|
||||
writeValue(value: string): void {
|
||||
this.value = value || '';
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: string) => void): void {
|
||||
this.onChangeFn = fn;
|
||||
}
|
||||
|
||||
registerOnTouched(fn: () => void): void {
|
||||
this.onTouchedFn = fn;
|
||||
}
|
||||
|
||||
setDisabledState(isDisabled: boolean): void {
|
||||
this.disabled = isDisabled;
|
||||
}
|
||||
|
||||
onChange(value: string): void {
|
||||
this.value = value;
|
||||
this.onChangeFn(value);
|
||||
}
|
||||
|
||||
onTouched(): void {
|
||||
this.onTouchedFn();
|
||||
}
|
||||
|
||||
showInsertMD2Icon() {
|
||||
this.dialogService.open(MD2IconPickerDlgComponent, {
|
||||
closeOnBackdropClick: true,
|
||||
closeOnEsc: true
|
||||
}).onClose.pipe(first()).subscribe((html: string) => {
|
||||
if (html && this.editor) {
|
||||
// Insert the HTML content at the current cursor position
|
||||
// Use ProseMirror's dispatch method to insert content at cursor
|
||||
const view = this.editor.view;
|
||||
if (view && view.state) {
|
||||
try {
|
||||
// Parse the HTML content
|
||||
const dom = document.createElement('div');
|
||||
dom.innerHTML = html;
|
||||
|
||||
// Use ProseMirror's DOMParser to parse HTML
|
||||
// Access it from the view's state
|
||||
const pmState = view.state;
|
||||
|
||||
//Insert
|
||||
|
||||
//Get all icon html
|
||||
let iconHtml = [];
|
||||
for (let icon of Object.values(MD2Icon) as MD2Icon[]) {
|
||||
iconHtml.push(this.md2StateService.iconHtml(icon));
|
||||
// Use the editor's exec method or manual dispatch
|
||||
if ((this.editor as any).exec) {
|
||||
// Try using exec with 'insertHTML' command if available
|
||||
try {
|
||||
(this.editor as any).exec('insertHTML', html);
|
||||
} catch (e) {
|
||||
throw new Error('insertHTML not supported');
|
||||
}
|
||||
|
||||
//Show dialog with all icon html
|
||||
//then user can select one icon and insert it to the html editor current cursor position
|
||||
|
||||
} else {
|
||||
throw new Error('exec method not available');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error inserting HTML:', e);
|
||||
// Fallback: append to the end
|
||||
const currentValue = this.editor.value || '';
|
||||
const newValue = currentValue + ' ' + html;
|
||||
this.value = newValue;
|
||||
this.onChange(newValue);
|
||||
}
|
||||
} else {
|
||||
// Fallback: append to the end
|
||||
const currentValue = this.editor.value || '';
|
||||
const newValue = currentValue + ' ' + html;
|
||||
this.value = newValue;
|
||||
this.onChange(newValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,81 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NbDialogRef } from '@nebular/theme';
|
||||
import { MD2Icon } from '../massive-darkness2.model';
|
||||
import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'md2-icon-picker-dlg',
|
||||
template: `
|
||||
<nb-card style="max-width: 800px;">
|
||||
<nb-card-header>
|
||||
<h5>Insert MD2 Icon</h5>
|
||||
</nb-card-header>
|
||||
<nb-card-body>
|
||||
<div class="icon-grid">
|
||||
<div
|
||||
*ngFor="let iconData of iconList"
|
||||
(click)="selectIcon(iconData)"
|
||||
class="icon-item"
|
||||
[innerHTML]="iconData.html">
|
||||
</div>
|
||||
</div>
|
||||
</nb-card-body>
|
||||
<nb-card-footer>
|
||||
<button nbButton status="primary" (click)="cancel()">Cancel</button>
|
||||
</nb-card-footer>
|
||||
</nb-card>
|
||||
`,
|
||||
styles: [`
|
||||
.icon-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
|
||||
gap: 10px;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.icon-item {
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s;
|
||||
}
|
||||
.icon-item:hover {
|
||||
background-color: #f0f0f0;
|
||||
border-color: #007bff;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
`]
|
||||
})
|
||||
export class MD2IconPickerDlgComponent implements OnInit {
|
||||
|
||||
iconList: Array<{ icon: MD2Icon, name: string, html: string }> = [];
|
||||
|
||||
constructor(
|
||||
private dlgRef: NbDialogRef<MD2IconPickerDlgComponent>,
|
||||
private md2StateService: MD2StateService
|
||||
) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
// Get all icons
|
||||
for (let icon of Object.values(MD2Icon).filter(val => typeof val === 'number') as MD2Icon[]) {
|
||||
this.iconList.push({
|
||||
icon: icon,
|
||||
name: MD2Icon[icon],
|
||||
html: this.md2StateService.iconHtml(icon)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
selectIcon(iconData: { icon: MD2Icon, name: string, html: string }) {
|
||||
this.dlgRef.close(iconData.html);
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.dlgRef.close(null);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user