Skip to content
This repository has been archived by the owner on Oct 2, 2024. It is now read-only.

Commit

Permalink
Adding initial table ui and configuration screen and connecting it to…
Browse files Browse the repository at this point in the history
… queryWrapperService
  • Loading branch information
rpeach-sag committed Jun 25, 2020
1 parent c068b53 commit 45574f5
Show file tree
Hide file tree
Showing 8 changed files with 174 additions and 30 deletions.
6 changes: 3 additions & 3 deletions cumulocity.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "Runtime Loaded Widget",
"contextPath": "cumulocity-runtime-widget",
"key": "cumulocity-runtime-widget-application-key",
"name": "Datahub Widget",
"contextPath": "cumulocity-datahub-widget",
"key": "cumulocity-datahub-widget-application-key",
"contentSecurityPolicy": "default-src 'self'",
"icon": {
"class": "fa fa-puzzle-piece"
Expand Down
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"name": "cumulocity-runtime-widget",
"name": "cumulocity-datahub-widget",
"interleave": {
"dist\\bundle-src\\custom-widget.js": "cumulocity-runtime-widget-CustomWidget",
"dist/bundle-src/custom-widget.js": "cumulocity-runtime-widget-CustomWidget"
"dist\\bundle-src\\custom-widget.js": "cumulocity-datahub-widget-CustomWidget",
"dist/bundle-src/custom-widget.js": "cumulocity-datahub-widget-CustomWidget"
},
"version": "0.0.0-development",
"description": "Template widget for runtime loading in Cumulocity using the cumulocity-runtime-widget-loader (written by Software AG Global Presales)",
"description": "An example widget that pulls data from Cumulocity IoT DataHub (written by Software AG Global Presales)",
"scripts": {
"build": "gulp"
},
Expand Down
7 changes: 3 additions & 4 deletions src/datahub-widget/datahub-query-wrapper-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@ export interface JobResult<T> {
rows: T[]
}


@Injectable()
@Injectable({providedIn: 'root'})
export class QueryWrapperService {

constructor(private queryService: QueryService) { }

async queryForResults<T = any>(queryString: string, config?: QueryConfig): Promise<JobResult<T>> {
async queryForResults<T = any>(queryString: string, config: QueryConfig = {}): Promise<JobResult<T>> {
//post job
const jobId = await this.postQuery(queryString);

Expand Down Expand Up @@ -76,4 +75,4 @@ export class QueryWrapperService {
sleep(milliseconds) {
return new Promise(resolve => setTimeout(resolve, milliseconds));
}
}
}
100 changes: 91 additions & 9 deletions src/datahub-widget/datahub-widget-config.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,98 @@
* limitations under the License.
*/

import {Component, Input} from '@angular/core';
import {Component, Input, OnDestroy} from '@angular/core';
import {switchMap} from "rxjs/operators";
import {from, Subject, Subscription} from "rxjs";
import {QueryWrapperService} from "./datahub-query-wrapper-service";

export interface IDatahubWidgetConfig {
queryString: string,
columns: {
colName: string,
displayName: string,
visibility: 'visible' | 'hidden'
}[]
}

@Component({
template: `<div class="form-group">
<c8y-form-group>
<label translate>Text</label>
<textarea style="width:100%" [(ngModel)]="config.text"></textarea>
</c8y-form-group>
</div>`
template: `
<div class="form-group">
<c8y-form-group>
<label translate>Text</label>
<textarea class="form-control" [(ngModel)]="config.queryString"
(change)="updateColumnDefinitions()"></textarea>
</c8y-form-group>
<table class="table">
<thead>
<button (click)="updateColumnDefinitions()">Refresh</button>
<tr>
<th>Visible</th>
<th>Datahub Column</th>
<th>Label</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let col of config.columns">
<td><input class="form-control" type="checkbox" [checked]="col.visibility == 'visible'" (change)="col.visibility = $any($event.target).checked ? 'visible' : 'hidden'"/></td>
<td>{{col.colName}}</td>
<td><input class="form-control" [(ngModel)]="col.displayName"/></td>
</tr>
</tbody>
</table>
</div>`
})
export class DatahubWidgetConfig {
@Input() config: any = {};
export class DatahubWidgetConfig implements OnDestroy {
_config: IDatahubWidgetConfig = {
queryString: '',
columns: []
};

@Input() set config(config: IDatahubWidgetConfig) {
this._config = Object.assign(config, {
...this._config,
...config
});
};
get config(): IDatahubWidgetConfig {
return this._config
}

querySubject = new Subject<string>()
subscriptions = new Subscription();

constructor(private queryService: QueryWrapperService) {
this.subscriptions.add(
this.querySubject
.pipe(switchMap(query => from(this.queryService.queryForResults(query))))
.subscribe(result => {
this.config.columns = result.schema
.map(column => column.name)
.map(colName => {
let matchingColumn = this.config.columns.find(col => col.colName == colName);
if (matchingColumn) {
return matchingColumn;
} else {
return {
colName,
displayName: this.formatHeading(colName),
visibility: 'visible'
};
}
});
})
);
}

updateColumnDefinitions() {
this.querySubject.next(this.config.queryString);
}

formatHeading(value: string): string {
return value.replace(/_/g, " ").replace(/([^A-Z\s])(?=[A-Z])/g, "$1 ").replace(/\s+/g, " ")
}

ngOnDestroy() {
this.subscriptions.unsubscribe();
}
}
11 changes: 10 additions & 1 deletion src/datahub-widget/datahub-widget.component.html
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
<p class="text">{{config?.text || 'No text'}}</p>
<table class="table">
<thead>
<tr><th *ngFor="let col of visibleColumns">{{col.displayName}}</th></tr>
</thead>
<tbody>
<tr *ngFor="let row of rows">
<td *ngFor="let col of visibleColumns">{{row[col.colName]}}</td>
</tr>
</tbody>
</table>
56 changes: 53 additions & 3 deletions src/datahub-widget/datahub-widget.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,62 @@
* limitations under the License.
*/

import { Component, Input } from '@angular/core';
import {Component, Input, OnDestroy} from '@angular/core';
import {BehaviorSubject, from, Subscription} from "rxjs";
import {distinctUntilChanged, switchMap} from "rxjs/operators";
import {IDatahubWidgetConfig} from "./datahub-widget-config.component";
import {QueryWrapperService} from "./datahub-query-wrapper-service";

@Component({
templateUrl: './datahub-widget.component.html',
styles: [ `.text { transform: scaleX(-1); font-size: 3em ;}` ]
})
export class DatahubWidgetComponent {
@Input() config;
export class DatahubWidgetComponent implements OnDestroy {
_config: IDatahubWidgetConfig = {
queryString: '',
columns: []
};

@Input() set config(config: IDatahubWidgetConfig) {
this._config = Object.assign(config, {
...this._config,
...config
});
this.querySubject.next(this.config.queryString);
this.visibleColumns = this.config.columns.filter(col => col.visibility == 'visible') as {
colName: string,
displayName: string,
visibility: 'visible'
}[];
};
get config(): IDatahubWidgetConfig {
return this._config
}

subscriptions = new Subscription();
querySubject = new BehaviorSubject<undefined | string>(undefined);

visibleColumns: {
colName: string,
displayName: string,
visibility: 'visible'
}[];
rows: string[];

constructor(private queryService: QueryWrapperService) {
this.subscriptions.add(
this.querySubject
.pipe(
distinctUntilChanged(),
switchMap(query => from(this.queryService.queryForResults(query)))
)
.subscribe(results => {
this.rows = results.rows
})
);
}

ngOnDestroy() {
this.subscriptions.unsubscribe();
}
}
4 changes: 2 additions & 2 deletions src/datahub-widget/datahub-widget.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ import {DatahubWidgetComponent} from "./datahub-widget.component";
{
provide: HOOK_COMPONENTS,
multi: true,
useValue: [{
useValue: {
id: 'acme.test.widget',
label: 'Test widget',
description: 'Displays some mirrored text',
component: DatahubWidgetComponent,
configComponent: DatahubWidgetConfig,
}]
}
}
],
})
Expand Down
12 changes: 8 additions & 4 deletions src/datahub-widget/query.service.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { Injectable } from '@angular/core';
import {Injectable, Injector} from '@angular/core';
import { FetchClient } from '@c8y/ngx-components/api';
import { IFetchOptions } from '@c8y/client';

@Injectable()
@Injectable({providedIn: 'root'})
export class QueryService {
private readonly dataHubDremioApi = '/service/datahub/dremio/api/v3';
private readonly fetchClient: FetchClient;

private fetchOptions: IFetchOptions = {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
};

constructor(private fetchClient: FetchClient) { }
constructor(injector: Injector) {
// Cumulocity won't let you inject this if your @Injectable is provided in root... so this is a workaround..
this.fetchClient = injector.get(FetchClient);
}

async getJobState(jobId) {
const response = await this.fetchClient.fetch(this.dataHubDremioApi + '/job/' + jobId, this.fetchOptions);
Expand Down Expand Up @@ -39,4 +43,4 @@ export class QueryService {
throw new Error(await response.text());
}
}
}
}

0 comments on commit 45574f5

Please sign in to comment.