Skip to content

Commit c5c8b71

Browse files
dmitriy-borzenkoDmitriy Borzenko
and
Dmitriy Borzenko
authored
Kamu UI 514 query explainer improve input data section view (#518)
* improved input data section view for query explainer * changed CHANGELOG.md * extract common code to shared helper --------- Co-authored-by: Dmitriy Borzenko <[email protected]>
1 parent 7369246 commit c5c8b71

File tree

7 files changed

+77
-39
lines changed

7 files changed

+77
-39
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
## [Unreleased]
99
### Added
1010
- Added initialization messages at the start of the flow
11+
### Changed
12+
- Query explainer: improved `INPUT DATA` section view
13+
- added `Run` and `Copy` buttons for a sql code
1114
### Fixed
1215
- Flows table: fixed broken filters in pagination
1316

src/app/common/app.helpers.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,3 +111,39 @@ export function changeCopyIcon(event: MouseEvent): void {
111111
htmlButtonElement.classList.add("clipboard-btn--success");
112112
}
113113
}
114+
115+
export function addMarkdownRunButton(sqlQueries: RegExpMatchArray | null, path: string): void {
116+
const containerRunButtonElement: HTMLCollectionOf<Element> =
117+
document.getElementsByClassName("container-run-button");
118+
119+
if (sqlQueries?.length && !containerRunButtonElement.length) {
120+
const preElements: NodeListOf<Element> = document.querySelectorAll("pre.language-sql");
121+
preElements.forEach((preElement: Element, index: number) => {
122+
const divElement: HTMLDivElement = document.createElement("div");
123+
divElement.classList.add("container-run-button");
124+
divElement.style.position = "absolute";
125+
divElement.style.top = "10px";
126+
divElement.style.right = "65px";
127+
const linkElement = document.createElement("a");
128+
linkElement.classList.add("markdown-run-button");
129+
linkElement.style.padding = "3.6px 16px";
130+
linkElement.style.color = "#ffff";
131+
linkElement.style.fontSize = "13px";
132+
linkElement.style.textDecoration = "none";
133+
linkElement.style.backgroundColor = "rgba(255,255, 255, 0.07)";
134+
linkElement.style.borderRadius = "4px";
135+
linkElement.style.transition = "all 250ms ease-out";
136+
linkElement.setAttribute("target", "_blank");
137+
linkElement.setAttribute("href", `${path}=${encodeURI(sqlQueries[index])}`);
138+
linkElement.addEventListener("mouseover", () => {
139+
linkElement.style.backgroundColor = "rgba(255,255, 255, 0.14)";
140+
});
141+
linkElement.addEventListener("mouseleave", () => {
142+
linkElement.style.backgroundColor = "rgba(255,255, 255, 0.07)";
143+
});
144+
linkElement.innerHTML = "Run";
145+
divElement.appendChild(linkElement);
146+
preElement.after(divElement);
147+
});
148+
}
149+
}

src/app/dataset-view/additional-components/overview-component/components/readme-section/readme-section.component.ts

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ import { DatasetCommitService } from "../../services/dataset-commit.service";
1818
import { LoggedUserService } from "src/app/auth/logged-user.service";
1919
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
2020
import { DatasetViewTypeEnum } from "src/app/dataset-view/dataset-view.interface";
21+
import ProjectLinks from "src/app/project-links";
22+
import { addMarkdownRunButton } from "src/app/common/app.helpers";
2123

2224
@Component({
2325
selector: "app-readme-section",
@@ -101,42 +103,10 @@ export class ReadmeSectionComponent extends BaseComponent implements OnChanges,
101103
if (this.readmeState) {
102104
// Find all sql queries between ```sql and ```
103105
const sqlQueries = this.readmeState.match(/(?<=```sql\s+).*?(?=\s+```)/gs);
104-
const containerRunButtonElement: HTMLCollectionOf<Element> =
105-
document.getElementsByClassName("container-run-button");
106-
107-
if (sqlQueries?.length && !containerRunButtonElement.length) {
108-
const preElements: NodeListOf<Element> = document.querySelectorAll("pre.language-sql");
109-
preElements.forEach((preElement: Element, index: number) => {
110-
const divElement: HTMLDivElement = document.createElement("div");
111-
divElement.classList.add("container-run-button");
112-
divElement.style.position = "absolute";
113-
divElement.style.top = "10px";
114-
divElement.style.right = "65px";
115-
const linkElement = document.createElement("a");
116-
linkElement.classList.add("markdown-run-button");
117-
linkElement.style.padding = "3.6px 16px";
118-
linkElement.style.color = "#ffff";
119-
linkElement.style.fontSize = "13px";
120-
linkElement.style.textDecoration = "none";
121-
linkElement.style.backgroundColor = "rgba(255,255, 255, 0.07)";
122-
linkElement.style.borderRadius = "4px";
123-
linkElement.style.transition = "all 250ms ease-out";
124-
linkElement.setAttribute("target", "_blank");
125-
linkElement.setAttribute(
126-
"href",
127-
`/${this.datasetBasics.owner.accountName}/${this.datasetBasics.name}?tab=${DatasetViewTypeEnum.Data}&sqlQuery=${encodeURI(sqlQueries[index])}`,
128-
);
129-
linkElement.addEventListener("mouseover", () => {
130-
linkElement.style.backgroundColor = "rgba(255,255, 255, 0.14)";
131-
});
132-
linkElement.addEventListener("mouseleave", () => {
133-
linkElement.style.backgroundColor = "rgba(255,255, 255, 0.07)";
134-
});
135-
linkElement.innerHTML = "Run";
136-
divElement.appendChild(linkElement);
137-
preElement.after(divElement);
138-
});
139-
}
106+
addMarkdownRunButton(
107+
sqlQueries,
108+
`/${this.datasetBasics.owner.accountName}/${this.datasetBasics.name}?${ProjectLinks.URL_QUERY_PARAM_TAB}=${DatasetViewTypeEnum.Data}&${ProjectLinks.URL_QUERY_PARAM_SQL_QUERY}`,
109+
);
140110
}
141111
}
142112
}

