Skip to content

Commit 0df6b89

Browse files
sogladevactions-userHelias
authored
feat: SQL Editor - Syntax Coloring (#3317)
Co-authored-by: i18n Sync Bot <[email protected]> Co-authored-by: Helias <[email protected]>
1 parent 41c71a3 commit 0df6b89

File tree

7 files changed

+288
-33
lines changed

7 files changed

+288
-33
lines changed

apps/keira/src/assets/i18n/de.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@
255255
"DETECTION_RANGE": "Steuert den Bereich, in dem Kreaturen Spieler erkennen und sehen.",
256256
"ITEMID1": "Dies ist die Gegenstandsnummer der Ausrüstung, die in der rechten Hand aus Item.dbc verwendet wird.",
257257
"ITEMID2": "Dies ist die Gegenstandsnummer der Ausrüstung, die in der linken Hand aus Item.dbc verwendet wird.",
258-
"ITEMID3": "Dies ist die Gegenstandsnummer der Ausrüstung, die im Fernkampf-Slot aus Item.dbc verwendet wird.",
258+
"ItemID3": "This is the item number of the equipment used in the ranged slot from Item.dbc.",
259259
"FactionHint": "When refering to the Creature's Faction ID it's the column on the left 'ID' in the selector, more information check 'faction' in the wiki."
260260
},
261261
"TEMPLATE_ADDON": {

libs/features/sql-editor/src/sql-editor.component.html

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,16 @@
1313
</div>
1414
</div>
1515

16-
<textarea id="code" class="mb-1" [(ngModel)]="service.code" (keydown.f9)="execute()" rows="6" spellcheck="false"></textarea>
16+
<code-editor
17+
id="code"
18+
[extensions]="extensions"
19+
[lineWrapping]="true"
20+
(keydown.f9)="execute()"
21+
[languages]="languages"
22+
[language]="'MySQL'"
23+
[setup]="'basic'"
24+
[(ngModel)]="service.code"
25+
/>
1726

1827
<div class="row">
1928
<div class="col-sm-7">

libs/features/sql-editor/src/sql-editor.component.scss

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
#code {
2-
width: 100%;
3-
padding: 9.5px;
4-
word-break: break-all;
5-
word-wrap: break-word;
6-
background-color: #f5f5f5;
7-
border: 1px solid #ccc;
8-
border-radius: 4px;
2+
overflow: auto;
3+
resize: vertical;
4+
min-height: calc(1.5em * 6);
5+
margin-bottom: 1rem;
6+
border: 1px solid #e49649;
7+
border-radius: 0.25rem;
8+
}
9+
10+
#code ::ng-deep .cm-editor {
11+
outline: none; // remove the default outline
912
}
1013

