Skip to content

Commit

Permalink
Merge pull request #83 from GridProtectionAlliance/features/fix-issue…
Browse files Browse the repository at this point in the history
…s-2.1.0-rc

Features/fix issues 2.1.0 rc
  • Loading branch information
clackner-gpa authored Jul 15, 2022
2 parents adf0ffa + 5515b41 commit e21f543
Show file tree
Hide file tree
Showing 12 changed files with 3,007 additions and 3,442 deletions.
16 changes: 8 additions & 8 deletions dist/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

This data source provides access to OSIsoft PI and PI-AF data through PI Web API.

![display](https://raw.githubusercontent.com/GridProtectionAlliance/osisoftpi-grafana/master/docs/img/system_overview.png)
![display](dist/docs/img/system_overview.png)

# Usage

Expand All @@ -24,7 +24,7 @@ for more information on configuring PI Web API.

## Querying via the PI Asset Framework

![elements_and_attributes.png](https://raw.githubusercontent.com/GridProtectionAlliance/osisoftpi-grafana/master/docs/img/elements_and_attributes.png)
![elements_and_attributes.png](dist/docs/img/elements_and_attributes.png)

1. Verify that the `PI Point Search` toggle is greyed off
2. In `Element` click `Select AF Database` and choose desired database in list
Expand All @@ -40,7 +40,7 @@ for more information on configuring PI Web API.

## Querying via the PI Dataserver (PI Points)

![pi_point_query.png](https://raw.githubusercontent.com/GridProtectionAlliance/osisoftpi-grafana/master/docs/img/pi_point_query.png)
![pi_point_query.png](dist/docs/img/pi_point_query.png)

1. Toggle the `Pi Point Search` on
2. Under `Data Server` click `Select Dataserver` and select desired PI Dataserver
Expand All @@ -57,21 +57,21 @@ Currently, the query interface requires a json query.
An example config is shown below.
`{"path": "PISERVER\\DatabaseName\\ElementNameWithChildren"}`

![template_setup_1.png](https://raw.githubusercontent.com/GridProtectionAlliance/osisoftpi-grafana/master/docs/img/template_setup_1.png)
![template_setup_1.png](dist/docs/img/template_setup_1.png)


# Event Frames and Annotations

This datasource can use AF Event Frames as annotations.

![event-frame](https://raw.githubusercontent.com/GridProtectionAlliance/osisoftpi-grafana/master/docs/img/event_frame.png)
![event-frame](dist/docs/img/event_frame.png)

Creating an annotation query and use the Event Frame category as the query string.
Color and regex replacement strings for the name are supported.

For example:
![event-frame-setup-1](https://raw.githubusercontent.com/GridProtectionAlliance/osisoftpi-grafana/master/docs/img/event_frame_setup_1.png)
![event-frame-setup-2](https://raw.githubusercontent.com/GridProtectionAlliance/osisoftpi-grafana/master/docs/img/event_frame_setup_2.png)
![event-frame-setup-1](dist/docs/img/event_frame_setup_1.png)
![event-frame-setup-2](dist/docs/img/event_frame_setup_2.png)


# Installation
Expand All @@ -90,4 +90,4 @@ All product names, logos, and brands are property of their respective owners.
All company, product and service names used in this website are for identification purposes only.
Use of these names, logos, and brands does not imply endorsement.

OSIsoft, the OSIsoft logo and logotype, and PI Web API are all trademarks of OSIsoft, LLC.
OSIsoft, the OSIsoft logo and logotype, and PI Web API are all trademarks of OSIsoft, LLC.
3 changes: 2 additions & 1 deletion dist/module.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/module.js.map

Large diffs are not rendered by default.

28 changes: 24 additions & 4 deletions dist/partials/annotations.editor.html
Original file line number Diff line number Diff line change
@@ -1,16 +1,36 @@
<h5 class="section-heading">Search Options 123</h5>
<h5 class="section-heading">Search Options</h5>
<div class="gf-form-inline">
<div class="gf-form">
<div class="gf-form max-width-30">
<label class="gf-form-label query-keyword width-8">AF Database</label>
<select ng-options='opt as opt.Name for opt in ctrl.annotation.databases track by opt.WebId' ng-model='ctrl.annotation.database' ng-change='ctrl.databaseChanged()'></select>
<select
ng-options='opt as opt.Name for opt in ctrl.annotation.databases track by opt.WebId'
ng-model='ctrl.annotation.database'
ng-change='ctrl.databaseChanged()'
ng-disabled='ctrl.annotation.databases.length == 0'>
<option value="" disabled selected ng-if="ctrl.annotation.databases.length == 0">
Loading...
</option>
</select>
</div>
<div class="gf-form max-width-30">
<label class="gf-form-label query-keyword width-8">Template</label>
<select ng-options='opt as opt.Name for opt in ctrl.annotation.templates track by opt.WebId' ng-model='ctrl.annotation.template' ng-change='ctrl.templateChanged()'></select>
<select
ng-options='opt as opt.Name for opt in ctrl.annotation.templates track by opt.WebId'
ng-model='ctrl.annotation.template'
ng-change='ctrl.templateChanged()'
ng-disabled='ctrl.annotation.templates.length == 0'>
<option value="" disabled selected ng-if="ctrl.annotation.databases.length > 0 && ctrl.annotation.templates.length == 0">
Loading...
</option>
</select>
</div>
<div class="gf-form">
<gf-form-switch class="gf-form" label="Show Start and End Time" label-class="query-keyword" checked="ctrl.annotation.showEndTime"
<gf-form-switch
class="gf-form"
label="Show Start and End Time"
label-class="query-keyword"
checked="ctrl.annotation.showEndTime"
on-change="ctrl.targetBlur()">
</gf-form-switch>
</div>
Expand Down
8 changes: 4 additions & 4 deletions dist/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"id": "gridprotectionalliance-osisoftpi-datasource",
"metrics": true,
"annotations": true,
"alerting": true,
"alerting": false,
"info": {
"description": "Datasource plugin for OSIsoft PI Web API",
"author": {
Expand All @@ -24,16 +24,16 @@
},
{
"name": "License",
"url": "https://github.com/grafana/grafana-starter-datasource/blob/master/LICENSE"
"url": "https://github.com/GridProtectionAlliance/osisoftpi-grafana/blob/LICENSE"
},
{
"name": "PI System",
"url": "https://www.osisoft.com/pi-system"
}
],
"screenshots": [],
"version": "2.0.0",
"updated": "2022-05-04"
"version": "2.1.0",
"updated": "2022-07-07"
},
"dependencies": {
"grafanaDependency": ">=8.4.0",
Expand Down
10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "grid-protection-alliance-osisoftpi-grafana",
"version": "2.0.0",
"version": "2.1.0",
"description": "OSISoft PI Grafana Plugin",
"scripts": {
"build": "grafana-toolkit plugin:build",
Expand All @@ -13,10 +13,10 @@
"author": "GridProtectionAlliance",
"license": "Apache-2.0",
"devDependencies": {
"@grafana/data": "latest",
"@grafana/runtime": "latest",
"@grafana/toolkit": "latest",
"@grafana/ui": "latest",
"@grafana/data": "^8.5.0",
"@grafana/runtime": "^8.5.0",
"@grafana/toolkit": "^8.5.0",
"@grafana/ui": "^8.5.0",
"@testing-library/jest-dom": "5.4.0",
"@testing-library/react": "^10.0.2",
"@types/lodash": "latest"
Expand Down
25 changes: 18 additions & 7 deletions src/AnnotationsQueryCtrl.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,47 @@
export class AnnotationsQueryCtrl {
static templateUrl = 'partials/annotations.editor.html';

$scope: any;
annotation: any;
datasource: any;

/** @ngInject */
constructor() {
constructor($scope: any) {
this.$scope = $scope;
this.annotation = $scope.ctrl.annotation;
this.datasource = $scope.ctrl.datasource;

// load defaults
this.annotation.query = this.annotation.query || {};
this.annotation.databases = this.annotation.databases || [];
this.annotation.templates = this.annotation.templates || [];
this.annotation.regex = this.annotation.regex || {};
this.annotation.attribute = this.annotation.attribute || {};
this.annotation.showEndTime = this.annotation.showEndTime || false;
this.getDatabases();

this.datasource.getAssetServer(this.datasource.afserver.name).then((result: any) => {
return this.getDatabases(result.WebId);
});
}
templateChanged() {
// do nothing
}
databaseChanged() {
this.annotation.templates = [];
this.getEventFrames();
}
getDatabases() {
getDatabases(webid: string) {
var ctrl = this;
// @ts-ignore
return ctrl.datasource.getDatabases(ctrl.datasource.afserver.webid!).then((dbs: any) => {
ctrl.datasource.getDatabases(webid).then((dbs: any) => {
ctrl.annotation.databases = dbs;
this.$scope.$apply();
});
}
getEventFrames() {
var ctrl = this;
// @ts-ignore
return ctrl.datasource.getEventFrameTemplates(this.annotation.database.WebId).then((templates: any) => {
ctrl.datasource.getEventFrameTemplates(this.annotation.database.WebId).then((templates: any) => {
ctrl.annotation.templates = templates;
this.$scope.$apply();
});
}
}
2 changes: 1 addition & 1 deletion src/ConfigEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export class PIWebAPIConfigEditor extends PureComponent<Props, State> {
return (
<div>
<DataSourceHttpSettings
defaultUrl="https://server.name/webapi"
defaultUrl="https://server.name/piwebapi"
dataSourceConfig={options}
onChange={this.onMyOptionsChange}
showAccessOptions
Expand Down
57 changes: 35 additions & 22 deletions src/QueryEditor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,15 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
};

// get a ui segment for the attributes
getElementSegments = (index: number): Promise<Array<SelectableValue<PIWebAPISelectableValue>>> => {
const { datasource, query } = this.props;
getElementSegments = (
index: number,
currentSegment?: Array<SelectableValue<PIWebAPISelectableValue>>
): Promise<Array<SelectableValue<PIWebAPISelectableValue>>> => {
const { datasource, query, data } = this.props;
var ctrl = this;
var findQuery = query.isPiPoint
? { type: 'dataserver' }
: { path: this.getSegmentPathUpTo(this.state.segments.slice(0), index) };
: { path: this.getSegmentPathUpTo(currentSegment ?? this.state.segments.slice(0), index) };

if (!query.isPiPoint) {
if (datasource.afserver?.name && index === 0) {
Expand Down Expand Up @@ -362,7 +365,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
// }
}
return datasource
.metricFindQuery(findQuery, { isPiPoint: query.isPiPoint })
.metricFindQuery(findQuery, Object.assign(data?.request?.scopedVars ?? {}, { isPiPoint: query.isPiPoint }))
.then((items: any[]) => {
var altSegments = map(items, (item: any) => {
let selectableValue: SelectableValue<PIWebAPISelectableValue> = {
Expand Down Expand Up @@ -411,7 +414,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {

// get the list of attributes for the user interface - PI
getAttributeSegmentsPI = (attributeText?: string): Promise<Array<SelectableValue<PIWebAPISelectableValue>>> => {
const { datasource, query } = this.props;
const { datasource, query, data } = this.props;
const ctrl = this;
const findQuery = {
path: '',
Expand All @@ -421,7 +424,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
};
let segments: Array<SelectableValue<PIWebAPISelectableValue>> = [];
return datasource
.metricFindQuery(findQuery, { isPiPoint: query.isPiPoint })
.metricFindQuery(findQuery, Object.assign(data?.request?.scopedVars ?? {}, { isPiPoint: query.isPiPoint }))
.then((items: any[]) => {
segments = map(items, (item: any) => {
let selectableValue: SelectableValue<PIWebAPISelectableValue> = {
Expand Down Expand Up @@ -494,7 +497,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
// remove element hierarchy from attribute collection
splitAttributes.splice(0, 1);

each(splitElements, function (item, index) {
each(splitElements, (item, _) => {
segmentsArray.push({
label: item,
value: {
Expand All @@ -503,7 +506,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
},
});
});
each(splitAttributes, function (item, index) {
each(splitAttributes, (item, _) => {
if (item !== '') {
// set current value
attributesArray.push({
Expand All @@ -515,7 +518,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
});
}
});
return this.getElementSegments(segmentsArray.length + 1).then((elements) => {
return this.getElementSegments(splitElements.length + 1, segmentsArray).then((elements) => {
if (elements.length > 0) {
segmentsArray.push({
label: 'Select Element',
Expand Down Expand Up @@ -567,14 +570,14 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
attributes: Array<SelectableValue<PIWebAPISelectableValue>>,
segments: Array<SelectableValue<PIWebAPISelectableValue>>
): Promise<any> {
const { datasource } = this.props;
const { datasource, data } = this.props;
var ctrl = this;
var findQuery = {
path: this.getSegmentPathUpTo(segments.slice(0), segments.length),
type: 'attributes',
};
return datasource
.metricFindQuery(findQuery, { isPiPoint: false })
.metricFindQuery(findQuery, Object.assign(data?.request?.scopedVars ?? {}, { isPiPoint: false }))
.then((attributesResponse: any) => {
var validAttributes: any = {};

Expand Down Expand Up @@ -607,7 +610,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
attribute: SelectableValue<PIWebAPISelectableValue>,
attributes: Array<SelectableValue<PIWebAPISelectableValue>>
) {
const { datasource } = this.props;
const { datasource, data } = this.props;
var ctrl = this;
var findQuery = {
path: attribute.path,
Expand All @@ -616,7 +619,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
type: 'pipoint',
};
return datasource
.metricFindQuery(findQuery, { isPiPoint: true })
.metricFindQuery(findQuery, Object.assign(data?.request?.scopedVars ?? {}, { isPiPoint: true }))
.then(() => {
ctrl.attributeChangeValue(attributes);
})
Expand Down Expand Up @@ -663,7 +666,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
// remove element hierarchy from attribute collection
splitAttributes.splice(0, 1);

each(splitElements, function (item, index) {
each(splitElements, (item, _) => {
segments.push({
label: item,
value: {
Expand All @@ -673,7 +676,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
},
});
});
this.getElementSegments(segments.length + 1).then((elements) => {
this.getElementSegments(splitElements.length + 1, segments).then((elements) => {
if (elements.length > 0) {
segments.push({
label: 'Select Element',
Expand Down Expand Up @@ -764,9 +767,9 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
* @memberOf PIWebAPIQueryEditor
*/
updateArray = (
segmentsArray: any[],
attributesArray: any[],
summariesArray: any[],
segmentsArray: Array<SelectableValue<PIWebAPISelectableValue>>,
attributesArray: Array<SelectableValue<PIWebAPISelectableValue>>,
summariesArray: Array<SelectableValue<PIWebAPISelectableValue>>,
isPiPoint: boolean,
cb?: (() => void) | undefined
) => {
Expand All @@ -786,14 +789,24 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
);
};

// React action when component is mounted
// React action when component is initialized/updated
scopedVarsDone = false;
componentDidMount = () => {
this.initialLoad(false);
};
componentDidUpdate = () => {
if (this.props.data?.state === 'Done' && !!this.props.data?.request?.scopedVars && !this.scopedVarsDone) {
this.scopedVarsDone = true;
this.initialLoad(true);
}
};
initialLoad = (force: boolean) => {
const { query } = this.props;
const metricsQuery = defaults(query, defaultQuery) as PIWebAPIQuery;
const { segments, attributes, summary, isPiPoint } = metricsQuery;

let segmentsArray: Array<SelectableValue<PIWebAPISelectableValue>> = segments?.slice(0) ?? [];
let attributesArray: Array<SelectableValue<PIWebAPISelectableValue>> = attributes?.slice(0) ?? [];
let segmentsArray: Array<SelectableValue<PIWebAPISelectableValue>> = force ? [] : segments?.slice(0) ?? [];
let attributesArray: Array<SelectableValue<PIWebAPISelectableValue>> = force ? [] : attributes?.slice(0) ?? [];
let summariesArray = summary?.types ?? [];

if (!isPiPoint && segmentsArray.length === 0) {
Expand Down Expand Up @@ -1061,7 +1074,7 @@ export class PIWebAPIQueryEditor extends PureComponent<Props, State> {
})
}
type="number"
placeholder="150000"
placeholder="1000"
/>
</InlineField>
<InlineField label="Recorded Values" labelWidth={LABEL_WIDTH}>
Expand Down
Loading

0 comments on commit e21f543

Please sign in to comment.