src/app/query-explainer/components/input-data-section/input-data-section.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<div class="mt-4 mx-4">
55
<div class="fw-semibold">Query:</div>
66
<div class="mt-2">
7-
<pre><code [highlight]="inputData.sqlQueryExplainerResponse.input.query" [languages]="['sql'] " [attr.data-test-id]="'query-explainer-viewer'" class="rounded-3"></code></pre>
7+
<markdown clipboard class="variable-binding" [data]="sqlWrapper(this.sqlCode)" />
88
</div>
99
</div>
1010
<div

src/app/query-explainer/components/input-data-section/input-data-section.component.spec.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ import ProjectLinks from "src/app/project-links";
1616
import { AngularSvgIconModule } from "angular-svg-icon";
1717
import { HttpClientTestingModule } from "@angular/common/http/testing";
1818
import { findElementByDataTestId } from "src/app/common/base-test.helpers.spec";
19+
import { MarkdownModule } from "ngx-markdown";
20+
import { HttpClient } from "@angular/common/http";
21+
import { SecurityContext } from "@angular/core";
1922

2023
describe("InputDataSectionComponent", () => {
2124
let component: InputDataSectionComponent;
@@ -31,6 +34,10 @@ describe("InputDataSectionComponent", () => {
3134
RouterModule,
3235
AngularSvgIconModule.forRoot(),
3336
HttpClientTestingModule,
37+
MarkdownModule.forRoot({
38+
loader: HttpClient,
39+
sanitize: SecurityContext.NONE,
40+
}),
3441
],
3542
providers: [
3643
{

src/app/query-explainer/components/input-data-section/input-data-section.component.ts

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ChangeDetectionStrategy, Component, Input } from "@angular/core";
1+
import { AfterViewChecked, ChangeDetectionStrategy, Component, Input } from "@angular/core";
22
import { Observable } from "rxjs";
33
import {
44
VerifyQueryDatasetBlockNotFoundError,
@@ -10,19 +10,25 @@ import { DatasetInfo } from "src/app/interface/navigation.interface";
1010
import { MaybeUndefined } from "src/app/common/app.types";
1111
import AppValues from "src/app/common/app.values";
1212
import { QueryExplainerComponentData } from "../../query-explainer.component";
13+
import ProjectLinks from "src/app/project-links";
14+
import { addMarkdownRunButton } from "src/app/common/app.helpers";
1315

1416
@Component({
1517
selector: "app-input-data-section",
1618
templateUrl: "./input-data-section.component.html",
1719
styleUrls: ["./input-data-section.component.scss"],
1820
changeDetection: ChangeDetectionStrategy.OnPush,
1921
})
20-
export class InputDataSectionComponent {
22+
export class InputDataSectionComponent implements AfterViewChecked {
2123
@Input({ required: true }) public blockHashObservables$: Observable<Date>[];
2224
@Input({ required: true }) public datasetInfoObservables$: Observable<DatasetInfo>[];
2325
@Input({ required: true }) inputData: QueryExplainerComponentData;
2426
public readonly DATE_FORMAT = AppValues.DISPLAY_FLOW_DATE_FORMAT;
2527

28+
ngAfterViewChecked(): void {
29+
this.addDynamicRunButton();
30+
}
31+
2632
public isDatasetBlockNotFoundError(error: MaybeUndefined<VerifyQueryError>, blockHash: string): boolean {
2733
return (
2834
error?.kind === VerifyQueryKindError.DatasetBlockNotFound &&
@@ -36,4 +42,18 @@ export class InputDataSectionComponent {
3642
(error as VerifyQueryDatasetNotFoundError).dataset_id === datasetId
3743
);
3844
}
45+
46+
public get sqlCode(): string {
47+
return this.inputData.sqlQueryExplainerResponse.input.query;
48+
}
49+
50+
public sqlWrapper(sqlCode: string): string {
51+
return "```sql\n" + sqlCode + "\n```";
52+
}
53+
54+
private addDynamicRunButton(): void {
55+
// Find all sql queries between ```sql and ```
56+
const sqlQueries = this.sqlWrapper(this.sqlCode).match(/(?<=```sql\s+).*?(?=\s+```)/gs);
57+
addMarkdownRunButton(sqlQueries, `/${ProjectLinks.URL_QUERY}?${ProjectLinks.URL_QUERY_PARAM_SQL_QUERY}`);
58+
}
3959
}

src/app/query-explainer/query-explainer.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { DisplayHashModule } from "../components/display-hash/display-hash.modul
1313
import { DynamicTableModule } from "../components/dynamic-table/dynamic-table.module";
1414
import { FormsModule } from "@angular/forms";
1515
import { AutofocusModule } from "../common/directives/autofocus.module";
16+
import { MarkdownModule } from "ngx-markdown";
1617

1718
@NgModule({
1819
declarations: [
@@ -32,6 +33,7 @@ import { AutofocusModule } from "../common/directives/autofocus.module";
3233
DynamicTableModule,
3334
FormsModule,
3435
AutofocusModule,
36+
MarkdownModule,
3537
],
3638
})
3739
export class QueryExplainerModule {}

0 commit comments

Comments
 (0)