Skip to content

Commit

Permalink
closes #77
Browse files Browse the repository at this point in the history
  • Loading branch information
seiyria committed Aug 26, 2024
1 parent ffc3123 commit 9519338
Show file tree
Hide file tree
Showing 10 changed files with 483 additions and 17 deletions.
245 changes: 230 additions & 15 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
"@sweetalert2/ngx-sweetalert2": "12.4.0",
"@sweetalert2/theme-dark": "5.0.17",
"ag-grid-angular": "32.0.2",
"alasql": "4.5.1",
"angular-svg-icon": "18.0.1",
"js-yaml": "4.1.0",
"lodash": "4.17.21",
Expand All @@ -52,6 +53,7 @@
"rxjs": "7.8.1",
"tslib": "2.6.2",
"uuid": "10.0.0",
"xlsx": "0.18.5",
"zone.js": "0.14.4"
},
"devDependencies": {
Expand Down
12 changes: 12 additions & 0 deletions src/app/home/home.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
<li><a (click)="closeMenu(); toggleModValidation()">Validate Mod</a></li>
<li><a (click)="closeMenu(); toggleAnalyzing()">Analyze...</a></li>
<li><a (click)="closeMenu(); togglePinpointing()">Pinpoint...</a></li>
<li><a (click)="closeMenu(); toggleQuerying()">Query...</a></li>
<li>
<a (click)="closeMenu(); debugService.toggleDebug()">Debug Mode {{ debugService.isDebug() ? '☑' : '☐'
}}</a>
Expand Down Expand Up @@ -85,6 +86,17 @@
</div>
</div>

} @else if(queryService.isQuerying()) {
<div class="root-body">
<div class="root-content p-3">
<div class="card bg-base-100 w-full shadow-xl">
<div class="card-body">
<app-query></app-query>
</div>
</div>
</div>
</div>

} @else {
<div class="root-body">
<div role="tablist" class="tabs tabs-boxed rounded-none flex flex-wrap">
Expand Down
13 changes: 13 additions & 0 deletions src/app/home/home.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DebugService } from '../services/debug.service';
import { ElectronService } from '../services/electron.service';
import { ModService } from '../services/mod.service';
import { PinpointService } from '../services/pinpoint.service';
import { QueryService } from '../services/query.service';