1114
.select-limit {

libs/features/sql-editor/src/sql-editor.component.spec.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import { TooltipModule } from 'ngx-bootstrap/tooltip';
66
import { ClipboardService } from 'ngx-clipboard';
77
import { of, throwError } from 'rxjs';
88
import { SqlEditorComponent } from './sql-editor.component';
9+
import { By } from '@angular/platform-browser';
10+
import { CodeEditor } from '@acrodata/code-editor';
911
import Spy = jasmine.Spy;
1012

1113
export class SqlEditorPage extends PageObject<SqlEditorComponent> {
@@ -14,8 +16,8 @@ export class SqlEditorPage extends PageObject<SqlEditorComponent> {
1416
get affectedRows(): HTMLTextAreaElement {
1517
return this.query<HTMLTextAreaElement>('#affected-rows-box');
1618
}
17-
get code(): HTMLTextAreaElement {
18-
return this.query<HTMLTextAreaElement>('textarea#code');
19+
get code(): HTMLElement {
20+
return this.query<HTMLElement>('code-editor');
1921
}
2022
get copyBtn(): HTMLButtonElement {
2123
return this.query<HTMLButtonElement>('#copy-btn');
@@ -47,9 +49,12 @@ describe('SqlEditorComponent', () => {
4749
const mysqlQueryService = TestBed.inject(MysqlQueryService);
4850
spyOn(mysqlQueryService, 'query').and.returnValue(of(mockRows));
4951

52+
const codeEditorDebugElement = fixture.debugElement.query(By.directive(CodeEditor));
53+
const codeEditorInstance = codeEditorDebugElement.componentInstance as CodeEditor;
54+
5055
fixture.detectChanges();
5156

52-
return { page, mysqlQueryService, component };
57+
return { page, mysqlQueryService, component, codeEditorInstance };
5358
};
5459

5560
it('should correctly query', () => {
@@ -68,10 +73,10 @@ describe('SqlEditorComponent', () => {
6873
});
6974

7075
it('should allow the user to insert a custom query', () => {
71-
const { page, mysqlQueryService } = setup();
76+
const { page, mysqlQueryService, codeEditorInstance } = setup();
7277
const customQuery = 'SELECT col FROM table WHERE col > 10';
7378

74-
page.setInputValue(page.code, customQuery);
79+
codeEditorInstance.writeValue(customQuery);
7580
page.clickElement(page.executeBtn);
7681

7782
expect(mysqlQueryService.query).toHaveBeenCalledWith(customQuery);
@@ -102,7 +107,7 @@ describe('SqlEditorComponent', () => {
102107

103108
page.clickElement(page.executeBtn);
104109

105-
expect(component.columns.length).toBe(0);
110+
expect(component['columns'].length).toBe(0);
106111
});
107112

108113
it('should display the affected rows box when necessary', () => {
@@ -149,15 +154,15 @@ describe('SqlEditorComponent', () => {
149154

150155
page.clickElement(page.executeBtn);
151156

152-
expect(component.columns.length).toBe(20);
157+
expect(component['columns'].length).toBe(20);
153158
});
154159

155160
it('clicking the copy button should copy the query', () => {
156-
const { page } = setup();
161+
const { page, codeEditorInstance } = setup();
157162
const spy = spyOn(TestBed.inject(ClipboardService), 'copyFromContent');
158163
const customQuery = '-- some text that will be copied';
159164

160-
page.setInputValue(page.code, customQuery);
165+
codeEditorInstance.writeValue(customQuery);
161166
page.clickElement(page.copyBtn);
162167

163168
expect(spy).toHaveBeenCalledWith(customQuery);

libs/features/sql-editor/src/sql-editor.component.ts

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,58 +13,61 @@ import { TooltipModule } from 'ngx-bootstrap/tooltip';
1313
import { QueryErrorComponent } from '@keira/shared/base-editor-components';
1414
import { MysqlQueryService } from '@keira/shared/db-layer';
1515

16+
import { CodeEditor } from '@acrodata/code-editor';
17+
import { LanguageDescription } from '@codemirror/language';
18+
import { MySQL, sql } from '@codemirror/lang-sql';
19+
import { githubLight } from '@uiw/codemirror-theme-github';
20+
1621
@Component({
1722
changeDetection: ChangeDetectionStrategy.OnPush,
1823
selector: 'keira-sql-editor',
1924
templateUrl: './sql-editor.component.html',
2025
styleUrls: ['./sql-editor.component.scss'],
21-
imports: [TooltipModule, FormsModule, QueryErrorComponent, NgxDatatableModule, TranslateModule],
26+
imports: [CodeEditor, TooltipModule, FormsModule, QueryErrorComponent, NgxDatatableModule, TranslateModule],
2227
})
2328
export class SqlEditorComponent extends SubscriptionHandler {
2429
private readonly mysqlQueryService = inject(MysqlQueryService);
2530
private readonly clipboardService = inject(ClipboardService);
26-
readonly service = inject(SqlEditorService);
31+
protected readonly service = inject(SqlEditorService);
2732
private readonly changeDetectorRef = inject(ChangeDetectorRef);
2833

29-
readonly DTCFG = DTCFG;
30-
readonly docUrl = 'https://www.w3schools.com/sql/sql_intro.asp';
34+
protected readonly DTCFG = DTCFG;
35+
protected readonly docUrl = 'https://www.w3schools.com/sql/sql_intro.asp';
3136
private readonly MAX_COL_SHOWN = 20;
3237

33-
// displayLimit = 10;
34-
// get displayLimitOptions() {
35-
// return [10, 20, 50, 100, 200, 500, 1000];
36-
// }
38+
protected readonly languages = [LanguageDescription.of({ name: 'MySQL', support: sql({ dialect: MySQL, upperCaseKeywords: true }) })];
39+
protected readonly extensions = [githubLight];
3740

3841
private _error: QueryError | undefined;
39-
get error(): QueryError | undefined {
42+
protected get error(): QueryError | undefined {
4043
return this._error;
4144
}
4245

4346
private _rows: TableRow[] = [];
44-
get rows(): TableRow[] {
47+
protected get rows(): TableRow[] {
4548
return this._rows;
4649
}
4750

4851
private _columns!: string[];
49-
get columns(): string[] {
52+
protected get columns(): string[] {
5053
return this._columns;
5154
}
5255

5356
private _affectedRows!: number;
54-
get affectedRows(): number {
57+
protected get affectedRows(): number {
5558
return this._affectedRows;
5659
}
5760

5861
private _message!: string;
59-
get message(): string {
62+
protected get message(): string {
6063
return this._message;
6164
}
6265

63-
copy(): void {
66+
protected copy(): void {
6467
this.clipboardService.copyFromContent(this.service.code);
6568
}
6669

67-
execute(): void {
70+
protected execute(): void {
6871
this.subscriptions.push(
6972
this.mysqlQueryService.query(this.service.code).subscribe({
7073
next: (rows: TableRow[] | { affectedRows: number; message: string }) => {

0 commit comments

Comments
 (0)