552402 - Simple XY-Chartviewer
Multi channelgroup selection. Individual x-axis per channel.
Refactoring
Signed-off-by: Johannes Stamm <j.stamm@peak-solution.de>
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chart-viewer.style.css b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chart-viewer.style.css
index 35fbfd6..364c1cb 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chart-viewer.style.css
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chart-viewer.style.css
@@ -20,10 +20,52 @@
margin-bottom: 4px;
}
-.toolbar .thin {
+.thin {
padding: 4px;
}
+.toggler {
+ text-align: right;
+ color: #6c757d;
+ cursor: pointer;
+}
+
+.toggler:hover {
+ color: black;
+}
+
+p-listbox >>> .ui-listbox-item {
+ padding: 4px 0 4px 8px !important;
+}
+
+p-listbox >>> p-header {
+ display: grid;
+ grid-template-columns: 12% 63% 25%;
+ align-items: center;
+}
+
+p-listbox >>> .ui-listbox-header {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ /* border-bottom-color: rgb(166,166,166); */
+}
+
+p-listbox >>> .ui-listbox-header-w-checkbox {
+ padding: 4px 8px;
+}
+
+.hiddenList >>> .ui-listbox-list-wrapper {
+ display: none;
+}
+
+.hiddenList >>> .ui-listbox-header-w-checkbox {
+ display: none;
+}
+
+p-listbox >>> .ypanel .ui-listbox-header-w-checkbox {
+ text-align: right;
+}
+
p-togglebutton >>> .ui-button {
font-size: 14px;
margin: 0 3px;
@@ -54,6 +96,10 @@
color: #6c757d!important;
}
+p-spinner {
+ margin: 0 3px;
+}
+
p-spinner >>> .ui-button {
font-size: 14px;
color: #6c757d;
@@ -66,4 +112,56 @@
background-color:#c8c8c8;
border-color:#c8c8c8;
color:#333333;
+}
+
+p-spinner >>> .ui-spinner {
+ margin-top: -3px;
+}
+
+p-spinner >>> .ui-spinner-input {
+ height: 32px;
+}
+
+.hidden {
+ display: none;
+}
+
+.channelList {
+ list-style-type: none;
+ padding: 0;
+ margin-bottom: 0;
+ min-height: 80px;
+}
+
+.row {
+ display: grid;
+ grid-template-columns: 155px 185px;
+ align-items: center;
+ padding: 1px 8px 1px 8px;
+}
+
+p-panel >>> .ui-panel-content.ui-widget-content {
+ overflow-x: scroll;
+ overflow-y: visible;
+}
+
+p-panel >>> .ui-panel .ui-panel-titlebar {
+ background-color: inherit;
+ border-color: rgb(166,166,166);
+ padding: 6px 12px;
+}
+
+p-panel >>> .ui-panel .ui-panel-content {
+ border-color: rgb(166,166,166);
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+ padding: 4px 10px
+}
+
+p-panel >>> .ui-inputtext {
+ padding: 2px 0.429em;
+}
+
+p-panel label {
+ font-weight: inherit;
}
\ No newline at end of file
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chartviewer.module.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chartviewer.module.ts
index 2fcb508..03a4e8d 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chartviewer.module.ts
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/chartviewer.module.ts
@@ -26,6 +26,8 @@
import { ToggleButtonModule } from 'primeng/togglebutton';
import { SpinnerModule } from 'primeng/spinner';
import { MultiSelectModule } from 'primeng/multiselect';
+import { ListboxModule } from 'primeng/listbox';
+import { PanelModule } from 'primeng/panel';
import { MDMCoreModule } from '../core/mdm-core.module';
import { ChartViewerComponent } from './components/chartviewer/chart-viewer.component';
@@ -34,6 +36,8 @@
import { XyChartViewerComponent } from './components/xy-chart-viewer/xy-chart-viewer.component';
import { XyChartViewerNavCardComponent } from './components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component';
import { RequestOptionsComponent } from './components/request-options/request-options.component';
+import { XyChartViewerToolbarComponent } from './components/xy-chart-viewer-toolbar/xy-chart-viewer-toolbar.component';
+import { XyChartDataSelectionPanelComponent } from './components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component';
@NgModule({
imports: [
@@ -49,7 +53,9 @@
ChartModule,
ToggleButtonModule,
SpinnerModule,
- MultiSelectModule
+ MultiSelectModule,
+ ListboxModule,
+ PanelModule
],
declarations: [
ChartViewerNavCardComponent,
@@ -58,6 +64,8 @@
XyChartViewerComponent,
XyChartViewerNavCardComponent,
RequestOptionsComponent,
+ XyChartViewerToolbarComponent,
+ XyChartDataSelectionPanelComponent,
],
exports: [
ChartViewerNavCardComponent,
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/request-options/request-options.component.html b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/request-options/request-options.component.html
index 8348eb8..108ee9a 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/request-options/request-options.component.html
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/request-options/request-options.component.html
@@ -1,3 +1,16 @@
+<!--********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************-->
<p-accordion [style]="{'width':'100%'}">
<p-accordionTab header="Optionen" [disabled]="!channelGroups || channelGroups.length === 0">
<div class="p-grid nested-grid p-align-center">
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.html b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.html
new file mode 100644
index 0000000..f64b5c1
--- /dev/null
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.html
@@ -0,0 +1,145 @@
+<!--********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************-->
+
+<div class="p-grid">
+ <div class="p-col-12" style="margin-top: 4px">
+ <p-listbox
+ [options]="channelGroups"
+ [(ngModel)]="selectedChannelGroups"
+ multiple="multiple"
+ checkbox="checkbox"
+ filter="filter"
+ optionLabel="name"
+ (onChange)="onSelectedChannelGroupsChanged($event)"
+ [ngClass]="{'hiddenList': hiddenGroups}"
+ [style]="{'width':'100%'}"
+ [listStyle]="{'height':'100px'}">
+ <p-header>
+ <span class="icon channelgroup"></span>
+ {{'SubMatrix' | mdmdatasourcetranslate}}
+ <span
+ class="fa toggler"
+ [ngClass]="{'fa-chevron-down': !hiddenGroups, 'fa-chevron-right': hiddenGroups}"
+ (click)="onToggleChannelGroupPanel($event)"></span>
+ </p-header>
+ </p-listbox>
+ <!-- <p-multiSelect
+ [style]="{'width':'100%'}"
+ defaultLabel="Choose ChannelGroups"
+ [options]="channelGroups"
+ [(ngModel)]="selectedChannelGroups"
+ optionLabel="name"
+ (onChange)="onSelectedChannelGroupsChanged($event)">
+ </p-multiSelect> -->
+ </div>
+ <div class="p-col-12">
+ <p-listbox [options]="yChannelOptions"
+ [(ngModel)]="selectedYChannels"
+ multiple="multiple"
+ checkbox="checkbox"
+ filter="filter"
+ optionLabel="name"
+ (onChange)="onSelectedYChannelsChanged($event)"
+ [ngClass]="{'hiddenList': hiddenYChannels}"
+ [style]="{'width':'100%'}"
+ [styleClass]="'ypanel'"
+ [listStyle]="{'height':'200px'}"
+ [showToggleAll]="false">
+ <p-header>
+ <span class="icon channel"></span>
+ Y-{{'MeaQuantity' | mdmdatasourcetranslate}}
+ <span
+ class="fa toggler"
+ [ngClass]="{'fa-chevron-down': !hiddenYChannels, 'fa-chevron-right': hiddenYChannels}"
+ (click)="onToggleYChannelPanel($event)"></span>
+ </p-header>
+ </p-listbox>
+ <!-- <p-multiSelect
+ [style]="{'width':'100%'}"
+ defaultLabel="Choose Channels"
+ [options]="yChannelOptions"
+ [(ngModel)]="selectedYChannels"
+ optionLabel="name"
+ (onChange)="onSelectedYChannelsChanged($event)"
+ [showToggleAll]="false">
+ </p-multiSelect> -->
+ </div>
+ <div class="p-col-12">
+ <p-panel
+ [toggleable]="true"
+ [collapsed]="true"
+ expandIcon="fa fa-chevron-right"
+ collapseIcon="fa fa-chevron-down">
+ <p-header>
+ <span class="icon channel"></span>
+ X-{{'MeaQuantity' | mdmdatasourcetranslate}}
+ </p-header>
+ <!-- <p-table [value]="selectedChannelRows">
+ <ng-template pTemplate="header">
+ <tr>
+ <th>Channel</th>
+ <th></th>
+ </tr>
+ </ng-template>
+ <ng-template pTemplate="body" let-rowData>
+ <tr>
+ <td>{{rowData.yChannel.name}}</td>
+ <td>
+ <p-dropdown
+ [style]="{'width':'100%'}"
+ [options]="xChannelOptions[rowData.channelGroup.id]"
+ [(ngModel)]="rowData.xChannel"
+ placeholder="Select X"
+ optionLabel="name"
+ [showClear]="true"
+ (onChange)="onSelectedXChannelChanged($event, rowData)">
+ </p-dropdown>
+ </td>
+ </tr>
+ </ng-template>
+ </p-table> -->
+ <ul class="channelList">
+ <li *ngFor="let rowData of selectedChannelRows">
+ <div class="row">
+ <label>
+ {{rowData.yChannel.name}}
+ </label>
+
+ <!-- appendTo="body" is workarround for overlay is hidden in panel. Problem: AppendTo body makes overly stuck on scroll -->
+ <p-dropdown
+ [(ngModel)]="rowData.xChannel"
+ [options]="xChannelOptions[rowData.channelGroup.id]"
+ appendTo="body"
+ [filter]="xChannelOptions[rowData.channelGroup.id]?.length > 5"
+ (onChange)="onSelectedXChannelChanged($event, rowData)"
+ placeholder="{{'chartviewer.xy-chart-data-selection-panel.select-channel-placeholder' | translate}}"
+ optionLabel="name"
+ [showClear]="false"
+ [style]="{'width':'95%'}">
+ </p-dropdown>
+ </div>
+ </li>
+ </ul>
+ </p-panel>
+ <!-- <p-dropdown
+ [style]="{'width':'100%'}"
+ [options]="xChannels"
+ [(ngModel)]="selectedXChannel"
+ placeholder="Select X"
+ optionLabel="name"
+ [showClear]="true"
+ (onChange)="onSelectedXChannelChanged($event)">
+ </p-dropdown> -->
+ </div>
+</div>
\ No newline at end of file
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.ts
new file mode 100644
index 0000000..3465d68
--- /dev/null
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-data-selection-panel/xy-chart-data-selection-panel.component.ts
@@ -0,0 +1,472 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+import { Component, OnInit, Input, OnDestroy, EventEmitter, Output, OnChanges, SimpleChanges } from '@angular/core';
+import { ChannelSelectionRow, MeasuredValues} from '../../model/chartviewer.model';
+import { Subscription, of } from 'rxjs';
+import { ChartViewerDataService } from '../../services/chart-viewer-data.service';
+import { ChartViewerService } from '../../services/chart-viewer.service';
+import { ArrayUtilService } from 'src/app/core/services/array-util.service';
+import { MDMNotificationService } from 'src/app/core/mdm-notification.service';
+import { TYPE_MEASUREMENT, TYPE_CHANNELGROUP, TYPE_CHANNEL } from '../../model/constants';
+import { tap } from 'rxjs/operators';
+import { Node } from '../../../navigator/node';
+
+@Component({
+ selector: 'mdm5-xy-chart-data-selection-panel',
+ templateUrl: './xy-chart-data-selection-panel.component.html',
+ styleUrls: ['../../chart-viewer.style.css']
+})
+export class XyChartDataSelectionPanelComponent implements OnInit, OnDestroy, OnChanges {
+
+ @Input()
+ public channelGroups: Node[];
+ @Input()
+ public channels: Map<string, Node[]>;
+
+ @Input()
+ public xyMode: boolean;
+
+ @Output()
+ public onSelectionChanged = new EventEmitter<ChannelSelectionRow[]>();
+
+ // select options for channels
+ public yChannelOptions: Node[] = [];
+ public xChannelOptions: {[key: string]: Node[]} = {};
+
+ // channel(group) selection for chart
+ // !! change via setter to update cache for workarround !!
+ public selectedChannelGroups: Node[] = [];
+ public selectedYChannels: Node[] = [];
+
+ private xYcache = new Map<string, MeasuredValues[]>();
+ private selectionChanged = false;
+
+ // listbox workarround to determine toggled item(s)
+ private lastChannelGroupSelection: Node[] = [];
+ private lastYChannelSelection: Node[] = [];
+
+ public selectedChannelRows: ChannelSelectionRow[] = [];
+
+ // Toggle selection panel visibility
+ public hiddenGroups = false;
+ public hiddenYChannels = false;
+
+ // for x-channel default value
+ private independentChannels = new Map<string, Node>();
+
+ /********** subscriptions */
+ private chartViewerSub: Subscription;
+
+ constructor(private chartviewerDataService: ChartViewerDataService,
+ private chartViewerService: ChartViewerService,
+ private arrayUtil: ArrayUtilService,
+ private notificationService: MDMNotificationService) { }
+
+
+ /**************** Angular lifecycle-hooks ****************************/
+
+ ngOnInit() {
+ this.chartViewerSub = this.chartViewerService.onNodeMetaChange().subscribe(node => this.handleNodeSelectionInNavTree(node));
+ }
+
+ ngOnDestroy() {
+ this.chartViewerSub.unsubscribe();
+ }
+
+ ngOnChanges(changes: SimpleChanges) {
+ if (changes['xyMode']) {
+ this.reloadAxisSelectOptions().subscribe(() => {
+ if (this.selectionChanged) {
+ this.fireSelectionChanged();
+ this.selectionChanged = false;
+ }
+ });
+ }
+ }
+
+ /**************** Html-template listeners *****************************/
+
+ // x-axis
+ public onSelectedXChannelChanged(event: any) {
+ if (event.value == undefined) {
+ // work arround: if x-axis is deselected for an y-channel, plat over independent channel.
+ // should force selection on dropdown instead.
+ this.selectedChannelRows
+ .filter(row => row.xChannel == undefined)
+ .map(row => row.xChannel = this.independentChannels.get(row.channelGroup.id));
+ }
+ this.fireSelectionChanged();
+ }
+
+ // y-axis
+ public onSelectedYChannelsChanged(event: any) {
+ let channel: Node;
+ // Deselect
+ if (this.selectedYChannels.length < this.lastYChannelSelection.length) {
+ channel = this.lastYChannelSelection.find(yChannel => !this.selectedYChannels.some(c => yChannel.id === c.id));
+ // .forEach(yChannel => this.addOrRemoveRow(this.findChannelGroup(yChannel), yChannel));
+ // Select
+ } else {
+ channel = this.selectedYChannels.find(group => !this.lastYChannelSelection.some(g => group.id === g.id));
+ }
+ this.addOrRemoveRow(this.findChannelGroup(channel), channel);
+ this.lastYChannelSelection = this.selectedYChannels;
+ this.fireSelectionChanged();
+ }
+ // // y-axis
+ // public onSelectedYChannelsChanged(event: any) {
+ // const yChannel = event.itemValue;
+ // this.addOrRemoveRow(this.findChannelGroup(yChannel), );
+ // this.fireSelectionChanged();
+ // }
+
+ // channelgroups
+ // public onSelectedChannelGroupsChanged(event: any) {
+ // const item = event.itemValue;
+ // // item is undefined, if select-all check box is clicked.
+ // if (item == undefined) {
+ // if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)) {
+ // this.selectedChannelGroups.forEach(g => this.handleOnSelectChannelGroup(g));
+ // } else {
+ // this.resetChannelData();
+ // this.fireSelectionChanged();
+ // }
+ // } else {
+ // // item contains toggled channelGroup if single select box is clicked
+ // this.handleOnSelectChannelGroup(item);
+ // }
+ // }
+
+ public onSelectedChannelGroupsChanged(event: any) {
+ // All deselected
+ if (this.selectedChannelGroups.length === 0) {
+ this.resetChannelData();
+ this.fireSelectionChanged();
+ } else {
+ // Deselect
+ if (this.selectedChannelGroups.length < this.lastChannelGroupSelection.length) {
+ this.lastChannelGroupSelection
+ .filter(group => !this.selectedChannelGroups.some(g => group.id === g.id))
+ .forEach(group => this.handleDeselectChannelGroup(group));
+ // Select
+ } else {
+ this.selectedChannelGroups
+ .filter(group => !this.lastChannelGroupSelection.some(g => group.id === g.id))
+ .forEach(group => this.handleSelectChannelGroup(group));
+ }
+ }
+ this.lastChannelGroupSelection = this.selectedChannelGroups;
+ }
+
+ // private handleOnSelectChannelGroup(channelGroup: any) {
+ // // the currently toggled group is selected (ngModel is updated faster then event.)
+ // if (this.isNodeIn(channelGroup, this.selectedChannelGroups)) {
+ // this.handleSelectChannelGroup(channelGroup);
+ // // the currently toggled group is deselected
+ // } else {
+ // this.handleDeselectChannelGroup(channelGroup);
+ // }
+ // }
+
+ public onToggleChannelGroupPanel(event: Event) {
+ this.hiddenGroups = !this.hiddenGroups;
+ }
+
+ public onToggleYChannelPanel(event: Event) {
+ this.hiddenYChannels = !this.hiddenYChannels;
+ }
+
+ private handleDeselectChannelGroup(channelGroup: Node) {
+ // remove rows
+ if (this.arrayUtil.isNotEmpty(this.selectedChannelRows)) {
+ this.selectedChannelRows = this.selectedChannelRows.filter(row => row.channelGroup.id !== channelGroup.id);
+ }
+ // remove selection
+ if (this.arrayUtil.isNotEmpty(this.selectedYChannels)) {
+ this.setSelectedYChannels(this.selectedYChannels.filter(channel =>
+ this.channels.get(channelGroup.id).findIndex(c => channel.id === c.id) === -1));
+ }
+ this.reloadAxisSelectOptions().subscribe(() => this.fireSelectionChanged());
+ }
+
+ /**
+ * Handle channelGroup selection via multiselect in html template
+ * @param channelGroup
+ */
+ private handleSelectChannelGroup(channelGroup: Node) {
+ const cached = this.xYcache.get(channelGroup.id);
+ if (cached != undefined) {
+ this.setChannelOptions(cached, channelGroup);
+ this.fireSelectionChanged();
+ } else {
+ this.chartviewerDataService.readAxisType(channelGroup)
+ .subscribe(mvls => {
+ this.setChannelOptions(mvls, channelGroup);
+ this.fireSelectionChanged();
+ });
+ }
+ }
+
+ private handleNodeSelectionInNavTree(node: Node) {
+ if (node != undefined) {
+ switch (node.type) {
+ case TYPE_MEASUREMENT:
+ this.xYcache.clear();
+ this.resetChannelData();
+ this.fireSelectionChanged();
+ break;
+ case TYPE_CHANNELGROUP:
+ this.cleanOldState();
+ this.addChannelGroupToSelection(node.id, node);
+ break;
+ case TYPE_CHANNEL:
+ this.cleanOldState();
+ // add related channel group to selection
+ if (this.arrayUtil.isNotEmpty(this.channelGroups) && this.channels != undefined) {
+ const channelGroup = this.findChannelGroup(node);
+ // this.addChannelGroupToSelection(channelGroupId, this.channelGroups.find(cg => cg.id === channelGroupId));
+ if (!this.isNodeIn(channelGroup, this.selectedChannelGroups)) {
+ this.setSelectedChannelGroups(this.selectedChannelGroups.concat([channelGroup]));
+ this.chartviewerDataService.readAxisType(channelGroup)
+ .subscribe(mvls => {
+ this.setChannelOptions(mvls, channelGroup);
+ this.addChannelToSelection(node, channelGroup);
+ });
+ } else {
+ // if channel is in axis type y, set as selected, if not selected already
+ this.addChannelToSelection(node, channelGroup);
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ /**
+ * reset chart data, select options and selection, if selected channelgroups
+ * contain a channelGroup which does not belongto this measurement.
+ *
+ * notice: this works for channels aswell, since a channel cannot be selected without
+ * selecting the parent channelGroup aswell.
+ */
+ private cleanOldState() {
+ if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)
+ && this.selectedChannelGroups.some(selected => !this.isNodeIn(selected, this.channelGroups))) {
+ this.xYcache.clear();
+ this.resetChannelData();
+ }
+ }
+
+ /**
+ * Handle channel selection via nav-tree
+ * @param channel
+ * @param channelGroup
+ */
+ private addChannelToSelection(channel: Node, channelGroup: Node) {
+ // adds channel to selected y-channels if possible and creates row in table
+ if (this.isNodeIn(channel, this.yChannelOptions)) {
+ const index = this.selectedYChannels.findIndex(c => c.id === channel.id);
+ if (index === -1) {
+ this.setSelectedYChannels(this.selectedYChannels.concat([channel]));
+ this.addRow(channelGroup, channel);
+ this.fireSelectionChanged();
+ }
+ /**
+ * @TODO -> expected behaviour on selecting x-channel in tree.
+ * suggestion: set it as x-channel for all selected y-channels of that channelgroup.
+ */
+ // if channel is of axis type x, set ... ?
+ } else if (this.isNodeIn(channel, this.xChannelOptions[channelGroup.id])) {
+ this.notificationService.notifyWarn('Selected X-Channel', 'Selected channel is of type x-axis. Change x/y mode.');
+ } else {
+ this.notificationService.notifyError('Unknown channel option', 'Not sure where you found this..');
+ }
+ }
+
+ /**
+ * Handle channelGroup selection via nav-tree
+ * @param id
+ * @param channelGroup
+ */
+ private addChannelGroupToSelection(id: string, channelGroup: Node) {
+ if (this.selectedChannelGroups == undefined) {
+ this.setSelectedChannelGroups([]);
+ }
+ if (!this.isNodeIn(channelGroup, this.selectedChannelGroups)) {
+ this.setSelectedChannelGroups(this.selectedChannelGroups.concat([channelGroup]));
+ this.handleSelectChannelGroup(channelGroup);
+ }
+ }
+
+ /**
+ * Adds options for x- and y-channels depending on given channelGroup
+ *
+ * @param measuredValues
+ * @param channelGroup
+ */
+ private setChannelOptions(measuredValues: MeasuredValues[], channelGroup: Node) {
+ if (channelGroup != undefined) {
+ // cache measuredValues to avoid reloading
+ this.xYcache.set(channelGroup.id, measuredValues);
+
+ // create empty array if property not exists
+ this.xChannelOptions[channelGroup.id] = this.xChannelOptions[channelGroup.id] || [];
+
+ if (this.xyMode) {
+ measuredValues.forEach(mvl => {
+ const tmpChannel = this.channels.get(channelGroup.id).filter(c => c.name === mvl.name)[0];
+ if (mvl.axisType === 'X_AXIS' || ( mvl.axisType == undefined && mvl.independent)) {
+ this.xChannelOptions[channelGroup.id] = this.xChannelOptions[channelGroup.id].concat(tmpChannel);
+ // cache independent channels for default x-axis.
+ if (mvl.independent) {
+ this.independentChannels.set(channelGroup.id, tmpChannel);
+ }
+ } else if (mvl.axisType === 'Y_AXIS') {
+ this.yChannelOptions = this.yChannelOptions.concat(tmpChannel);
+ }
+ });
+ } else {
+ // cache independent channel for default x-axis.
+ const value = measuredValues.find(mvl => mvl.independent);
+ const tmpChannel = this.channels.get(channelGroup.id).filter(c => c.name === value.name)[0];
+ this.independentChannels.set(channelGroup.id, tmpChannel);
+
+ const tmpChannels = this.channels.get(channelGroup.id);
+ this.xChannelOptions[channelGroup.id] = this.xChannelOptions[channelGroup.id].concat(tmpChannels);
+ this.yChannelOptions = this.yChannelOptions.concat(tmpChannels);
+ }
+ }
+ }
+
+ /**
+ * Resets selections and select options to empty state.
+ */
+ private resetChannelData() {
+ this.setSelectedChannelGroups([]);
+ this.selectedChannelRows = [];
+ this.setSelectedYChannels([]);
+ this.channelGroups = [].concat(this.channelGroups);
+ this.xChannelOptions = {};
+ this.yChannelOptions = [];
+ }
+
+ // /**
+ // * Reloads the select options for the x- and y-axis dropdowns
+ // */
+ // private reloadAxisSelectOptions() {
+ // this.xChannelOptions = {};
+ // this.yChannelOptions = [];
+ // if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)) {
+ // const uncached = this.selectedChannelGroups.filter(g => this.xYcache.get(g.id) === undefined);
+ // const cached = this.selectedChannelGroups.filter(g => this.xYcache.get(g.id) !== undefined);
+
+ // const obs = uncached.map(cg => this.chartviewerDataService.readAxisType(cg));
+ // return forkJoin(
+ // forkJoin(obs)
+ // .pipe(tap(array => array.forEach((mvls, index) => this.setChannelOptions(mvls, uncached[index])))),
+ // of(cached.map((group, index) => this.setChannelOptions(this.xYcache.get(group.id), cached[index]))))
+ // .pipe(tap(() => this.removeSelectionsNotMatchingXYMode()));
+ // }
+ // return of();
+ // }
+
+ /**
+ * Reloads the select options for the x- and y-axis dropdowns
+ */
+ private reloadAxisSelectOptions() {
+ this.xChannelOptions = {};
+ this.yChannelOptions = [];
+ if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)) {
+ const cached = this.selectedChannelGroups.filter(g => this.xYcache.get(g.id) !== undefined);
+ return of(cached.map((group, index) => this.setChannelOptions(this.xYcache.get(group.id), cached[index])))
+ .pipe(tap(() => this.removeSelectionsNotMatchingXYMode()));
+ }
+ return of();
+ }
+
+ private removeSelectionsNotMatchingXYMode() {
+ if (this.selectedYChannels.length > 0) {
+ const l = this.selectedChannelRows.length;
+ this.selectedChannelRows = this.selectedChannelRows.filter(row => this.isNodeIn(row.yChannel, this.yChannelOptions));
+ this.setSelectedYChannels(this.selectedYChannels.filter(channel => this.isNodeIn(channel, this.yChannelOptions)));
+ this.selectionChanged = l !== this.selectedChannelRows.length;
+ }
+ }
+
+ /**
+ * Row control for table with x-channel selection.
+ *
+ * @param channelGroup
+ * @param yChannel
+ */
+ private addOrRemoveRow(channelGroup: Node, yChannel: Node) {
+ const index = this.selectedChannelRows.findIndex(row => row.yChannel.id === yChannel.id);
+ if (index > -1) {
+ this.selectedChannelRows.splice(index, 1);
+ this.selectedChannelRows = [].concat(this.selectedChannelRows);
+ } else {
+ this.addRow(channelGroup, yChannel);
+ }
+ }
+
+ /**
+ * Add row to selection
+ * @param channelGroup
+ * @param yChannel
+ */
+ private addRow(channelGroup: Node, yChannel: Node) {
+ const row = new ChannelSelectionRow(channelGroup, yChannel, this.independentChannels.get(channelGroup.id));
+ this.selectedChannelRows.push(row);
+ }
+
+ /**
+ * Returns true if node with given id is in the given array.
+ *
+ * @param array the array
+ * @param id the id
+ */
+ private isNodeIn(node: Node, array: Node[]) {
+ let response = false;
+ if (node != undefined && this.arrayUtil.isNotEmpty(array)) {
+ response = array.findIndex(n => n.id === node.id) > -1;
+ }
+ return response;
+ }
+
+ /**
+ * Looks up parent channelGroup for channel via the channel map.
+ *
+ * @param channel
+ */
+ private findChannelGroup(channel: Node) {
+ const channelGroupId = Array.from(this.channels.keys())
+ .find(key => this.isNodeIn(channel, this.channels.get(key)));
+ return this.channelGroups.find(cg => cg.id === channelGroupId);
+ }
+
+ private fireSelectionChanged() {
+ this.onSelectionChanged.emit(this.selectedChannelRows);
+ }
+
+ private setSelectedYChannels(channels: Node[]) {
+ this.selectedYChannels = channels;
+ this.lastYChannelSelection = channels;
+ }
+
+ private setSelectedChannelGroups(channelGroups: Node[]) {
+ this.selectedChannelGroups = channelGroups;
+ this.lastChannelGroupSelection = channelGroups;
+ }
+}
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.html b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.html
index e23db48..01b2142 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.html
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.html
@@ -13,10 +13,11 @@
********************************************************************************-->
<div *ngIf="measurement === undefined || channelGroups === undefined || channels === undefined">
- No Node selected.
- <button (click)="onClick()">Click</button>
+ <div class="alert alert-info" style="margin: 0;">
+ <strong>{{'chartviewer.xy-chart-viewer-nav-card.no-node-selected' | translate}}</strong>
+ </div>
</div>
<div *ngIf="measurement !== undefined && channelGroups !== undefined && channels !== undefined">
- <app-xy-chart-viewer [measurement]="measurement" [channelGroups]="channelGroups" [channels]="channels"></app-xy-chart-viewer>
+ <app-xy-chart-viewer [channelGroups]="channelGroups" [channels]="channels"></app-xy-chart-viewer>
</div>
\ No newline at end of file
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.ts
index 06b030b..af4d82d 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.ts
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-nav-card/xy-chart-viewer-nav-card.component.ts
@@ -17,12 +17,11 @@
import { MDMNotificationService } from 'src/app/core/mdm-notification.service';
import { Node } from '../../../navigator/node';
import { TYPE_CHANNEL, TYPE_CHANNELGROUP, TYPE_MEASUREMENT } from '../../model/constants';
-import { Subscription, concat, forkJoin, zip, of } from 'rxjs';
+import { Subscription, forkJoin } from 'rxjs';
import { NodeService } from 'src/app/navigator/node.service';
-import { map, flatMap, tap } from 'rxjs/operators';
+import { map, tap } from 'rxjs/operators';
import { MDMItem } from 'src/app/core/mdm-item';
import { ChartViewerService } from '../../services/chart-viewer.service';
-import { ArrayUtilService } from 'src/app/core/services/array-util.service';
@Component({
selector: 'app-xy-chart-viewer-nav-card',
@@ -34,9 +33,10 @@
public channelGroups: Node[];
public measurement: Node;
+ private selectedNode: Node;
+
// Subscriptions
private selectedNodeSub: Subscription;
- private selectedNode: Node;
constructor(
private navigatorService: NavigatorService,
@@ -57,14 +57,6 @@
}
/**
- * @TODO remove
- */
- onClick() {
- const item = new MDMItem('MDMCRASH', 'Measurement', '180');
- setTimeout(() => this.navigatorService.fireOnOpenInTree([item]));
- }
-
- /**
* Handle node selection in navigation tree.
* Loads necessary data for xy chart, if not present:
* - Measurement:
@@ -105,7 +97,7 @@
}
private selectedChannelGroup(node: Node) {
- if (this.isChannelGroupPresent(node)) {
+ if (!this.isChannelGroupPresent(node)) {
this.loadMeasurement(node);
} else {
this.chartViewerService.sendNodeMeta(this.selectedNode);
@@ -170,58 +162,14 @@
});
}
- // private load(node: Node) {
- // this.searchNodes(node, TYPE_MEASUREMENT)
- // .pipe(
- // /** @TODO in general true? */
- // // parent measurement must be distinct
- // map(measurements => measurements[0]),
- // tap(measurement => this.measurement = measurement),
- // flatMap(measurement => this.searchNodes(measurement, TYPE_CHANNELGROUP)),
- // tap(channelGroups => this.channelGroups = channelGroups),
- // flatMap(channelGroups => forkJoin(channelGroups.map(channelGroup => this.searchNodes(channelGroup, TYPE_CHANNEL)))),
- // map(n => n.map((x, i) => ({group: channelGroups[i], channels: x})))
-
- // ).subscribe(measurement => {
- // this.measurement = measurement;
- // this.loadChannelGroups(this.measurement);
- // });
- // }
-
private loadChannels(channelGroups: Node[]) {
+ this.channels.clear();
let obsArray = channelGroups.map(channelGroup => this.searchNodes(channelGroup, TYPE_CHANNEL));
forkJoin(obsArray).pipe(
tap(array => array.forEach((channels, index) => this.channels.set(channelGroups[index].id, channels)))
).subscribe(datasets => this.chartViewerService.sendNodeMeta(this.selectedNode));
-
- // forkJoin(obsArray).pipe(
- // map(n => n.map((x, i) => ({group: channelGroups[i], channels: x})))
- // ).subscribe(datasets => {
- // datasets.forEach(data => this.channels.set(data.group.id, data.channels));
- // this.chartViewerService.sendNodeMeta(this.selectedNode);
- // }
- // );
-
- // forkJoin(obsArray)
- // .pipe(
- // flatMap(channelsArray => zip(channelGroups, channelsArray))
- // )
- // .subscribe(([cg, channels]) => {
- // console.log('everevver???');
- // console.log(cg);
- // console.log(channels)
- // this.channels.set(cg.id, channels)});
- // return forkJoin(channelGroups.map(channelGroup => this.searchNodes(channelGroup, TYPE_CHANNEL)));
}
-
- // private loadChannels2(channelGroups: Node[]) {
- // channelGroups.forEach(channelGroup =>
- // this.searchNodes(channelGroup, TYPE_CHANNEL)
- // .subscribe(channels => this.channels.set(channelGroup.id, channels))
- // );
- // }
-
private searchNodes(node: Node, targetType: string) {
const filter = 'filter=' + node.type + '.Id eq \"' + node.id + '\"';
return this.nodeService.searchNodes(filter, node.sourceName, targetType);
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-toolbar/xy-chart-viewer-toolbar.component.html b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-toolbar/xy-chart-viewer-toolbar.component.html
new file mode 100644
index 0000000..bb0d753
--- /dev/null
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-toolbar/xy-chart-viewer-toolbar.component.html
@@ -0,0 +1,101 @@
+<!--********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************-->
+<div class="p-col-12 thin" >
+ <!-- ChannelSelection -->
+ <p-toggleButton
+ [(ngModel)]="properties.showSelection"
+ [onIcon]="'fa fa-columns'"
+ offIcon="fa fa-square-o"
+ onLabel=""
+ offLabel=""
+ (onChange)="onChangeProperty($event)"
+ title="{{(properties.showSelection ? 'chartviewer.xy-chart-viewer-toolbar.hide-data-selection-panel' : 'chartviewer.xy-chart-viewer-toolbar.show-data-selection-panel')| translate }}">
+ </p-toggleButton>
+ <!-- X/Y-mode -->
+ <p-toggleButton
+ [(ngModel)]="xyMode"
+ [onIcon]="'fa fa-filter'"
+ offIcon="fa fa-filter"
+ onLabel=""
+ offLabel=""
+ (onChange)="onToggleXyMode($event)"
+ title="{{(xyMode ? 'chartviewer.xy-chart-viewer-toolbar.deactivate-xy-mode' : 'chartviewer.xy-chart-viewer-toolbar.activate-xy-mode')| translate }}">
+ </p-toggleButton>
+ <span style="width:12px; display:inline-block;"></span>
+ <!-- Legend -->
+ <p-toggleButton
+ [onIcon]="'fa fa-map'"
+ offIcon="fa fa-map-o"
+ onLabel=""
+ offLabel=""
+ [(ngModel)]="properties.options.legend.display"
+ (onChange)="onChangeProperty($event)"
+ title="{{(properties?.options?.legend?.display ? 'chartviewer.xy-chart-viewer-toolbar.hide-chart-legend' : 'chartviewer.xy-chart-viewer-toolbar.show-chart-legend')| translate }}">
+ </p-toggleButton>
+ <!-- Linewidth -->
+ <p-spinner
+ [(ngModel)]="properties.lineWidth"
+ [min]="0.25"
+ [step]="0.25"
+ size="1"
+ (onChange)="onChangeProperty($event)"
+ title="{{'chartviewer.xy-chart-viewer-toolbar.line-width' | translate }}">
+ </p-spinner>
+ <!-- draw lines -->
+ <p-toggleButton
+ [onIcon]="'fa fa-line-chart'"
+ offIcon="fa fa-line-chart"
+ onLabel=""
+ offLabel=""
+ [(ngModel)]="properties.showLines"
+ (onChange)="onToggleShowLines($event)"
+ title="{{(properties.showLines ? 'chartviewer.xy-chart-viewer-toolbar.hide-lines' : 'chartviewer.xy-chart-viewer-toolbar.show-lines')| translate }}">
+ </p-toggleButton>
+ <!-- fill area -->
+ <p-toggleButton
+ [onIcon]="'fa fa-area-chart'"
+ offIcon="fa fa-area-chart"
+ onLabel=""
+ offLabel=""
+ [(ngModel)]="properties.fillArea"
+ (onChange)="onChangeProperty($event)"
+ [disabled]="!properties.showLines"
+ title="{{(properties.fillArea ? 'chartviewer.xy-chart-viewer-toolbar.clear-area' : 'chartviewer.xy-chart-viewer-toolbar.fill-area')| translate }}">
+ </p-toggleButton>
+ <!-- Datapoints -->
+ <p-toggleButton
+ title="Show Datapoints"
+ [onIcon]="'fa fa-share-alt'"
+ offIcon="fa fa-share-alt"
+ onLabel=""
+ offLabel=""
+ [(ngModel)]="properties.drawPoints"
+ (onChange)="onChangeProperty($event)"
+ title="{{(properties.drawPoints ? 'chartviewer.xy-chart-viewer-toolbar.hide-datapoints' : 'chartviewer.xy-chart-viewer-toolbar.show-datapoints'| translate) }}">
+ </p-toggleButton>
+ <!-- tension -->
+ <p-spinner
+ size="1"
+ [(ngModel)]="properties.lineTension"
+ [min]="0"
+ [step]="0.1"
+ [max]="1"
+ (onChange)="onChangeProperty($event)"
+ title="{{'chartviewer.xy-chart-viewer-toolbar.tension' | translate }}">
+ </p-spinner>
+
+<!-- <div class="ui-g-12 ui-md-2">
+ <p-button label="Reset" (onClick)="onResetZoom()"></p-button>
+</div> -->
+</div>
\ No newline at end of file
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-toolbar/xy-chart-viewer-toolbar.component.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-toolbar/xy-chart-viewer-toolbar.component.ts
new file mode 100644
index 0000000..b22f402
--- /dev/null
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer-toolbar/xy-chart-viewer-toolbar.component.ts
@@ -0,0 +1,82 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
+import { ChartToolbarProperties } from '../../model/chartviewer.model';
+
+@Component({
+ selector: 'mdm5-xy-chart-viewer-toolbar',
+ templateUrl: './xy-chart-viewer-toolbar.component.html',
+ styleUrls: ['../../chart-viewer.style.css']
+})
+export class XyChartViewerToolbarComponent implements OnInit {
+
+ @Output()
+ public xyModeChanged = new EventEmitter<boolean>();
+ @Output()
+ public toolbarPropertiesChanged = new EventEmitter<ChartToolbarProperties>();
+
+ // if true, x- and y-channels have to be channels with axisType 'X_AXIS', or 'Y_AXIS' respectively.
+ // change xy requires reloading of select options. Thus requires own event.
+ public xyMode = true;
+ // holds actual properties
+ public properties = new ChartToolbarProperties();
+ // model for showlines.
+ public showLegend = true;
+
+ constructor() { }
+
+ ngOnInit() {
+
+ /** properties for cahrt elements */
+
+ // if true, shows pannel with channel(-group) selection
+ this.properties.showSelection = true;
+ // if true, draws datapoints
+ this.properties.drawPoints = false;
+ // the charts borderwidth (width of lines, border for points)
+ this.properties.lineWidth = 1;
+ // if true, draws lines connecting datapoints
+ this.properties.showLines = true;
+ // if true, fills are below graph
+ this.properties.fillArea = false;
+ // the interpolation degree. 0 = linear, 0.4 = Bezier
+ this.properties.lineTension = 0;
+
+ // /** properties directly passed to cahrt options */
+ // if legend.display true, shows chart legend
+ this.properties.options = {legend: {display: true}};
+
+ // emit to send initial properties to chart viewer
+ this.xyModeChanged.emit(this.xyMode);
+ this.toolbarPropertiesChanged.emit(this.properties);
+ }
+
+ // X- and y-axis options are determined by channels axis type, if xyMode toggled to true
+ public onToggleXyMode(event: Event) {
+ this.xyModeChanged.emit(this.xyMode);
+ }
+
+ public onChangeProperty(event: Event) {
+ this.toolbarPropertiesChanged.emit(this.properties);
+ }
+
+ // displays/hides lines connecting data points
+ public onToggleShowLines(event: Event) {
+ if (!this.properties.showLines) {
+ this.properties.fillArea = false;
+ }
+ this.toolbarPropertiesChanged.emit(this.properties);
+ }
+}
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html
index 191b87e..e689d0b 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.html
@@ -1,59 +1,21 @@
+<!--********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************-->
<div class="p-grid toolbar">
- <!-- Toolbar -->
- <div class="p-col-12 thin" >
- <!-- ChannelSelection -->
- <p-toggleButton
- [(ngModel)]="showSelection"
- [onIcon]="'fa fa-columns'"
- offIcon="fa fa-square-o"
- onLabel=""
- offLabel="">
- </p-toggleButton>
- <span style="width:4px; display:inline-block;"></span>
- <!-- X/Y-mode -->
- <p-toggleButton
- [(ngModel)]="xyMode"
- onLabel="X/Y"
- offLabel="All"
- (onChange)="onToggleXyMode($event)">
- </p-toggleButton>
- <span style="width:4px; display:inline-block;"></span>
- <!-- Legend -->
- <p-toggleButton
- title="Show legend"
- [onIcon]="'fa fa-map'"
- offIcon="fa fa-map-o"
- onLabel=""
- offLabel=""
- [(ngModel)]="showLegend"
- (onChange)="onToggleLegend($event)">
- </p-toggleButton>
- <span style="width:4px; display:inline-block;"></span>
- <!-- Linewidth -->
- <p-spinner
- size="1"
- [(ngModel)]="lineWidth"
- title="Line width"
- [min]="0.25"
- [step]="0.25"
- (onChange)="onChangeLineWidth($event)">
- </p-spinner>
- <span style="width:4px; display:inline-block;"></span>
- <!-- Datapoints -->
- <p-toggleButton
- title="Show Datapoints"
- [onIcon]="'fa fa-share-alt'"
- offIcon="fa fa-share-alt"
- onLabel=""
- offLabel=""
- [(ngModel)]="drawPoints"
- (onChange)="onToggleDrawPoints($event)">
- </p-toggleButton>
-
- <!-- <div class="ui-g-12 ui-md-2">
- <p-button label="Reset" (onClick)="onResetZoom()"></p-button>
- </div> -->
- </div>
+ <mdm5-xy-chart-viewer-toolbar #toolbar
+ (xyModeChanged)="onXyModeChanged($event)"
+ (toolbarPropertiesChanged)="onToolbarPropertiesChanged($event)">
+ </mdm5-xy-chart-viewer-toolbar>
</div>
<!-- <ng-template let-dataset pTemplate="item">
@@ -63,51 +25,22 @@
<!-- View area -->
<div class="p-grid nested-grid">
<!-- Axis selection -->
- <div *ngIf="showSelection" class="p-col-3">
- <div class="p-grid">
- <div class="p-col-12" style="margin-top: 4px">
- <p-multiSelect
- [style]="{'width':'100%'}"
- defaultLabel="Choose ChannelGroups"
- [options]="channelGroups"
- [(ngModel)]="selectedChannelGroups"
- optionLabel="name"
- (onChange)="onSelectedChannelGroupsChanged($event)">
- </p-multiSelect>
- </div>
- <div class="p-col-12">
- <p-multiSelect
- [style]="{'width':'100%'}"
- defaultLabel="Choose Channels"
- [options]="yChannels"
- [(ngModel)]="selectedYChannels"
- optionLabel="name"
- (onChange)="onSelectedYChannelsChanged($event)"
- [virtualScroll]="true"
- [itemSize]="34">
- </p-multiSelect>
- </div>
- <div class="p-col-12">
- <p-dropdown
- [style]="{'width':'100%'}"
- [options]="xChannels"
- [(ngModel)]="selectedXChannel"
- placeholder="Select X"
- optionLabel="name"
- [showClear]="true"
- (onChange)="onSelectedXChannelChanged($event)">
- </p-dropdown>
- </div>
- </div>
+ <div [ngClass]="showSelection ? 'p-col-3' : 'hidden'">
+ <mdm5-xy-chart-data-selection-panel
+ [channelGroups]="channelGroups"
+ [channels]="channels"
+ [xyMode]="xyMode"
+ (onSelectionChanged)="onDataSelectionChanged($event)"
+ ></mdm5-xy-chart-data-selection-panel>
</div>
<!-- Chart / Table -->
<div [ngClass]="showSelection ? 'p-col-9' : 'p-col-12'">
- <p-chart #xyChart type="scatter" [data]="data" [options]="options"></p-chart>
+ <p-chart #xyChart type="scatter" [data]="data"></p-chart>
</div>
</div>
<div class="p-grid">
<div class="p-col-12">
- <mdm5-request-options [channelGroups]="selectedChannelGroups" (onRequestOptionsChanged)="onRequestOptionsChanged($event)"></mdm5-request-options>
+ <mdm5-request-options [channelGroups]="channelGroups" (onRequestOptionsChanged)="onRequestOptionsChanged($event)"></mdm5-request-options>
</div>
</div>
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts
index 96d4142..f25438e 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/components/xy-chart-viewer/xy-chart-viewer.component.ts
@@ -12,412 +12,189 @@
*
********************************************************************************/
-import { Component, OnInit, Input, ViewChild, OnDestroy } from '@angular/core';
+import { Component, OnInit, Input, ViewChild } from '@angular/core';
import { UIChart } from 'primeng/chart';
-import { map, tap, reduce } from 'rxjs/operators';
+import { map, flatMap } from 'rxjs/operators';
import { Node } from '../../../navigator/node';
-import { ChartData, ChartDataSet, MeasuredValues, RequestOptions, ChartXyDataSet } from '../../model/chartviewer.model';
-import { ChartViewerDataService, getDataArray } from '../../services/chart-viewer-data.service';
-import { TYPE_CHANNEL, TYPE_CHANNELGROUP, TYPE_MEASUREMENT } from '../../model/constants';
+import { ChartData, ChartDataSet, MeasuredValues, RequestOptions, ChannelSelectionRow,
+ ChartXyDataSet, ChartToolbarProperties} from '../../model/chartviewer.model';
+import { ChartViewerDataService } from '../../services/chart-viewer-data.service';
import { ArrayUtilService } from 'src/app/core/services/array-util.service';
import { ChartViewerService } from '../../services/chart-viewer.service';
-import { Subscription, forkJoin, zip, of } from 'rxjs';
+import { forkJoin} from 'rxjs';
+import { MDMNotificationService } from 'src/app/core/mdm-notification.service';
@Component({
selector: 'app-xy-chart-viewer',
templateUrl: './xy-chart-viewer.component.html',
styleUrls: ['../../chart-viewer.style.css']
})
-export class XyChartViewerComponent implements OnInit, OnDestroy {
+export class XyChartViewerComponent implements OnInit {
@ViewChild('xyChart')
public chart: UIChart;
- /** measurement and all available channels / channelgroups for that measurement
- * based on node selection in navigation tree. Is managed by "parent" component
- * to avoid unnecessary reloads.
- */
- @Input()
- public measurement: Node;
@Input()
public channelGroups: Node[];
@Input()
public channels: Map<string, Node[]>;
- // options for channels
- public xChannels: Node[] = [];
- public yChannels: Node[] = [];
-
- // channel(group) selection for chart
- public selectedChannelGroups: Node[] = [];
- public selectedXChannel: Node;
- public selectedYChannels: Node[] = [];
-
- // measured values of x-channel are cached to avoid unneccessary relaods
- // on y-channel selection and while creating data points for the chart
- private xValues = new Map<string, MeasuredValues>();
- private independentChannels = new Map<string, Node>();
-
- // chart data
+ // the chart data
public data: ChartData;
- /** Toolbar ****************/
-
- // if true, shows pannel with channel(-group) selection
- public showSelection = true;
- // if true, x- and y-channels have to be channels with axisType 'X_AXIS', or 'Y_AXIS' respectively.
- public xyMode = true;
- // if true, shows chart legend
- public showLegend = true;
- // if true, draws datapoints
- public drawPoints = false;
- // the charts borderwidth (width of lines, border for points)
- public lineWidth = 1;
-
- /**^***********************/
-
+ // options for meausred value data request
private requestOptions: RequestOptions;
+ // chart properties set via toolbar
+ private toolbarProperties: ChartToolbarProperties;
+ // shows selection pannel if true, set via toolbar
+ public showSelection: boolean;
+ // passed to selection pannel
+ public xyMode: boolean;
- public options = {legend: {display: this.showLegend}};
-
- /** subscriptions */
- private chartViewerSub: Subscription;
+ public selectedChannelRows: ChannelSelectionRow[] = [];
constructor(private chartviewerDataService: ChartViewerDataService,
private chartviewerService: ChartViewerService,
- private arrayUtil: ArrayUtilService) { }
-
-
- /**************** Angular lifecycle-hooks ****************************/
+ private arrayUtil: ArrayUtilService,
+ private notificationService: MDMNotificationService) { }
ngOnInit() {
this.initChartData();
- this.chartViewerSub = this.chartviewerService.onNodeMetaChange().subscribe(node => this.handleNodeSelectionInNavTree(node));
- }
-
- ngOnDestroy() {
- this.chartViewerSub.unsubscribe();
- }
-
- // empty chart on initialization
- private initChartData() {
- const dataset = new ChartDataSet('No data', []);
- dataset.borderColor = '#fff';
- this.data = new ChartData([], [dataset]);
}
/**************** Html-template listeners *****************************/
- // --- Data Selection ---
+ /**
+ * Draws chart when data selection changes
+ * @param rows
+ */
+ public onDataSelectionChanged(rows: ChannelSelectionRow[]) {
+ this.selectedChannelRows = rows;
+ this.doChart();
+ }
- // x-axis
- public onSelectedXChannelChanged(event: Event) {
- if (this.selectedXChannel != undefined) {
- const channelGroup = this.findChannelGroup(this.selectedXChannel);
- this.loadXValues(channelGroup);
- } else {
- this.initChartData();
+ /**
+ * Passes xyModeChanges from toolbar to selection pannel
+ * @param isXyMode
+ */
+ public onXyModeChanged(isXyMode: boolean) {
+ this.xyMode = isXyMode;
+ }
+
+ /**
+ * Handles toolbar property changes
+ * @param properties
+ */
+ public onToolbarPropertiesChanged(properties: ChartToolbarProperties) {
+ this.toolbarProperties = properties;
+ this.showSelection = properties.showSelection;
+ this.chart.options = properties.options;
+ if (this.chart.data != undefined) {
+ this.chart.data.datasets.forEach( dataSet => {
+ dataSet.showLine = properties.showLines;
+ dataSet.pointRadius = properties.drawPoints ? 3 : 0;
+ dataSet.borderWidth = properties.lineWidth;
+ dataSet.lineTension = properties.lineTension;
+ dataSet.fill = properties.fillArea;
+ });
+ this.chart.reinit();
}
}
- // y-axis
- public onSelectedYChannelsChanged(event: Event) {
- if (this.arrayUtil.isNotEmpty(this.selectedYChannels)) {
- this.doChart();
- } else {
- this.initChartData();
- }
- }
-
- // channelgroups
- public onSelectedChannelGroupsChanged(event: any) {
- // some channelgroup selected
- if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)) {
- const tmpGroup = event.itemValue;
- // the currently toggled group is selected (ngModel is updated faster then event.)
- if (this.isNodeIn(this.selectedChannelGroups, tmpGroup.id)) {
- this.handleSelectChannelGroup(tmpGroup);
- // the currently toggled group is deselected
- } else {
- this.handleDeselectChannelGroup(tmpGroup);
- }
- // no channelgroup selected
- } else {
- this.resetChannelData();
- this.initChartData();
- }
- }
-
- // --- Toolbar ---
-
- // X- and y-axis options are determined by channels axis type, if xyMode toggled to true
- public onToggleXyMode(event: Event) {
- this.reloadAxisSelectOptions();
- }
-
- // displays/hides chart legend
- public onToggleLegend(event: Event) {
- this.options.legend.display = this.showLegend;
- this.chart.reinit();
- }
-
- // displays/hides visible markers in chart at data points
- public onToggleDrawPoints(event: Event) {
- this.chart.data.datasets.forEach(ds => ds.pointRadius = this.drawPoints ? 3 : 0);
- this.chart.reinit();
- }
-
- // displays chart with new line width
- public onChangeLineWidth(event: Event) {
- this.chart.data.datasets.forEach(ds => ds.borderWidth = this.lineWidth);
- this.chart.reinit();
- }
-
// Sets new data request options and redraws the graph
public onRequestOptionsChanged(options: RequestOptions) {
this.requestOptions = options;
this.doChart();
}
- /** Observable response handler *********************************************/
-
- private handleDeselectChannelGroup(channelGroup: Node) {
- /**
- * @TODO implement
- */
- this.handleSelectChannelGroup(channelGroup);
- // this.xChannels = this.xChannels.filter(c => c.relations[0].)
- }
-
- /**
- * Handle channelGroup selection via multiselect in html template
- * @param channelGroup
- */
- private handleSelectChannelGroup(channelGroup: Node) {
- this.chartviewerDataService.readAxisType(channelGroup)
- .subscribe(mvls => {
- this.addXandYchannels(mvls, channelGroup);
- if (this.xValues.get(channelGroup.id) == undefined) {
- this.loadXValues(channelGroup);
- } else {
- this.doChart();
- }
- });
- }
-
- private handleNodeSelectionInNavTree(node: Node) {
- if (node != undefined) {
- switch (node.type) {
- case TYPE_MEASUREMENT:
- this.resetChannelData();
- this.doChart();
- break;
- case TYPE_CHANNELGROUP:
- this.addChannelGroupToSelection(node.id, node);
- break;
- case TYPE_CHANNEL:
- // add related channel group to selection
- if (this.arrayUtil.isNotEmpty(this.channelGroups) && this.channels != undefined) {
- const channelGroup = this.findChannelGroup(node);
- // this.addChannelGroupToSelection(channelGroupId, this.channelGroups.find(cg => cg.id === channelGroupId));
- if (!this.isNodeIn(this.selectedChannelGroups, channelGroup.id)) {
- this.selectedChannelGroups = this.selectedChannelGroups.concat([channelGroup]);
- this.chartviewerDataService.readAxisType(channelGroup)
- .subscribe(mvls => {
- this.addXandYchannels(mvls, channelGroup);
- this.addChannelToSelection(node, channelGroup);
- });
- } else {
- // if channel is in axis type y, set as selected, if not selected already
- this.addChannelToSelection(node, channelGroup);
- }
- }
- break;
- }
- }
- }
-
- /**
- * Handle channel selection via nav-tree
- * @param channel
- * @param channelGroup
- */
- private addChannelToSelection(channel: Node, channelGroup: Node) {
- if (this.isNodeIn(this.yChannels, channel.id)) {
- const index = this.selectedYChannels.findIndex(c => c.id === channel.id);
- if (index === -1) {
- this.selectedYChannels = this.selectedYChannels.concat([channel]);
- if (this.xValues.get(channelGroup.id) == undefined) {
- this.loadXValues(channelGroup);
- } else {
- this.doChart();
- }
- }
- // if channel is of axis type x, set as x channel, if not set already
- } else if (this.isNodeIn(this.xChannels, channel.id)) {
- if (this.selectedXChannel == undefined || this.selectedXChannel.id === channel.id) {
- this.selectedXChannel = channel;
- this.loadXValues(channelGroup);
- }
- }
- }
-
- /**
- * Handle channelGroup selection via nav-tree
- * @param id
- * @param channelGroup
- */
- private addChannelGroupToSelection(id: string, channelGroup: Node) {
- if (this.selectedChannelGroups == undefined) {
- this.selectedChannelGroups = [];
- }
- if (!this.isNodeIn(this.selectedChannelGroups, channelGroup.id)) {
- this.selectedChannelGroups = this.selectedChannelGroups.concat([channelGroup]);
- this.handleSelectChannelGroup(channelGroup);
- }
- }
-
- /**
- * Adds options for x- and y-channels depending on given channelGroup
- *
- * @param measuredValues
- * @param channelGroup
- */
- private addXandYchannels(measuredValues: MeasuredValues[], channelGroup: Node) {
- if (this.xyMode) {
- measuredValues.forEach(mvl => {
- if (mvl.axisType === 'X_AXIS' || ( mvl.axisType == undefined && mvl.independent)) {
- const tmpChannels = this.channels.get(channelGroup.id).filter(c => c.name === mvl.name);
- this.xChannels = this.xChannels.concat(tmpChannels);
- // set independent column as default x-axis.
- if (this.selectedXChannel == undefined && mvl.independent) {
- this.selectedXChannel = tmpChannels[0];
- }
- if (mvl.independent) {
- this.independentChannels.set(channelGroup.id, tmpChannels[0]);
- }
- } else if (mvl.axisType === 'Y_AXIS') {
- this.yChannels = this.yChannels.concat(this.channels.get(channelGroup.id).filter(c => c.name === mvl.name));
- }
- });
- } else {
- this.xChannels = this.xChannels.concat(this.channels.get(channelGroup.id));
- this.yChannels = this.yChannels.concat(this.channels.get(channelGroup.id));
- }
- }
-
/********** private methods / class logic ********************************************************/
- /**
- * Loads measured values for x-axis depending on the channelgroup.
- * (Is used for eager loading on channelgroup slection.)
- *
- * @param channelGroup
- */
- private loadXValues(channelGroup: Node) {
- console.log(this.channels.get(channelGroup.id))
- console.log(this.selectedXChannel.id)
- // if (this.isNodeIn(this.channels.get(channelGroup.id), this.selectedXChannel.id)) {
- // return this.chartviewerDataService.loadMeasuredValues(channelGroup, [this.selectedXChannel])
- if (this.independentChannels.get(channelGroup.id) != undefined) {
- return this.chartviewerDataService.loadMeasuredValues(channelGroup, [this.independentChannels.get(channelGroup.id)])
- .pipe(
- tap(measuredValues => this.xValues.set(channelGroup.id, Object.assign(new MeasuredValues(), measuredValues[0])))
- )
- .subscribe(() => this.doChart());
- }
- }
-
- /**
- * Resets selections and select options to empty state.
- */
- private resetChannelData() {
- this.selectedYChannels = [];
- this.selectedXChannel = undefined;
- this.xChannels = [];
- this.yChannels = [];
- }
-
- /**
- * Reloads the select options for the x- and y-axis dropdowns
- */
- private reloadAxisSelectOptions() {
- this.xChannels = [];
- this.yChannels = [];
- if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)) {
- this.selectedChannelGroups.forEach(cg => this.chartviewerDataService.readAxisType(cg)
- .subscribe(mvls => this.addXandYchannels(mvls, cg)));
- }
+ // empty chart on initialization
+ private initChartData() {
+ const dataset = new ChartDataSet('No data', []);
+ dataset.borderColor = '#fff';
+ this.data = new ChartData([], [dataset]);
}
/**
* Loads measured values for current selection and draws the new chart.
*/
private doChart() {
- if (this.arrayUtil.isNotEmpty(this.selectedChannelGroups)
- && this.arrayUtil.isNotEmpty(this.selectedYChannels)
- && this.selectedXChannel != undefined
- && this.requestOptions != undefined) {
+ if (this.arrayUtil.isNotEmpty(this.selectedChannelRows) && this.requestOptions != undefined) {
+ const xChannels = this.selectedChannelRows.map(row => this.chartviewerDataService.loadMeasuredValues(
+ row.channelGroup, [row.xChannel], this.requestOptions.startIndex, this.requestOptions.requestSize));
+ forkJoin(xChannels)
+ .pipe(
+ map(array => array.map((mea, index) => ({yChannel: this.selectedChannelRows[index].yChannel, measuredValues: mea[0]}))),
+ flatMap(xValues => this.loadYData(xValues))
+ )
+ .subscribe(resp => this.data = resp);
+ } else {
+ this.initChartData();
+ }
+ }
- const tmpYChannels = new Map<string, Node[]>();
- this.selectedChannelGroups.forEach(cg =>
- tmpYChannels.set(cg.id, this.selectedYChannels.filter(c => this.isNodeIn(this.channels.get(cg.id), c.id))));
+ /**
+ * Loads measured values for y-channels, merges them with given values for x
+ * @param xValues
+ */
+ private loadYData(xValues: {yChannel: Node; measuredValues: MeasuredValues}[]) {
+ if (xValues != undefined) {
+ const yChannels = this.groupYChannelsByChannelGroup(this.selectedChannelRows);
+ // const channelGroups = this.selectedChannelGroups.filter(cg => this.arrayUtil.isNotEmpty(yChannels[cg.id]));
+ const channelGroups = Array.from(new Set(this.selectedChannelRows.map(row => row.channelGroup)));
- const tmpChannelGroups = this.selectedChannelGroups.filter(cg => this.arrayUtil.isNotEmpty(tmpYChannels.get(cg.id)));
- const obs = tmpChannelGroups.map(cg =>
- this.chartviewerDataService.loadMeasuredValues(
- cg, tmpYChannels.get(cg.id), this.requestOptions.startIndex, this.requestOptions.requestSize)
- );
+ const obs = channelGroups.map(cg => this.chartviewerDataService.loadMeasuredValues(
+ cg, yChannels[cg.id], this.requestOptions.startIndex, this.requestOptions.requestSize));
// forkJoin return observables in order of input array. Therefore channelgroup id has to be like tmpChannelGroups[index].id
- forkJoin(obs).pipe(
- map(array => array.map((yData, index) =>
- yData.map(y => {
- return this.chartviewerService.toXyDataSet(this.getXValues(tmpChannelGroups[index].id) as number[], y)
+ return forkJoin(obs)
+ .pipe(
+ map(array => array.map((yData, channelGroupIndex) =>
+ yData.map((yValues, yChannelIndex) => {
+ const cgId = channelGroups[channelGroupIndex].id;
+ const xData = this.extractXValues(xValues, yChannels[cgId][yChannelIndex].id);
+ const dataSet = this.chartviewerService.toXyDataSet(xData, yValues);
+ return this.setChartProperties(dataSet);
}))),
- map(array => array.map(sets =>
- sets.map(set => this.chartviewerService.setStandardProperties(set, this.drawPoints, this.lineWidth)))),
map(sets => new ChartData([], sets.reduce((a, b) => a.concat(b), [])))
- ).subscribe(r => this.data = r);
+ );
+ }
+ }
+
+ private extractXValues(xValues: {yChannel: Node; measuredValues: MeasuredValues}[], channelId: string) {
+ const val = xValues.find(v => v.yChannel.id === channelId);
+ if (val != undefined ) {
+ return val.measuredValues.getDataArray().values as number[];
}
}
/******* Helping functions */
- /**
- * Returns sequence of the xValues for the specified ChannelGroup, with length and start index given by current request options.
- * @param channelGroupId
- */
- private getXValues(channelGroupId: string) {
- if (this.xValues.get(channelGroupId) != undefined) {
- return this.xValues
- .get(channelGroupId)
- .getDataArray()
- .values
- .slice(this.requestOptions.startIndex); //, this.requestOptions.startIndex + this.requestOptions.requestSize
+ private groupYChannelsByChannelGroup(array: ChannelSelectionRow[]) {
+ return array.reduce(
+ (obj, next) => {
+ const value = next.channelGroup.id;
+ obj[value] = obj[value] || [];
+ obj[value] = obj[value].concat(next.yChannel);
+ return obj;
+ }, {});
+ }
+
+ private setChartProperties(dataset: ChartXyDataSet) {
+ if (!this.toolbarProperties.drawPoints) {
+ dataset.pointRadius = 0;
}
- }
+ dataset.showLine = this.toolbarProperties.showLines;
+ dataset.fill = this.toolbarProperties.fillArea;
+ dataset.lineTension = this.toolbarProperties.lineTension;
+ dataset.borderWidth = this.toolbarProperties.lineWidth;
+ const color = '#' + Math.random().toString(16).substr(-6);
+ dataset.borderColor = color;
+ dataset.backgroundColor = color;
- /**
- * Returns true if node with given id is in the given array.
- *
- * @param array the array
- * @param id the id
- */
- private isNodeIn(array: Node[], id: string) {
- return array.findIndex(n => n.id === id) > -1;
- }
-
- /**
- * Looks up parent channelGroup for channel via the channel map.
- *
- * @param channel
- */
- private findChannelGroup(channel: Node) {
- const channelGroupId = Array.from(this.channels.keys())
- .find(key => this.isNodeIn(this.channels.get(key), channel.id));
- return this.channelGroups.find(cg => cg.id === channelGroupId);
+ return dataset;
}
}
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/chartviewer.model.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/chartviewer.model.ts
index 7ae281d..82089da 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/chartviewer.model.ts
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/chartviewer.model.ts
@@ -23,6 +23,9 @@
export { ChartXyDataSet } from './types/chart-xy-data-set.class';
export { ChartPoint } from './types/chart-point.class';
export { RequestOptions } from './types/request-options.class';
+export { ChannelSelectionRow } from './types/channel-selection-row';
+export { ChartToolbarProperties } from './types/chart-toolbar-properties.class';
+
export { PrimeChartDataSet } from './primeNgHelper/prime-chart-data-set.interface';
export { PrimeChartData } from './primeNgHelper/prime-chart-data.interface';
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/channel-selection-row.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/channel-selection-row.ts
new file mode 100644
index 0000000..23f0072
--- /dev/null
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/channel-selection-row.ts
@@ -0,0 +1,26 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+import {Node} from '../../../navigator/node';
+
+export class ChannelSelectionRow {
+ channelGroup: Node;
+ xChannel: Node;
+ yChannel: Node;
+
+ constructor(channelGroup: Node, yChannel: Node, xChannel?: Node) {
+ this.channelGroup = channelGroup;
+ this.yChannel = yChannel;
+ this.xChannel = xChannel;
+ }
+}
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/chart-toolbar-properties.class.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/chart-toolbar-properties.class.ts
new file mode 100644
index 0000000..454d718
--- /dev/null
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/chart-toolbar-properties.class.ts
@@ -0,0 +1,31 @@
+/********************************************************************************
+ * Copyright (c) 2015-2018 Contributors to the Eclipse Foundation
+ *
+ * See the NOTICE file(s) distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v. 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ ********************************************************************************/
+
+export class ChartToolbarProperties {
+
+ // if true, shows pannel with channel(-group) selection
+ public showSelection: boolean;
+ // if true, draws datapoints
+ public drawPoints: boolean;
+ // the charts borderwidth (width of lines, border for points)
+ public lineWidth: number;
+ // if true, draws lines connecting datapoints
+ public showLines: boolean;
+ // if true, fills are below graph
+ public fillArea: boolean;
+ // the interpolation degree. 0 = linear, 0.4 = Bezier
+ public lineTension: number;
+
+ public options: {legend: {display: boolean}};
+}
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/chart-xy-data-set.class.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/chart-xy-data-set.class.ts
index 4a94e47..90e98fb 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/chart-xy-data-set.class.ts
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/model/types/chart-xy-data-set.class.ts
@@ -38,7 +38,7 @@
borderWidth: number;
fill: boolean;
borderColor: string;
- tension: number;
+ lineTension: number;
showLine: boolean;
// general
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/services/chart-viewer.service.ts b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/services/chart-viewer.service.ts
index 0b55858..f99e8ba 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/services/chart-viewer.service.ts
+++ b/org.eclipse.mdm.application/src/main/webapp/src/app/chartviewer/services/chart-viewer.service.ts
@@ -12,7 +12,7 @@
private nodeMetaSubject = new Subject<Node>();
- constructor() { }
+ constructor() {}
public sendNodeMeta(nodeMeta: Node) {
this.nodeMetaSubject.next(nodeMeta);
@@ -29,22 +29,6 @@
return dataset;
}
- public setStandardProperties(dataset: ChartXyDataSet, drawPoints?: boolean, lineWidth?: number) {
- if (!drawPoints) {
- dataset.pointRadius = 0;
- }
- // lines
- dataset.showLine = true;
- dataset.fill = false;
- dataset.tension = 0; // linear interpolation
- dataset.borderWidth = lineWidth;
- const color = '#' + Math.random().toString(16).substr(-6);
- dataset.borderColor = color;
- dataset.backgroundColor = color;
-
- return dataset;
- }
-
private getDataPoints(xData: number[], yData: number[], startIndex = 0) {
if (xData != undefined && xData.length <= yData.length) {
return xData.map((x, i) => new ChartPoint(x, yData[i]));
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/de.json b/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/de.json
index 906aeec..e39f921 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/de.json
+++ b/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/de.json
@@ -317,5 +317,31 @@
"tooltip-save-view": "Ansicht speichern",
"tooltip-select-view": "Ansicht auswählen"
}
+ },
+ "chartviewer": {
+ "request-options": {},
+ "xy-chart-data-selection-panel": {
+ "select-channel-placeholder": "Kanal wählen"
+ },
+ "xy-chart-viewer": {},
+ "xy-chart-viewer-nav-card": {
+ "no-node-selected": "Kein Knoten ausgewählt"
+ },
+ "xy-chart-viewer-toolbar": {
+ "hide-data-selection-panel": "Datenauswahlpanel verbergen",
+ "show-data-selection-panel": "Datenauswahlpanel anzeigen",
+ "activate-xy-mode": "Kanal Auswahloptionen nach Achsentyp filtern",
+ "deactivate-xy-mode": "Alle Kanäle als Auswahloptionen anzeigen",
+ "hide-chart-legend": "Legende des Diagramms verbergen",
+ "show-chart-legend": "Legende des Diagramms anzeigen",
+ "line-width": "Linienstärke",
+ "show-lines": "Verbindungslinien anzeigen",
+ "hide-lines": "Verbindungslinien verbergen",
+ "fill-area": "Fläche unter dem Graph füllen",
+ "clear-area": "Fläche unter dem Graph leeren",
+ "show-datapoints": "Datenpunkte markieren",
+ "hide-datapoints": "Datenpunkte verbergen",
+ "tension": "Tension: 0 = Linear, 0.4 = Bezierkurve"
+ }
}
}
\ No newline at end of file
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/en.json b/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/en.json
index 2ef7534..fe1267e 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/en.json
+++ b/org.eclipse.mdm.application/src/main/webapp/src/assets/i18n/en.json
@@ -317,5 +317,31 @@
"tooltip-save-view": "Save view",
"tooltip-select-view": "Select view"
}
+ },
+ "chartviewer": {
+ "request-options": {},
+ "xy-chart-data-selection-panel": {
+ "select-channel-placeholder": "Select Channel"
+ },
+ "xy-chart-viewer": {},
+ "xy-chart-viewer-nav-card": {
+ "no-node-selected": "No node selected"
+ },
+ "xy-chart-viewer-toolbar": {
+ "hide-data-selection-panel": "Hide data selection panel",
+ "show-data-selection-panel": "Show data selection panel",
+ "activate-xy-mode": "Filter channel options by axis-type",
+ "deactivate-xy-mode": "Provide all channel options",
+ "hide-chart-legend": "Hide chart legend",
+ "show-chart-legend": "Show chart legend",
+ "line-width": "Line width",
+ "show-lines": "Draw lines",
+ "hide-lines": "Hide lines",
+ "fill-area": "Fill area underneath the graph",
+ "clear-area": "Clear area underneath the graph",
+ "show-datapoints": "Mark datapoints",
+ "hide-datapoints": "Hide datapoints",
+ "tension": "Line tension: 0 = linear, 0.4 = Bezier curve"
+ }
}
}
\ No newline at end of file
diff --git a/org.eclipse.mdm.application/src/main/webapp/src/styles.css b/org.eclipse.mdm.application/src/main/webapp/src/styles.css
index 4334b66..9905f4d 100644
--- a/org.eclipse.mdm.application/src/main/webapp/src/styles.css
+++ b/org.eclipse.mdm.application/src/main/webapp/src/styles.css
@@ -25,7 +25,7 @@
.navbar {
font-size: 1em;
- margin-bottom: 1em;
+ margin-bottom: 0.5em;
padding: 0rem 1rem;
}