WIP
This commit is contained in:
parent
b8b35645ac
commit
46ec236ed5
@ -43,10 +43,12 @@ import { GridModule } from '@progress/kendo-angular-grid';
|
||||
import { DialogModule } from '@progress/kendo-angular-dialog';
|
||||
import { InputsModule } from '@progress/kendo-angular-inputs';
|
||||
import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
|
||||
import { LayoutModule } from '@progress/kendo-angular-layout';
|
||||
import { ReactiveFormsModule } from '@angular/forms';
|
||||
import { MD2MobInfoMaintenanceComponent } from './massive-darkness2/md2-mob-info-maintenance/md2-mob-info-maintenance.component';
|
||||
import { MD2MobInfoEditorComponent } from './massive-darkness2/md2-mob-info-maintenance/md2-mob-info-editor/md2-mob-info-editor.component';
|
||||
import { MD2MobInfoDetailComponent } from './massive-darkness2/md2-mob-info-maintenance/md2-mob-info-detail/md2-mob-info-detail.component';
|
||||
import { MD2MobSkillEditorComponent } from './massive-darkness2/md2-mob-info-maintenance/md2-mob-skill-editor/md2-mob-skill-editor.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
@ -79,7 +81,8 @@ import { MD2MobInfoDetailComponent } from './massive-darkness2/md2-mob-info-main
|
||||
MD2IconPickerDlgComponent,
|
||||
MD2MobInfoMaintenanceComponent,
|
||||
MD2MobInfoEditorComponent,
|
||||
MD2MobInfoDetailComponent
|
||||
MD2MobInfoDetailComponent,
|
||||
MD2MobSkillEditorComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
@ -119,7 +122,8 @@ import { MD2MobInfoDetailComponent } from './massive-darkness2/md2-mob-info-main
|
||||
GridModule,
|
||||
DialogModule,
|
||||
InputsModule,
|
||||
DropDownsModule
|
||||
DropDownsModule,
|
||||
LayoutModule
|
||||
]
|
||||
})
|
||||
export class GamesModule { }
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
<kendo-editor [value]="value" (valueChange)="onChange($event)" (blur)="onTouched()" [disabled]="disabled"
|
||||
[schema]="messageTemplateSchema" [iframe]="false">
|
||||
[schema]="messageTemplateSchema" [iframe]="false" class="h-100">
|
||||
<kendo-toolbar>
|
||||
<!-- Standard editing tools -->
|
||||
<kendo-toolbar-buttongroup>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, ElementRef, EventEmitter, Inject, Input, NgZone, Output, PLATFORM_ID, Renderer2, ViewChild, AfterViewInit } from '@angular/core';
|
||||
import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors } from '@angular/forms';
|
||||
import { Component, ElementRef, EventEmitter, Inject, Input, NgZone, Output, PLATFORM_ID, Renderer2, ViewChild, AfterViewInit, forwardRef, ChangeDetectorRef } from '@angular/core';
|
||||
import { ControlValueAccessor, Validator, AbstractControl, ValidationErrors, NG_VALUE_ACCESSOR } from '@angular/forms';
|
||||
import { EditorComponent, NodeSpec, schema, Schema, FontSizeItem } from '@progress/kendo-angular-editor';
|
||||
|
||||
import { MsgBoxService } from '../../../services/msg-box.service';
|
||||
@ -10,10 +10,18 @@ import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||
import { MD2IconPickerDlgComponent } from './md2-icon-picker-dlg.component';
|
||||
import { NbDialogService } from '@nebular/theme';
|
||||
import { DOMParser as ProseMirrorDOMParser } from 'prosemirror-model';
|
||||
import { DialogService } from '@progress/kendo-angular-dialog';
|
||||
@Component({
|
||||
selector: 'md2-html-editor',
|
||||
templateUrl: './md2-html-editor.component.html',
|
||||
styleUrl: './md2-html-editor.component.scss'
|
||||
styleUrl: './md2-html-editor.component.scss',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALUE_ACCESSOR,
|
||||
useExisting: forwardRef(() => MD2HtmlEditorComponent),
|
||||
multi: true
|
||||
}
|
||||
]
|
||||
})
|
||||
export class MD2HtmlEditorComponent implements ControlValueAccessor, AfterViewInit {
|
||||
@ViewChild(EditorComponent) editor: EditorComponent;
|
||||
@ -52,7 +60,8 @@ export class MD2HtmlEditorComponent implements ControlValueAccessor, AfterViewIn
|
||||
constructor(
|
||||
private msgBoxService: MsgBoxService,
|
||||
private md2StateService: MD2StateService,
|
||||
private dialogService: NbDialogService,
|
||||
private dialogService: DialogService,
|
||||
private cdr: ChangeDetectorRef,
|
||||
elementRef: ElementRef, ngZone: NgZone, @Inject(PLATFORM_ID) platformId: Object) {
|
||||
|
||||
}
|
||||
@ -71,12 +80,38 @@ export class MD2HtmlEditorComponent implements ControlValueAccessor, AfterViewIn
|
||||
this.fontSizeDropdown.defaultItem = this.defaultFontSize;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the editor value is set if writeValue was called before view init
|
||||
if (this.editor && this.value && this.editor.value !== this.value) {
|
||||
this.editor.value = this.value;
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// ControlValueAccessor implementation
|
||||
writeValue(value: string): void {
|
||||
this.value = value || '';
|
||||
writeValue(value: string | null | undefined): void {
|
||||
const newValue = value || '';
|
||||
|
||||
// Only update if the value actually changed to avoid unnecessary updates
|
||||
if (this.value !== newValue) {
|
||||
this.value = newValue;
|
||||
|
||||
// Angular's [value] binding will handle updating the editor
|
||||
// But if editor is already initialized and value is out of sync, ensure sync
|
||||
if (this.editor && this.editor.value !== this.value) {
|
||||
// Use setTimeout to avoid ExpressionChangedAfterItHasBeenCheckedError
|
||||
setTimeout(() => {
|
||||
if (this.editor && this.editor.value !== this.value) {
|
||||
this.editor.value = this.value;
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// Trigger change detection to ensure the binding updates
|
||||
if (!this.cdr['destroyed']) {
|
||||
this.cdr.markForCheck();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
registerOnChange(fn: (value: string) => void): void {
|
||||
@ -92,8 +127,11 @@ export class MD2HtmlEditorComponent implements ControlValueAccessor, AfterViewIn
|
||||
}
|
||||
|
||||
onChange(value: string): void {
|
||||
this.value = value;
|
||||
this.onChangeFn(value);
|
||||
// Only update if value actually changed to prevent infinite loops
|
||||
if (this.value !== value) {
|
||||
this.value = value || '';
|
||||
this.onChangeFn(this.value);
|
||||
}
|
||||
}
|
||||
|
||||
onTouched(): void {
|
||||
@ -101,10 +139,12 @@ export class MD2HtmlEditorComponent implements ControlValueAccessor, AfterViewIn
|
||||
}
|
||||
|
||||
showInsertMD2Icon() {
|
||||
this.dialogService.open(MD2IconPickerDlgComponent, {
|
||||
closeOnBackdropClick: true,
|
||||
closeOnEsc: true
|
||||
}).onClose.pipe(first()).subscribe((html: string) => {
|
||||
this.dialogService.open({
|
||||
title: 'Insert MD2 Icon',
|
||||
content: MD2IconPickerDlgComponent,
|
||||
width: '800px',
|
||||
height: 600
|
||||
}).result.subscribe((html: string) => {
|
||||
if (html && this.editor) {
|
||||
this.insertAfterSelection(html, true);
|
||||
return;
|
||||
|
||||
@ -2,16 +2,11 @@ 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';
|
||||
import { DialogRef } from '@progress/kendo-angular-dialog';
|
||||
|
||||
@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="md2-icon-grid">
|
||||
template: ` <div class="md2-icon-grid">
|
||||
<div
|
||||
*ngFor="let iconData of iconList"
|
||||
(click)="selectIcon(iconData)"
|
||||
@ -19,13 +14,23 @@ import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||
[innerHTML]="iconData.html">
|
||||
</div>
|
||||
</div>
|
||||
<!-- <nb-card>
|
||||
<nb-card-header>
|
||||
<h5>Insert MD2 Icon</h5>
|
||||
</nb-card-header>
|
||||
<nb-card-body>
|
||||
|
||||
</nb-card-body>
|
||||
<nb-card-footer>
|
||||
<button nbButton status="primary" (click)="cancel()">Cancel</button>
|
||||
</nb-card-footer>
|
||||
</nb-card>
|
||||
</nb-card> -->
|
||||
`,
|
||||
styles: [`
|
||||
nb-card{
|
||||
max-width: 800px;
|
||||
z-index: 1050;
|
||||
}
|
||||
.md2-icon-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(60px, 1fr));
|
||||
@ -57,7 +62,7 @@ export class MD2IconPickerDlgComponent implements OnInit {
|
||||
iconList: Array<{ icon: MD2Icon, name: string, html: string }> = [];
|
||||
|
||||
constructor(
|
||||
private dlgRef: NbDialogRef<MD2IconPickerDlgComponent>,
|
||||
private dlgRef: DialogRef,
|
||||
private md2StateService: MD2StateService
|
||||
) { }
|
||||
|
||||
|
||||
@ -1 +1 @@
|
||||
<span class="MD2Icon {{iconName}} {{iconClass}} {{sizeClass}}"></span>
|
||||
<span [innerHtml]="iconHtml" class="g-font-size-20 g-line-height-0 mx-2"></span>
|
||||
@ -1,5 +1,6 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { MD2Icon } from '../massive-darkness2.model';
|
||||
import { MD2StateService } from '../../../services/MD2/md2-state.service';
|
||||
|
||||
@Component({
|
||||
selector: 'md2-icon',
|
||||
@ -10,13 +11,17 @@ export class MD2IconComponent implements OnInit {
|
||||
|
||||
@Input() iconClass: string = 'mr-1';
|
||||
|
||||
|
||||
iconHtml: string;
|
||||
private _icon: string | MD2Icon;
|
||||
|
||||
@Input() public set icon(v: string | MD2Icon) {
|
||||
if (this._icon != v) {
|
||||
this._icon = v;
|
||||
|
||||
//if it's string, convert it to MD2Icon
|
||||
if (typeof v === 'string') {
|
||||
v = MD2Icon[v];
|
||||
}
|
||||
this.iconHtml = this.md2StateService.iconHtml(v as MD2Icon);
|
||||
}
|
||||
if (this.isMD2Icon(v)) {
|
||||
this.iconName = MD2Icon[v].toLowerCase();
|
||||
@ -30,7 +35,7 @@ export class MD2IconComponent implements OnInit {
|
||||
}
|
||||
@Input() size: string = 'sm';
|
||||
iconName: string;
|
||||
constructor() { }
|
||||
constructor(private md2StateService: MD2StateService) { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
@ -158,12 +158,11 @@
|
||||
|
||||
<kendo-grid #skillsGrid [data]="skillsData" [loading]="isLoading" [pageSize]="skillsState.take"
|
||||
[skip]="skillsState.skip" [sortable]="true" [filterable]="true" [pageable]="true" [height]="400"
|
||||
kendoGridTemplateEditing (save)="saveSkillHandler($event)" (remove)="removeSkillHandler($event)"
|
||||
(dataStateChange)="skillsState = $event">
|
||||
(remove)="removeSkillHandler($event)" (dataStateChange)="skillsState = $event">
|
||||
|
||||
<kendo-grid-column field="name" title="Name" [width]="150">
|
||||
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
|
||||
<input kendoTextBox [(ngModel)]="dataItem.name" name="name" placeholder="Enter skill name" />
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
{{ dataItem.name }}
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
@ -171,55 +170,37 @@
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
{{ getSkillTypeName(dataItem.type) }}
|
||||
</ng-template>
|
||||
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
|
||||
<kendo-dropdownlist [(ngModel)]="dataItem.type" name="type" [data]="skillTypes" [valueField]="'value'"
|
||||
[textField]="'text'">
|
||||
</kendo-dropdownlist>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-column field="skillTarget" title="Target" [width]="150">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
{{ getSkillTargetName(dataItem.skillTarget) }}
|
||||
</ng-template>
|
||||
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
|
||||
<kendo-dropdownlist [(ngModel)]="dataItem.skillTarget" name="skillTarget" [data]="skillTargets"
|
||||
[valueField]="'value'" [textField]="'text'">
|
||||
</kendo-dropdownlist>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-column field="clawRoll" title="Claw Roll" [width]="100">
|
||||
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
|
||||
<kendo-numerictextbox [(ngModel)]="dataItem.clawRoll" name="clawRoll" [min]="0">
|
||||
</kendo-numerictextbox>
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
{{ dataItem.clawRoll }}
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-column field="skillRoll" title="Skill Roll" [width]="100">
|
||||
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
|
||||
<kendo-numerictextbox [(ngModel)]="dataItem.skillRoll" name="skillRoll" [min]="0">
|
||||
</kendo-numerictextbox>
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
{{ dataItem.skillRoll }}
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-column field="description" title="Description" [width]="300">
|
||||
<ng-template kendoGridEditTemplate let-dataItem="dataItem">
|
||||
<textarea kendoTextArea [(ngModel)]="dataItem.description" name="description"
|
||||
placeholder="Enter skill description" rows="3">
|
||||
</textarea>
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<div [innerHTML]="dataItem.description"></div>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-command-column title="Actions" [width]="200">
|
||||
<ng-template kendoGridCellTemplate let-isNew="isNew" let-dataItem="dataItem" let-rowIndex="rowIndex">
|
||||
<button kendoGridEditCommand [primary]="true">Edit</button>
|
||||
<button kendoButton [primary]="true" (click)="editSkillHandler(dataItem)">Edit</button>
|
||||
<button kendoGridRemoveCommand>Remove</button>
|
||||
</ng-template>
|
||||
<ng-template kendoGridEditCommandTemplate let-isNew="isNew" let-rowIndex="rowIndex">
|
||||
<button kendoGridSaveCommand>Save</button>
|
||||
<button kendoGridCancelCommand>Cancel</button>
|
||||
</ng-template>
|
||||
</kendo-grid-command-column>
|
||||
</kendo-grid>
|
||||
</div>
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { Component, Input, OnInit, ViewChild } from '@angular/core';
|
||||
import { DialogRef, DialogContentBase } from '@progress/kendo-angular-dialog';
|
||||
import { DialogRef, DialogContentBase, DialogService } from '@progress/kendo-angular-dialog';
|
||||
import { GridComponent, GridDataResult } from '@progress/kendo-angular-grid';
|
||||
import { State } from '@progress/kendo-data-query';
|
||||
import { first } from 'rxjs/operators';
|
||||
@ -8,6 +8,7 @@ import { MobType } from '../../massive-darkness2.model';
|
||||
import { MobSkillType } from '../../massive-darkness2.model.boss';
|
||||
import { MD2MobLevelInfoService, MD2MobSkillService } from '../../service/massive-darkness2.service';
|
||||
import { MsgBoxService } from '../../../../services/msg-box.service';
|
||||
import { MD2MobSkillEditorComponent } from '../md2-mob-skill-editor/md2-mob-skill-editor.component';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-md2-mob-info-detail',
|
||||
@ -48,6 +49,7 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
||||
|
||||
constructor(
|
||||
public dialog: DialogRef,
|
||||
private dialogService: DialogService,
|
||||
private mobLevelInfoService: MD2MobLevelInfoService,
|
||||
private mobSkillService: MD2MobSkillService,
|
||||
private msgBoxService: MsgBoxService
|
||||
@ -224,45 +226,64 @@ export class MD2MobInfoDetailComponent extends DialogContentBase implements OnIn
|
||||
description: ''
|
||||
};
|
||||
|
||||
if (!this.selectedLevelInfo.skills) {
|
||||
this.selectedLevelInfo.skills = [];
|
||||
this.openSkillEditor(newSkill, true);
|
||||
}
|
||||
|
||||
public editSkillHandler(dataItem: MD2MobSkill): void {
|
||||
if (!this.selectedLevelInfo) return;
|
||||
|
||||
// Create a copy of the skill for editing
|
||||
const skillCopy: MD2MobSkill = JSON.parse(JSON.stringify(dataItem));
|
||||
this.openSkillEditor(skillCopy, false);
|
||||
}
|
||||
|
||||
private openSkillEditor(skill: MD2MobSkill, isNew: boolean): void {
|
||||
if (!this.selectedLevelInfo) return;
|
||||
|
||||
const dialogRef = this.dialogService.open({
|
||||
title: isNew ? 'Add New Skill' : 'Edit Skill',
|
||||
content: MD2MobSkillEditorComponent,
|
||||
width: '80vw',
|
||||
height: 700
|
||||
});
|
||||
|
||||
const editor = dialogRef.content.instance;
|
||||
editor.isAdding = isNew;
|
||||
editor.data = skill;
|
||||
editor.mobLevelInfoId = this.selectedLevelInfo.id;
|
||||
|
||||
// Force model re-initialization after data is set
|
||||
setTimeout(() => {
|
||||
editor.initializeModel();
|
||||
}, 0);
|
||||
|
||||
dialogRef.result.subscribe(result => {
|
||||
if (result && typeof result === 'object' && 'id' in result) {
|
||||
this.handleSkillSaved(result as MD2MobSkill, isNew);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private handleSkillSaved(result: MD2MobSkill, isNew: boolean): void {
|
||||
if (!this.selectedLevelInfo) return;
|
||||
|
||||
if (isNew) {
|
||||
if (!this.selectedLevelInfo.skills) {
|
||||
this.selectedLevelInfo.skills = [];
|
||||
}
|
||||
this.selectedLevelInfo.skills.push(result);
|
||||
} else {
|
||||
const index = this.selectedLevelInfo.skills?.findIndex(s => s.id === result.id);
|
||||
if (index !== undefined && index !== -1 && this.selectedLevelInfo.skills) {
|
||||
this.selectedLevelInfo.skills[index] = result;
|
||||
}
|
||||
}
|
||||
this.selectedLevelInfo.skills.push(newSkill);
|
||||
this.loadSkills(this.selectedLevelInfo);
|
||||
}
|
||||
|
||||
public saveSkillHandler({ dataItem, isNew }: any): void {
|
||||
if (isNew) {
|
||||
dataItem.id = this.generateId();
|
||||
dataItem.mobLevelInfoId = this.selectedLevelInfo?.id;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
this.mobSkillService.createOrUpdate(dataItem).pipe(first()).subscribe(result => {
|
||||
this.isLoading = false;
|
||||
if (this.selectedLevelInfo) {
|
||||
if (isNew) {
|
||||
if (!this.selectedLevelInfo.skills) {
|
||||
this.selectedLevelInfo.skills = [];
|
||||
}
|
||||
const index = this.selectedLevelInfo.skills.findIndex(s => s.id === dataItem.id);
|
||||
if (index !== -1) {
|
||||
this.selectedLevelInfo.skills[index] = result;
|
||||
} else {
|
||||
this.selectedLevelInfo.skills.push(result);
|
||||
}
|
||||
} else {
|
||||
const index = this.selectedLevelInfo.skills.findIndex(s => s.id === result.id);
|
||||
if (index !== -1) {
|
||||
this.selectedLevelInfo.skills[index] = result;
|
||||
}
|
||||
}
|
||||
this.loadSkills(this.selectedLevelInfo);
|
||||
}
|
||||
}, error => {
|
||||
this.isLoading = false;
|
||||
console.error('Error saving skill:', error);
|
||||
});
|
||||
// This method is no longer used but kept for backward compatibility
|
||||
// Skills are now edited via dialog
|
||||
}
|
||||
|
||||
public removeSkillHandler({ dataItem }: { dataItem: MD2MobSkill }): void {
|
||||
|
||||
@ -0,0 +1,64 @@
|
||||
<div class="k-dialog-content">
|
||||
<form #form="ngForm" class="k-form">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="k-label">Name</label>
|
||||
<input kendoTextBox [(ngModel)]="model.name" name="name" class="k-input"
|
||||
placeholder="Enter skill name" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label class="k-label">Type *</label>
|
||||
<kendo-dropdownlist [(ngModel)]="selectedSkillType" name="type" [data]="skillTypes"
|
||||
[valueField]="'value'" [textField]="'text'"
|
||||
[defaultItem]="{ value: null, text: 'Select type...' }">
|
||||
</kendo-dropdownlist>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label class="k-label">Target</label>
|
||||
<kendo-dropdownlist [(ngModel)]="selectedSkillTarget" name="skillTarget" [data]="skillTargets"
|
||||
[valueField]="'value'" [textField]="'text'">
|
||||
</kendo-dropdownlist>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label class="k-label"><md2-icon icon="EnemyClaw"></md2-icon>Claw Roll</label>
|
||||
<kendo-numerictextbox [(ngModel)]="model.clawRoll" name="clawRoll" [min]="0" [decimals]="0"
|
||||
[format]="'n0'">
|
||||
</kendo-numerictextbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label class="k-label"><md2-icon icon="EnemySkill"></md2-icon>Skill Roll</label>
|
||||
<kendo-numerictextbox [(ngModel)]="model.skillRoll" name="skillRoll" [min]="0" [decimals]="0"
|
||||
[format]="'n0'">
|
||||
</kendo-numerictextbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="form-group">
|
||||
<label class="k-label">Description</label>
|
||||
<md2-html-editor [(ngModel)]="model.description" name="description"
|
||||
class="htmlEditor"></md2-html-editor>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<kendo-dialog-actions>
|
||||
<button kendoButton (click)="close()">Cancel</button>
|
||||
<button kendoButton [primary]="true" (click)="save()" [disabled]="!isValid || processing">
|
||||
{{ processing ? 'Saving...' : 'Save' }}
|
||||
</button>
|
||||
</kendo-dialog-actions>
|
||||
@ -0,0 +1,8 @@
|
||||
.k-label {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
md2-html-editor {
|
||||
width: 100%;
|
||||
min-height: 300px;
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
import { Component, Input, OnInit, ViewChild, ChangeDetectorRef } from '@angular/core';
|
||||
import { DialogRef, DialogContentBase } from '@progress/kendo-angular-dialog';
|
||||
import { NgForm } from '@angular/forms';
|
||||
import { first } from 'rxjs/operators';
|
||||
import { MD2MobSkill, MobSkillTarget } from '../../massive-darkness2.db.model';
|
||||
import { MobSkillType } from '../../massive-darkness2.model.boss';
|
||||
import { MD2MobSkillService } from '../../service/massive-darkness2.service';
|
||||
|
||||
@Component({
|
||||
selector: 'ngx-md2-mob-skill-editor',
|
||||
templateUrl: './md2-mob-skill-editor.component.html',
|
||||
styleUrls: ['./md2-mob-skill-editor.component.scss']
|
||||
})
|
||||
export class MD2MobSkillEditorComponent extends DialogContentBase implements OnInit {
|
||||
@Input() public data: MD2MobSkill;
|
||||
@Input() public mobLevelInfoId: string;
|
||||
@Input() public isAdding: boolean = false;
|
||||
@ViewChild('form') form: NgForm;
|
||||
|
||||
public model: MD2MobSkill;
|
||||
public processing: boolean = false;
|
||||
public skillTypes: Array<{ value: MobSkillType; text: string }> = [];
|
||||
public skillTargets: Array<{ value: MobSkillTarget | null; text: string }> = [];
|
||||
public selectedSkillType: { value: MobSkillType; text: string } | null = null;
|
||||
public selectedSkillTarget: { value: MobSkillTarget | null; text: string } | null = null;
|
||||
|
||||
constructor(
|
||||
public dialog: DialogRef,
|
||||
private mobSkillService: MD2MobSkillService,
|
||||
private cdr: ChangeDetectorRef
|
||||
) {
|
||||
super(dialog);
|
||||
this.initializeEnums();
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.initializeModel();
|
||||
}
|
||||
|
||||
public initializeModel(): void {
|
||||
const typeValue = this.data?.type !== undefined && this.data?.type !== null ? this.data.type : MobSkillType.Combat;
|
||||
const targetValue = this.data?.skillTarget !== undefined ? this.data.skillTarget : null;
|
||||
|
||||
this.model = {
|
||||
id: this.data?.id || '',
|
||||
mobLevelInfoId: this.mobLevelInfoId || this.data?.mobLevelInfoId || '',
|
||||
type: typeValue,
|
||||
skillTarget: targetValue,
|
||||
clawRoll: this.data?.clawRoll ?? 0,
|
||||
skillRoll: this.data?.skillRoll ?? 1,
|
||||
name: this.data?.name || '',
|
||||
description: this.data?.description || ''
|
||||
};
|
||||
|
||||
// Set selected objects for dropdowns
|
||||
this.selectedSkillType = this.skillTypes.find(t => t.value === typeValue) || this.skillTypes[0] || null;
|
||||
this.selectedSkillTarget = this.skillTargets.find(t => t.value === targetValue) || this.skillTargets[0] || null;
|
||||
|
||||
this.cdr.detectChanges();
|
||||
}
|
||||
|
||||
private initializeEnums(): void {
|
||||
// Initialize MobSkillType options
|
||||
Object.keys(MobSkillType).filter(key => isNaN(Number(key))).forEach(key => {
|
||||
this.skillTypes.push({
|
||||
value: MobSkillType[key] as MobSkillType,
|
||||
text: key
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize MobSkillTarget options
|
||||
this.skillTargets.push({ value: null, text: 'None' });
|
||||
Object.keys(MobSkillTarget).filter(key => isNaN(Number(key))).forEach(key => {
|
||||
this.skillTargets.push({
|
||||
value: MobSkillTarget[key] as MobSkillTarget,
|
||||
text: key
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public close(): void {
|
||||
this.dialog.close();
|
||||
}
|
||||
|
||||
public save(): void {
|
||||
if (!this.processing) {
|
||||
this.processing = true;
|
||||
|
||||
// Extract enum values from selected objects
|
||||
const mobSkill: MD2MobSkill = {
|
||||
...this.model,
|
||||
type: this.selectedSkillType?.value ?? MobSkillType.Combat,
|
||||
skillTarget: this.selectedSkillTarget?.value ?? null,
|
||||
mobLevelInfoId: this.mobLevelInfoId || this.model.mobLevelInfoId
|
||||
};
|
||||
|
||||
this.mobSkillService.createOrUpdate(mobSkill).pipe(first()).subscribe(result => {
|
||||
this.processing = false;
|
||||
this.dialog.close(result);
|
||||
}, error => {
|
||||
this.processing = false;
|
||||
console.error('Error saving mob skill:', error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public get isValid(): boolean {
|
||||
if (!this.model) {
|
||||
return false;
|
||||
}
|
||||
const typeValid = this.selectedSkillType !== null && this.selectedSkillType !== undefined;
|
||||
return typeValid;
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user