@Component({
selector: 'app-home',
Expand All @@ -25,6 +26,7 @@ export class HomeComponent {
private localStorage = inject(LocalStorageService);
public pinpointService = inject(PinpointService);
public analysisService = inject(AnalysisService);
public queryService = inject(QueryService);
public debugService = inject(DebugService);
public electronService = inject(ElectronService);
public modService = inject(ModService);
Expand Down Expand Up @@ -80,6 +82,7 @@ export class HomeComponent {
constructor() {
const lastTab = (this.localStorage.retrieve('lasttab') as number) ?? 0;
this.activeTab.set(lastTab);
this.toggleQuerying();
}

changeTab(newTab: number) {
Expand Down Expand Up @@ -125,18 +128,28 @@ export class HomeComponent {
this.isValidating.set(!this.isValidating());
this.pinpointService.togglePinpointing(false);
this.analysisService.toggleAnalyzing(false);
this.queryService.toggleQuerying(false);
}

togglePinpointing() {
this.pinpointService.togglePinpointing(true);
this.isValidating.set(false);
this.analysisService.toggleAnalyzing(false);
this.queryService.toggleQuerying(false);
}

toggleAnalyzing() {
this.analysisService.toggleAnalyzing(true);
this.isValidating.set(false);
this.pinpointService.togglePinpointing(false);
this.queryService.toggleQuerying(false);
}

toggleQuerying() {
this.queryService.toggleQuerying(true);
this.isValidating.set(false);
this.pinpointService.togglePinpointing(false);
this.analysisService.toggleAnalyzing(false);
}

toggleTester() {
Expand Down
6 changes: 5 additions & 1 deletion src/app/home/home.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { TraitTreesEditorComponent } from '../tabs/trait-trees/trait-trees-edito
import { TraitTreesComponent } from '../tabs/trait-trees/trait-trees.component';
import { ValidationComponent } from '../validation/validation.component';
import { HomeComponent } from './home.component';
import { QueryComponent } from '../query/query.component';

@NgModule({
declarations: [
Expand Down Expand Up @@ -64,6 +65,7 @@ import { HomeComponent } from './home.component';
StemsEditorComponent,
PinpointComponent,
AnalysisComponent,
QueryComponent,
],
imports: [
CommonModule,
Expand All @@ -76,6 +78,8 @@ import { HomeComponent } from './home.component';
CodeEditorModule,
ColorPickerModule,
],
exports: [],
exports: [
QueryComponent
],
})
export class HomeModule {}
76 changes: 76 additions & 0 deletions src/app/query/query.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<div role="tablist" class="tabs tabs-boxed rounded-none">

@for(tab of tabOrder; track tab.name; let i = $index) {
<a role="tab" class="tab" [class.tab-active]="activeQueryTab() === i" (click)="changeTab(i)">
{{ tab.name }}
</a>
}

<div class="tab flex flex-row justify-end">
@switch (activeQueryTab()) {
@case (0) {
<button class="btn-sm btn btn-primary mr-3" (click)="updateJSFunction()">Run JS</button>
}
@case (1) {
<button class="btn-sm btn btn-primary mr-3" (click)="updateSQLFunction()">Run SQL</button>
}
}
<button class="btn-sm btn btn-success mr-3" (click)="queryService.toggleQuerying()">Done</button>
</div>

</div>


@switch (activeQueryTab()) {
@case (0) {
<div class="flex flex-row gap-2 mb-3">
<div class="form-column">
<div class="form-row">
<ngs-code-editor class="editor-container" [theme]="'vs-dark'" [codeModel]="jsModel"
[options]="{ contextmenu: true }" (valueChanged)="onJSChanged($event)"
(keydown.control.s)="$event.preventDefault(); updateJSFunction()"></ngs-code-editor>
</div>
</div>

<div class="form-column max-w-[50%] max-h-[70vh] overflow-scroll">
<div class="form-row">
@if(jsError(); as error) {
<div class="error">{{ error }}</div>
}
@if(jsResult(); as result) {
<pre>
{{ result | json }}
</pre>
}
<pre></pre>
</div>
</div>
</div>
}

@case (1) {
<div class="flex flex-row gap-2 mb-3">
<div class="form-column">
<div class="form-row">
<ngs-code-editor class="editor-container" [theme]="'vs-dark'" [codeModel]="sqlModel"
[options]="{ contextmenu: true }" (valueChanged)="onSQLChanged($event)"
(keydown.control.s)="$event.preventDefault(); updateSQLFunction()"></ngs-code-editor>
</div>
</div>

<div class="form-column max-w-[50%] max-h-[70vh] overflow-scroll">
<div class="form-row">
@if(sqlError(); as error) {
<div class="error">{{ error }}</div>
}
@if(sqlResult(); as result) {
<pre>
{{ result | json }}
</pre>
}
<pre></pre>
</div>
</div>
</div>
}
}
3 changes: 3 additions & 0 deletions src/app/query/query.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.editor-container {
height: 70vh;
}
108 changes: 108 additions & 0 deletions src/app/query/query.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Component, inject, signal } from '@angular/core';
import { CodeModel } from '@ngstack/code-editor';
import * as alasql from 'alasql';
import * as _ from 'lodash';
import { LocalStorageService } from 'ngx-webstorage';

import { QueryService } from '../services/query.service';

@Component({
selector: 'app-query',
templateUrl: './query.component.html',
styleUrl: './query.component.scss',
})
export class QueryComponent {
private localStorage = inject(LocalStorageService);

public queryService = inject(QueryService);

public activeQueryTab = signal<number>(0);

public jsResult = signal<any>(undefined);
public jsError = signal<string>('');

public sqlResult = signal<any>(undefined);
public sqlError = signal<string>('');

public tabOrder = [
{
name: 'JavaScript',
},
{
name: 'SQL',
},
];

public readonly jsModel: CodeModel = {
language: 'javascript',
uri: 'query.js',
value: 'function query(mod) {\n\n}',
};

public readonly sqlModel: CodeModel = {
language: 'sql',
uri: 'query.sql',
value: 'SELECT type, COUNT(type) from ? GROUP BY type;',
};

constructor() {
(window as any)._ = _;

const lastQueryTab =
(this.localStorage.retrieve('lastquerytab') as number) ?? 0;
this.activeQueryTab.set(lastQueryTab);

const oldJSString = this.localStorage.retrieve('jsfunc');
if (oldJSString) {
this.jsModel.value = oldJSString;
}

const oldSQLString = this.localStorage.retrieve('sqlfunc');
if (oldSQLString) {
this.sqlModel.value = oldSQLString;
}
}

public changeTab(newTab: number) {
this.activeQueryTab.set(newTab);
this.localStorage.store('lastquerytab', newTab);
}

public onJSChanged($event: string) {
this.localStorage.store('jsfunc', $event);
}

public updateJSFunction() {
this.jsResult.set(undefined);
this.jsError.set('');

try {
// eslint-disable-next-line @typescript-eslint/no-implied-eval
const func = new Function(`return ${this.jsModel.value};`);
const result = func()(this.queryService.modForJS());
this.jsResult.set(result);
} catch (e: any) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
this.jsError.set(e?.message ?? 'JS parsing error');
}
}

public onSQLChanged($event: string) {
this.localStorage.store('sqlfunc', $event);
}

public updateSQLFunction() {
this.sqlResult.set(undefined);
this.sqlError.set('');

try {
const result = alasql(this.sqlModel.value, [
this.queryService.modForSQL(),
]);
this.sqlResult.set(result);
} catch (e: any) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
this.sqlError.set(e?.message ?? 'SQL parsing error');
}
}
}
2 changes: 1 addition & 1 deletion src/app/services/analysis.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,7 @@ export class AnalysisService {
const report: AnalysisReportDisplay = {
type: AnalysisDisplayType.Table,
table: {
title: `Global Armor Distribution`,
title: `Global Weapon Distribution`,
headers: [
'Item Class',
'# Items',
Expand Down
33 changes: 33 additions & 0 deletions src/app/services/query.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { computed, inject, Injectable, signal } from '@angular/core';
import { ModService } from './mod.service';

@Injectable({
providedIn: 'root',
})
export class QueryService {
private modService = inject(ModService);

public isQuerying = signal<boolean>(false);

public modForJS = computed(() => structuredClone(this.modService.mod()));
public modForSQL = computed(() => {
const mod = structuredClone(this.modService.mod());
return [
...mod.cores.map((c) => ({ type: 'core', data: c })),
...mod.dialogs.map((c) => ({ type: 'dialog', data: c })),
...mod.drops.map((c) => ({ type: 'drop', data: c })),
...mod.items.map((c) => ({ type: 'item', data: c })),
...mod.maps.map((c) => ({ type: 'map', data: c })),
...mod.npcs.map((c) => ({ type: 'npc', data: c })),
...mod.quests.map((c) => ({ type: 'quest', data: c })),
...mod.recipes.map((c) => ({ type: 'recipe', data: c })),
...mod.spawners.map((c) => ({ type: 'spawner', data: c })),
...mod.stems.map((c) => ({ type: 'stem', data: c })),
...mod.traitTrees.map((c) => ({ type: 'traitTree', data: c })),
];
});

public toggleQuerying(newSetting = !this.isQuerying()) {
this.isQuerying.set(newSetting);
}
}

0 comments on commit 9519338

Please sign in to comment.