This commit is contained in:
Chris Chen
2024-04-08 16:48:41 -07:00
parent 0ee2e7e545
commit cd9021d9c0
19 changed files with 438 additions and 39 deletions
+8 -2
View File
@@ -32,6 +32,9 @@ import { MobAttackInfoComponent } from './massive-darkness2/mobs/mob-detail-info
import { MobDefInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-def-info/mob-def-info.component';
import { MobCombatInfoComponent } from './massive-darkness2/mobs/mob-detail-info/mob-combat-info/mob-combat-info.component';
import { MobStandInfoComponent } from './massive-darkness2/mobs/mob-stand-info/mob-stand-info.component';
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';
@NgModule({
@@ -59,7 +62,8 @@ import { MobStandInfoComponent } from './massive-darkness2/mobs/mob-stand-info/m
MobAttackInfoComponent,
MobDefInfoComponent,
MobCombatInfoComponent,
MobStandInfoComponent
MobStandInfoComponent,
MD2HtmlEditorComponent
],
imports: [
CommonModule,
@@ -89,7 +93,9 @@ import { MobStandInfoComponent } from './massive-darkness2/mobs/mob-stand-info/m
CurrencyInputModule,
NbDialogModule.forRoot(),
AlertDlgModule,
DropDownListModule
DropDownListModule,
HtmlEditorModule,
EditorModule
]
})
export class GamesModule { }
@@ -8,6 +8,7 @@ export class MD2Clone {
let cloneObj = null;
switch (type) {
case "TreasureItem":
//let copy = structuredClone(obj);
return new TreasureItem(obj['type'], 1);
break;
case "MobInfo":
@@ -83,7 +83,7 @@ export class HeroDashboardComponent extends MD2Base implements OnInit {
}
public get allowAttack(): boolean {
return this.hero.uiBossFight || (!!this.md2Service.mobs && this.md2Service.mobs.length > 0) || (!!this.md2Service.roamingMonsters && this.md2Service.roamingMonsters.length > 0);
return this.hero.uiBossFight || this.md2Service.mobs?.length > 0 || this.md2Service.roamingMonsters?.length > 0;
}
ngOnInit(): void {
@@ -11,6 +11,9 @@
</nb-accordion-item>
</nb-accordion>
</div> -->
<div class="col-12">
<md2-html-editor></md2-html-editor>
</div>
<div class="col-12 col-md-5">
<nb-card>
@@ -0,0 +1 @@
<editor [init]="htmlEditorSetting"></editor>
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MD2HtmlEditorComponent } from './md2-html-editor.component';
describe('MD2HtmlEditorComponent', () => {
let component: MD2HtmlEditorComponent;
let fixture: ComponentFixture<MD2HtmlEditorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [MD2HtmlEditorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(MD2HtmlEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,109 @@
import { Component, ElementRef, EventEmitter, Input, Output, Renderer2 } from '@angular/core';
import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
import { Editor, RawEditorOptions } from 'tinymce';
import { MsgBoxService } from '../../../services/msg-box.service';
import { DropDownOption } from '../../../entity/dropDownOption';
import { MD2Icon } from '../massive-darkness2.model';
import { first } from 'rxjs/operators';
@Component({
selector: 'md2-html-editor',
templateUrl: './md2-html-editor.component.html',
styleUrl: './md2-html-editor.component.scss'
})
export class MD2HtmlEditorComponent implements ControlValueAccessor, Validator {
private _lastBlurValue: string;
readonly: boolean = false;
isRequired: boolean = false;
@Input() id? = '';
@Input() name = '';
@Input() data: string;
@Output() focus = new EventEmitter();
@Output() blur = new EventEmitter<string>();
@Input('readonly')
public set input_readonly(value) {
this.readonly = typeof value !== 'undefined' && value !== false;
}
@Input('isRequired')
public set input_isRequired(value) {
this.isRequired = typeof value !== 'undefined' && value !== false;
}
constructor(
private msgBoxService: MsgBoxService,
private elementRef: ElementRef,
private renderer: Renderer2) {
this.htmlEditorSetting.base_url = '/tinymce';
this.htmlEditorSetting.suffix = '.min';
this.htmlEditorSetting['parentComponent'] = this;
this.htmlEditorSetting.plugins = 'lists link image table code';
this.htmlEditorSetting.toolbar2 = 'customInsertButton'
this.htmlEditorSetting.setup = this.htmlEditorSetup;
}
htmlEditorSetting: RawEditorOptions = {};
htmlEditorSetup(editor: Editor) {
let component = this.htmlEditorSetting['parentComponent'] as MD2HtmlEditorComponent;
editor.ui.registry.addButton('customInsertButton', {
icon: 'code-sample',
text: 'MD2 Icon',
onAction: (_) => component.showInsertMD2Icon(editor)
});
}
showInsertMD2Icon(editor: Editor) {
var iconKeys = Object.keys(MD2Icon);
iconKeys = iconKeys.slice(iconKeys.length / 2, iconKeys.length - 1);
this.msgBoxService.showInputbox('Insert MD2 Icon', '', { inputType: 'dropdown', dropDownOptions: iconKeys.map(k => new DropDownOption(k, k)) })
.pipe(first()).subscribe(result => {
editor.insertContent(`&nbsp;<strong>${result}</strong>&nbsp;`);
this.writeValue(editor.getContent());
});
}
validate(control: AbstractControl): ValidationErrors {
// if (this.required && (this.value == null || this.value == 0)) {
// return { 'currency': '' };
// }
return null;
}
registerOnValidatorChange?(fn: () => void): void {
}
onChange = (value: number) => { };
onTouched = () => { };
writeValue(obj: string): void {
this.data = obj;
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.readonly = isDisabled;
}
ngOnInit() {
}
ngAfterViewInit() {
this.renderer.removeAttribute(this.elementRef.nativeElement, 'id')
}
onBlur() {
if (this._lastBlurValue != this.data) {
this._lastBlurValue = this.data;
this.blur.emit(this.data);
}
}
}
@@ -5,7 +5,6 @@ import { Observable } from 'rxjs';
import { EMPTY } from 'rxjs';
import { environment } from '../../../environments/environment';
import { DateUtils } from '../../utilities/date-utils';
@Injectable()
export class ApiPrefixInterceptor implements HttpInterceptor {
constructor(
@@ -0,0 +1,4 @@
<!-- <editor [init]="{
base_url: '/tinymce',
suffix: '.min' , height: 300
}"></editor> -->
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HtmlEditorComponent } from './html-editor.component';
describe('HtmlEditorComponent', () => {
let component: HtmlEditorComponent;
let fixture: ComponentFixture<HtmlEditorComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HtmlEditorComponent]
})
.compileComponents();
fixture = TestBed.createComponent(HtmlEditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
@@ -0,0 +1,48 @@
import { Component, ElementRef, EventEmitter, Inject, Input, NgZone, Output, PLATFORM_ID, Renderer2 } from '@angular/core';
import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
import { EditorComponent } from '@tinymce/tinymce-angular';
import { HtmlEditorSettings } from './html-editor.model';
@Component({
selector: 'my-html-editor',
templateUrl: './html-editor.component.html',
styleUrl: './html-editor.component.scss'
})
export class HtmlEditorComponent extends EditorComponent implements ControlValueAccessor {
private _elementRef2: ElementRef;
writeValue(value: string | null): void {
super.writeValue(value);
}
registerOnChange(fn: (value: string) => void): void {
super.registerOnChange(fn);
}
registerOnTouched(fn: any): void {
super.registerOnTouched(fn);
}
setDisabledState(isDisabled: boolean): void {
super.setDisabledState(isDisabled);
}
constructor(elementRef: ElementRef, ngZone: NgZone, @Inject(PLATFORM_ID) platformId: Object) {
super(elementRef, ngZone, platformId);
// this.elementRef is private. Need a duplicate
this._elementRef2 = elementRef;
}
checkDomAttachment(): boolean {
// check if component has been attached to DOM yet
return document.body.contains(this._elementRef2.nativeElement);
}
ngAfterViewInit() {
this.init = new HtmlEditorSettings({});
super.ngAfterViewInit();
}
initialise: () => {}
private InitializeEditor() {
this.init = new HtmlEditorSettings({});
//super.initialise();
}
}
+147
View File
@@ -0,0 +1,147 @@
import { RawEditorOptions } from "tinymce";
export class HtmlEditorSettings implements RawEditorOptions {
parentComponent?: any = null;
base_url?: string = '/tinymce';
suffix?: string = '.min';
menubar?: boolean = false;
inline?: boolean = false;
indent_use_margin? = false;
theme?: string = 'silver';
plugins?: string[] = [
'link',
'lists',
'autolink',
'noneditable',
'table',
'code',
'fullscreen'
];
toolbar?: string[] = [
'undo redo | bold italic underline | fontselect fontsizeselect forecolor backcolor | alignleft aligncenter alignright alignfull | numlist bullist outdent indent | code fullscreen'
];
extraToolBar?: string;
fullscreen_native?: boolean = false;
statusbar?: boolean = false;
noneditable_editable_class?: string = 'editable';
noneditable_noneditable_class?: string = 'templateParameter';
autoresize_bottom_margin?: number = 2;
min_height?: number = 200;
height?: number | string;
content_style?: string =
'.parameterInput { color:antiquewhite; background:lightslategrey; padding-left:5px; padding-right:5px; }' +
'.reportParameter { color:antiquewhite; background:slateblue; padding-left:5px; padding-right:5px;} ' +
'.parameterInput:empty:not(:focus):before { content: \' \' attr(data-name) \' (Empty)\'; }';
extended_valid_elements?: string = `parameter[id|style|class]`;
constructor(config: Partial<HtmlEditorSettings>) {
if (config.extraToolBar) {
this.toolbar[0] += ' ' + config.extraToolBar;
}
Object.assign(this, config);
}
}
export interface ITinyMceEditor {
// focus(skipFocus: Boolean);
// addCommand(name: String, callback: Function, scope: Object);
// hasPlugin(name: String, loaded: Boolean): Boolean;
// getDoc(): HTMLElement;
// getContent(args?: Object): String;
// //https://www.tiny.cloud/docs/tinymce/6/apis/tinymce.editor/#insertContent
// insertContent(content: String, args?: Object);
// isDirty(): Boolean;
// off(name?: String, callback?: Function): Object;
// instance.on('event', (e) => {
// // Callback logic
// });
on(name: String, callback?: Function, prepend?: Boolean): Object;
resetContent(initialContent: String);
documentBaseUrl: string;
baseUri: string;
id: string;
plugins: Record<string, Plugin>;
documentBaseURI: string;
baseURI: string;
contentCSS: string[];
contentStyles: string[];
setMode: (mode: string) => void;
loadedCSS: Record<string, any>;
suffix: string;
inline: boolean;
isNotDirty: boolean;
callbackLookup: any;
bodyElement: HTMLElement;
bookmark: any;
composing: boolean;
container: HTMLElement;
contentAreaContainer: HTMLElement;
contentDocument: Document;
contentWindow: Window;
delegates: Record<string, (event: any) => void>;
destroyed: boolean;
editorContainer: HTMLElement;
eventRoot?: Element;
formElement: HTMLElement;
formEventDelegate: (e: Event) => void;
hasHiddenInput: boolean;
hasVisual: boolean;
hidden: boolean;
iframeElement: HTMLIFrameElement | null;
iframeHTML: string;
initialized: boolean;
orgDisplay: string;
orgVisibility: string;
readonly: boolean;
removed: boolean;
startContent: string;
targetElm: HTMLElement;
theme: string;
validate: boolean;
_beforeUnload: () => void;
_mceOldSubmit: any;
_pendingNativeEvents: string[];
_skinLoaded: boolean;
render(): void;
focus(skipFocus?: boolean): void;
hasFocus(): boolean;
execCallback(name: string, ...x: any[]): any;
getParam<T>(name: string, defaultVal: T, type?: string): T;
hasPlugin(name: string, loaded?: boolean): boolean;
nodeChanged(args?: any): void;
execCommand(cmd: string, ui?: boolean, value?: any, args?: any): boolean;
queryCommandState(cmd: string): boolean;
queryCommandValue(cmd: string): string;
queryCommandSupported(cmd: string): boolean;
show(): void;
hide(): void;
isHidden(): boolean;
setProgressState(state: boolean, time?: number): void;
load(args?: any): string;
save(args?: any): string;
setContent(content: string): string;
getContent(): string;
insertContent(content: string, args?: any): void;
resetContent(initialContent?: string): void;
isDirty(): boolean;
setDirty(state: boolean): void;
getContainer(): HTMLElement;
getContentAreaContainer(): HTMLElement;
getElement(): HTMLElement;
getWin(): Window;
getDoc(): Document;
getBody(): HTMLElement;
convertURL(url: string, name: string, elm?: any): string;
addVisual(elm?: HTMLElement): void;
remove(): void;
destroy(automatic?: boolean): void;
addButton(): void;
addSidebar(): void;
addMenuItem(): void;
addContextToolbar(): void;
}
@@ -0,0 +1,19 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HtmlEditorComponent } from './html-editor.component';
import { EditorModule } from '@tinymce/tinymce-angular';
import { FormsModule } from '@angular/forms';
@NgModule({
declarations: [HtmlEditorComponent],
imports: [
CommonModule,
FormsModule,
EditorModule
],
exports: [HtmlEditorComponent],
})
export class HtmlEditorModule { }
+1
View File
@@ -8,4 +8,5 @@ export class EnumUtils {
}
return false;
}
}