This is an automated email from the ASF dual-hosted git repository.
riemer pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/streampipes.git
The following commit(s) were added to refs/heads/dev by this push:
new 89bfeb29d8 feat: add panel resize component (#3585)
89bfeb29d8 is described below
commit 89bfeb29d8a87939b422a214217752d7e802d5af
Author: Marcel Früholz <[email protected]>
AuthorDate: Fri May 23 12:55:02 2025 +0200
feat: add panel resize component (#3585)
* feat: add panel resize component
* Resize panel on dragEnd only
* Fix resizing of content panel
* Improve resizing of charts
---------
Co-authored-by: Dominik Riemer <[email protected]>
---
.../sidebar-resize/sidebar-resize.component.html | 36 +++++++++++
.../sidebar-resize/sidebar-resize.component.scss} | 64 ++++++++++----------
.../sidebar-resize/sidebar-resize.component.ts | 70 ++++++++++++++++++++++
.../shared-ui/src/lib/shared-ui.module.ts | 5 ++
.../streampipes/shared-ui/src/public-api.ts | 1 +
.../charts/base/echarts-widget.component.ts | 19 ++++--
.../services/resize-echarts.service.ts} | 46 +++-----------
.../data-explorer-chart-view.component.html | 23 ++++---
.../data-explorer-chart-view.component.scss | 5 +-
.../data-explorer-chart-view.component.ts | 23 ++++++-
10 files changed, 209 insertions(+), 83 deletions(-)
diff --git
a/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.html
b/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.html
new file mode 100644
index 0000000000..56f62f8e08
--- /dev/null
+++
b/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.html
@@ -0,0 +1,36 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ ~
+ -->
+<div class="outer-container">
+ <div
+ *ngIf="isDragging"
+ class="ghost-bar"
+ [style.right.px]="ghostLeft"
+ ></div>
+ <div class="resize-container" [style.width.px]="currentWidth">
+ <div
+ class="resizer"
+ cdkDrag
+ (cdkDragStarted)="onDragStarted($event)"
+ (cdkDragMoved)="onDragMoved($event)"
+ (cdkDragEnded)="onDragEnded()"
+ >
+ <span class="drag-icon">⠿</span>
+ </div>
+ <ng-content></ng-content>
+ </div>
+</div>
diff --git
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
b/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.scss
similarity index 58%
copy from
ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
copy to
ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.scss
index b8ebed30f9..c70032259e 100644
---
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
+++
b/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.scss
@@ -1,4 +1,4 @@
-/*
+/*!
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
@@ -16,44 +16,46 @@
*
*/
-.fixed-height {
- height: 50px;
-}
-
-.data-explorer-options {
- padding: 0px;
-}
-
-.data-explorer-options-item {
- display: inline;
- margin-right: 10px;
-}
-
-.m-20 {
- margin: 20px;
+.resizer {
+ width: 6px;
+ cursor: ew-resize;
+ background: rgba(0, 0, 0, 0.1);
+ height: 100%;
+ position: absolute;
+ z-index: 10;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ &:hover {
+ background-color: #aaa;
+ }
}
-.h-100 {
- height: 100%;
+.drag-icon {
+ font-size: 10px;
+ color: #555;
}
-.dashboard-grid {
- display: flex;
- flex-direction: column;
- flex: 1 1 100%;
+.ghost-bar {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ width: 2px;
+ background-color: var(--color-bg-3);
+ z-index: 100;
+ pointer-events: none;
}
-.designer-panel-container {
+.outer-container {
+ position: relative;
width: 100%;
height: 100%;
}
-.designer-panel {
- width: 450px;
- border: 1px solid var(--color-tab-border);
-}
-
-.widget-title-text {
- white-space: nowrap;
- margin-right: 12px;
+.resize-container {
+ position: relative;
+ height: 100%;
+ display: flex;
+ flex-direction: row;
+ overflow: hidden;
}
diff --git
a/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.ts
b/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.ts
new file mode 100644
index 0000000000..39e57e020c
--- /dev/null
+++
b/ui/projects/streampipes/shared-ui/src/lib/components/sidebar-resize/sidebar-resize.component.ts
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+
+import { Component, EventEmitter, inject, Input, Output } from '@angular/core';
+import { CdkDragMove, CdkDragStart } from '@angular/cdk/drag-drop';
+import { MatDrawerContainer } from '@angular/material/sidenav';
+
+@Component({
+ selector: 'sp-sidebar-resize',
+ templateUrl: './sidebar-resize.component.html',
+ styleUrls: ['./sidebar-resize.component.scss'],
+})
+export class SidebarResizeComponent {
+ @Input() currentWidth: number = 450;
+ @Input() minWidth: number = 450;
+ @Input() maxWidth: number = 1000;
+
+ @Output() widthChanged = new EventEmitter<number>();
+
+ private drawerContainer = inject(MatDrawerContainer);
+
+ isDragging = false;
+ ghostLeft = 0;
+ startX = 0;
+ startWidth = 0;
+
+ protected onDragStarted(event: CdkDragStart) {
+ this.isDragging = true;
+
+ const element = event.source.element.nativeElement.parentElement;
+ const rect = element.getBoundingClientRect();
+
+ this.startX = rect.left;
+ this.startWidth = this.currentWidth;
+
+ this.ghostLeft = this.startWidth;
+ }
+
+ protected onDragMoved(event: CdkDragMove) {
+ const deltaX = -event.distance.x;
+ this.ghostLeft = Math.min(
+ Math.max(this.startWidth + deltaX, this.minWidth),
+ this.maxWidth,
+ );
+ const element = event.source.element.nativeElement;
+ element.style.transform = 'none';
+ }
+
+ protected onDragEnded() {
+ this.isDragging = false;
+ this.currentWidth = this.ghostLeft;
+ this.widthChanged.emit(this.currentWidth);
+ setTimeout(() => this.drawerContainer.updateContentMargins(), 0);
+ }
+}
diff --git a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
index 394a8caa6c..0ead4013e3 100644
--- a/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
+++ b/ui/projects/streampipes/shared-ui/src/lib/shared-ui.module.ts
@@ -65,6 +65,7 @@ import { TimeRangeSelectorComponent } from
'./components/time-selector/time-rang
import { TimeRangeSelectorMenuComponent } from
'./components/time-selector/time-selector-menu/time-selector-menu.component';
import { CustomTimeRangeSelectionComponent } from
'./components/time-selector/time-selector-menu/custom-time-range-selection/custom-time-range-selection.component';
import { DataExplorerRefreshIntervalSettingsComponent } from
'./components/time-selector/refresh-interval-settings/refresh-interval-settings.component';
+import { SidebarResizeComponent } from
'./components/sidebar-resize/sidebar-resize.component';
import { MatSelectModule } from '@angular/material/select';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatMenuModule } from '@angular/material/menu';
@@ -96,6 +97,7 @@ import { InputSchemaPanelComponent } from
'./components/input-schema-panel/input
import { InputSchemaPropertyComponent } from
'./components/input-schema-panel/input-schema-property/input-schema-property.component';
import { MatExpansionModule } from '@angular/material/expansion';
import { SortByRuntimeNamePipe } from './pipes/sort-by-runtime-name.pipe';
+import { DragDropModule } from '@angular/cdk/drag-drop';
@NgModule({
declarations: [
@@ -136,6 +138,7 @@ import { SortByRuntimeNamePipe } from
'./pipes/sort-by-runtime-name.pipe';
SpConfigurationBoxComponent,
SelectDataRangeComponent,
SelectDataMissingValuesComponent,
+ SidebarResizeComponent,
LivePreviewLoadingComponent,
LivePreviewTableComponent,
LivePreviewErrorComponent,
@@ -175,6 +178,7 @@ import { SortByRuntimeNamePipe } from
'./pipes/sort-by-runtime-name.pipe';
MatProgressSpinnerModule,
MatSort,
TranslateModule.forChild({}),
+ DragDropModule,
MarkdownModule.forRoot(),
],
providers: [
@@ -211,6 +215,7 @@ import { SortByRuntimeNamePipe } from
'./pipes/sort-by-runtime-name.pipe';
PipelineElementHelpComponent,
PipelineElementComponent,
InputSchemaPanelComponent,
+ SidebarResizeComponent,
],
})
export class SharedUiModule {}
diff --git a/ui/projects/streampipes/shared-ui/src/public-api.ts
b/ui/projects/streampipes/shared-ui/src/public-api.ts
index 5eccf65f77..ae6cdd29c1 100644
--- a/ui/projects/streampipes/shared-ui/src/public-api.ts
+++ b/ui/projects/streampipes/shared-ui/src/public-api.ts
@@ -52,6 +52,7 @@ export * from
'./lib/components/pipeline-element-runtime-info/pipeline-element-r
export * from
'./lib/components/pipeline-element-documentation/pipeline-element-documentation.component';
export * from './lib/components/pipeline-element/pipeline-element.component';
export * from
'./lib/components/input-schema-panel/input-schema-panel.component';
+export * from './lib/components/sidebar-resize/sidebar-resize.component';
export * from './lib/models/sp-navigation.model';
diff --git
a/ui/src/app/data-explorer-shared/components/charts/base/echarts-widget.component.ts
b/ui/src/app/data-explorer-shared/components/charts/base/echarts-widget.component.ts
index dd8895db5a..e6e5629f55 100644
---
a/ui/src/app/data-explorer-shared/components/charts/base/echarts-widget.component.ts
+++
b/ui/src/app/data-explorer-shared/components/charts/base/echarts-widget.component.ts
@@ -16,7 +16,7 @@
*
*/
-import { Component, OnInit } from '@angular/core';
+import { Component, inject, OnInit } from '@angular/core';
import {
DataExplorerField,
DataExplorerWidgetModel,
@@ -28,6 +28,7 @@ import { ECharts } from 'echarts/core';
import { EChartsOption } from 'echarts';
import { Subject, Subscription } from 'rxjs';
import { debounceTime } from 'rxjs/operators';
+import { ResizeEchartsService } from
'../../../services/resize-echarts.service';
@Component({
selector: 'sp-data-explorer-echarts-widget',
@@ -48,15 +49,24 @@ export class SpEchartsWidgetComponent<T extends
DataExplorerWidgetModel>
latestData: SpQueryResult[];
renderSubject = new Subject<void>();
- renderSubjectSubscription: Subscription;
+ renderSubject$: Subscription;
+ resizeEcharts$: Subscription;
renderer: SpEchartsRenderer<T>;
+ resizeEchartsService = inject(ResizeEchartsService);
+
widgetTypeLabel: string;
ngOnInit(): void {
super.ngOnInit();
this.renderer = this.getRenderer();
- this.renderSubjectSubscription = this.renderSubject
+ this.resizeEcharts$ =
+ this.resizeEchartsService.echartsResizeSubject.subscribe(width => {
+ this.currentWidth = width - this.widthOffset;
+ this.applySize(this.currentWidth, this.currentHeight);
+ this.refreshView();
+ });
+ this.renderSubject$ = this.renderSubject
.pipe(debounceTime(300))
.subscribe(() => {
this.renderChartOptions(this.latestData);
@@ -124,7 +134,8 @@ export class SpEchartsWidgetComponent<T extends
DataExplorerWidgetModel>
public cleanupSubscriptions(): void {
super.cleanupSubscriptions();
- this.renderSubjectSubscription.unsubscribe();
+ this.resizeEcharts$?.unsubscribe();
+ this.renderSubject$?.unsubscribe();
}
getRenderer(): SpEchartsRenderer<T> {
diff --git
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
b/ui/src/app/data-explorer-shared/services/resize-echarts.service.ts
similarity index 60%
copy from
ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
copy to ui/src/app/data-explorer-shared/services/resize-echarts.service.ts
index b8ebed30f9..d930b02676 100644
---
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
+++ b/ui/src/app/data-explorer-shared/services/resize-echarts.service.ts
@@ -16,44 +16,14 @@
*
*/
-.fixed-height {
- height: 50px;
-}
-
-.data-explorer-options {
- padding: 0px;
-}
-
-.data-explorer-options-item {
- display: inline;
- margin-right: 10px;
-}
-
-.m-20 {
- margin: 20px;
-}
+import { Injectable } from '@angular/core';
+import { Subject } from 'rxjs';
-.h-100 {
- height: 100%;
-}
-
-.dashboard-grid {
- display: flex;
- flex-direction: column;
- flex: 1 1 100%;
-}
-
-.designer-panel-container {
- width: 100%;
- height: 100%;
-}
-
-.designer-panel {
- width: 450px;
- border: 1px solid var(--color-tab-border);
-}
+@Injectable({ providedIn: 'root' })
+export class ResizeEchartsService {
+ public echartsResizeSubject: Subject<number> = new Subject<number>();
-.widget-title-text {
- white-space: nowrap;
- margin-right: 12px;
+ public notify(width: number): void {
+ this.echartsResizeSubject.next(width);
+ }
}
diff --git
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.html
b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.html
index 2f3c30bf4c..ac7c19b8c4 100644
---
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.html
+++
b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.html
@@ -46,18 +46,25 @@
>
<mat-drawer
[opened]="editMode"
+ [style.width.px]="drawerWidth"
mode="side"
position="end"
class="designer-panel"
>
- <div fxLayout="column" fxFlex="100">
- <sp-data-explorer-designer-panel
- [currentlyConfiguredWidget]="dataView"
- [dataLakeMeasure]="dataLakeMeasure"
- fxFlex="100"
- >
- </sp-data-explorer-designer-panel>
- </div>
+ <sp-sidebar-resize
+ [minWidth]="450"
+ [maxWidth]="1000"
+ (widthChanged)="onWidthChanged($event)"
+ >
+ <div fxLayout="column" fxFlex="100">
+ <sp-data-explorer-designer-panel
+ [currentlyConfiguredWidget]="dataView"
+ [dataLakeMeasure]="dataLakeMeasure"
+ fxFlex="100"
+ >
+ </sp-data-explorer-designer-panel>
+ </div>
+ </sp-sidebar-resize>
</mat-drawer>
<mat-drawer-content class="h-100 dashboard-grid">
<div #panel fxFlex="100" fxLayout="column">
diff --git
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
index b8ebed30f9..b286235804 100644
---
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
+++
b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.scss
@@ -49,8 +49,11 @@
}
.designer-panel {
- width: 450px;
border: 1px solid var(--color-tab-border);
+ width: auto;
+ flex: 0 0 auto;
+ display: inline-block;
+ overflow-x: hidden;
}
.widget-title-text {
diff --git
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts
b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts
index 3e27ab7404..3d0e5cb82a 100644
---
a/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts
+++
b/ui/src/app/data-explorer/components/chart-view/data-explorer-chart-view.component.ts
@@ -16,7 +16,14 @@
*
*/
-import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
+import {
+ Component,
+ ElementRef,
+ inject,
+ OnInit,
+ signal,
+ ViewChild,
+} from '@angular/core';
import {
ChartService,
DataExplorerWidgetModel,
@@ -40,6 +47,7 @@ import { Observable, of } from 'rxjs';
import { MatDialog } from '@angular/material/dialog';
import { map } from 'rxjs/operators';
import { TranslateService } from '@ngx-translate/core';
+import { ResizeEchartsService } from
'../../../data-explorer-shared/services/resize-echarts.service';
@Component({
selector: 'sp-data-explorer-data-view',
@@ -57,6 +65,10 @@ export class DataExplorerChartViewComponent
originalDataView: DataExplorerWidgetModel;
dataLakeMeasure: DataLakeMeasure;
gridsterItemComponent: any;
+ drawerWidth = 450;
+ panelWidth = '100%';
+
+ resizeEchartsService = inject(ResizeEchartsService);
@ViewChild('panel', { static: false }) outerPanel: ElementRef;
@@ -225,4 +237,13 @@ export class DataExplorerChartViewComponent
this.dataView,
);
}
+
+ onWidthChanged(newWidth: number) {
+ this.drawerWidth = newWidth;
+ setTimeout(() => {
+ this.resizeEchartsService.notify(
+ this.outerPanel.nativeElement.offsetWidth,
+ );
+ }, 100);
+ }
}