diff --git a/package-lock.json b/package-lock.json index 548fe14..35c045b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6161,6 +6161,14 @@ "tslib": "^2.3.0" } }, + "ngx-uplot": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/ngx-uplot/-/ngx-uplot-0.0.6.tgz", + "integrity": "sha512-4VWVSUn0Pn3japWazU8/eYjSWb3UHakiRnzmVbGhzCTM3Ti1Xie8HGwNvvfhF5BNbdB/YiXpLWVZtfBlEeq+dw==", + "requires": { + "tslib": "^2.3.0" + } + }, "nice-napi": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz", diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 43eaa7d..3e2f712 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -1,30 +1,5 @@ import { Component, ChangeDetectionStrategy } from '@angular/core'; - -export interface HashParams { - query?: string; - db_host?: string; - db_login?: string; - db_pass?: string; - kiosk?: boolean; - mode?: 'dark' | 'light' | null | undefined; - table?: boolean; - chart?: boolean; - panel?: boolean; - query_field?: boolean; -} -export let getParam: HashParams = { - db_host: "", - db_login: "", - db_pass: "", - query: "", - kiosk: false, - mode: "light", - panel: false, - query_field: true, - table: true, - chart: true, -}; - +import { GetParamsService } from './services/get-params.service'; @Component({ selector: 'app-root', @@ -35,43 +10,6 @@ export let getParam: HashParams = { export class AppComponent { title = 'ClickHousePlay'; - constructor() { - const params: any[] = location.hash?.replace('#', '')?.split("&")?.map((i: any) => i.split('=')) || []; - params.forEach(([key, value]) => { - switch (key) { - case 'chart': - getParam.chart = !!(+value); - break; - case 'db_host': - getParam.db_host = value; - break; - case 'db_login': - getParam.db_login = value; - break; - case 'db_pass': - getParam.db_pass = value; - break; - case 'kiosk': - getParam.kiosk = !!(+value); - break; - case 'mode': - getParam.mode = value; - break; - case 'panel': - getParam.panel = !!(+value); - break; - case 'query': - getParam.query = decodeURI(value + '') || value; - break; - case 'query_field': - getParam.query_field = !!(+value); - break; - case 'table': - getParam.table = !!(+value); - break; - } - }) - - // console.log('constructor:::', { params, getParam }); + constructor(private getParamsService: GetParamsService) { } } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 88352e1..22b16af 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -1,3 +1,4 @@ +import { PopupTextModule } from './components/popup-text/popup-text.module'; import { ChHelpModule } from './components/ch-help/ch-help.module'; import { AceEditorExtModule } from './components/ace-editor-ext/ace-editor-ext.module'; import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; @@ -44,6 +45,7 @@ import { NgxUplotModule } from 'ngx-uplot'; AceEditorExtModule, LoadingCircleModule, ChHelpModule, + PopupTextModule, NgxUplotModule, // MatDialogModule, // MatButtonModule, diff --git a/src/app/components/ch-help/ch-help.component.scss b/src/app/components/ch-help/ch-help.component.scss index 169e81a..e9051e4 100644 --- a/src/app/components/ch-help/ch-help.component.scss +++ b/src/app/components/ch-help/ch-help.component.scss @@ -3,7 +3,6 @@ background-color: #fafafa; max-height: calc(100% - 1rem); overflow: hidden; - // flex: 1; } .frame { border: 0; diff --git a/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.html b/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.html index cfa6872..28bd86c 100644 --- a/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.html +++ b/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.html @@ -1,17 +1,16 @@ -
+
{{ value }} - + NULL
diff --git a/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.scss b/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.scss new file mode 100644 index 0000000..7d7ca8f --- /dev/null +++ b/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.scss @@ -0,0 +1,15 @@ +.cell { + + // .full-text-popup { + // position: absolute; + // // display: none; + // padding: 1rem; + // background-color: #fff; + // border: 1px solid #ccc; + // box-shadow: 0 0 3px rgba(0, 0, 0, 0.2); + // z-index: 99999999; + // } + // &:hover .full-text-popup { + // display: block; + // } +} diff --git a/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.ts b/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.ts index 67cc3f2..20187ea 100644 --- a/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.ts +++ b/src/app/components/custom-ag-grid/cell-type-detector/cell-type-detector.component.ts @@ -1,10 +1,13 @@ -import { Component, ChangeDetectionStrategy } from '@angular/core'; +import { Component, ChangeDetectionStrategy, ViewChild } from '@angular/core'; +import { PopupTextService } from '@app/components/popup-text/popup-text.service'; import { ICellRendererAngularComp } from 'ag-grid-angular'; import { maxRowHeight } from '../custom-ag-grid.component'; import { defaultRowHeight } from '../custom-ag-grid.component'; + @Component({ selector: 'app-cell-type-detector', templateUrl: './cell-type-detector.component.html', + styleUrls: ['./cell-type-detector.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush }) export class CellTypeDetectorComponent implements ICellRendererAngularComp { @@ -16,14 +19,19 @@ export class CellTypeDetectorComponent implements ICellRendererAngularComp { isMultiLine: boolean = false; rowHeight = defaultRowHeight; defaultRowHeight = defaultRowHeight; + + @ViewChild('cell') cell: any; + + constructor(private popupTextService: PopupTextService) { } + agInit(params: any): void { this.params = params; - if(/[\n\r]/.test(params.value)) { - this.isMultiLine = true - const newLineCount = params.value.split(/\n|\r\n/).length - 1; - const rowHeightWithNewLines = newLineCount * defaultRowHeight; - this.rowHeight = Math.min(rowHeightWithNewLines, maxRowHeight); - } + // if (/[\n\r]/.test(params.value)) { + // this.isMultiLine = true + // const newLineCount = params.value.split(/\n|\r\n/).length - 1; + // const rowHeightWithNewLines = newLineCount * defaultRowHeight; + // this.rowHeight = Math.min(rowHeightWithNewLines, maxRowHeight); + // } if (!isNaN(+params.value)) { this.isNumber = true; } @@ -36,6 +44,16 @@ export class CellTypeDetectorComponent implements ICellRendererAngularComp { // console.log(params.value); } + onClick() { + const rect = this.cell.nativeElement.getBoundingClientRect(); + + this.popupTextService.setText(this.value); + this.popupTextService.setPosition({ + top: rect.top, + left: rect.left + }) + } + refresh(): boolean { return false; } diff --git a/src/app/components/custom-ag-grid/custom-ag-grid.component.html b/src/app/components/custom-ag-grid/custom-ag-grid.component.html index 4770f50..e3bbb14 100644 --- a/src/app/components/custom-ag-grid/custom-ag-grid.component.html +++ b/src/app/components/custom-ag-grid/custom-ag-grid.component.html @@ -1,16 +1,16 @@ + + { let isAutoHeight = false; - if ( - typeof firstItemOfDetails[key] === 'string' && - this.details.some((value) => regex.test(value[key])) - ) { - // isAutoHeight = true; - // this.autoHeightColumns.push(key) - } + // if ( + // typeof firstItemOfDetails[key] === 'string' && + // this.details.some((value) => regex.test(value[key])) + // ) { + // // isAutoHeight = true; + // // this.autoHeightColumns.push(key) + // } return { field: key, hide: !val.includes(key), @@ -192,8 +192,7 @@ export class CustomAgGridComponent implements OnInit, AfterContentChecked { public resizeGrid() { requestAnimationFrame(() => { if (this.agGridSizeControl.selectedType === GRID_FIT) { - this.gridColumnApi?.autoSizeAllColumns(); - + // this.gridColumnApi?.autoSizeAllColumns(); } else { this.gridApi?.sizeColumnsToFit(); } @@ -216,34 +215,35 @@ export class CustomAgGridComponent implements OnInit, AfterContentChecked { settings: SettingButtonComponent, cellHeader: CellHeaderComponent, cellTypeDetector: CellTypeDetectorComponent, - expandRenderer: ExpandRendererComponent, + // expandRenderer: ExpandRendererComponent, }; } public getRowHeight(params: RowHeightParams) { - const isFullWidth = params.data.isExpanded; - // changing defaultRowHeight also requires changing th and tr height in full-row-renderer.component.scss - const margins = 10; - // changing maxRowHeight also requires changing :host max-height in full-row-renderer.component.scss - if (isFullWidth) { - const columnCount = Object.keys(params.data)?.length; - const exapndedRowSize = (columnCount * defaultRowHeight) + margins; - return Math.min(exapndedRowSize, maxRowHeight); - } else { - let maxNewlineCount = 1; - Object.values(params.data).forEach((element) => { - if (typeof element === 'string'){ - const newLineCount = element.split(/\n|\r\n/).length - 1; - if (newLineCount > maxNewlineCount) { - maxNewlineCount = newLineCount; - } - } - }); - const rowHeightWithNewLines = maxNewlineCount * defaultRowHeight; - return Math.min(rowHeightWithNewLines, maxRowHeight) - } - - + return 30; } + // public getRowHeight_(params: RowHeightParams) { + // const isFullWidth = params.data.isExpanded; + // // changing defaultRowHeight also requires changing th and tr height in full-row-renderer.component.scss + // const margins = 10; + // // changing maxRowHeight also requires changing :host max-height in full-row-renderer.component.scss + // if (isFullWidth) { + // const columnCount = Object.keys(params.data)?.length; + // const exapndedRowSize = (columnCount * defaultRowHeight) + margins; + // return Math.min(exapndedRowSize, maxRowHeight); + // } else { + // let maxNewlineCount = 1; + // Object.values(params.data).forEach((element) => { + // if (typeof element === 'string'){ + // const newLineCount = element.split(/\n|\r\n/).length - 1; + // if (newLineCount > maxNewlineCount) { + // maxNewlineCount = newLineCount; + // } + // } + // }); + // const rowHeightWithNewLines = maxNewlineCount * defaultRowHeight; + // return Math.min(rowHeightWithNewLines, maxRowHeight); + // } + // } ngOnInit() { this.agEventService.listen().subscribe((data) => { if (data) { diff --git a/src/app/components/custom-ag-grid/renderers/full-row-renderer/full-row-renderer.component.html b/src/app/components/custom-ag-grid/renderers/full-row-renderer/full-row-renderer.component.html index 34a3fd7..d801f20 100644 --- a/src/app/components/custom-ag-grid/renderers/full-row-renderer/full-row-renderer.component.html +++ b/src/app/components/custom-ag-grid/renderers/full-row-renderer/full-row-renderer.component.html @@ -9,7 +9,7 @@ }}
-
+ diff --git a/src/app/components/popup-text/popup-text.component.html b/src/app/components/popup-text/popup-text.component.html new file mode 100644 index 0000000..a281e6e --- /dev/null +++ b/src/app/components/popup-text/popup-text.component.html @@ -0,0 +1,7 @@ +
+
+
+ {{ text }} + +
+
diff --git a/src/app/components/popup-text/popup-text.component.scss b/src/app/components/popup-text/popup-text.component.scss new file mode 100644 index 0000000..80c6a6a --- /dev/null +++ b/src/app/components/popup-text/popup-text.component.scss @@ -0,0 +1,28 @@ +.back-place { + position: absolute; + // display: none; + top: 0; + left: 0; + bottom: 0; + right: 0; + width: 100%; + height: 100%; + background-color: rgba(255, 255, 255, 0.2); + z-index: 99999999; +} +.full-text-popup { + position: absolute; + // display: none; + top: 0; + left: 0; + padding: 6px 4px; + background-color: #fff; + border: 1px solid #ccc; + box-shadow: 0 0 3px rgba(0, 0, 0, 0.2); + white-space: pre; + z-index: 99999999; + max-width: 400px; + max-height: 400px; + overflow: auto; + transition: top 0.3s, left 0.3s; +} diff --git a/src/app/components/popup-text/popup-text.component.ts b/src/app/components/popup-text/popup-text.component.ts new file mode 100644 index 0000000..cbcc4f9 --- /dev/null +++ b/src/app/components/popup-text/popup-text.component.ts @@ -0,0 +1,60 @@ +import { PopupTextService } from '@app/components/popup-text/popup-text.service'; +import { Component, OnInit, ViewChild, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; + +@Component({ + selector: 'app-popup-text', + templateUrl: './popup-text.component.html', + styleUrls: ['./popup-text.component.scss'], + changeDetection: ChangeDetectionStrategy.OnPush +}) +export class PopupTextComponent implements OnInit { + + text: string = ''; + top = 0; + left = 0; + @ViewChild('textPopup') textPopup: any; + constructor(private popupTextService: PopupTextService, private cdr: ChangeDetectorRef) { } + + get isJson(): boolean { + try { + return !!JSON.parse(this.text); + } catch (e) { + return false; + } + } + + getJSON(): any { + return JSON.parse(this.text); + } + + ngOnInit() { + this.popupTextService.listen().subscribe(data => { + if (data?.text || data?.text === '') { + this.text = data?.text; + } + + if (data?.top || data?.left) { + this.top = data?.top - 2; + this.left = data?.left - 5; + + setTimeout(() => { + const el = this.textPopup?.nativeElement; + const rect = el?.getBoundingClientRect() || { height: 500, width: 500 }; + + this.top = Math.min(data.top - 2, window.innerHeight - rect.height - 50); + this.left = Math.min(data.left - 5, window.innerWidth - rect.width - 50); + + this.cdr.detectChanges(); + }, 100); + } + + this.cdr.detectChanges(); + }); + } + + onHide() { + this.text = ''; + this.cdr.detectChanges(); + } + +} diff --git a/src/app/components/popup-text/popup-text.module.ts b/src/app/components/popup-text/popup-text.module.ts new file mode 100644 index 0000000..5c1e833 --- /dev/null +++ b/src/app/components/popup-text/popup-text.module.ts @@ -0,0 +1,14 @@ +import { NgxJsonViewerModule } from 'ngx-json-viewer'; +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { PopupTextComponent } from './popup-text.component'; + +@NgModule({ + imports: [ + CommonModule, + NgxJsonViewerModule + ], + declarations: [PopupTextComponent], + exports: [PopupTextComponent] +}) +export class PopupTextModule { } diff --git a/src/app/components/popup-text/popup-text.service.ts b/src/app/components/popup-text/popup-text.service.ts new file mode 100644 index 0000000..433397d --- /dev/null +++ b/src/app/components/popup-text/popup-text.service.ts @@ -0,0 +1,26 @@ +import { Observable, BehaviorSubject } from 'rxjs'; +import { Injectable } from '@angular/core'; + +@Injectable({ + providedIn: 'root' +}) +export class PopupTextService { + top = 0; + left = 0; + text = ''; + obs: BehaviorSubject = new BehaviorSubject(null); + + listen() { + return this.obs.asObservable(); + } + setPosition({ top, left }: any) { + this.top = top; + this.left = left; + this.obs.next({ top, left }); + } + + setText(text: string) { + this.text = text; + this.obs.next({ text }); + } +} diff --git a/src/app/pages/home.page/home.page.component.html b/src/app/pages/home.page/home.page.component.html index cbf3add..443758e 100644 --- a/src/app/pages/home.page/home.page.component.html +++ b/src/app/pages/home.page/home.page.component.html @@ -252,3 +252,4 @@

No Data

(testConnection)="connectToDB($event, true)" (changeDbItems)="setDBItems($event)" > + diff --git a/src/app/services/get-params.service.ts b/src/app/services/get-params.service.ts new file mode 100644 index 0000000..77dee86 --- /dev/null +++ b/src/app/services/get-params.service.ts @@ -0,0 +1,71 @@ +import { Injectable } from '@angular/core'; +export interface HashParams { + query?: string; + db_host?: string; + db_login?: string; + db_pass?: string; + kiosk?: boolean; + mode?: 'dark' | 'light' | null | undefined; + table?: boolean; + chart?: boolean; + panel?: boolean; + query_field?: boolean; +} +export let getParam: HashParams = { + db_host: "", + db_login: "", + db_pass: "", + query: "", + kiosk: false, + mode: "light", + panel: false, + query_field: true, + table: true, + chart: true, +}; + +@Injectable({ + providedIn: 'root' +}) +export class GetParamsService { + + constructor() { + + const params: any[] = location.hash?.replace('#', '')?.split("&")?.map((i: any) => i.split('=')) || []; + params.forEach(([key, value]) => { + switch (key) { + case 'chart': + getParam.chart = !!(+value); + break; + case 'db_host': + getParam.db_host = value; + break; + case 'db_login': + getParam.db_login = value; + break; + case 'db_pass': + getParam.db_pass = value; + break; + case 'kiosk': + getParam.kiosk = !!(+value); + break; + case 'mode': + getParam.mode = value; + break; + case 'panel': + getParam.panel = !!(+value); + break; + case 'query': + getParam.query = decodeURI(value + '') || value; + break; + case 'query_field': + getParam.query_field = !!(+value); + break; + case 'table': + getParam.table = !!(+value); + break; + } + }) + } + +}