Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added array widget #334

Merged
merged 2 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## [Unreleased]
### Added
- Added Array Widget

## [1.8.1] 2024-08-01
### Fixed
- The currently selected mod is now properly displayed in the settings menu
Expand Down
8 changes: 6 additions & 2 deletions webapp/src/app/components/widgets/abstract-widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ import { AttributeValue, CCEntity } from '../../services/phaser/entities/cc-enti

@Directive()
// eslint-disable-next-line @angular-eslint/directive-class-suffix
export abstract class AbstractWidget<T = any> implements OnInit, OnChanges {
export abstract class AbstractWidget<T = any, Attr = AttributeValue> implements OnInit, OnChanges {
@Input() key!: string;
@Input() attribute!: AttributeValue;
@Input() attribute!: Attr;
@Input() entity?: CCEntity;
@Input() custom?: T;

// Cannot subscribe to
@Input() changeVal = (val: T) => {};

@Output() onChange = new EventEmitter<any>();

settings: T = {} as any;
Expand Down Expand Up @@ -52,5 +55,6 @@ export abstract class AbstractWidget<T = any> implements OnInit, OnChanges {
updateType(value: any) {
this.entity?.updateType();
this.onChange.emit(value);
this.changeVal(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<div class="flex flex-col property-container">
<div class="flex flex-row items-center mb-2">
<label class="property-name" [matTooltip]="attribute?.description!">{{ key }}:</label>
<button mat-icon-button (click)="add()">
<mat-icon>add</mat-icon>
</button>
</div>

<div class="flex flex-col">
@for (comp of dynamicComponents; track $index) {
<div class="relative">
<div class="remove-button">
<button mat-icon-button (click)="remove($index)">
<mat-icon>remove</mat-icon>
</button>
</div>
<ng-container
*ngComponentOutlet="comp.comp; inputs: comp.inputs"
></ng-container>
</div>
}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@use '@angular/material' as mat;

:host {
@include mat.icon-button-density(-4);
}

.remove-button {
position: absolute;
left: 50px;
top: -4px;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { Component, OnChanges, Type, ViewChild, ViewContainerRef } from '@angular/core';
import { AbstractWidget } from '../abstract-widget';
import { FlexModule } from '@angular/flex-layout';
import { MatRipple } from '@angular/material/core';
import { ReactiveFormsModule } from '@angular/forms';
import { MatTooltip } from '@angular/material/tooltip';
import { JsonPipe, NgComponentOutlet, NgIf } from '@angular/common';
import { AttributeValue } from '../../../services/phaser/entities/cc-entity';
import { WidgetRegistryService } from '../widget-registry.service';
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatDivider } from '@angular/material/divider';

export interface ArrayWidgetSub {
_type: string;
_popup?: boolean;
_select?: Record<string, number>;
}

export interface ArrayAttributes extends AttributeValue {
sub: ArrayWidgetSub;
}

interface ArraySettings {
[key: string]: unknown[] | undefined;
}

interface DynamicComponent {
comp: Type<AbstractWidget>;
inputs: Partial<AbstractWidget>;
}

@Component({
selector: 'app-array-widget',
standalone: true,
imports: [
FlexModule,
MatRipple,
ReactiveFormsModule,
MatTooltip,
NgIf,
JsonPipe,
NgComponentOutlet,
MatIconButton,
MatIcon,
MatDivider
],
templateUrl: './array-widget.component.html',
styleUrls: ['./array-widget.component.scss', '../widget.scss']
})
export class ArrayWidgetComponent extends AbstractWidget<ArraySettings, ArrayAttributes> implements OnChanges {

@ViewChild('compContainer', {read: ViewContainerRef, static: true}) compContainer!: ViewContainerRef;

dynamicComponents: DynamicComponent[] = [];

constructor(
private widgetRegistry: WidgetRegistryService,
) {
super();
}


override ngOnChanges() {
super.ngOnChanges();
this.init();
}

override updateType(value: any) {
super.updateType(value);
this.init();
}

init() {
this.dynamicComponents = [];
const arrayOptions = this.settings[this.key] ?? [];
this.settings[this.key] = arrayOptions;
const len = arrayOptions.length;
for (let i = 0; i < len; i++) {
this.dynamicComponents.push({
comp: this.widgetRegistry.getWidget(this.attribute.sub._type),
inputs: {
custom: arrayOptions,
key: i.toString(),
attribute: {
type: this.attribute.sub._type,
description: '',
options: this.attribute.sub._select
},
changeVal: val => this.update()
}
});
}
}

remove(index: number) {
this.settings[this.key]?.splice(index, 1);
this.update();
}

add() {
this.settings[this.key]?.push(undefined);
this.update();
}

private update() {
this.updateType(this.settings[this.key]);
}
}
2 changes: 2 additions & 0 deletions webapp/src/app/components/widgets/widget-registry.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { PropTypeWidgetComponent } from './prop-type-widget/prop-type-widget.com
import { ScalablePropConfigWidgetComponent } from './scalable-prop-config-widget/scalable-prop-config-widget.component';
import { CustomDesTypeWidgetComponent } from './custom-des-type-widget/custom-des-type-widget.component';
import { CharacterWidgetComponent } from './character-widget/character-widget.component';
import { ArrayWidgetComponent } from './array-widget/array-widget.component';

@Injectable({
providedIn: 'root'
Expand Down Expand Up @@ -40,6 +41,7 @@ export class WidgetRegistryService {
this.register('EntityAnim', StringWidgetComponent);
this.register('CustomDesType', CustomDesTypeWidgetComponent);
this.register('VarCondition', StringWidgetComponent);
this.register('Array', ArrayWidgetComponent);
}

private setDefaultWidget(widget: any) {
Expand Down
Loading