mirror of
https://github.com/nasa/openmct.git
synced 2024-12-22 14:32:22 +00:00
Merge remote-tracking branch 'origin/open670'
This commit is contained in:
commit
7e60593501
1
main.js
1
main.js
@ -77,6 +77,7 @@ define([
|
|||||||
'./platform/features/plot/bundle',
|
'./platform/features/plot/bundle',
|
||||||
'./platform/features/scrolling/bundle',
|
'./platform/features/scrolling/bundle',
|
||||||
'./platform/features/timeline/bundle',
|
'./platform/features/timeline/bundle',
|
||||||
|
'./platform/features/table/bundle',
|
||||||
'./platform/forms/bundle',
|
'./platform/forms/bundle',
|
||||||
'./platform/identity/bundle',
|
'./platform/identity/bundle',
|
||||||
'./platform/persistence/aggregator/bundle',
|
'./platform/persistence/aggregator/bundle',
|
||||||
|
125
platform/features/table/bundle.js
Normal file
125
platform/features/table/bundle.js
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define([
|
||||||
|
"./src/directives/MCTTable",
|
||||||
|
"./src/controllers/TelemetryTableController",
|
||||||
|
"./src/controllers/TableOptionsController",
|
||||||
|
'../../commonUI/regions/src/Region',
|
||||||
|
'../../commonUI/browse/src/InspectorRegion',
|
||||||
|
"legacyRegistry"
|
||||||
|
], function (
|
||||||
|
MCTTable,
|
||||||
|
TelemetryTableController,
|
||||||
|
TableOptionsController,
|
||||||
|
Region,
|
||||||
|
InspectorRegion,
|
||||||
|
legacyRegistry
|
||||||
|
) {
|
||||||
|
"use strict";
|
||||||
|
/**
|
||||||
|
* Two region parts are defined here. One that appears only in browse
|
||||||
|
* mode, and one that appears only in edit mode. For not they both point
|
||||||
|
* to the same representation, but a different key could be used here to
|
||||||
|
* include a customized representation for edit mode.
|
||||||
|
*/
|
||||||
|
var tableInspector = new InspectorRegion(),
|
||||||
|
tableOptionsEditRegion = new Region({
|
||||||
|
name: "table-options",
|
||||||
|
title: "Table Options",
|
||||||
|
modes: ['edit'],
|
||||||
|
content: {
|
||||||
|
key: "table-options-edit"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tableInspector.addRegion(tableOptionsEditRegion);
|
||||||
|
|
||||||
|
legacyRegistry.register("platform/features/table", {
|
||||||
|
"extensions": {
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"key": "table",
|
||||||
|
"name": "Table",
|
||||||
|
"glyph": "\ue605",
|
||||||
|
"description": "A table for displaying telemetry data",
|
||||||
|
"features": "creation",
|
||||||
|
"delegates": [
|
||||||
|
"telemetry"
|
||||||
|
],
|
||||||
|
"inspector": tableInspector,
|
||||||
|
"contains": [
|
||||||
|
{
|
||||||
|
"has": "telemetry"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"model": {
|
||||||
|
"composition": []
|
||||||
|
},
|
||||||
|
"views": [
|
||||||
|
"table"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"controllers": [
|
||||||
|
{
|
||||||
|
"key": "TelemetryTableController",
|
||||||
|
"implementation": TelemetryTableController,
|
||||||
|
"depends": ["$scope", "telemetryHandler", "telemetryFormatter"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "TableOptionsController",
|
||||||
|
"implementation": TableOptionsController,
|
||||||
|
"depends": ["$scope"]
|
||||||
|
}
|
||||||
|
|
||||||
|
],
|
||||||
|
"views": [
|
||||||
|
{
|
||||||
|
"name": "Table",
|
||||||
|
"key": "table",
|
||||||
|
"glyph": "\ue605",
|
||||||
|
"templateUrl": "templates/table.html",
|
||||||
|
"needs": [
|
||||||
|
"telemetry"
|
||||||
|
],
|
||||||
|
"delegation": true,
|
||||||
|
"editable": true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
{
|
||||||
|
"key": "mctTable",
|
||||||
|
"implementation": MCTTable,
|
||||||
|
"depends": ["$timeout"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"representations": [
|
||||||
|
{
|
||||||
|
"key": "table-options-edit",
|
||||||
|
"templateUrl": "templates/table-options-edit.html"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
64
platform/features/table/res/templates/mct-data-table.html
Normal file
64
platform/features/table/res/templates/mct-data-table.html
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
<div class="l-view-section scrolling"
|
||||||
|
style="overflow: auto;"
|
||||||
|
>
|
||||||
|
<table class="filterable"
|
||||||
|
ng-style="overrideRowPositioning && {
|
||||||
|
height: totalHeight + 'px',
|
||||||
|
'table-layout': overrideRowPositioning ? 'fixed' : 'auto'
|
||||||
|
}">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th ng-repeat="header in displayHeaders"
|
||||||
|
ng-style="overrideRowPositioning && {
|
||||||
|
width: columnWidths[$index] + 'px',
|
||||||
|
'max-width': columnWidths[$index] + 'px',
|
||||||
|
overflow: 'none',
|
||||||
|
'box-sizing': 'border-box'
|
||||||
|
}"
|
||||||
|
ng-class="[
|
||||||
|
enableSort ? 'sortable' : '',
|
||||||
|
sortColumn === header ? 'sort' : '',
|
||||||
|
sortDirection || ''
|
||||||
|
].join(' ')"
|
||||||
|
ng-click="toggleSort(header)">
|
||||||
|
{{ header }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr ng-if="enableFilter" class="s-filters">
|
||||||
|
<th ng-repeat="header in displayHeaders"
|
||||||
|
ng-style="overrideRowPositioning && {
|
||||||
|
width: columnWidths[$index] + 'px',
|
||||||
|
'max-width': columnWidths[$index] + 'px',
|
||||||
|
overflow: 'none',
|
||||||
|
'box-sizing': 'border-box'
|
||||||
|
}">
|
||||||
|
<input type="text"
|
||||||
|
ng-model="filters[header]"/>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody ng-style="overrideRowPositioning ? '' : {
|
||||||
|
'opacity': '0.0'
|
||||||
|
}">
|
||||||
|
<tr ng-repeat="visibleRow in visibleRows track by visibleRow.rowIndex"
|
||||||
|
ng-style="overrideRowPositioning && {
|
||||||
|
position: 'absolute',
|
||||||
|
top: visibleRow.offsetY + 'px',
|
||||||
|
}">
|
||||||
|
<td ng-repeat="header in displayHeaders"
|
||||||
|
ng-style="overrideRowPositioning && {
|
||||||
|
width: columnWidths[$index] + 'px',
|
||||||
|
'white-space': 'nowrap',
|
||||||
|
'max-width': columnWidths[$index] + 'px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
'box-sizing': 'border-box'
|
||||||
|
}"
|
||||||
|
class="{{visibleRow.contents[header].cssClass}}">
|
||||||
|
{{ visibleRow.contents[header].text }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
</div>
|
@ -0,0 +1,30 @@
|
|||||||
|
<!--
|
||||||
|
Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
Administration. All rights reserved.
|
||||||
|
|
||||||
|
Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
"License"); you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
License for the specific language governing permissions and limitations
|
||||||
|
under the License.
|
||||||
|
|
||||||
|
Open MCT Web includes source code licensed under additional open source
|
||||||
|
licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
this source code distribution or the Licensing information page available
|
||||||
|
at runtime from the About dialog for additional information.
|
||||||
|
-->
|
||||||
|
<div ng-controller="TableOptionsController" class="flex-elem grows l-inspector-part">
|
||||||
|
<em class="t-inspector-part-header" title="Display properties for this object">Display</em>
|
||||||
|
<mct-form
|
||||||
|
ng-model="configuration.table.columns"
|
||||||
|
structure="columnsForm"
|
||||||
|
name="columnsFormState"
|
||||||
|
class="flex-elem l-flex-row no-validate no-margin reduced-min-width">
|
||||||
|
</mct-form>
|
||||||
|
</div>
|
8
platform/features/table/res/templates/table.html
Normal file
8
platform/features/table/res/templates/table.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<div ng-controller="TelemetryTableController">
|
||||||
|
<mct-table
|
||||||
|
headers="headers"
|
||||||
|
rows="rows"
|
||||||
|
enableFilter="true"
|
||||||
|
enableSort="true">
|
||||||
|
</mct-table>
|
||||||
|
</div>
|
64
platform/features/table/src/DomainColumn.js
Normal file
64
platform/features/table/src/DomainColumn.js
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,moment*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining DomainColumn.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A column which will report telemetry domain values
|
||||||
|
* (typically, timestamps.) Used by the ScrollingListController.
|
||||||
|
*
|
||||||
|
* @memberof platform/features/table
|
||||||
|
* @constructor
|
||||||
|
* @param domainMetadata an object with the machine- and human-
|
||||||
|
* readable names for this domain (in `key` and `name`
|
||||||
|
* fields, respectively.)
|
||||||
|
* @param {TelemetryFormatter} telemetryFormatter the telemetry
|
||||||
|
* formatting service, for making values human-readable.
|
||||||
|
*/
|
||||||
|
function DomainColumn(domainMetadata, telemetryFormatter) {
|
||||||
|
this.domainMetadata = domainMetadata;
|
||||||
|
this.telemetryFormatter = telemetryFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
DomainColumn.prototype.getTitle = function () {
|
||||||
|
return this.domainMetadata.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
DomainColumn.prototype.getValue = function (domainObject, datum) {
|
||||||
|
return {
|
||||||
|
text: this.telemetryFormatter.formatDomainValue(
|
||||||
|
datum[this.domainMetadata.key],
|
||||||
|
this.domainMetadata.format
|
||||||
|
)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return DomainColumn;
|
||||||
|
}
|
||||||
|
);
|
54
platform/features/table/src/NameColumn.js
Normal file
54
platform/features/table/src/NameColumn.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,Promise*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining NameColumn. Created by vwoeltje on 11/18/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A column which will report the name of the domain object
|
||||||
|
* which exposed specific telemetry values.
|
||||||
|
*
|
||||||
|
* @memberof platform/features/table
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function NameColumn() {
|
||||||
|
}
|
||||||
|
|
||||||
|
NameColumn.prototype.getTitle = function () {
|
||||||
|
return "Name";
|
||||||
|
};
|
||||||
|
|
||||||
|
NameColumn.prototype.getValue = function (domainObject) {
|
||||||
|
return {
|
||||||
|
text: domainObject.getModel().name
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return NameColumn;
|
||||||
|
}
|
||||||
|
);
|
67
platform/features/table/src/RangeColumn.js
Normal file
67
platform/features/table/src/RangeColumn.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,Promise*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Module defining DomainColumn. Created by vwoeltje on 11/18/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A column which will report telemetry range values
|
||||||
|
* (typically, measurements.) Used by the ScrollingListController.
|
||||||
|
*
|
||||||
|
* @memberof platform/features/table
|
||||||
|
* @constructor
|
||||||
|
* @param rangeMetadata an object with the machine- and human-
|
||||||
|
* readable names for this range (in `key` and `name`
|
||||||
|
* fields, respectively.)
|
||||||
|
* @param {TelemetryFormatter} telemetryFormatter the telemetry
|
||||||
|
* formatting service, for making values human-readable.
|
||||||
|
*/
|
||||||
|
function RangeColumn(rangeMetadata, telemetryFormatter) {
|
||||||
|
this.rangeMetadata = rangeMetadata;
|
||||||
|
this.telemetryFormatter = telemetryFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
RangeColumn.prototype.getTitle = function () {
|
||||||
|
return this.rangeMetadata.name;
|
||||||
|
};
|
||||||
|
|
||||||
|
RangeColumn.prototype.getValue = function (domainObject, datum) {
|
||||||
|
var range = this.rangeMetadata.key,
|
||||||
|
limit = domainObject.getCapability('limit'),
|
||||||
|
value = isNaN(datum[range]) ? datum[range] : parseFloat(datum[range]),
|
||||||
|
alarm = limit && limit.evaluate(datum, range);
|
||||||
|
|
||||||
|
return {
|
||||||
|
cssClass: alarm && alarm.cssClass,
|
||||||
|
text: typeof(value) === 'undefined' ? undefined : this.telemetryFormatter.formatRangeValue(value)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
return RangeColumn;
|
||||||
|
}
|
||||||
|
);
|
180
platform/features/table/src/TableConfiguration.js
Normal file
180
platform/features/table/src/TableConfiguration.js
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,moment*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'./DomainColumn',
|
||||||
|
'./RangeColumn',
|
||||||
|
'./NameColumn'
|
||||||
|
],
|
||||||
|
function (DomainColumn, RangeColumn, NameColumn) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class that manages table metadata, state, and contents.
|
||||||
|
* @memberof platform/features/table
|
||||||
|
* @param domainObject
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function TableConfiguration(domainObject, telemetryFormatter) {
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.columns = [];
|
||||||
|
this.telemetryFormatter = telemetryFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build column definitions based on supplied telemetry metadata
|
||||||
|
* @param metadata Metadata describing the domains and ranges available
|
||||||
|
* @returns {TableConfiguration} This object
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.buildColumns = function(metadata) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.columns = [];
|
||||||
|
|
||||||
|
if (metadata) {
|
||||||
|
|
||||||
|
if (metadata.length > 1){
|
||||||
|
self.addColumn(new NameColumn(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.forEach(function (metadatum) {
|
||||||
|
//Push domains first
|
||||||
|
(metadatum.domains || []).forEach(function (domainMetadata) {
|
||||||
|
self.addColumn(new DomainColumn(domainMetadata, self.telemetryFormatter));
|
||||||
|
});
|
||||||
|
(metadatum.ranges || []).forEach(function (rangeMetadata) {
|
||||||
|
self.addColumn(new RangeColumn(rangeMetadata, self.telemetryFormatter));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a column definition to this Table
|
||||||
|
* @param {RangeColumn | DomainColumn | NameColumn} column
|
||||||
|
* @param {Number} [index] Where the column should appear (will be
|
||||||
|
* affected by column filtering)
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.addColumn = function (column, index) {
|
||||||
|
if (typeof index === 'undefined') {
|
||||||
|
this.columns.push(column);
|
||||||
|
} else {
|
||||||
|
this.columns.splice(index, 0, column);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* @param column
|
||||||
|
* @returns {*|string}
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.getColumnTitle = function (column) {
|
||||||
|
return column.getTitle();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a simple list of column titles
|
||||||
|
* @returns {Array} The titles of the columns
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.getHeaders = function() {
|
||||||
|
var self = this;
|
||||||
|
return this.columns.map(function (column, i){
|
||||||
|
return self.getColumnTitle(column) || 'Column ' + (i + 1);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve and format values for a given telemetry datum.
|
||||||
|
* @param telemetryObject The object that the telemetry data is
|
||||||
|
* associated with
|
||||||
|
* @param datum The telemetry datum to retrieve values from
|
||||||
|
* @returns {Object} Key value pairs where the key is the column
|
||||||
|
* title, and the value is the formatted value from the provided datum.
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.getRowValues = function(telemetryObject, datum) {
|
||||||
|
var self = this;
|
||||||
|
return this.columns.reduce(function(rowObject, column, i){
|
||||||
|
var columnTitle = self.getColumnTitle(column) || 'Column ' + (i + 1),
|
||||||
|
columnValue = column.getValue(telemetryObject, datum);
|
||||||
|
|
||||||
|
if (columnValue !== undefined && columnValue.text === undefined){
|
||||||
|
columnValue.text = '';
|
||||||
|
}
|
||||||
|
// Don't replace something with nothing.
|
||||||
|
// This occurs when there are multiple columns with the
|
||||||
|
// column title
|
||||||
|
if (rowObject[columnTitle] === undefined || rowObject[columnTitle].text === undefined || rowObject[columnTitle].text.length === 0) {
|
||||||
|
rowObject[columnTitle] = columnValue;
|
||||||
|
}
|
||||||
|
return rowObject;
|
||||||
|
}, {});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.defaultColumnConfiguration = function () {
|
||||||
|
return ((this.domainObject.getModel().configuration || {}).table || {}).columns || {};
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the established configuration on the domain object
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.saveColumnConfiguration = function (columnConfig) {
|
||||||
|
this.domainObject.useCapability('mutation', function (model) {
|
||||||
|
model.configuration = model.configuration || {};
|
||||||
|
model.configuration.table = model.configuration.table || {};
|
||||||
|
model.configuration.table.columns = columnConfig;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* As part of the process of building the table definition, extract
|
||||||
|
* configuration from column definitions.
|
||||||
|
* @returns {Object} A configuration object consisting of key-value
|
||||||
|
* pairs where the key is the column title, and the value is a
|
||||||
|
* boolean indicating whether the column should be shown.
|
||||||
|
*/
|
||||||
|
TableConfiguration.prototype.getColumnConfiguration = function() {
|
||||||
|
var configuration = {},
|
||||||
|
//Use existing persisted config, or default it
|
||||||
|
defaultConfig = this.defaultColumnConfiguration();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each column header, define a configuration value
|
||||||
|
* specifying whether the column is visible or not. Default to
|
||||||
|
* existing (persisted) configuration if available
|
||||||
|
*/
|
||||||
|
this.getHeaders().forEach(function(columnTitle) {
|
||||||
|
configuration[columnTitle] = typeof defaultConfig[columnTitle] === 'undefined' ? true : defaultConfig[columnTitle];
|
||||||
|
});
|
||||||
|
|
||||||
|
return configuration;
|
||||||
|
};
|
||||||
|
|
||||||
|
return TableConfiguration;
|
||||||
|
}
|
||||||
|
);
|
354
platform/features/table/src/controllers/MCTTableController.js
Normal file
354
platform/features/table/src/controllers/MCTTableController.js
Normal file
@ -0,0 +1,354 @@
|
|||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function MCTTableController($scope, $timeout, element) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.element = element;
|
||||||
|
this.$timeout = $timeout;
|
||||||
|
this.maxDisplayRows = 50;
|
||||||
|
|
||||||
|
$scope.visibleRows = [];
|
||||||
|
$scope.overrideRowPositioning = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set default values for optional parameters on a given scope
|
||||||
|
*/
|
||||||
|
function setDefaults($scope) {
|
||||||
|
if (typeof $scope.enableFilter === 'undefined') {
|
||||||
|
$scope.enableFilter = true;
|
||||||
|
$scope.filters = {};
|
||||||
|
}
|
||||||
|
if (typeof $scope.enableSort === 'undefined') {
|
||||||
|
$scope.enableSort = true;
|
||||||
|
$scope.sortColumn = undefined;
|
||||||
|
$scope.sortDirection = undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setDefaults($scope);
|
||||||
|
|
||||||
|
element.find('div').on('scroll', this.onScroll.bind(this));
|
||||||
|
|
||||||
|
$scope.toggleSort = function (key) {
|
||||||
|
if (!$scope.enableSort) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($scope.sortColumn !== key) {
|
||||||
|
$scope.sortColumn = key;
|
||||||
|
$scope.sortDirection = 'asc';
|
||||||
|
} else if ($scope.sortDirection === 'asc') {
|
||||||
|
$scope.sortDirection = 'desc';
|
||||||
|
} else if ($scope.sortDirection === 'desc') {
|
||||||
|
$scope.sortColumn = undefined;
|
||||||
|
$scope.sortDirection = undefined;
|
||||||
|
}
|
||||||
|
self.updateRows($scope.rows);
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.$watchCollection('filters', function () {
|
||||||
|
self.updateRows(self.$scope.rows);
|
||||||
|
});
|
||||||
|
$scope.$watchCollection('headers', this.updateHeaders.bind(this));
|
||||||
|
$scope.$watchCollection('rows', this.updateRows.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On scroll, calculate which rows indexes are visible and
|
||||||
|
* ensure that an equal number of rows are preloaded for
|
||||||
|
* scrolling in either direction.
|
||||||
|
*/
|
||||||
|
MCTTableController.prototype.onScroll = function (event) {
|
||||||
|
var self = this,
|
||||||
|
topScroll = event.target.scrollTop,
|
||||||
|
bottomScroll = topScroll + event.target.offsetHeight,
|
||||||
|
firstVisible,
|
||||||
|
lastVisible,
|
||||||
|
totalVisible,
|
||||||
|
numberOffscreen,
|
||||||
|
start,
|
||||||
|
end;
|
||||||
|
|
||||||
|
if (this.$scope.displayRows.length < this.maxDisplayRows) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (topScroll < this.$scope.headerHeight) {
|
||||||
|
firstVisible = 0;
|
||||||
|
} else {
|
||||||
|
firstVisible = Math.floor(
|
||||||
|
(topScroll - this.$scope.headerHeight) / this.$scope.rowHeight
|
||||||
|
);
|
||||||
|
}
|
||||||
|
lastVisible = Math.ceil(
|
||||||
|
(bottomScroll - this.$scope.headerHeight) / this.$scope.rowHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
totalVisible = lastVisible - firstVisible;
|
||||||
|
numberOffscreen = this.maxDisplayRows - totalVisible;
|
||||||
|
start = firstVisible - Math.floor(numberOffscreen / 2);
|
||||||
|
end = lastVisible + Math.ceil(numberOffscreen / 2);
|
||||||
|
|
||||||
|
if (start < 0) {
|
||||||
|
start = 0;
|
||||||
|
end = this.$scope.visibleRows.length - 1;
|
||||||
|
} else if (end >= this.$scope.displayRows.length) {
|
||||||
|
end = this.$scope.displayRows.length - 1;
|
||||||
|
start = end - this.maxDisplayRows + 1;
|
||||||
|
}
|
||||||
|
if (this.$scope.visibleRows[0].rowIndex === start &&
|
||||||
|
this.$scope.visibleRows[this.$scope.visibleRows.length-1]
|
||||||
|
.rowIndex === end) {
|
||||||
|
|
||||||
|
return; // don't update if no changes are required.
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$scope.visibleRows = this.$scope.displayRows.slice(start, end)
|
||||||
|
.map(function(row, i) {
|
||||||
|
return {
|
||||||
|
rowIndex: start + i,
|
||||||
|
offsetY: ((start + i) * self.$scope.rowHeight) +
|
||||||
|
self.$scope.headerHeight,
|
||||||
|
contents: row
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$scope.$digest();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update table headers with new headers. If filtering is
|
||||||
|
* enabled, reset filters. If sorting is enabled, reset
|
||||||
|
* sorting.
|
||||||
|
*/
|
||||||
|
MCTTableController.prototype.updateHeaders = function (newHeaders) {
|
||||||
|
if (!newHeaders){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$scope.displayHeaders = newHeaders;
|
||||||
|
if (this.$scope.enableFilter) {
|
||||||
|
this.$scope.filters = {};
|
||||||
|
}
|
||||||
|
// Reset column sort information unless the new headers
|
||||||
|
// contain the column current sorted on.
|
||||||
|
if (this.$scope.enableSort && newHeaders.indexOf(this.$scope.sortColumn) === -1) {
|
||||||
|
this.$scope.sortColumn = undefined;
|
||||||
|
this.$scope.sortDirection = undefined;
|
||||||
|
}
|
||||||
|
this.updateRows(this.$scope.rows);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read styles from the DOM and use them to calculate offsets
|
||||||
|
* for individual rows.
|
||||||
|
*/
|
||||||
|
MCTTableController.prototype.setElementSizes = function () {
|
||||||
|
var self = this,
|
||||||
|
thead = this.element.find('thead'),
|
||||||
|
tbody = this.element.find('tbody'),
|
||||||
|
firstRow = tbody.find('tr'),
|
||||||
|
column = firstRow.find('td'),
|
||||||
|
headerHeight = thead.prop('offsetHeight'),
|
||||||
|
//row height is hard-coded for now.
|
||||||
|
rowHeight = 20,
|
||||||
|
overallHeight = headerHeight + (rowHeight * (this.$scope.displayRows ? this.$scope.displayRows.length - 1 : 0));
|
||||||
|
|
||||||
|
this.$scope.columnWidths = [];
|
||||||
|
|
||||||
|
while (column.length) {
|
||||||
|
this.$scope.columnWidths.push(column.prop('offsetWidth'));
|
||||||
|
column = column.next();
|
||||||
|
}
|
||||||
|
this.$scope.headerHeight = headerHeight;
|
||||||
|
this.$scope.rowHeight = rowHeight;
|
||||||
|
this.$scope.totalHeight = overallHeight;
|
||||||
|
|
||||||
|
this.$scope.visibleRows = this.$scope.displayRows.slice(0, this.maxDisplayRows).map(function(row, i) {
|
||||||
|
return {
|
||||||
|
rowIndex: i,
|
||||||
|
offsetY: (i * self.$scope.rowHeight) + self.$scope.headerHeight,
|
||||||
|
contents: row
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$scope.overrideRowPositioning = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a new array which is a result of applying the sort
|
||||||
|
* criteria defined in $scope.
|
||||||
|
*
|
||||||
|
* Does not modify the array that was passed in.
|
||||||
|
*/
|
||||||
|
MCTTableController.prototype.sortRows = function(rowsToSort) {
|
||||||
|
/**
|
||||||
|
* Compare two variables, returning a number that represents
|
||||||
|
* which is larger. Similar to the default array sort
|
||||||
|
* comparator, but does not coerce all values to string before
|
||||||
|
* conversion. Strings are lowercased before comparison.
|
||||||
|
*/
|
||||||
|
function genericComparator(a, b) {
|
||||||
|
if (typeof a === "string" && typeof b === "string") {
|
||||||
|
a = a.toLowerCase();
|
||||||
|
b = b.toLowerCase();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (a < b) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a > b) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.$scope.sortColumn || !this.$scope.sortDirection) {
|
||||||
|
return rowsToSort;
|
||||||
|
}
|
||||||
|
var sortKey = this.$scope.sortColumn,
|
||||||
|
sortDirectionMultiplier;
|
||||||
|
|
||||||
|
if (this.$scope.sortDirection === 'asc') {
|
||||||
|
sortDirectionMultiplier = 1;
|
||||||
|
} else if (this.$scope.sortDirection === 'desc') {
|
||||||
|
sortDirectionMultiplier = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rowsToSort.slice(0).sort(function(a, b) {
|
||||||
|
//If the values to compare can be compared as
|
||||||
|
// numbers, do so. String comparison of number
|
||||||
|
// values can cause inconsistencies
|
||||||
|
var valA = isNaN(a[sortKey].text) ? a[sortKey].text : parseFloat(a[sortKey].text),
|
||||||
|
valB = isNaN(b[sortKey].text) ? b[sortKey].text : parseFloat(b[sortKey].text);
|
||||||
|
|
||||||
|
return genericComparator(valA, valB) *
|
||||||
|
sortDirectionMultiplier;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an object which contains the largest values
|
||||||
|
* for each key in the given set of rows. This is used to
|
||||||
|
* pre-calculate optimal column sizes without having to render
|
||||||
|
* every row.
|
||||||
|
*/
|
||||||
|
MCTTableController.prototype.findLargestRow = function(rows) {
|
||||||
|
var largestRow = rows.reduce(function (largestRow, row) {
|
||||||
|
Object.keys(row).forEach(function (key) {
|
||||||
|
var currentColumn = row[key].text,
|
||||||
|
currentColumnLength =
|
||||||
|
(currentColumn && currentColumn.length) ?
|
||||||
|
currentColumn.length :
|
||||||
|
currentColumn,
|
||||||
|
largestColumn = largestRow[key].text,
|
||||||
|
largestColumnLength =
|
||||||
|
(largestColumn && largestColumn.length) ?
|
||||||
|
largestColumn.length :
|
||||||
|
largestColumn;
|
||||||
|
|
||||||
|
if (currentColumnLength > largestColumnLength) {
|
||||||
|
largestRow[key] = JSON.parse(JSON.stringify(row[key]));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return largestRow;
|
||||||
|
}, JSON.parse(JSON.stringify(rows[0] || {})));
|
||||||
|
|
||||||
|
// Pad with characters to accomodate variable-width fonts,
|
||||||
|
// and remove characters that would allow word-wrapping.
|
||||||
|
largestRow = JSON.parse(JSON.stringify(largestRow));
|
||||||
|
Object.keys(largestRow).forEach(function(key) {
|
||||||
|
var padCharacters,
|
||||||
|
i;
|
||||||
|
|
||||||
|
largestRow[key].text = String(largestRow[key].text);
|
||||||
|
padCharacters = largestRow[key].text.length / 10;
|
||||||
|
for (i = 0; i < padCharacters; i++) {
|
||||||
|
largestRow[key].text = largestRow[key].text + 'W';
|
||||||
|
}
|
||||||
|
largestRow[key].text = largestRow[key].text
|
||||||
|
.replace(/[ \-_]/g, 'W');
|
||||||
|
});
|
||||||
|
return largestRow;
|
||||||
|
};
|
||||||
|
|
||||||
|
MCTTableController.prototype.resize = function (){
|
||||||
|
var largestRow = this.findLargestRow(this.$scope.displayRows);
|
||||||
|
this.$scope.visibleRows = [
|
||||||
|
{
|
||||||
|
rowIndex: 0,
|
||||||
|
offsetY: undefined,
|
||||||
|
contents: largestRow
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
this.$timeout(this.setElementSizes.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update rows with new data. If filtering is enabled, rows
|
||||||
|
* will be sorted before display.
|
||||||
|
*/
|
||||||
|
MCTTableController.prototype.updateRows = function (newRows) {
|
||||||
|
var displayRows = newRows;
|
||||||
|
this.$scope.visibleRows = [];
|
||||||
|
this.$scope.overrideRowPositioning = false;
|
||||||
|
|
||||||
|
if (!this.$scope.displayHeaders) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.$scope.enableFilter) {
|
||||||
|
displayRows = this.filterRows(displayRows);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.$scope.enableSort) {
|
||||||
|
displayRows = this.sortRows(displayRows);
|
||||||
|
}
|
||||||
|
this.$scope.displayRows = displayRows;
|
||||||
|
this.resize();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter rows.
|
||||||
|
*/
|
||||||
|
MCTTableController.prototype.filterRows = function(rowsToFilter) {
|
||||||
|
var filters = {},
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if row matches all filters.
|
||||||
|
*/
|
||||||
|
function matchRow(filters, row) {
|
||||||
|
return Object.keys(filters).every(function(key) {
|
||||||
|
if (!row[key]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var testVal = String(row[key].text).toLowerCase();
|
||||||
|
return testVal.indexOf(filters[key]) !== -1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Object.keys(this.$scope.filters).length) {
|
||||||
|
return rowsToFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
Object.keys(this.$scope.filters).forEach(function(key) {
|
||||||
|
if (!self.$scope.filters[key]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
filters[key] = self.$scope.filters[key].toLowerCase();
|
||||||
|
});
|
||||||
|
|
||||||
|
return rowsToFilter.filter(matchRow.bind(null, filters));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return MCTTableController;
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,94 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notes on implementation of plot options
|
||||||
|
*
|
||||||
|
* Multiple y-axes will have to be handled with multiple forms as
|
||||||
|
* they will need to be stored on distinct model object
|
||||||
|
*
|
||||||
|
* Likewise plot series options per-child will need to be separate
|
||||||
|
* forms.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The LayoutController is responsible for supporting the
|
||||||
|
* Layout view. It arranges frames according to saved configuration
|
||||||
|
* and provides methods for updating these based on mouse
|
||||||
|
* movement.
|
||||||
|
* @memberof platform/features/plot
|
||||||
|
* @constructor
|
||||||
|
* @param {Scope} $scope the controller's Angular scope
|
||||||
|
*/
|
||||||
|
function TableOptionsController($scope) {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.domainObject = $scope.domainObject;
|
||||||
|
|
||||||
|
$scope.columnsForm = {};
|
||||||
|
|
||||||
|
this.domainObject.getCapability('mutation').listen(function (model) {
|
||||||
|
self.populateForm(model);
|
||||||
|
});
|
||||||
|
|
||||||
|
$scope.$watchCollection('configuration.table.columns', function(columns){
|
||||||
|
if (columns){
|
||||||
|
self.domainObject.useCapability('mutation', function(model) {
|
||||||
|
model.configuration.table.columns = columns;
|
||||||
|
});
|
||||||
|
self.domainObject.getCapability('persistence').persist();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TableOptionsController.prototype.populateForm = function (model) {
|
||||||
|
var columnsDefinition = (((model.configuration || {}).table || {}).columns || {}),
|
||||||
|
rows = [];
|
||||||
|
this.$scope.columnsForm = {
|
||||||
|
'name':'Columns',
|
||||||
|
'sections': [{
|
||||||
|
'name': 'Columns',
|
||||||
|
'rows': rows
|
||||||
|
}]};
|
||||||
|
|
||||||
|
Object.keys(columnsDefinition).forEach(function (key){
|
||||||
|
rows.push({
|
||||||
|
'name': key,
|
||||||
|
'control': 'checkbox',
|
||||||
|
'key': key
|
||||||
|
});
|
||||||
|
});
|
||||||
|
this.$scope.configuration = JSON.parse(JSON.stringify(model.configuration));
|
||||||
|
};
|
||||||
|
|
||||||
|
return TableOptionsController;
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,189 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This bundle adds a table view for displaying telemetry data.
|
||||||
|
* @namespace platform/features/table
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
'../TableConfiguration'
|
||||||
|
],
|
||||||
|
function (TableConfiguration) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TableController is responsible for getting data onto the page
|
||||||
|
* in the table widget. This includes handling composition,
|
||||||
|
* configuration, and telemetry subscriptions.
|
||||||
|
* @memberof platform/features/table
|
||||||
|
* @param $scope
|
||||||
|
* @param telemetryHandler
|
||||||
|
* @param telemetryFormatter
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function TelemetryTableController(
|
||||||
|
$scope,
|
||||||
|
telemetryHandler,
|
||||||
|
telemetryFormatter
|
||||||
|
) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.columns = {}; //Range and Domain columns
|
||||||
|
this.handle = undefined;
|
||||||
|
//this.pending = false;
|
||||||
|
this.telemetryHandler = telemetryHandler;
|
||||||
|
this.table = new TableConfiguration($scope.domainObject, telemetryFormatter);
|
||||||
|
this.changeListeners = [];
|
||||||
|
|
||||||
|
$scope.rows = [];
|
||||||
|
|
||||||
|
// Subscribe to telemetry when a domain object becomes available
|
||||||
|
this.$scope.$watch('domainObject', function(domainObject){
|
||||||
|
if (!domainObject)
|
||||||
|
return;
|
||||||
|
|
||||||
|
self.subscribe();
|
||||||
|
self.registerChangeListeners();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Unsubscribe when the plot is destroyed
|
||||||
|
this.$scope.$on("$destroy", this.destroy.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
TelemetryTableController.prototype.registerChangeListeners = function() {
|
||||||
|
//Defer registration of change listeners until domain object is
|
||||||
|
// available in order to avoid race conditions
|
||||||
|
|
||||||
|
this.changeListeners.forEach(function (listener) {
|
||||||
|
return listener && listener();
|
||||||
|
});
|
||||||
|
this.changeListeners = [];
|
||||||
|
// When composition changes, re-subscribe to the various
|
||||||
|
// telemetry subscriptions
|
||||||
|
this.changeListeners.push(this.$scope.$watchCollection('domainObject.getModel().composition', this.subscribe.bind(this)));
|
||||||
|
|
||||||
|
//Change of bounds in time conductor
|
||||||
|
this.changeListeners.push(this.$scope.$on('telemetry:display:bounds', this.subscribe.bind(this)));
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release the current subscription (called when scope is destroyed)
|
||||||
|
*/
|
||||||
|
TelemetryTableController.prototype.destroy = function () {
|
||||||
|
if (this.handle) {
|
||||||
|
this.handle.unsubscribe();
|
||||||
|
this.handle = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a new subscription. This is called when
|
||||||
|
*/
|
||||||
|
TelemetryTableController.prototype.subscribe = function() {
|
||||||
|
|
||||||
|
if (this.handle) {
|
||||||
|
this.handle.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$scope.rows = [];
|
||||||
|
|
||||||
|
//Noop because not supporting realtime data right now
|
||||||
|
function noop(){
|
||||||
|
}
|
||||||
|
|
||||||
|
this.handle = this.$scope.domainObject && this.telemetryHandler.handle(
|
||||||
|
this.$scope.domainObject,
|
||||||
|
noop,
|
||||||
|
true // Lossless
|
||||||
|
);
|
||||||
|
|
||||||
|
this.handle.request({}, this.addHistoricalData.bind(this));
|
||||||
|
|
||||||
|
this.setup();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add any historical data available
|
||||||
|
*/
|
||||||
|
TelemetryTableController.prototype.addHistoricalData = function(domainObject, series) {
|
||||||
|
var i;
|
||||||
|
for (i=0; i < series.getPointCount(); i++) {
|
||||||
|
this.updateRows(domainObject, this.handle.makeDatum(domainObject, series, i));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setup table columns based on domain object metadata
|
||||||
|
*/
|
||||||
|
TelemetryTableController.prototype.setup = function() {
|
||||||
|
var handle = this.handle,
|
||||||
|
table = this.table,
|
||||||
|
self = this;
|
||||||
|
|
||||||
|
if (handle) {
|
||||||
|
handle.promiseTelemetryObjects().then(function (objects) {
|
||||||
|
table.buildColumns(handle.getMetadata());
|
||||||
|
|
||||||
|
self.filterColumns();
|
||||||
|
|
||||||
|
// When table column configuration changes, (due to being
|
||||||
|
// selected or deselected), filter columns appropriately.
|
||||||
|
self.changeListeners.push(self.$scope.$watchCollection(
|
||||||
|
'domainObject.getModel().configuration.table.columns',
|
||||||
|
self.filterColumns.bind(self)
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add data to rows
|
||||||
|
* @param object The object for which data is available (table may
|
||||||
|
* be composed of multiple objects)
|
||||||
|
* @param datum The data received from the telemetry source
|
||||||
|
*/
|
||||||
|
TelemetryTableController.prototype.updateRows = function (object, datum) {
|
||||||
|
this.$scope.rows.push(this.table.getRowValues(object, datum));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When column configuration changes, update the visible headers
|
||||||
|
* accordingly.
|
||||||
|
*/
|
||||||
|
TelemetryTableController.prototype.filterColumns = function (columnConfig) {
|
||||||
|
if (!columnConfig){
|
||||||
|
columnConfig = this.table.getColumnConfiguration();
|
||||||
|
this.table.saveColumnConfiguration(columnConfig);
|
||||||
|
}
|
||||||
|
//Populate headers with visible columns (determined by configuration)
|
||||||
|
this.$scope.headers = Object.keys(columnConfig).filter(function(column) {
|
||||||
|
return columnConfig[column];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return TelemetryTableController;
|
||||||
|
}
|
||||||
|
);
|
24
platform/features/table/src/directives/MCTTable.js
Normal file
24
platform/features/table/src/directives/MCTTable.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
["../controllers/MCTTableController"],
|
||||||
|
function (MCTTableController) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
function MCTTable($timeout) {
|
||||||
|
return {
|
||||||
|
restrict: "E",
|
||||||
|
templateUrl: "platform/features/table/res/templates/mct-data-table.html",
|
||||||
|
controller: ['$scope', '$timeout', '$element', MCTTableController],
|
||||||
|
scope: {
|
||||||
|
headers: "=",
|
||||||
|
rows: "=",
|
||||||
|
enableFilter: "=?",
|
||||||
|
enableSort: "=?"
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return MCTTable;
|
||||||
|
}
|
||||||
|
);
|
84
platform/features/table/test/DomainColumnSpec.js
Normal file
84
platform/features/table/test/DomainColumnSpec.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,xit*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MergeModelsSpec. Created by vwoeltje on 11/6/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../src/DomainColumn"],
|
||||||
|
function (DomainColumn) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var TEST_DOMAIN_VALUE = "some formatted domain value";
|
||||||
|
|
||||||
|
describe("A domain column", function () {
|
||||||
|
var mockDataSet,
|
||||||
|
testMetadata,
|
||||||
|
mockFormatter,
|
||||||
|
column;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDataSet = jasmine.createSpyObj(
|
||||||
|
"data",
|
||||||
|
[ "getDomainValue" ]
|
||||||
|
);
|
||||||
|
mockFormatter = jasmine.createSpyObj(
|
||||||
|
"formatter",
|
||||||
|
[ "formatDomainValue", "formatRangeValue" ]
|
||||||
|
);
|
||||||
|
testMetadata = {
|
||||||
|
key: "testKey",
|
||||||
|
name: "Test Name"
|
||||||
|
};
|
||||||
|
mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE);
|
||||||
|
|
||||||
|
column = new DomainColumn(testMetadata, mockFormatter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports a column header from domain metadata", function () {
|
||||||
|
expect(column.getTitle()).toEqual("Test Name");
|
||||||
|
});
|
||||||
|
|
||||||
|
xit("looks up data from a data set", function () {
|
||||||
|
column.getValue(undefined, mockDataSet, 42);
|
||||||
|
expect(mockDataSet.getDomainValue)
|
||||||
|
.toHaveBeenCalledWith(42, "testKey");
|
||||||
|
});
|
||||||
|
|
||||||
|
xit("formats domain values as time", function () {
|
||||||
|
mockDataSet.getDomainValue.andReturn(402513731000);
|
||||||
|
|
||||||
|
// Should have just given the value the formatter gave
|
||||||
|
expect(column.getValue(undefined, mockDataSet, 42).text)
|
||||||
|
.toEqual(TEST_DOMAIN_VALUE);
|
||||||
|
|
||||||
|
// Make sure that service interactions were as expected
|
||||||
|
expect(mockFormatter.formatDomainValue)
|
||||||
|
.toHaveBeenCalledWith(402513731000);
|
||||||
|
expect(mockFormatter.formatRangeValue)
|
||||||
|
.not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
58
platform/features/table/test/NameColumnSpec.js
Normal file
58
platform/features/table/test/NameColumnSpec.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MergeModelsSpec. Created by vwoeltje on 11/6/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../src/NameColumn"],
|
||||||
|
function (NameColumn) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("A name column", function () {
|
||||||
|
var mockDomainObject,
|
||||||
|
column;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[ "getModel" ]
|
||||||
|
);
|
||||||
|
mockDomainObject.getModel.andReturn({
|
||||||
|
name: "Test object name"
|
||||||
|
});
|
||||||
|
column = new NameColumn();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports a column header", function () {
|
||||||
|
expect(column.getTitle()).toEqual("Name");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("looks up name from an object's model", function () {
|
||||||
|
expect(column.getValue(mockDomainObject).text)
|
||||||
|
.toEqual("Test object name");
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
76
platform/features/table/test/RangeColumnSpec.js
Normal file
76
platform/features/table/test/RangeColumnSpec.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,xit*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MergeModelsSpec. Created by vwoeltje on 11/6/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../src/RangeColumn"],
|
||||||
|
function (RangeColumn) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var TEST_RANGE_VALUE = "some formatted range value";
|
||||||
|
|
||||||
|
describe("A range column", function () {
|
||||||
|
var testDatum,
|
||||||
|
testMetadata,
|
||||||
|
mockFormatter,
|
||||||
|
mockDomainObject,
|
||||||
|
column;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
testDatum = { testKey: 123, otherKey: 456 };
|
||||||
|
mockFormatter = jasmine.createSpyObj(
|
||||||
|
"formatter",
|
||||||
|
[ "formatDomainValue", "formatRangeValue" ]
|
||||||
|
);
|
||||||
|
testMetadata = {
|
||||||
|
key: "testKey",
|
||||||
|
name: "Test Name"
|
||||||
|
};
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[ "getModel", "getCapability" ]
|
||||||
|
);
|
||||||
|
mockFormatter.formatRangeValue.andReturn(TEST_RANGE_VALUE);
|
||||||
|
|
||||||
|
column = new RangeColumn(testMetadata, mockFormatter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports a column header from range metadata", function () {
|
||||||
|
expect(column.getTitle()).toEqual("Test Name");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("formats range values as numbers", function () {
|
||||||
|
expect(column.getValue(mockDomainObject, testDatum).text)
|
||||||
|
.toEqual(TEST_RANGE_VALUE);
|
||||||
|
|
||||||
|
// Make sure that service interactions were as expected
|
||||||
|
expect(mockFormatter.formatRangeValue)
|
||||||
|
.toHaveBeenCalledWith(testDatum.testKey);
|
||||||
|
expect(mockFormatter.formatDomainValue)
|
||||||
|
.not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
197
platform/features/table/test/TableConfigurationSpec.js
Normal file
197
platform/features/table/test/TableConfigurationSpec.js
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,xit*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
"../src/TableConfiguration",
|
||||||
|
"../src/DomainColumn"
|
||||||
|
],
|
||||||
|
function (Table, DomainColumn) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("A table", function () {
|
||||||
|
var mockDomainObject,
|
||||||
|
mockTelemetryFormatter,
|
||||||
|
table,
|
||||||
|
mockModel;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDomainObject = jasmine.createSpyObj('domainObject',
|
||||||
|
['getModel', 'useCapability', 'getCapability']
|
||||||
|
);
|
||||||
|
mockModel = {};
|
||||||
|
mockDomainObject.getModel.andReturn(mockModel);
|
||||||
|
mockTelemetryFormatter = jasmine.createSpyObj('telemetryFormatter',
|
||||||
|
[
|
||||||
|
'formatDomainValue',
|
||||||
|
'formatRangeValue'
|
||||||
|
]);
|
||||||
|
mockTelemetryFormatter.formatDomainValue.andCallFake(function(valueIn){
|
||||||
|
return valueIn;
|
||||||
|
});
|
||||||
|
mockTelemetryFormatter.formatRangeValue.andCallFake(function(valueIn){
|
||||||
|
return valueIn;
|
||||||
|
});
|
||||||
|
|
||||||
|
table = new Table(mockDomainObject, mockTelemetryFormatter);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Add column with no index adds new column to the end", function () {
|
||||||
|
var firstColumn = {title: 'First Column'},
|
||||||
|
secondColumn = {title: 'Second Column'},
|
||||||
|
thirdColumn = {title: 'Third Column'};
|
||||||
|
|
||||||
|
table.addColumn(firstColumn);
|
||||||
|
table.addColumn(secondColumn);
|
||||||
|
table.addColumn(thirdColumn);
|
||||||
|
|
||||||
|
expect(table.columns).toBeDefined();
|
||||||
|
expect(table.columns.length).toBe(3);
|
||||||
|
expect(table.columns[0]).toBe(firstColumn);
|
||||||
|
expect(table.columns[1]).toBe(secondColumn);
|
||||||
|
expect(table.columns[2]).toBe(thirdColumn);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Add column with index adds new column at the specified" +
|
||||||
|
" position", function () {
|
||||||
|
var firstColumn = {title: 'First Column'},
|
||||||
|
secondColumn = {title: 'Second Column'},
|
||||||
|
thirdColumn = {title: 'Third Column'};
|
||||||
|
|
||||||
|
table.addColumn(firstColumn);
|
||||||
|
table.addColumn(thirdColumn);
|
||||||
|
table.addColumn(secondColumn, 1);
|
||||||
|
|
||||||
|
expect(table.columns).toBeDefined();
|
||||||
|
expect(table.columns.length).toBe(3);
|
||||||
|
expect(table.columns[0]).toBe(firstColumn);
|
||||||
|
expect(table.columns[1]).toBe(secondColumn);
|
||||||
|
expect(table.columns[2]).toBe(thirdColumn);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Building columns from telemetry metadata", function() {
|
||||||
|
var metadata = [{
|
||||||
|
ranges: [
|
||||||
|
{
|
||||||
|
name: 'Range 1',
|
||||||
|
key: 'range1'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Range 2',
|
||||||
|
key: 'range2'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
domains: [
|
||||||
|
{
|
||||||
|
name: 'Domain 1',
|
||||||
|
key: 'domain1',
|
||||||
|
format: 'utc'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'Domain 2',
|
||||||
|
key: 'domain2',
|
||||||
|
format: 'utc'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
table.buildColumns(metadata);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("populates the columns attribute", function() {
|
||||||
|
expect(table.columns.length).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Build columns populates columns with domains to the left", function() {
|
||||||
|
expect(table.columns[0] instanceof DomainColumn).toBeTruthy();
|
||||||
|
expect(table.columns[1] instanceof DomainColumn).toBeTruthy();
|
||||||
|
expect(table.columns[2] instanceof DomainColumn).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Produces headers for each column based on title", function() {
|
||||||
|
var headers,
|
||||||
|
firstColumn = table.columns[0];
|
||||||
|
|
||||||
|
spyOn(firstColumn, 'getTitle');
|
||||||
|
headers = table.getHeaders();
|
||||||
|
expect(headers.length).toBe(4);
|
||||||
|
expect(firstColumn.getTitle).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Provides a default configuration with all columns" +
|
||||||
|
" visible", function() {
|
||||||
|
var configuration = table.getColumnConfiguration();
|
||||||
|
|
||||||
|
expect(configuration).toBeDefined();
|
||||||
|
expect(Object.keys(configuration).every(function(key){
|
||||||
|
return configuration[key];
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Column configuration exposes persisted configuration", function() {
|
||||||
|
var tableConfig,
|
||||||
|
modelConfig = {
|
||||||
|
table: {
|
||||||
|
columns : {
|
||||||
|
'Range 1': false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mockModel.configuration = modelConfig;
|
||||||
|
|
||||||
|
tableConfig = table.getColumnConfiguration();
|
||||||
|
|
||||||
|
expect(tableConfig).toBeDefined();
|
||||||
|
expect(tableConfig['Range 1']).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('retrieving row values', function () {
|
||||||
|
var datum,
|
||||||
|
rowValues;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
datum = {
|
||||||
|
'range1': 'range 1 value',
|
||||||
|
'range2': 'range 2 value',
|
||||||
|
'domain1': 0,
|
||||||
|
'domain2': 1
|
||||||
|
};
|
||||||
|
rowValues = table.getRowValues(mockDomainObject, datum);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Returns a value for every column", function() {
|
||||||
|
expect(rowValues['Range 1'].text).toBeDefined();
|
||||||
|
expect(rowValues['Range 1'].text).toEqual('range 1' +
|
||||||
|
' value');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Uses the telemetry formatter to appropriately format" +
|
||||||
|
" telemetry values", function() {
|
||||||
|
expect(mockTelemetryFormatter.formatRangeValue).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -0,0 +1,155 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,xit*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
"../../src/controllers/MCTTableController"
|
||||||
|
],
|
||||||
|
function (MCTTableController) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe('The MCTTable Controller', function() {
|
||||||
|
|
||||||
|
var controller,
|
||||||
|
mockScope,
|
||||||
|
watches,
|
||||||
|
mockTimeout,
|
||||||
|
mockElement;
|
||||||
|
|
||||||
|
function promise(value) {
|
||||||
|
return {
|
||||||
|
then: function (callback){
|
||||||
|
return promise(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
watches = {};
|
||||||
|
|
||||||
|
mockScope = jasmine.createSpyObj('scope', [
|
||||||
|
'$watchCollection'
|
||||||
|
]);
|
||||||
|
mockScope.$watchCollection.andCallFake(function(event, callback) {
|
||||||
|
watches[event] = callback;
|
||||||
|
});
|
||||||
|
|
||||||
|
mockElement = jasmine.createSpyObj('element', [
|
||||||
|
'find',
|
||||||
|
'on'
|
||||||
|
]);
|
||||||
|
mockElement.find.andReturn(mockElement);
|
||||||
|
|
||||||
|
mockScope.displayHeaders = true;
|
||||||
|
mockTimeout = jasmine.createSpy('$timeout');
|
||||||
|
|
||||||
|
controller = new MCTTableController(mockScope, mockTimeout, mockElement);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Reacts to changes to filters, headers, and rows', function() {
|
||||||
|
expect(mockScope.$watchCollection).toHaveBeenCalledWith('filters', jasmine.any(Function));
|
||||||
|
expect(mockScope.$watchCollection).toHaveBeenCalledWith('headers', jasmine.any(Function));
|
||||||
|
expect(mockScope.$watchCollection).toHaveBeenCalledWith('rows', jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('rows', function() {
|
||||||
|
var testRows = [];
|
||||||
|
beforeEach(function() {
|
||||||
|
testRows = [
|
||||||
|
{
|
||||||
|
'col1': {'text': 'row1 col1 match'},
|
||||||
|
'col2': {'text': 'def'},
|
||||||
|
'col3': {'text': 'row1 col3'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'col1': {'text': 'row2 col1 match'},
|
||||||
|
'col2': {'text': 'abc'},
|
||||||
|
'col3': {'text': 'row2 col3'}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'col1': {'text': 'row3 col1'},
|
||||||
|
'col2': {'text': 'ghi'},
|
||||||
|
'col3': {'text': 'row3 col3'}
|
||||||
|
}
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Filters results based on filter input', function() {
|
||||||
|
var filters = {},
|
||||||
|
filteredRows;
|
||||||
|
|
||||||
|
mockScope.filters = filters;
|
||||||
|
|
||||||
|
filteredRows = controller.filterRows(testRows);
|
||||||
|
expect(filteredRows.length).toBe(3);
|
||||||
|
filters.col1 = 'row1';
|
||||||
|
filteredRows = controller.filterRows(testRows);
|
||||||
|
expect(filteredRows.length).toBe(1);
|
||||||
|
filters.col1 = 'match';
|
||||||
|
filteredRows = controller.filterRows(testRows);
|
||||||
|
expect(filteredRows.length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sets rows on scope when rows change', function() {
|
||||||
|
controller.updateRows(testRows);
|
||||||
|
expect(mockScope.displayRows.length).toBe(3);
|
||||||
|
expect(mockScope.displayRows).toEqual(testRows);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('sorting', function() {
|
||||||
|
var sortedRows;
|
||||||
|
|
||||||
|
it('Sorts rows ascending', function() {
|
||||||
|
mockScope.sortColumn = 'col1';
|
||||||
|
mockScope.sortDirection = 'asc';
|
||||||
|
|
||||||
|
sortedRows = controller.sortRows(testRows);
|
||||||
|
expect(sortedRows[0].col1.text).toEqual('row1 col1 match');
|
||||||
|
expect(sortedRows[1].col1.text).toEqual('row2 col1' +
|
||||||
|
' match');
|
||||||
|
expect(sortedRows[2].col1.text).toEqual('row3 col1');
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Sorts rows descending', function() {
|
||||||
|
mockScope.sortColumn = 'col1';
|
||||||
|
mockScope.sortDirection = 'desc';
|
||||||
|
|
||||||
|
sortedRows = controller.sortRows(testRows);
|
||||||
|
expect(sortedRows[0].col1.text).toEqual('row3 col1');
|
||||||
|
expect(sortedRows[1].col1.text).toEqual('row2 col1 match');
|
||||||
|
expect(sortedRows[2].col1.text).toEqual('row1 col1 match');
|
||||||
|
});
|
||||||
|
it('Sorts rows descending based on selected sort column', function() {
|
||||||
|
mockScope.sortColumn = 'col2';
|
||||||
|
mockScope.sortDirection = 'desc';
|
||||||
|
|
||||||
|
sortedRows = controller.sortRows(testRows);
|
||||||
|
expect(sortedRows[0].col2.text).toEqual('ghi');
|
||||||
|
expect(sortedRows[1].col2.text).toEqual('def');
|
||||||
|
expect(sortedRows[2].col2.text).toEqual('abc');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,105 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,xit*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
"../../src/controllers/TableOptionsController"
|
||||||
|
],
|
||||||
|
function (TableOptionsController) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe('The Table Options Controller', function() {
|
||||||
|
var mockDomainObject,
|
||||||
|
mockCapability,
|
||||||
|
controller,
|
||||||
|
mockScope;
|
||||||
|
|
||||||
|
function promise(value) {
|
||||||
|
return {
|
||||||
|
then: function (callback){
|
||||||
|
return promise(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
mockCapability = jasmine.createSpyObj('mutationCapability', [
|
||||||
|
'listen'
|
||||||
|
]);
|
||||||
|
mockDomainObject = jasmine.createSpyObj('domainObject', [
|
||||||
|
'getCapability'
|
||||||
|
]);
|
||||||
|
mockDomainObject.getCapability.andReturn(mockCapability);
|
||||||
|
mockScope = jasmine.createSpyObj('scope', [
|
||||||
|
'$watchCollection'
|
||||||
|
]);
|
||||||
|
mockScope.domainObject = mockDomainObject;
|
||||||
|
|
||||||
|
controller = new TableOptionsController(mockScope);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Registers a listener for mutation events on the object', function() {
|
||||||
|
expect(mockCapability.listen).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Listens for changes to object composition and updates' +
|
||||||
|
' options accordingly', function() {
|
||||||
|
expect(mockScope.$watchCollection).toHaveBeenCalledWith('configuration.table.columns', jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Populates scope with a form definition based on provided' +
|
||||||
|
' column configuration', function() {
|
||||||
|
var mockModel;
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
mockModel = {
|
||||||
|
configuration: {
|
||||||
|
table: {
|
||||||
|
columns: {
|
||||||
|
'column1': true,
|
||||||
|
'column2': true,
|
||||||
|
'column3': false,
|
||||||
|
'column4': true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
controller.populateForm(mockModel);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('creates form on scope', function() {
|
||||||
|
expect(mockScope.columnsForm).toBeDefined();
|
||||||
|
expect(mockScope.columnsForm.sections[0]).toBeDefined();
|
||||||
|
expect(mockScope.columnsForm.sections[0].rows).toBeDefined();
|
||||||
|
expect(mockScope.columnsForm.sections[0].rows.length).toBe(4);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('presents columns as checkboxes', function() {
|
||||||
|
expect(mockScope.columnsForm.sections[0].rows.every(function(row){
|
||||||
|
return row.control === 'checkbox';
|
||||||
|
})).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,222 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,describe,it,expect,beforeEach,waitsFor,jasmine,xit*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[
|
||||||
|
"../../src/controllers/TelemetryTableController"
|
||||||
|
],
|
||||||
|
function (TableController) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe('The Table Controller', function() {
|
||||||
|
var mockScope,
|
||||||
|
mockTelemetryHandler,
|
||||||
|
mockTelemetryHandle,
|
||||||
|
mockTelemetryFormatter,
|
||||||
|
mockDomainObject,
|
||||||
|
mockTable,
|
||||||
|
mockConfiguration,
|
||||||
|
watches,
|
||||||
|
controller;
|
||||||
|
|
||||||
|
function promise(value) {
|
||||||
|
return {
|
||||||
|
then: function (callback){
|
||||||
|
return promise(callback(value));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(function() {
|
||||||
|
watches = {};
|
||||||
|
mockScope = jasmine.createSpyObj('scope', [
|
||||||
|
'$on',
|
||||||
|
'$watch',
|
||||||
|
'$watchCollection'
|
||||||
|
]);
|
||||||
|
|
||||||
|
mockScope.$on.andCallFake(function(expression, callback){
|
||||||
|
watches[expression] = callback;
|
||||||
|
});
|
||||||
|
mockScope.$watch.andCallFake(function(expression, callback){
|
||||||
|
watches[expression] = callback;
|
||||||
|
});
|
||||||
|
mockScope.$watchCollection.andCallFake(function(expression, callback){
|
||||||
|
watches[expression] = callback;
|
||||||
|
});
|
||||||
|
|
||||||
|
mockConfiguration = {
|
||||||
|
'range1': true,
|
||||||
|
'range2': true,
|
||||||
|
'domain1': true
|
||||||
|
};
|
||||||
|
|
||||||
|
mockTable = jasmine.createSpyObj('table',
|
||||||
|
[
|
||||||
|
'buildColumns',
|
||||||
|
'getColumnConfiguration',
|
||||||
|
'getRowValues',
|
||||||
|
'saveColumnConfiguration'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockTable.columns = [];
|
||||||
|
mockTable.getColumnConfiguration.andReturn(mockConfiguration);
|
||||||
|
|
||||||
|
mockDomainObject= jasmine.createSpyObj('domainObject', [
|
||||||
|
'getCapability',
|
||||||
|
'useCapability',
|
||||||
|
'getModel'
|
||||||
|
]);
|
||||||
|
mockDomainObject.getModel.andReturn({});
|
||||||
|
|
||||||
|
mockScope.domainObject = mockDomainObject;
|
||||||
|
|
||||||
|
mockTelemetryHandle = jasmine.createSpyObj('telemetryHandle', [
|
||||||
|
'request',
|
||||||
|
'promiseTelemetryObjects',
|
||||||
|
'getMetadata',
|
||||||
|
'unsubscribe',
|
||||||
|
'makeDatum'
|
||||||
|
]);
|
||||||
|
mockTelemetryHandle.promiseTelemetryObjects.andReturn(promise(undefined));
|
||||||
|
|
||||||
|
mockTelemetryHandler = jasmine.createSpyObj('telemetryHandler', [
|
||||||
|
'handle'
|
||||||
|
]);
|
||||||
|
mockTelemetryHandler.handle.andReturn(mockTelemetryHandle);
|
||||||
|
|
||||||
|
controller = new TableController(mockScope, mockTelemetryHandler, mockTelemetryFormatter);
|
||||||
|
controller.table = mockTable;
|
||||||
|
controller.handle = mockTelemetryHandle;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('subscribes to telemetry handler for telemetry updates', function() {
|
||||||
|
controller.subscribe();
|
||||||
|
expect(mockTelemetryHandler.handle).toHaveBeenCalled();
|
||||||
|
expect(mockTelemetryHandle.request).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Unsubscribes from telemetry when scope is destroyed',function() {
|
||||||
|
controller.handle = mockTelemetryHandle;
|
||||||
|
watches.$destroy();
|
||||||
|
expect(mockTelemetryHandle.unsubscribe).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('the controller makes use of the table', function() {
|
||||||
|
|
||||||
|
it('to create column definitions from telemetry' +
|
||||||
|
' metadata', function() {
|
||||||
|
controller.setup();
|
||||||
|
expect(mockTable.buildColumns).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('to create column configuration, which is written to the' +
|
||||||
|
' object model', function() {
|
||||||
|
var mockModel = {};
|
||||||
|
|
||||||
|
controller.setup();
|
||||||
|
expect(mockTable.getColumnConfiguration).toHaveBeenCalled();
|
||||||
|
expect(mockTable.saveColumnConfiguration).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates the rows on scope when historical telemetry is received', function(){
|
||||||
|
var mockSeries = {
|
||||||
|
getPointCount: function() {
|
||||||
|
return 5;
|
||||||
|
},
|
||||||
|
getDomainValue: function() {
|
||||||
|
return 'Domain Value';
|
||||||
|
},
|
||||||
|
getRangeValue: function() {
|
||||||
|
return 'Range Value';
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mockRow = {'domain': 'Domain Value', 'range': 'Range' +
|
||||||
|
' Value'};
|
||||||
|
|
||||||
|
mockTelemetryHandle.makeDatum.andCallFake(function(){
|
||||||
|
return mockRow;
|
||||||
|
});
|
||||||
|
mockTable.getRowValues.andReturn(mockRow);
|
||||||
|
controller.addHistoricalData(mockDomainObject, mockSeries);
|
||||||
|
|
||||||
|
expect(controller.$scope.rows.length).toBe(5);
|
||||||
|
expect(controller.$scope.rows[0]).toBe(mockRow);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('filters the visible columns based on configuration', function(){
|
||||||
|
controller.filterColumns();
|
||||||
|
expect(controller.$scope.headers.length).toBe(3);
|
||||||
|
expect(controller.$scope.headers[2]).toEqual('domain1');
|
||||||
|
|
||||||
|
mockConfiguration.domain1 = false;
|
||||||
|
controller.filterColumns();
|
||||||
|
expect(controller.$scope.headers.length).toBe(2);
|
||||||
|
expect(controller.$scope.headers[2]).toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('creates event listeners', function(){
|
||||||
|
beforeEach(function() {
|
||||||
|
spyOn(controller,'subscribe');
|
||||||
|
spyOn(controller, 'filterColumns');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers telemetry subscription update when domain' +
|
||||||
|
' object changes', function() {
|
||||||
|
controller.registerChangeListeners();
|
||||||
|
//'watches' object is populated by fake scope watch and
|
||||||
|
// watchCollection functions defined above
|
||||||
|
expect(watches.domainObject).toBeDefined();
|
||||||
|
watches.domainObject(mockDomainObject);
|
||||||
|
expect(controller.subscribe).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers telemetry subscription update when domain' +
|
||||||
|
' object composition changes', function() {
|
||||||
|
controller.registerChangeListeners();
|
||||||
|
expect(watches['domainObject.getModel().composition']).toBeDefined();
|
||||||
|
watches['domainObject.getModel().composition']();
|
||||||
|
expect(controller.subscribe).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers telemetry subscription update when time' +
|
||||||
|
' conductor bounds change', function() {
|
||||||
|
controller.registerChangeListeners();
|
||||||
|
expect(watches['telemetry:display:bounds']).toBeDefined();
|
||||||
|
watches['telemetry:display:bounds']();
|
||||||
|
expect(controller.subscribe).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('triggers refiltering of the columns when configuration' +
|
||||||
|
' changes', function() {
|
||||||
|
controller.setup();
|
||||||
|
expect(watches['domainObject.getModel().configuration.table.columns']).toBeDefined();
|
||||||
|
watches['domainObject.getModel().configuration.table.columns']();
|
||||||
|
expect(controller.filterColumns).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
Loading…
Reference in New Issue
Block a user