mirror of
https://github.com/nasa/openmct.git
synced 2025-06-26 19:12:02 +00:00
Compare commits
4 Commits
5211-tests
...
esm
Author | SHA1 | Date | |
---|---|---|---|
84c473cea8 | |||
b677d3b90e | |||
59a4d05a0b | |||
f663a6a5b1 |
@ -20,61 +20,79 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/EventTelemetryProvider"
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
EventTelemetryProvider
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
"use strict";
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import EventTelemetryProvider from './src/EventTelemetryProvider';
|
||||||
name: "example/eventGenerator",
|
|
||||||
definition: {
|
"use strict";
|
||||||
"name": "Event Message Generator",
|
|
||||||
"description": "For development use. Creates sample event message data that mimics a live data stream.",
|
export default {
|
||||||
"extensions": {
|
name: "example/eventGenerator",
|
||||||
"components": [
|
definition: {
|
||||||
{
|
"name": "Event Message Generator",
|
||||||
"implementation": EventTelemetryProvider,
|
"description": "For development use. Creates sample event message data that mimics a live data stream.",
|
||||||
"type": "provider",
|
"extensions": {
|
||||||
"provides": "telemetryService",
|
"components": [
|
||||||
"depends": [
|
{
|
||||||
"$q",
|
"implementation": EventTelemetryProvider,
|
||||||
"$timeout"
|
"type": "provider",
|
||||||
|
"provides": "telemetryService",
|
||||||
|
"depends": [
|
||||||
|
"$q",
|
||||||
|
"$timeout"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"key": "eventGenerator",
|
||||||
|
"name": "Event Message Generator",
|
||||||
|
"cssClass": "icon-generator-events",
|
||||||
|
"description": "For development use. Creates sample event message data that mimics a live data stream.",
|
||||||
|
"priority": 10,
|
||||||
|
"features": "creation",
|
||||||
|
"model": {
|
||||||
|
"telemetry": {}
|
||||||
|
},
|
||||||
|
"telemetry": {
|
||||||
|
"source": "eventGenerator",
|
||||||
|
"domains": [
|
||||||
|
{
|
||||||
|
"key": "utc",
|
||||||
|
"name": "Timestamp",
|
||||||
|
"format": "utc"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ranges": [
|
||||||
|
{
|
||||||
|
"key": "message",
|
||||||
|
"name": "Message",
|
||||||
|
"format": "string"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
}
|
||||||
"types": [
|
]
|
||||||
{
|
|
||||||
"key": "eventGenerator",
|
|
||||||
"name": "Event Message Generator",
|
|
||||||
"cssClass": "icon-generator-events",
|
|
||||||
"description": "For development use. Creates sample event message data that mimics a live data stream.",
|
|
||||||
"priority": 10,
|
|
||||||
"features": "creation",
|
|
||||||
"model": {
|
|
||||||
"telemetry": {}
|
|
||||||
},
|
|
||||||
"telemetry": {
|
|
||||||
"source": "eventGenerator",
|
|
||||||
"domains": [
|
|
||||||
{
|
|
||||||
"key": "utc",
|
|
||||||
"name": "Timestamp",
|
|
||||||
"format": "utc"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"ranges": [
|
|
||||||
{
|
|
||||||
"key": "message",
|
|
||||||
"name": "Message",
|
|
||||||
"format": "string"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -25,38 +25,62 @@
|
|||||||
* Created by chacskaylo on 06/18/2015.
|
* Created by chacskaylo on 06/18/2015.
|
||||||
* Modified by shale on 06/23/2015.
|
* Modified by shale on 06/23/2015.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
['../data/transcript.json'],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (messages) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var firstObservedTime = Date.now();
|
/**
|
||||||
|
* Module defining EventTelemetry.
|
||||||
|
* Created by chacskaylo on 06/18/2015.
|
||||||
|
* Modified by shale on 06/23/2015.
|
||||||
|
*/
|
||||||
|
import messages from '../data/transcript.json';
|
||||||
|
|
||||||
function EventTelemetry(request, interval) {
|
"use strict";
|
||||||
|
|
||||||
var latestObservedTime = Date.now(),
|
var firstObservedTime = Date.now();
|
||||||
count = Math.floor((latestObservedTime - firstObservedTime) / interval),
|
|
||||||
generatorData = {};
|
|
||||||
|
|
||||||
generatorData.getPointCount = function () {
|
function EventTelemetry(request, interval) {
|
||||||
return count;
|
|
||||||
};
|
|
||||||
|
|
||||||
generatorData.getDomainValue = function (i, domain) {
|
var latestObservedTime = Date.now(),
|
||||||
return i * interval
|
count = Math.floor((latestObservedTime - firstObservedTime) / interval),
|
||||||
+ (domain !== 'delta' ? firstObservedTime : 0);
|
generatorData = {};
|
||||||
};
|
|
||||||
|
|
||||||
generatorData.getRangeValue = function (i, range) {
|
generatorData.getPointCount = function () {
|
||||||
var domainDelta = this.getDomainValue(i) - firstObservedTime,
|
return count;
|
||||||
ind = i % messages.length;
|
};
|
||||||
|
|
||||||
return messages[ind] + " - [" + domainDelta.toString() + "]";
|
generatorData.getDomainValue = function (i, domain) {
|
||||||
};
|
return i * interval
|
||||||
|
+ (domain !== 'delta' ? firstObservedTime : 0);
|
||||||
|
};
|
||||||
|
|
||||||
return generatorData;
|
generatorData.getRangeValue = function (i, range) {
|
||||||
}
|
var domainDelta = this.getDomainValue(i) - firstObservedTime,
|
||||||
|
ind = i % messages.length;
|
||||||
|
|
||||||
return EventTelemetry;
|
return messages[ind] + " - [" + domainDelta.toString() + "]";
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
return generatorData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EventTelemetry;
|
@ -23,96 +23,118 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining EventTelemetryProvider. Created by chacskaylo on 06/18/2015.
|
* Module defining EventTelemetryProvider. Created by chacskaylo on 06/18/2015.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
["./EventTelemetry"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (EventTelemetry) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Module defining EventTelemetryProvider. Created by chacskaylo on 06/18/2015.
|
||||||
* @constructor
|
*/
|
||||||
*/
|
import EventTelemetry from './EventTelemetry';
|
||||||
function EventTelemetryProvider($q, $timeout) {
|
|
||||||
var subscriptions = [],
|
"use strict";
|
||||||
genInterval = 1000,
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function EventTelemetryProvider($q, $timeout) {
|
||||||
|
var subscriptions = [],
|
||||||
|
genInterval = 1000,
|
||||||
|
generating = false;
|
||||||
|
|
||||||
|
//
|
||||||
|
function matchesSource(request) {
|
||||||
|
return request.source === "eventGenerator";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Used internally; this will be repacked by doPackage
|
||||||
|
function generateData(request) {
|
||||||
|
return {
|
||||||
|
key: request.key,
|
||||||
|
telemetry: new EventTelemetry(request, genInterval)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
function doPackage(results) {
|
||||||
|
var packaged = {};
|
||||||
|
results.forEach(function (result) {
|
||||||
|
packaged[result.key] = result.telemetry;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Format as expected (sources -> keys -> telemetry)
|
||||||
|
return { eventGenerator: packaged };
|
||||||
|
}
|
||||||
|
|
||||||
|
function requestTelemetry(requests) {
|
||||||
|
return $timeout(function () {
|
||||||
|
return doPackage(requests.filter(matchesSource).map(generateData));
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSubscriptions(timeout) {
|
||||||
|
subscriptions.forEach(function (subscription) {
|
||||||
|
var requests = subscription.requests;
|
||||||
|
subscription.callback(doPackage(
|
||||||
|
requests.filter(matchesSource).map(generateData)
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startGenerating() {
|
||||||
|
generating = true;
|
||||||
|
$timeout(function () {
|
||||||
|
handleSubscriptions();
|
||||||
|
if (generating && subscriptions.length > 0) {
|
||||||
|
startGenerating();
|
||||||
|
} else {
|
||||||
generating = false;
|
generating = false;
|
||||||
|
|
||||||
//
|
|
||||||
function matchesSource(request) {
|
|
||||||
return request.source === "eventGenerator";
|
|
||||||
}
|
}
|
||||||
|
}, genInterval);
|
||||||
|
}
|
||||||
|
|
||||||
// Used internally; this will be repacked by doPackage
|
function subscribe(callback, requests) {
|
||||||
function generateData(request) {
|
var subscription = {
|
||||||
return {
|
callback: callback,
|
||||||
key: request.key,
|
requests: requests
|
||||||
telemetry: new EventTelemetry(request, genInterval)
|
};
|
||||||
};
|
function unsubscribe() {
|
||||||
}
|
subscriptions = subscriptions.filter(function (s) {
|
||||||
|
return s !== subscription;
|
||||||
//
|
});
|
||||||
function doPackage(results) {
|
|
||||||
var packaged = {};
|
|
||||||
results.forEach(function (result) {
|
|
||||||
packaged[result.key] = result.telemetry;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Format as expected (sources -> keys -> telemetry)
|
|
||||||
return { eventGenerator: packaged };
|
|
||||||
}
|
|
||||||
|
|
||||||
function requestTelemetry(requests) {
|
|
||||||
return $timeout(function () {
|
|
||||||
return doPackage(requests.filter(matchesSource).map(generateData));
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleSubscriptions(timeout) {
|
|
||||||
subscriptions.forEach(function (subscription) {
|
|
||||||
var requests = subscription.requests;
|
|
||||||
subscription.callback(doPackage(
|
|
||||||
requests.filter(matchesSource).map(generateData)
|
|
||||||
));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startGenerating() {
|
|
||||||
generating = true;
|
|
||||||
$timeout(function () {
|
|
||||||
handleSubscriptions();
|
|
||||||
if (generating && subscriptions.length > 0) {
|
|
||||||
startGenerating();
|
|
||||||
} else {
|
|
||||||
generating = false;
|
|
||||||
}
|
|
||||||
}, genInterval);
|
|
||||||
}
|
|
||||||
|
|
||||||
function subscribe(callback, requests) {
|
|
||||||
var subscription = {
|
|
||||||
callback: callback,
|
|
||||||
requests: requests
|
|
||||||
};
|
|
||||||
function unsubscribe() {
|
|
||||||
subscriptions = subscriptions.filter(function (s) {
|
|
||||||
return s !== subscription;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
subscriptions.push(subscription);
|
|
||||||
if (!generating) {
|
|
||||||
startGenerating();
|
|
||||||
}
|
|
||||||
|
|
||||||
return unsubscribe;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
requestTelemetry: requestTelemetry,
|
|
||||||
subscribe: subscribe
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EventTelemetryProvider;
|
subscriptions.push(subscription);
|
||||||
|
if (!generating) {
|
||||||
|
startGenerating();
|
||||||
|
}
|
||||||
|
|
||||||
|
return unsubscribe;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return {
|
||||||
|
requestTelemetry: requestTelemetry,
|
||||||
|
subscribe: subscribe
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EventTelemetryProvider;
|
@ -20,70 +20,90 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([], function () {
|
/*****************************************************************************
|
||||||
'use strict';
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
'use strict';
|
||||||
* An example of using the `exportService`; queries for telemetry
|
|
||||||
* and provides the results as a CSV file.
|
/**
|
||||||
* @param {platform/exporters.ExportService} exportService the
|
* An example of using the `exportService`; queries for telemetry
|
||||||
* service which will handle the CSV export
|
* and provides the results as a CSV file.
|
||||||
* @param {ActionContext} context the action's context
|
* @param {platform/exporters.ExportService} exportService the
|
||||||
* @constructor
|
* service which will handle the CSV export
|
||||||
* @memberof example/export
|
* @param {ActionContext} context the action's context
|
||||||
* @implements {Action}
|
* @constructor
|
||||||
*/
|
* @memberof example/export
|
||||||
function ExportTelemetryAsCSVAction(exportService, context) {
|
* @implements {Action}
|
||||||
this.exportService = exportService;
|
*/
|
||||||
this.context = context;
|
function ExportTelemetryAsCSVAction(exportService, context) {
|
||||||
|
this.exportService = exportService;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExportTelemetryAsCSVAction.prototype.perform = function () {
|
||||||
|
var context = this.context,
|
||||||
|
domainObject = context.domainObject,
|
||||||
|
telemetry = domainObject.getCapability("telemetry"),
|
||||||
|
metadata = telemetry.getMetadata(),
|
||||||
|
domains = metadata.domains,
|
||||||
|
ranges = metadata.ranges,
|
||||||
|
exportService = this.exportService;
|
||||||
|
|
||||||
|
function getName(domainOrRange) {
|
||||||
|
return domainOrRange.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
ExportTelemetryAsCSVAction.prototype.perform = function () {
|
telemetry.requestData({}).then(function (series) {
|
||||||
var context = this.context,
|
var headers = domains.map(getName).concat(ranges.map(getName)),
|
||||||
domainObject = context.domainObject,
|
rows = [],
|
||||||
telemetry = domainObject.getCapability("telemetry"),
|
row,
|
||||||
metadata = telemetry.getMetadata(),
|
i;
|
||||||
domains = metadata.domains,
|
|
||||||
ranges = metadata.ranges,
|
|
||||||
exportService = this.exportService;
|
|
||||||
|
|
||||||
function getName(domainOrRange) {
|
function copyDomainsToRow(telemetryRow, index) {
|
||||||
return domainOrRange.name;
|
domains.forEach(function (domain) {
|
||||||
|
telemetryRow[domain.name] = series.getDomainValue(index, domain.key);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
telemetry.requestData({}).then(function (series) {
|
function copyRangesToRow(telemetryRow, index) {
|
||||||
var headers = domains.map(getName).concat(ranges.map(getName)),
|
ranges.forEach(function (range) {
|
||||||
rows = [],
|
telemetryRow[range.name] = series.getRangeValue(index, range.key);
|
||||||
row,
|
});
|
||||||
i;
|
}
|
||||||
|
|
||||||
function copyDomainsToRow(telemetryRow, index) {
|
for (i = 0; i < series.getPointCount(); i += 1) {
|
||||||
domains.forEach(function (domain) {
|
row = {};
|
||||||
telemetryRow[domain.name] = series.getDomainValue(index, domain.key);
|
copyDomainsToRow(row, i);
|
||||||
});
|
copyRangesToRow(row, i);
|
||||||
}
|
rows.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
function copyRangesToRow(telemetryRow, index) {
|
exportService.exportCSV(rows, { headers: headers });
|
||||||
ranges.forEach(function (range) {
|
});
|
||||||
telemetryRow[range.name] = series.getRangeValue(index, range.key);
|
};
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < series.getPointCount(); i += 1) {
|
ExportTelemetryAsCSVAction.appliesTo = function (context) {
|
||||||
row = {};
|
return context.domainObject
|
||||||
copyDomainsToRow(row, i);
|
&& context.domainObject.hasCapability("telemetry");
|
||||||
copyRangesToRow(row, i);
|
};
|
||||||
rows.push(row);
|
|
||||||
}
|
|
||||||
|
|
||||||
exportService.exportCSV(rows, { headers: headers });
|
export default ExportTelemetryAsCSVAction;
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
ExportTelemetryAsCSVAction.appliesTo = function (context) {
|
|
||||||
return context.domainObject
|
|
||||||
&& context.domainObject.hasCapability("telemetry");
|
|
||||||
};
|
|
||||||
|
|
||||||
return ExportTelemetryAsCSVAction;
|
|
||||||
});
|
|
@ -20,27 +20,47 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
'./ExportTelemetryAsCSVAction'
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (ExportTelemetryAsCSVAction) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import ExportTelemetryAsCSVAction from './ExportTelemetryAsCSVAction';
|
||||||
name: "example/export",
|
|
||||||
definition: {
|
"use strict";
|
||||||
"name": "Example of using CSV Export",
|
|
||||||
"extensions": {
|
export default {
|
||||||
"actions": [
|
name: "example/export",
|
||||||
{
|
definition: {
|
||||||
"key": "example.export",
|
"name": "Example of using CSV Export",
|
||||||
"name": "Export Telemetry as CSV",
|
"extensions": {
|
||||||
"implementation": ExportTelemetryAsCSVAction,
|
"actions": [
|
||||||
"category": "contextual",
|
{
|
||||||
"cssClass": "icon-download",
|
"key": "example.export",
|
||||||
"depends": ["exportService"]
|
"name": "Export Telemetry as CSV",
|
||||||
}
|
"implementation": ExportTelemetryAsCSVAction,
|
||||||
]
|
"category": "contextual",
|
||||||
}
|
"cssClass": "icon-download",
|
||||||
|
"depends": ["exportService"]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,34 +20,52 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/ExampleFormController"
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
ExampleFormController
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
"use strict";
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import ExampleFormController from './src/ExampleFormController';
|
||||||
name: "example/forms",
|
|
||||||
definition: {
|
"use strict";
|
||||||
"name": "Declarative Forms example",
|
|
||||||
"sources": "src",
|
export default {
|
||||||
"extensions": {
|
name: "example/forms",
|
||||||
"controllers": [
|
definition: {
|
||||||
{
|
"name": "Declarative Forms example",
|
||||||
"key": "ExampleFormController",
|
"sources": "src",
|
||||||
"implementation": ExampleFormController,
|
"extensions": {
|
||||||
"depends": [
|
"controllers": [
|
||||||
"$scope"
|
{
|
||||||
]
|
"key": "ExampleFormController",
|
||||||
}
|
"implementation": ExampleFormController,
|
||||||
],
|
"depends": [
|
||||||
"routes": [
|
"$scope"
|
||||||
{
|
]
|
||||||
"templateUrl": "templates/exampleForm.html"
|
}
|
||||||
}
|
],
|
||||||
]
|
"routes": [
|
||||||
}
|
{
|
||||||
|
"templateUrl": "templates/exampleForm.html"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,186 +20,203 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
function ExampleFormController($scope) {
|
"use strict";
|
||||||
$scope.state = {
|
|
||||||
|
|
||||||
};
|
function ExampleFormController($scope) {
|
||||||
|
$scope.state = {
|
||||||
|
|
||||||
$scope.toolbar = {
|
};
|
||||||
name: "An example toolbar.",
|
|
||||||
sections: [
|
$scope.toolbar = {
|
||||||
|
name: "An example toolbar.",
|
||||||
|
sections: [
|
||||||
|
{
|
||||||
|
description: "First section",
|
||||||
|
items: [
|
||||||
{
|
{
|
||||||
description: "First section",
|
name: "X",
|
||||||
items: [
|
description: "X coordinate",
|
||||||
{
|
control: "textfield",
|
||||||
name: "X",
|
pattern: "^\\d+$",
|
||||||
description: "X coordinate",
|
disabled: true,
|
||||||
control: "textfield",
|
size: 2,
|
||||||
pattern: "^\\d+$",
|
key: "x"
|
||||||
disabled: true,
|
|
||||||
size: 2,
|
|
||||||
key: "x"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Y",
|
|
||||||
description: "Y coordinate",
|
|
||||||
control: "textfield",
|
|
||||||
pattern: "^\\d+$",
|
|
||||||
size: 2,
|
|
||||||
key: "y"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "W",
|
|
||||||
description: "Cell width",
|
|
||||||
control: "textfield",
|
|
||||||
pattern: "^\\d+$",
|
|
||||||
size: 2,
|
|
||||||
key: "w"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "H",
|
|
||||||
description: "Cell height",
|
|
||||||
control: "textfield",
|
|
||||||
pattern: "^\\d+$",
|
|
||||||
size: 2,
|
|
||||||
key: "h"
|
|
||||||
}
|
|
||||||
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
description: "Second section",
|
name: "Y",
|
||||||
items: [
|
description: "Y coordinate",
|
||||||
{
|
control: "textfield",
|
||||||
control: "button",
|
pattern: "^\\d+$",
|
||||||
csslass: "icon-save",
|
size: 2,
|
||||||
click: function () {
|
key: "y"
|
||||||
console.log("Save");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
control: "button",
|
|
||||||
csslass: "icon-x",
|
|
||||||
description: "Button B",
|
|
||||||
click: function () {
|
|
||||||
console.log("Cancel");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
control: "button",
|
|
||||||
csslass: "icon-trash",
|
|
||||||
description: "Button C",
|
|
||||||
disabled: true,
|
|
||||||
click: function () {
|
|
||||||
console.log("Delete");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
items: [
|
name: "W",
|
||||||
{
|
description: "Cell width",
|
||||||
control: "color",
|
control: "textfield",
|
||||||
key: "color"
|
pattern: "^\\d+$",
|
||||||
}
|
size: 2,
|
||||||
]
|
key: "w"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "H",
|
||||||
|
description: "Cell height",
|
||||||
|
control: "textfield",
|
||||||
|
pattern: "^\\d+$",
|
||||||
|
size: 2,
|
||||||
|
key: "h"
|
||||||
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
description: "Second section",
|
||||||
|
items: [
|
||||||
|
{
|
||||||
|
control: "button",
|
||||||
|
csslass: "icon-save",
|
||||||
|
click: function () {
|
||||||
|
console.log("Save");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
control: "button",
|
||||||
|
csslass: "icon-x",
|
||||||
|
description: "Button B",
|
||||||
|
click: function () {
|
||||||
|
console.log("Cancel");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
control: "button",
|
||||||
|
csslass: "icon-trash",
|
||||||
|
description: "Button C",
|
||||||
|
disabled: true,
|
||||||
|
click: function () {
|
||||||
|
console.log("Delete");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
},
|
||||||
|
{
|
||||||
$scope.form = {
|
items: [
|
||||||
name: "An example form.",
|
|
||||||
sections: [
|
|
||||||
{
|
{
|
||||||
name: "First section",
|
control: "color",
|
||||||
rows: [
|
key: "color"
|
||||||
{
|
|
||||||
name: "Check me",
|
|
||||||
control: "checkbox",
|
|
||||||
key: "checkMe"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Enter your name",
|
|
||||||
required: true,
|
|
||||||
control: "textfield",
|
|
||||||
key: "yourName"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Enter a number",
|
|
||||||
control: "textfield",
|
|
||||||
pattern: "^\\d+$",
|
|
||||||
key: "aNumber"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Second section",
|
|
||||||
rows: [
|
|
||||||
{
|
|
||||||
name: "Pick a date",
|
|
||||||
required: true,
|
|
||||||
description: "Enter date in form YYYY-DDD",
|
|
||||||
control: "datetime",
|
|
||||||
key: "aDate"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Choose something",
|
|
||||||
control: "select",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
name: "Hats",
|
|
||||||
value: "hats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Bats",
|
|
||||||
value: "bats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Cats",
|
|
||||||
value: "cats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Mats",
|
|
||||||
value: "mats"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
key: "aChoice"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Choose something",
|
|
||||||
control: "select",
|
|
||||||
required: true,
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
name: "Hats",
|
|
||||||
value: "hats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Bats",
|
|
||||||
value: "bats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Cats",
|
|
||||||
value: "cats"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "Mats",
|
|
||||||
value: "mats"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
key: "aRequiredChoice"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
}
|
||||||
}
|
]
|
||||||
|
};
|
||||||
|
|
||||||
return ExampleFormController;
|
$scope.form = {
|
||||||
}
|
name: "An example form.",
|
||||||
);
|
sections: [
|
||||||
|
{
|
||||||
|
name: "First section",
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
name: "Check me",
|
||||||
|
control: "checkbox",
|
||||||
|
key: "checkMe"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Enter your name",
|
||||||
|
required: true,
|
||||||
|
control: "textfield",
|
||||||
|
key: "yourName"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Enter a number",
|
||||||
|
control: "textfield",
|
||||||
|
pattern: "^\\d+$",
|
||||||
|
key: "aNumber"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Second section",
|
||||||
|
rows: [
|
||||||
|
{
|
||||||
|
name: "Pick a date",
|
||||||
|
required: true,
|
||||||
|
description: "Enter date in form YYYY-DDD",
|
||||||
|
control: "datetime",
|
||||||
|
key: "aDate"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Choose something",
|
||||||
|
control: "select",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "Hats",
|
||||||
|
value: "hats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bats",
|
||||||
|
value: "bats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cats",
|
||||||
|
value: "cats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mats",
|
||||||
|
value: "mats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
key: "aChoice"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Choose something",
|
||||||
|
control: "select",
|
||||||
|
required: true,
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
name: "Hats",
|
||||||
|
value: "hats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Bats",
|
||||||
|
value: "bats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Cats",
|
||||||
|
value: "cats"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mats",
|
||||||
|
value: "mats"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
key: "aRequiredChoice"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ExampleFormController;
|
@ -1,142 +1,136 @@
|
|||||||
define([
|
import _ from 'lodash';
|
||||||
'lodash'
|
|
||||||
], function (
|
|
||||||
_
|
|
||||||
) {
|
|
||||||
|
|
||||||
var METADATA_BY_TYPE = {
|
var METADATA_BY_TYPE = {
|
||||||
'generator': {
|
'generator': {
|
||||||
values: [
|
values: [
|
||||||
{
|
{
|
||||||
key: "name",
|
key: "name",
|
||||||
name: "Name",
|
name: "Name",
|
||||||
format: "string"
|
format: "string"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "utc",
|
key: "utc",
|
||||||
name: "Time",
|
name: "Time",
|
||||||
format: "utc",
|
format: "utc",
|
||||||
hints: {
|
hints: {
|
||||||
domain: 1
|
domain: 1
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "yesterday",
|
|
||||||
name: "Yesterday",
|
|
||||||
format: "utc",
|
|
||||||
hints: {
|
|
||||||
domain: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "cos",
|
|
||||||
name: "Cosine",
|
|
||||||
unit: "deg",
|
|
||||||
formatString: '%0.2f',
|
|
||||||
hints: {
|
|
||||||
domain: 3
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// Need to enable "LocalTimeSystem" plugin to make use of this
|
|
||||||
// {
|
|
||||||
// key: "local",
|
|
||||||
// name: "Time",
|
|
||||||
// format: "local-format",
|
|
||||||
// source: "utc",
|
|
||||||
// hints: {
|
|
||||||
// domain: 3
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
key: "sin",
|
|
||||||
name: "Sine",
|
|
||||||
unit: "Hz",
|
|
||||||
formatString: '%0.2f',
|
|
||||||
hints: {
|
|
||||||
range: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "cos",
|
|
||||||
name: "Cosine",
|
|
||||||
unit: "deg",
|
|
||||||
formatString: '%0.2f',
|
|
||||||
hints: {
|
|
||||||
range: 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
'example.state-generator': {
|
key: "yesterday",
|
||||||
values: [
|
name: "Yesterday",
|
||||||
{
|
format: "utc",
|
||||||
key: "name",
|
hints: {
|
||||||
name: "Name",
|
domain: 2
|
||||||
format: "string"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "utc",
|
|
||||||
name: "Time",
|
|
||||||
format: "utc",
|
|
||||||
hints: {
|
|
||||||
domain: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "local",
|
|
||||||
name: "Time",
|
|
||||||
format: "utc",
|
|
||||||
source: "utc",
|
|
||||||
hints: {
|
|
||||||
domain: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "state",
|
|
||||||
source: "value",
|
|
||||||
name: "State",
|
|
||||||
format: "enum",
|
|
||||||
enumerations: [
|
|
||||||
{
|
|
||||||
value: 0,
|
|
||||||
string: "OFF"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
value: 1,
|
|
||||||
string: "ON"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
hints: {
|
|
||||||
range: 1
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "value",
|
|
||||||
name: "Value",
|
|
||||||
hints: {
|
|
||||||
range: 2
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
};
|
key: "cos",
|
||||||
|
name: "Cosine",
|
||||||
function GeneratorMetadataProvider() {
|
unit: "deg",
|
||||||
|
formatString: '%0.2f',
|
||||||
|
hints: {
|
||||||
|
domain: 3
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Need to enable "LocalTimeSystem" plugin to make use of this
|
||||||
|
// {
|
||||||
|
// key: "local",
|
||||||
|
// name: "Time",
|
||||||
|
// format: "local-format",
|
||||||
|
// source: "utc",
|
||||||
|
// hints: {
|
||||||
|
// domain: 3
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
key: "sin",
|
||||||
|
name: "Sine",
|
||||||
|
unit: "Hz",
|
||||||
|
formatString: '%0.2f',
|
||||||
|
hints: {
|
||||||
|
range: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "cos",
|
||||||
|
name: "Cosine",
|
||||||
|
unit: "deg",
|
||||||
|
formatString: '%0.2f',
|
||||||
|
hints: {
|
||||||
|
range: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
'example.state-generator': {
|
||||||
|
values: [
|
||||||
|
{
|
||||||
|
key: "name",
|
||||||
|
name: "Name",
|
||||||
|
format: "string"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "utc",
|
||||||
|
name: "Time",
|
||||||
|
format: "utc",
|
||||||
|
hints: {
|
||||||
|
domain: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "local",
|
||||||
|
name: "Time",
|
||||||
|
format: "utc",
|
||||||
|
source: "utc",
|
||||||
|
hints: {
|
||||||
|
domain: 2
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "state",
|
||||||
|
source: "value",
|
||||||
|
name: "State",
|
||||||
|
format: "enum",
|
||||||
|
enumerations: [
|
||||||
|
{
|
||||||
|
value: 0,
|
||||||
|
string: "OFF"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: 1,
|
||||||
|
string: "ON"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
hints: {
|
||||||
|
range: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "value",
|
||||||
|
name: "Value",
|
||||||
|
hints: {
|
||||||
|
range: 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
GeneratorMetadataProvider.prototype.supportsMetadata = function (domainObject) {
|
function GeneratorMetadataProvider() {
|
||||||
return Object.prototype.hasOwnProperty.call(METADATA_BY_TYPE, domainObject.type);
|
|
||||||
};
|
|
||||||
|
|
||||||
GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) {
|
}
|
||||||
return Object.assign(
|
|
||||||
{},
|
|
||||||
domainObject.telemetry,
|
|
||||||
METADATA_BY_TYPE[domainObject.type]
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return GeneratorMetadataProvider;
|
GeneratorMetadataProvider.prototype.supportsMetadata = function (domainObject) {
|
||||||
|
return Object.prototype.hasOwnProperty.call(METADATA_BY_TYPE, domainObject.type);
|
||||||
|
};
|
||||||
|
|
||||||
});
|
GeneratorMetadataProvider.prototype.getMetadata = function (domainObject) {
|
||||||
|
return Object.assign(
|
||||||
|
{},
|
||||||
|
domainObject.telemetry,
|
||||||
|
METADATA_BY_TYPE[domainObject.type]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default GeneratorMetadataProvider;
|
||||||
|
@ -20,81 +20,98 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
'./WorkerInterface'
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
WorkerInterface
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var REQUEST_DEFAULTS = {
|
import WorkerInterface from './WorkerInterface';
|
||||||
amplitude: 1,
|
|
||||||
period: 10,
|
|
||||||
offset: 0,
|
|
||||||
dataRateInHz: 1,
|
|
||||||
randomness: 0,
|
|
||||||
phase: 0
|
|
||||||
};
|
|
||||||
|
|
||||||
function GeneratorProvider() {
|
var REQUEST_DEFAULTS = {
|
||||||
this.workerInterface = new WorkerInterface();
|
amplitude: 1,
|
||||||
}
|
period: 10,
|
||||||
|
offset: 0,
|
||||||
|
dataRateInHz: 1,
|
||||||
|
randomness: 0,
|
||||||
|
phase: 0
|
||||||
|
};
|
||||||
|
|
||||||
GeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
function GeneratorProvider() {
|
||||||
return domainObject.type === 'generator';
|
this.workerInterface = new WorkerInterface();
|
||||||
};
|
}
|
||||||
|
|
||||||
GeneratorProvider.prototype.supportsRequest =
|
GeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
||||||
GeneratorProvider.prototype.supportsSubscribe =
|
return domainObject.type === 'generator';
|
||||||
GeneratorProvider.prototype.canProvideTelemetry;
|
};
|
||||||
|
|
||||||
GeneratorProvider.prototype.makeWorkerRequest = function (domainObject, request) {
|
GeneratorProvider.prototype.supportsRequest =
|
||||||
var props = [
|
GeneratorProvider.prototype.supportsSubscribe =
|
||||||
'amplitude',
|
GeneratorProvider.prototype.canProvideTelemetry;
|
||||||
'period',
|
|
||||||
'offset',
|
|
||||||
'dataRateInHz',
|
|
||||||
'phase',
|
|
||||||
'randomness'
|
|
||||||
];
|
|
||||||
|
|
||||||
request = request || {};
|
GeneratorProvider.prototype.makeWorkerRequest = function (domainObject, request) {
|
||||||
|
var props = [
|
||||||
|
'amplitude',
|
||||||
|
'period',
|
||||||
|
'offset',
|
||||||
|
'dataRateInHz',
|
||||||
|
'phase',
|
||||||
|
'randomness'
|
||||||
|
];
|
||||||
|
|
||||||
var workerRequest = {};
|
request = request || {};
|
||||||
|
|
||||||
props.forEach(function (prop) {
|
var workerRequest = {};
|
||||||
if (domainObject.telemetry && Object.prototype.hasOwnProperty.call(domainObject.telemetry, prop)) {
|
|
||||||
workerRequest[prop] = domainObject.telemetry[prop];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (request && Object.prototype.hasOwnProperty.call(request, prop)) {
|
props.forEach(function (prop) {
|
||||||
workerRequest[prop] = request[prop];
|
if (domainObject.telemetry && Object.prototype.hasOwnProperty.call(domainObject.telemetry, prop)) {
|
||||||
}
|
workerRequest[prop] = domainObject.telemetry[prop];
|
||||||
|
}
|
||||||
|
|
||||||
if (!Object.prototype.hasOwnProperty.call(workerRequest, prop)) {
|
if (request && Object.prototype.hasOwnProperty.call(request, prop)) {
|
||||||
workerRequest[prop] = REQUEST_DEFAULTS[prop];
|
workerRequest[prop] = request[prop];
|
||||||
}
|
}
|
||||||
|
|
||||||
workerRequest[prop] = Number(workerRequest[prop]);
|
if (!Object.prototype.hasOwnProperty.call(workerRequest, prop)) {
|
||||||
});
|
workerRequest[prop] = REQUEST_DEFAULTS[prop];
|
||||||
|
}
|
||||||
|
|
||||||
workerRequest.name = domainObject.name;
|
workerRequest[prop] = Number(workerRequest[prop]);
|
||||||
|
});
|
||||||
|
|
||||||
return workerRequest;
|
workerRequest.name = domainObject.name;
|
||||||
};
|
|
||||||
|
|
||||||
GeneratorProvider.prototype.request = function (domainObject, request) {
|
return workerRequest;
|
||||||
var workerRequest = this.makeWorkerRequest(domainObject, request);
|
};
|
||||||
workerRequest.start = request.start;
|
|
||||||
workerRequest.end = request.end;
|
|
||||||
|
|
||||||
return this.workerInterface.request(workerRequest);
|
GeneratorProvider.prototype.request = function (domainObject, request) {
|
||||||
};
|
var workerRequest = this.makeWorkerRequest(domainObject, request);
|
||||||
|
workerRequest.start = request.start;
|
||||||
|
workerRequest.end = request.end;
|
||||||
|
|
||||||
GeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
return this.workerInterface.request(workerRequest);
|
||||||
var workerRequest = this.makeWorkerRequest(domainObject, {});
|
};
|
||||||
|
|
||||||
return this.workerInterface.subscribe(workerRequest, callback);
|
GeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||||
};
|
var workerRequest = this.makeWorkerRequest(domainObject, {});
|
||||||
|
|
||||||
return GeneratorProvider;
|
return this.workerInterface.subscribe(workerRequest, callback);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
export default GeneratorProvider;
|
@ -20,155 +20,170 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
], function (
|
var PURPLE = {
|
||||||
|
|
||||||
) {
|
|
||||||
|
|
||||||
var PURPLE = {
|
|
||||||
sin: 2.2,
|
sin: 2.2,
|
||||||
cos: 2.2
|
cos: 2.2
|
||||||
},
|
},
|
||||||
RED = {
|
RED = {
|
||||||
sin: 0.9,
|
sin: 0.9,
|
||||||
cos: 0.9
|
cos: 0.9
|
||||||
|
},
|
||||||
|
ORANGE = {
|
||||||
|
sin: 0.7,
|
||||||
|
cos: 0.7
|
||||||
|
},
|
||||||
|
YELLOW = {
|
||||||
|
sin: 0.5,
|
||||||
|
cos: 0.5
|
||||||
|
},
|
||||||
|
CYAN = {
|
||||||
|
sin: 0.45,
|
||||||
|
cos: 0.45
|
||||||
|
},
|
||||||
|
LIMITS = {
|
||||||
|
rh: {
|
||||||
|
cssClass: "is-limit--upr is-limit--red",
|
||||||
|
low: RED,
|
||||||
|
high: Number.POSITIVE_INFINITY,
|
||||||
|
name: "Red High"
|
||||||
},
|
},
|
||||||
ORANGE = {
|
rl: {
|
||||||
sin: 0.7,
|
cssClass: "is-limit--lwr is-limit--red",
|
||||||
cos: 0.7
|
high: -RED,
|
||||||
|
low: Number.NEGATIVE_INFINITY,
|
||||||
|
name: "Red Low"
|
||||||
},
|
},
|
||||||
YELLOW = {
|
yh: {
|
||||||
sin: 0.5,
|
cssClass: "is-limit--upr is-limit--yellow",
|
||||||
cos: 0.5
|
low: YELLOW,
|
||||||
|
high: RED,
|
||||||
|
name: "Yellow High"
|
||||||
},
|
},
|
||||||
CYAN = {
|
yl: {
|
||||||
sin: 0.45,
|
cssClass: "is-limit--lwr is-limit--yellow",
|
||||||
cos: 0.45
|
low: -RED,
|
||||||
},
|
high: -YELLOW,
|
||||||
LIMITS = {
|
name: "Yellow Low"
|
||||||
rh: {
|
}
|
||||||
cssClass: "is-limit--upr is-limit--red",
|
|
||||||
low: RED,
|
|
||||||
high: Number.POSITIVE_INFINITY,
|
|
||||||
name: "Red High"
|
|
||||||
},
|
|
||||||
rl: {
|
|
||||||
cssClass: "is-limit--lwr is-limit--red",
|
|
||||||
high: -RED,
|
|
||||||
low: Number.NEGATIVE_INFINITY,
|
|
||||||
name: "Red Low"
|
|
||||||
},
|
|
||||||
yh: {
|
|
||||||
cssClass: "is-limit--upr is-limit--yellow",
|
|
||||||
low: YELLOW,
|
|
||||||
high: RED,
|
|
||||||
name: "Yellow High"
|
|
||||||
},
|
|
||||||
yl: {
|
|
||||||
cssClass: "is-limit--lwr is-limit--yellow",
|
|
||||||
low: -RED,
|
|
||||||
high: -YELLOW,
|
|
||||||
name: "Yellow Low"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
function SinewaveLimitProvider() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
SinewaveLimitProvider.prototype.supportsLimits = function (domainObject) {
|
|
||||||
return domainObject.type === 'generator';
|
|
||||||
};
|
};
|
||||||
|
|
||||||
SinewaveLimitProvider.prototype.getLimitEvaluator = function (domainObject) {
|
function SinewaveLimitProvider() {
|
||||||
return {
|
|
||||||
evaluate: function (datum, valueMetadata) {
|
|
||||||
var range = valueMetadata && valueMetadata.key;
|
|
||||||
|
|
||||||
if (datum[range] > RED[range]) {
|
}
|
||||||
return LIMITS.rh;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (datum[range] < -RED[range]) {
|
SinewaveLimitProvider.prototype.supportsLimits = function (domainObject) {
|
||||||
return LIMITS.rl;
|
return domainObject.type === 'generator';
|
||||||
}
|
};
|
||||||
|
|
||||||
if (datum[range] > YELLOW[range]) {
|
SinewaveLimitProvider.prototype.getLimitEvaluator = function (domainObject) {
|
||||||
return LIMITS.yh;
|
return {
|
||||||
}
|
evaluate: function (datum, valueMetadata) {
|
||||||
|
var range = valueMetadata && valueMetadata.key;
|
||||||
|
|
||||||
if (datum[range] < -YELLOW[range]) {
|
if (datum[range] > RED[range]) {
|
||||||
return LIMITS.yl;
|
return LIMITS.rh;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
if (datum[range] < -RED[range]) {
|
||||||
|
return LIMITS.rl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datum[range] > YELLOW[range]) {
|
||||||
|
return LIMITS.yh;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datum[range] < -YELLOW[range]) {
|
||||||
|
return LIMITS.yl;
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
SinewaveLimitProvider.prototype.getLimits = function (domainObject) {
|
SinewaveLimitProvider.prototype.getLimits = function (domainObject) {
|
||||||
|
|
||||||
return {
|
return {
|
||||||
limits: function () {
|
limits: function () {
|
||||||
return Promise.resolve({
|
return Promise.resolve({
|
||||||
WATCH: {
|
WATCH: {
|
||||||
low: {
|
low: {
|
||||||
color: "cyan",
|
color: "cyan",
|
||||||
sin: -CYAN.sin,
|
sin: -CYAN.sin,
|
||||||
cos: -CYAN.cos
|
cos: -CYAN.cos
|
||||||
},
|
|
||||||
high: {
|
|
||||||
color: "cyan",
|
|
||||||
...CYAN
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
WARNING: {
|
high: {
|
||||||
low: {
|
color: "cyan",
|
||||||
color: "yellow",
|
...CYAN
|
||||||
sin: -YELLOW.sin,
|
|
||||||
cos: -YELLOW.cos
|
|
||||||
},
|
|
||||||
high: {
|
|
||||||
color: "yellow",
|
|
||||||
...YELLOW
|
|
||||||
}
|
|
||||||
},
|
|
||||||
DISTRESS: {
|
|
||||||
low: {
|
|
||||||
color: "orange",
|
|
||||||
sin: -ORANGE.sin,
|
|
||||||
cos: -ORANGE.cos
|
|
||||||
},
|
|
||||||
high: {
|
|
||||||
color: "orange",
|
|
||||||
...ORANGE
|
|
||||||
}
|
|
||||||
},
|
|
||||||
CRITICAL: {
|
|
||||||
low: {
|
|
||||||
color: "red",
|
|
||||||
sin: -RED.sin,
|
|
||||||
cos: -RED.cos
|
|
||||||
},
|
|
||||||
high: {
|
|
||||||
color: "red",
|
|
||||||
...RED
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SEVERE: {
|
|
||||||
low: {
|
|
||||||
color: "purple",
|
|
||||||
sin: -PURPLE.sin,
|
|
||||||
cos: -PURPLE.cos
|
|
||||||
},
|
|
||||||
high: {
|
|
||||||
color: "purple",
|
|
||||||
...PURPLE
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
}
|
WARNING: {
|
||||||
};
|
low: {
|
||||||
|
color: "yellow",
|
||||||
|
sin: -YELLOW.sin,
|
||||||
|
cos: -YELLOW.cos
|
||||||
|
},
|
||||||
|
high: {
|
||||||
|
color: "yellow",
|
||||||
|
...YELLOW
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DISTRESS: {
|
||||||
|
low: {
|
||||||
|
color: "orange",
|
||||||
|
sin: -ORANGE.sin,
|
||||||
|
cos: -ORANGE.cos
|
||||||
|
},
|
||||||
|
high: {
|
||||||
|
color: "orange",
|
||||||
|
...ORANGE
|
||||||
|
}
|
||||||
|
},
|
||||||
|
CRITICAL: {
|
||||||
|
low: {
|
||||||
|
color: "red",
|
||||||
|
sin: -RED.sin,
|
||||||
|
cos: -RED.cos
|
||||||
|
},
|
||||||
|
high: {
|
||||||
|
color: "red",
|
||||||
|
...RED
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SEVERE: {
|
||||||
|
low: {
|
||||||
|
color: "purple",
|
||||||
|
sin: -PURPLE.sin,
|
||||||
|
cos: -PURPLE.cos
|
||||||
|
},
|
||||||
|
high: {
|
||||||
|
color: "purple",
|
||||||
|
...PURPLE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
};
|
||||||
|
|
||||||
return SinewaveLimitProvider;
|
export default SinewaveLimitProvider;
|
||||||
});
|
|
@ -20,64 +20,78 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
], function (
|
function StateGeneratorProvider() {
|
||||||
|
|
||||||
) {
|
}
|
||||||
|
|
||||||
function StateGeneratorProvider() {
|
function pointForTimestamp(timestamp, duration, name) {
|
||||||
|
return {
|
||||||
|
name: name,
|
||||||
|
utc: Math.floor(timestamp / duration) * duration,
|
||||||
|
value: Math.floor(timestamp / duration) % 2
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
StateGeneratorProvider.prototype.supportsSubscribe = function (domainObject) {
|
||||||
|
return domainObject.type === 'example.state-generator';
|
||||||
|
};
|
||||||
|
|
||||||
|
StateGeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||||
|
var duration = domainObject.telemetry.duration * 1000;
|
||||||
|
|
||||||
|
var interval = setInterval(function () {
|
||||||
|
var now = Date.now();
|
||||||
|
var datum = pointForTimestamp(now, duration, domainObject.name);
|
||||||
|
datum.value = String(datum.value);
|
||||||
|
callback(datum);
|
||||||
|
}, duration);
|
||||||
|
|
||||||
|
return function () {
|
||||||
|
clearInterval(interval);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
StateGeneratorProvider.prototype.supportsRequest = function (domainObject, options) {
|
||||||
|
return domainObject.type === 'example.state-generator';
|
||||||
|
};
|
||||||
|
|
||||||
|
StateGeneratorProvider.prototype.request = function (domainObject, options) {
|
||||||
|
var start = options.start;
|
||||||
|
var end = Math.min(Date.now(), options.end); // no future values
|
||||||
|
var duration = domainObject.telemetry.duration * 1000;
|
||||||
|
if (options.strategy === 'latest' || options.size === 1) {
|
||||||
|
start = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
function pointForTimestamp(timestamp, duration, name) {
|
var data = [];
|
||||||
return {
|
while (start <= end && data.length < 5000) {
|
||||||
name: name,
|
data.push(pointForTimestamp(start, duration, domainObject.name));
|
||||||
utc: Math.floor(timestamp / duration) * duration,
|
start += duration;
|
||||||
value: Math.floor(timestamp / duration) % 2
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
StateGeneratorProvider.prototype.supportsSubscribe = function (domainObject) {
|
return Promise.resolve(data);
|
||||||
return domainObject.type === 'example.state-generator';
|
};
|
||||||
};
|
|
||||||
|
|
||||||
StateGeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
export default StateGeneratorProvider;
|
||||||
var duration = domainObject.telemetry.duration * 1000;
|
|
||||||
|
|
||||||
var interval = setInterval(function () {
|
|
||||||
var now = Date.now();
|
|
||||||
var datum = pointForTimestamp(now, duration, domainObject.name);
|
|
||||||
datum.value = String(datum.value);
|
|
||||||
callback(datum);
|
|
||||||
}, duration);
|
|
||||||
|
|
||||||
return function () {
|
|
||||||
clearInterval(interval);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
StateGeneratorProvider.prototype.supportsRequest = function (domainObject, options) {
|
|
||||||
return domainObject.type === 'example.state-generator';
|
|
||||||
};
|
|
||||||
|
|
||||||
StateGeneratorProvider.prototype.request = function (domainObject, options) {
|
|
||||||
var start = options.start;
|
|
||||||
var end = Math.min(Date.now(), options.end); // no future values
|
|
||||||
var duration = domainObject.telemetry.duration * 1000;
|
|
||||||
if (options.strategy === 'latest' || options.size === 1) {
|
|
||||||
start = end;
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = [];
|
|
||||||
while (start <= end && data.length < 5000) {
|
|
||||||
data.push(pointForTimestamp(start, duration, domainObject.name));
|
|
||||||
start += duration;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.resolve(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
return StateGeneratorProvider;
|
|
||||||
|
|
||||||
});
|
|
@ -20,89 +20,106 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
'raw-loader!./generatorWorker.js',
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
'uuid'
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
], function (
|
* Administration. All rights reserved.
|
||||||
workerText,
|
*
|
||||||
uuid
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var workerBlob = new Blob(
|
import workerText from 'raw-loader!./generatorWorker.js';
|
||||||
[workerText],
|
|
||||||
{type: 'application/javascript'}
|
|
||||||
);
|
|
||||||
var workerUrl = URL.createObjectURL(workerBlob);
|
|
||||||
|
|
||||||
function WorkerInterface() {
|
import uuid from 'uuid';
|
||||||
this.worker = new Worker(workerUrl);
|
|
||||||
this.worker.onmessage = this.onMessage.bind(this);
|
var workerBlob = new Blob(
|
||||||
this.callbacks = {};
|
[workerText],
|
||||||
|
{type: 'application/javascript'}
|
||||||
|
);
|
||||||
|
var workerUrl = URL.createObjectURL(workerBlob);
|
||||||
|
|
||||||
|
function WorkerInterface() {
|
||||||
|
this.worker = new Worker(workerUrl);
|
||||||
|
this.worker.onmessage = this.onMessage.bind(this);
|
||||||
|
this.callbacks = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkerInterface.prototype.onMessage = function (message) {
|
||||||
|
message = message.data;
|
||||||
|
var callback = this.callbacks[message.id];
|
||||||
|
if (callback) {
|
||||||
|
callback(message);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
WorkerInterface.prototype.dispatch = function (request, data, callback) {
|
||||||
|
var message = {
|
||||||
|
request: request,
|
||||||
|
data: data,
|
||||||
|
id: uuid()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (callback) {
|
||||||
|
this.callbacks[message.id] = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
WorkerInterface.prototype.onMessage = function (message) {
|
this.worker.postMessage(message);
|
||||||
message = message.data;
|
|
||||||
var callback = this.callbacks[message.id];
|
|
||||||
if (callback) {
|
|
||||||
callback(message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
WorkerInterface.prototype.dispatch = function (request, data, callback) {
|
return message.id;
|
||||||
var message = {
|
};
|
||||||
request: request,
|
|
||||||
data: data,
|
|
||||||
id: uuid()
|
|
||||||
};
|
|
||||||
|
|
||||||
if (callback) {
|
WorkerInterface.prototype.request = function (request) {
|
||||||
this.callbacks[message.id] = callback;
|
var deferred = {};
|
||||||
|
var promise = new Promise(function (resolve, reject) {
|
||||||
|
deferred.resolve = resolve;
|
||||||
|
deferred.reject = reject;
|
||||||
|
});
|
||||||
|
var messageId;
|
||||||
|
|
||||||
|
let self = this;
|
||||||
|
function callback(message) {
|
||||||
|
if (message.error) {
|
||||||
|
deferred.reject(message.error);
|
||||||
|
} else {
|
||||||
|
deferred.resolve(message.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.worker.postMessage(message);
|
delete self.callbacks[messageId];
|
||||||
|
|
||||||
return message.id;
|
}
|
||||||
};
|
|
||||||
|
|
||||||
WorkerInterface.prototype.request = function (request) {
|
messageId = this.dispatch('request', request, callback.bind(this));
|
||||||
var deferred = {};
|
|
||||||
var promise = new Promise(function (resolve, reject) {
|
return promise;
|
||||||
deferred.resolve = resolve;
|
};
|
||||||
deferred.reject = reject;
|
|
||||||
|
WorkerInterface.prototype.subscribe = function (request, cb) {
|
||||||
|
function callback(message) {
|
||||||
|
cb(message.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
var messageId = this.dispatch('subscribe', request, callback);
|
||||||
|
|
||||||
|
return function () {
|
||||||
|
this.dispatch('unsubscribe', {
|
||||||
|
id: messageId
|
||||||
});
|
});
|
||||||
var messageId;
|
delete this.callbacks[messageId];
|
||||||
|
}.bind(this);
|
||||||
|
};
|
||||||
|
|
||||||
let self = this;
|
export default WorkerInterface;
|
||||||
function callback(message) {
|
|
||||||
if (message.error) {
|
|
||||||
deferred.reject(message.error);
|
|
||||||
} else {
|
|
||||||
deferred.resolve(message.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete self.callbacks[messageId];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
messageId = this.dispatch('request', request, callback.bind(this));
|
|
||||||
|
|
||||||
return promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
WorkerInterface.prototype.subscribe = function (request, cb) {
|
|
||||||
function callback(message) {
|
|
||||||
cb(message.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
var messageId = this.dispatch('subscribe', request, callback);
|
|
||||||
|
|
||||||
return function () {
|
|
||||||
this.dispatch('unsubscribe', {
|
|
||||||
id: messageId
|
|
||||||
});
|
|
||||||
delete this.callbacks[messageId];
|
|
||||||
}.bind(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
return WorkerInterface;
|
|
||||||
});
|
|
@ -20,6 +20,28 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
(function () {
|
(function () {
|
||||||
|
|
||||||
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
var FIFTEEN_MINUTES = 15 * 60 * 1000;
|
||||||
@ -181,4 +203,4 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}());
|
}());
|
@ -20,135 +20,149 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./GeneratorProvider",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./SinewaveLimitProvider",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"./StateGeneratorProvider",
|
* Administration. All rights reserved.
|
||||||
"./GeneratorMetadataProvider"
|
*
|
||||||
], function (
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
GeneratorProvider,
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
SinewaveLimitProvider,
|
* You may obtain a copy of the License at
|
||||||
StateGeneratorProvider,
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
GeneratorMetadataProvider
|
*
|
||||||
) {
|
* 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return function (openmct) {
|
import GeneratorProvider from './GeneratorProvider';
|
||||||
|
|
||||||
openmct.types.addType("example.state-generator", {
|
import SinewaveLimitProvider from './SinewaveLimitProvider';
|
||||||
name: "State Generator",
|
import StateGeneratorProvider from './StateGeneratorProvider';
|
||||||
description: "For development use. Generates test enumerated telemetry by cycling through a given set of states",
|
import GeneratorMetadataProvider from './GeneratorMetadataProvider';
|
||||||
cssClass: "icon-generator-telemetry",
|
|
||||||
creatable: true,
|
export default function (openmct) {
|
||||||
form: [
|
|
||||||
{
|
openmct.types.addType("example.state-generator", {
|
||||||
name: "State Duration (seconds)",
|
name: "State Generator",
|
||||||
control: "numberfield",
|
description: "For development use. Generates test enumerated telemetry by cycling through a given set of states",
|
||||||
cssClass: "l-input-sm l-numeric",
|
cssClass: "icon-generator-telemetry",
|
||||||
key: "duration",
|
creatable: true,
|
||||||
required: true,
|
form: [
|
||||||
property: [
|
{
|
||||||
"telemetry",
|
name: "State Duration (seconds)",
|
||||||
"duration"
|
control: "numberfield",
|
||||||
]
|
cssClass: "l-input-sm l-numeric",
|
||||||
}
|
key: "duration",
|
||||||
],
|
required: true,
|
||||||
initialize: function (object) {
|
property: [
|
||||||
object.telemetry = {
|
"telemetry",
|
||||||
duration: 5
|
"duration"
|
||||||
};
|
]
|
||||||
}
|
}
|
||||||
});
|
],
|
||||||
|
initialize: function (object) {
|
||||||
|
object.telemetry = {
|
||||||
|
duration: 5
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
openmct.telemetry.addProvider(new StateGeneratorProvider());
|
openmct.telemetry.addProvider(new StateGeneratorProvider());
|
||||||
|
|
||||||
openmct.types.addType("generator", {
|
openmct.types.addType("generator", {
|
||||||
name: "Sine Wave Generator",
|
name: "Sine Wave Generator",
|
||||||
description: "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
|
description: "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
|
||||||
cssClass: "icon-generator-telemetry",
|
cssClass: "icon-generator-telemetry",
|
||||||
creatable: true,
|
creatable: true,
|
||||||
form: [
|
form: [
|
||||||
{
|
{
|
||||||
name: "Period",
|
name: "Period",
|
||||||
control: "numberfield",
|
control: "numberfield",
|
||||||
cssClass: "l-input-sm l-numeric",
|
cssClass: "l-input-sm l-numeric",
|
||||||
key: "period",
|
key: "period",
|
||||||
required: true,
|
required: true,
|
||||||
property: [
|
property: [
|
||||||
"telemetry",
|
"telemetry",
|
||||||
"period"
|
"period"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Amplitude",
|
name: "Amplitude",
|
||||||
control: "numberfield",
|
control: "numberfield",
|
||||||
cssClass: "l-input-sm l-numeric",
|
cssClass: "l-input-sm l-numeric",
|
||||||
key: "amplitude",
|
key: "amplitude",
|
||||||
required: true,
|
required: true,
|
||||||
property: [
|
property: [
|
||||||
"telemetry",
|
"telemetry",
|
||||||
"amplitude"
|
"amplitude"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Offset",
|
name: "Offset",
|
||||||
control: "numberfield",
|
control: "numberfield",
|
||||||
cssClass: "l-input-sm l-numeric",
|
cssClass: "l-input-sm l-numeric",
|
||||||
key: "offset",
|
key: "offset",
|
||||||
required: true,
|
required: true,
|
||||||
property: [
|
property: [
|
||||||
"telemetry",
|
"telemetry",
|
||||||
"offset"
|
"offset"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Data Rate (hz)",
|
name: "Data Rate (hz)",
|
||||||
control: "numberfield",
|
control: "numberfield",
|
||||||
cssClass: "l-input-sm l-numeric",
|
cssClass: "l-input-sm l-numeric",
|
||||||
key: "dataRateInHz",
|
key: "dataRateInHz",
|
||||||
required: true,
|
required: true,
|
||||||
property: [
|
property: [
|
||||||
"telemetry",
|
"telemetry",
|
||||||
"dataRateInHz"
|
"dataRateInHz"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Phase (radians)",
|
name: "Phase (radians)",
|
||||||
control: "numberfield",
|
control: "numberfield",
|
||||||
cssClass: "l-input-sm l-numeric",
|
cssClass: "l-input-sm l-numeric",
|
||||||
key: "phase",
|
key: "phase",
|
||||||
required: true,
|
required: true,
|
||||||
property: [
|
property: [
|
||||||
"telemetry",
|
"telemetry",
|
||||||
"phase"
|
"phase"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Randomness",
|
name: "Randomness",
|
||||||
control: "numberfield",
|
control: "numberfield",
|
||||||
cssClass: "l-input-sm l-numeric",
|
cssClass: "l-input-sm l-numeric",
|
||||||
key: "randomness",
|
key: "randomness",
|
||||||
required: true,
|
required: true,
|
||||||
property: [
|
property: [
|
||||||
"telemetry",
|
"telemetry",
|
||||||
"randomness"
|
"randomness"
|
||||||
]
|
]
|
||||||
}
|
|
||||||
],
|
|
||||||
initialize: function (object) {
|
|
||||||
object.telemetry = {
|
|
||||||
period: 10,
|
|
||||||
amplitude: 1,
|
|
||||||
offset: 0,
|
|
||||||
dataRateInHz: 1,
|
|
||||||
phase: 0,
|
|
||||||
randomness: 0
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
});
|
],
|
||||||
|
initialize: function (object) {
|
||||||
|
object.telemetry = {
|
||||||
|
period: 10,
|
||||||
|
amplitude: 1,
|
||||||
|
offset: 0,
|
||||||
|
dataRateInHz: 1,
|
||||||
|
phase: 0,
|
||||||
|
randomness: 0
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
openmct.telemetry.addProvider(new GeneratorProvider());
|
openmct.telemetry.addProvider(new GeneratorProvider());
|
||||||
openmct.telemetry.addProvider(new GeneratorMetadataProvider());
|
openmct.telemetry.addProvider(new GeneratorMetadataProvider());
|
||||||
openmct.telemetry.addProvider(new SinewaveLimitProvider());
|
openmct.telemetry.addProvider(new SinewaveLimitProvider());
|
||||||
};
|
};
|
||||||
|
|
||||||
});
|
|
@ -20,29 +20,47 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/ExampleIdentityService"
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
ExampleIdentityService
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
"use strict";
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import ExampleIdentityService from './src/ExampleIdentityService';
|
||||||
name: "example/identity",
|
|
||||||
definition: {
|
"use strict";
|
||||||
"extensions": {
|
|
||||||
"components": [
|
export default {
|
||||||
{
|
name: "example/identity",
|
||||||
"implementation": ExampleIdentityService,
|
definition: {
|
||||||
"provides": "identityService",
|
"extensions": {
|
||||||
"type": "provider",
|
"components": [
|
||||||
"depends": [
|
{
|
||||||
"dialogService",
|
"implementation": ExampleIdentityService,
|
||||||
"$q"
|
"provides": "identityService",
|
||||||
]
|
"type": "provider",
|
||||||
}
|
"depends": [
|
||||||
]
|
"dialogService",
|
||||||
}
|
"$q"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,75 +20,71 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
"use strict";
|
||||||
function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var DEFAULT_IDENTITY = {
|
var DEFAULT_IDENTITY = {
|
||||||
key: "user",
|
key: "user",
|
||||||
name: "Example User"
|
name: "Example User"
|
||||||
},
|
},
|
||||||
DIALOG_STRUCTURE = {
|
DIALOG_STRUCTURE = {
|
||||||
name: "Identify Yourself",
|
name: "Identify Yourself",
|
||||||
sections: [{
|
sections: [{
|
||||||
rows: [
|
rows: [
|
||||||
{
|
{
|
||||||
name: "User ID",
|
name: "User ID",
|
||||||
control: "textfield",
|
control: "textfield",
|
||||||
key: "key",
|
key: "key",
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "Human name",
|
name: "Human name",
|
||||||
control: "textfield",
|
control: "textfield",
|
||||||
key: "name",
|
key: "name",
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Example implementation of an identity service. This prompts the
|
* Example implementation of an identity service. This prompts the
|
||||||
* user to enter a name and user ID; in a more realistic
|
* user to enter a name and user ID; in a more realistic
|
||||||
* implementation, this would be read from a server, possibly
|
* implementation, this would be read from a server, possibly
|
||||||
* prompting for a user name and password (or similar) as
|
* prompting for a user name and password (or similar) as
|
||||||
* appropriate.
|
* appropriate.
|
||||||
*
|
*
|
||||||
* @implements {IdentityService}
|
* @implements {IdentityService}
|
||||||
* @memberof platform/identity
|
* @memberof platform/identity
|
||||||
*/
|
*/
|
||||||
function ExampleIdentityProvider(dialogService, $q) {
|
function ExampleIdentityProvider(dialogService, $q) {
|
||||||
this.dialogService = dialogService;
|
this.dialogService = dialogService;
|
||||||
this.$q = $q;
|
this.$q = $q;
|
||||||
|
|
||||||
this.returnUser = this.returnUser.bind(this);
|
this.returnUser = this.returnUser.bind(this);
|
||||||
this.returnUndefined = this.returnUndefined.bind(this);
|
this.returnUndefined = this.returnUndefined.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExampleIdentityProvider.prototype.getUser = function () {
|
ExampleIdentityProvider.prototype.getUser = function () {
|
||||||
if (this.user) {
|
if (this.user) {
|
||||||
return this.$q.when(this.user);
|
return this.$q.when(this.user);
|
||||||
} else {
|
} else {
|
||||||
return this.dialogService.getUserInput(DIALOG_STRUCTURE, DEFAULT_IDENTITY)
|
return this.dialogService.getUserInput(DIALOG_STRUCTURE, DEFAULT_IDENTITY)
|
||||||
.then(this.returnUser, this.returnUndefined);
|
.then(this.returnUser, this.returnUndefined);
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ExampleIdentityProvider.prototype.returnUser = function (user) {
|
|
||||||
return this.user = user;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ExampleIdentityProvider.prototype.returnUndefined = function () {
|
|
||||||
return undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
return ExampleIdentityProvider;
|
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ExampleIdentityProvider.prototype.returnUser = function (user) {
|
||||||
|
return this.user = user;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
ExampleIdentityProvider.prototype.returnUndefined = function () {
|
||||||
|
return undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ExampleIdentityProvider;
|
@ -20,6 +20,28 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
const DEFAULT_IMAGE_SAMPLES = [
|
const DEFAULT_IMAGE_SAMPLES = [
|
||||||
"https://www.hq.nasa.gov/alsj/a16/AS16-117-18731.jpg",
|
"https://www.hq.nasa.gov/alsj/a16/AS16-117-18731.jpg",
|
||||||
"https://www.hq.nasa.gov/alsj/a16/AS16-117-18732.jpg",
|
"https://www.hq.nasa.gov/alsj/a16/AS16-117-18732.jpg",
|
||||||
@ -235,4 +257,4 @@ function pointForTimestamp(timestamp, name, imageSamples, delay) {
|
|||||||
heading: getCompassValues(0, 360),
|
heading: getCompassValues(0, 360),
|
||||||
imageDownloadName
|
imageDownloadName
|
||||||
};
|
};
|
||||||
}
|
}
|
@ -20,22 +20,42 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([], function () {
|
/*****************************************************************************
|
||||||
"use strict";
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
"use strict";
|
||||||
name: "example/mobile",
|
|
||||||
definition: {
|
export default {
|
||||||
"name": "Mobile",
|
name: "example/mobile",
|
||||||
"description": "Allows elements with pertinence to mobile usage and development",
|
definition: {
|
||||||
"extensions": {
|
"name": "Mobile",
|
||||||
"stylesheets": [
|
"description": "Allows elements with pertinence to mobile usage and development",
|
||||||
{
|
"extensions": {
|
||||||
"stylesheetUrl": "css/mobile-example.css",
|
"stylesheets": [
|
||||||
"priority": "mandatory"
|
{
|
||||||
}
|
"stylesheetUrl": "css/mobile-example.css",
|
||||||
]
|
"priority": "mandatory"
|
||||||
}
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,96 +20,111 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/RemsTelemetryServerAdapter",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/RemsTelemetryModelProvider",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"./src/RemsTelemetryProvider"
|
* Administration. All rights reserved.
|
||||||
], function (
|
*
|
||||||
RemsTelemetryServerAdapter,
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
RemsTelemetryModelProvider,
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
RemsTelemetryProvider
|
* You may obtain a copy of the License at
|
||||||
) {
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
"use strict";
|
*
|
||||||
|
* 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import RemsTelemetryServerAdapter from './src/RemsTelemetryServerAdapter';
|
||||||
name: "example/msl",
|
|
||||||
definition: {
|
import RemsTelemetryModelProvider from './src/RemsTelemetryModelProvider';
|
||||||
"name": "Mars Science Laboratory Data Adapter",
|
import RemsTelemetryProvider from './src/RemsTelemetryProvider';
|
||||||
"extensions": {
|
"use strict";
|
||||||
"types": [
|
|
||||||
{
|
export default {
|
||||||
|
name: "example/msl",
|
||||||
|
definition: {
|
||||||
|
"name": "Mars Science Laboratory Data Adapter",
|
||||||
|
"extensions": {
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"name": "Mars Science Laboratory",
|
||||||
|
"key": "msl.curiosity",
|
||||||
|
"cssClass": "icon-object"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Instrument",
|
||||||
|
"key": "msl.instrument",
|
||||||
|
"cssClass": "icon-object",
|
||||||
|
"model": {"composition": []}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Measurement",
|
||||||
|
"key": "msl.measurement",
|
||||||
|
"cssClass": "icon-telemetry",
|
||||||
|
"model": {"telemetry": {}},
|
||||||
|
"telemetry": {
|
||||||
|
"source": "rems.source",
|
||||||
|
"domains": [
|
||||||
|
{
|
||||||
|
"name": "Time",
|
||||||
|
"key": "utc",
|
||||||
|
"format": "utc"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"constants": [
|
||||||
|
{
|
||||||
|
"key": "REMS_WS_URL",
|
||||||
|
"value": "/proxyUrl?url=http://cab.inta-csic.es/rems/wp-content/plugins/marsweather-widget/api.php"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"roots": [
|
||||||
|
{
|
||||||
|
"id": "msl:curiosity"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"models": [
|
||||||
|
{
|
||||||
|
"id": "msl:curiosity",
|
||||||
|
"priority": "preferred",
|
||||||
|
"model": {
|
||||||
|
"type": "msl.curiosity",
|
||||||
"name": "Mars Science Laboratory",
|
"name": "Mars Science Laboratory",
|
||||||
"key": "msl.curiosity",
|
"composition": ["msl_tlm:rems"]
|
||||||
"cssClass": "icon-object"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Instrument",
|
|
||||||
"key": "msl.instrument",
|
|
||||||
"cssClass": "icon-object",
|
|
||||||
"model": {"composition": []}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Measurement",
|
|
||||||
"key": "msl.measurement",
|
|
||||||
"cssClass": "icon-telemetry",
|
|
||||||
"model": {"telemetry": {}},
|
|
||||||
"telemetry": {
|
|
||||||
"source": "rems.source",
|
|
||||||
"domains": [
|
|
||||||
{
|
|
||||||
"name": "Time",
|
|
||||||
"key": "utc",
|
|
||||||
"format": "utc"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
}
|
||||||
"constants": [
|
],
|
||||||
{
|
"services": [
|
||||||
"key": "REMS_WS_URL",
|
{
|
||||||
"value": "/proxyUrl?url=http://cab.inta-csic.es/rems/wp-content/plugins/marsweather-widget/api.php"
|
"key": "rems.adapter",
|
||||||
}
|
"implementation": RemsTelemetryServerAdapter,
|
||||||
],
|
"depends": ["$http", "$log", "REMS_WS_URL"]
|
||||||
"roots": [
|
}
|
||||||
{
|
],
|
||||||
"id": "msl:curiosity"
|
"components": [
|
||||||
}
|
{
|
||||||
],
|
"provides": "modelService",
|
||||||
"models": [
|
"type": "provider",
|
||||||
{
|
"implementation": RemsTelemetryModelProvider,
|
||||||
"id": "msl:curiosity",
|
"depends": ["rems.adapter"]
|
||||||
"priority": "preferred",
|
},
|
||||||
"model": {
|
{
|
||||||
"type": "msl.curiosity",
|
"provides": "telemetryService",
|
||||||
"name": "Mars Science Laboratory",
|
"type": "provider",
|
||||||
"composition": ["msl_tlm:rems"]
|
"implementation": RemsTelemetryProvider,
|
||||||
}
|
"depends": ["rems.adapter", "$q"]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"key": "rems.adapter",
|
|
||||||
"implementation": RemsTelemetryServerAdapter,
|
|
||||||
"depends": ["$http", "$log", "REMS_WS_URL"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"provides": "modelService",
|
|
||||||
"type": "provider",
|
|
||||||
"implementation": RemsTelemetryModelProvider,
|
|
||||||
"depends": ["rems.adapter"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"provides": "telemetryService",
|
|
||||||
"type": "provider",
|
|
||||||
"implementation": RemsTelemetryProvider,
|
|
||||||
"depends": ["rems.adapter", "$q"]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
||||||
|
|
@ -20,59 +20,45 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
export default {
|
||||||
[],
|
"name": "Mars Science Laboratory",
|
||||||
/**
|
"identifier": "msl",
|
||||||
* A data dictionary describes the telemetry available from a data
|
"instruments": [
|
||||||
* source and its data types. The data dictionary will be parsed by a custom
|
{
|
||||||
* server provider for this data source (in this case
|
"name": "rems",
|
||||||
* {@link RemsTelemetryServerAdapter}).
|
"identifier": "rems",
|
||||||
*
|
"measurements": [
|
||||||
* Typically a data dictionary would be made available alongside the
|
|
||||||
* telemetry data source itself.
|
|
||||||
*/
|
|
||||||
function () {
|
|
||||||
return {
|
|
||||||
"name": "Mars Science Laboratory",
|
|
||||||
"identifier": "msl",
|
|
||||||
"instruments": [
|
|
||||||
{
|
{
|
||||||
"name": "rems",
|
"name": "Min. Air Temperature",
|
||||||
"identifier": "rems",
|
"identifier": "min_temp",
|
||||||
"measurements": [
|
"units": "Degrees (C)",
|
||||||
{
|
"type": "float"
|
||||||
"name": "Min. Air Temperature",
|
},
|
||||||
"identifier": "min_temp",
|
{
|
||||||
"units": "Degrees (C)",
|
"name": "Max. Air Temperature",
|
||||||
"type": "float"
|
"identifier": "max_temp",
|
||||||
},
|
"units": "Degrees (C)",
|
||||||
{
|
"type": "float"
|
||||||
"name": "Max. Air Temperature",
|
},
|
||||||
"identifier": "max_temp",
|
{
|
||||||
"units": "Degrees (C)",
|
"name": "Atmospheric Pressure",
|
||||||
"type": "float"
|
"identifier": "pressure",
|
||||||
},
|
"units": "Millibars",
|
||||||
{
|
"type": "float"
|
||||||
"name": "Atmospheric Pressure",
|
},
|
||||||
"identifier": "pressure",
|
{
|
||||||
"units": "Millibars",
|
"name": "Min. Ground Temperature",
|
||||||
"type": "float"
|
"identifier": "min_gts_temp",
|
||||||
},
|
"units": "Degrees (C)",
|
||||||
{
|
"type": "float"
|
||||||
"name": "Min. Ground Temperature",
|
},
|
||||||
"identifier": "min_gts_temp",
|
{
|
||||||
"units": "Degrees (C)",
|
"name": "Max. Ground Temperature",
|
||||||
"type": "float"
|
"identifier": "max_gts_temp",
|
||||||
},
|
"units": "Degrees (C)",
|
||||||
{
|
"type": "float"
|
||||||
"name": "Max. Ground Temperature",
|
|
||||||
"identifier": "max_gts_temp",
|
|
||||||
"units": "Degrees (C)",
|
|
||||||
"type": "float"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
}
|
||||||
}
|
]
|
||||||
);
|
};
|
@ -20,77 +20,73 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
"use strict";
|
||||||
function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
var PREFIX = "msl_tlm:",
|
var PREFIX = "msl_tlm:",
|
||||||
FORMAT_MAPPINGS = {
|
FORMAT_MAPPINGS = {
|
||||||
float: "number",
|
float: "number",
|
||||||
integer: "number",
|
integer: "number",
|
||||||
string: "string"
|
string: "string"
|
||||||
};
|
};
|
||||||
|
|
||||||
function RemsTelemetryModelProvider(adapter) {
|
function RemsTelemetryModelProvider(adapter) {
|
||||||
|
|
||||||
function isRelevant(id) {
|
function isRelevant(id) {
|
||||||
return id.indexOf(PREFIX) === 0;
|
return id.indexOf(PREFIX) === 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeId(element) {
|
function makeId(element) {
|
||||||
return PREFIX + element.identifier;
|
return PREFIX + element.identifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildTaxonomy(dictionary) {
|
function buildTaxonomy(dictionary) {
|
||||||
var models = {};
|
var models = {};
|
||||||
|
|
||||||
function addMeasurement(measurement, parent) {
|
function addMeasurement(measurement, parent) {
|
||||||
var format = FORMAT_MAPPINGS[measurement.type];
|
var format = FORMAT_MAPPINGS[measurement.type];
|
||||||
models[makeId(measurement)] = {
|
models[makeId(measurement)] = {
|
||||||
type: "msl.measurement",
|
type: "msl.measurement",
|
||||||
name: measurement.name,
|
name: measurement.name,
|
||||||
location: parent,
|
location: parent,
|
||||||
telemetry: {
|
telemetry: {
|
||||||
key: measurement.identifier,
|
key: measurement.identifier,
|
||||||
ranges: [{
|
ranges: [{
|
||||||
key: "value",
|
key: "value",
|
||||||
name: measurement.units,
|
name: measurement.units,
|
||||||
units: measurement.units,
|
units: measurement.units,
|
||||||
format: format
|
format: format
|
||||||
}]
|
}]
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function addInstrument(subsystem, spacecraftId) {
|
|
||||||
var measurements = (subsystem.measurements || []),
|
|
||||||
instrumentId = makeId(subsystem);
|
|
||||||
|
|
||||||
models[instrumentId] = {
|
|
||||||
type: "msl.instrument",
|
|
||||||
name: subsystem.name,
|
|
||||||
location: spacecraftId,
|
|
||||||
composition: measurements.map(makeId)
|
|
||||||
};
|
|
||||||
measurements.forEach(function (measurement) {
|
|
||||||
addMeasurement(measurement, instrumentId);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
(dictionary.instruments || []).forEach(function (instrument) {
|
|
||||||
addInstrument(instrument, "msl:curiosity");
|
|
||||||
});
|
|
||||||
|
|
||||||
return models;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
getModels: function (ids) {
|
|
||||||
return ids.some(isRelevant) ? buildTaxonomy(adapter.dictionary) : {};
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return RemsTelemetryModelProvider;
|
function addInstrument(subsystem, spacecraftId) {
|
||||||
|
var measurements = (subsystem.measurements || []),
|
||||||
|
instrumentId = makeId(subsystem);
|
||||||
|
|
||||||
|
models[instrumentId] = {
|
||||||
|
type: "msl.instrument",
|
||||||
|
name: subsystem.name,
|
||||||
|
location: spacecraftId,
|
||||||
|
composition: measurements.map(makeId)
|
||||||
|
};
|
||||||
|
measurements.forEach(function (measurement) {
|
||||||
|
addMeasurement(measurement, instrumentId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
(dictionary.instruments || []).forEach(function (instrument) {
|
||||||
|
addInstrument(instrument, "msl:curiosity");
|
||||||
|
});
|
||||||
|
|
||||||
|
return models;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return {
|
||||||
|
getModels: function (ids) {
|
||||||
|
return ids.some(isRelevant) ? buildTaxonomy(adapter.dictionary) : {};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default RemsTelemetryModelProvider;
|
@ -19,65 +19,83 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
define (
|
/*****************************************************************************
|
||||||
['./RemsTelemetrySeries'],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (RemsTelemetrySeries) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
import RemsTelemetrySeries from './RemsTelemetrySeries';
|
||||||
|
|
||||||
var SOURCE = "rems.source";
|
"use strict";
|
||||||
|
|
||||||
function RemsTelemetryProvider(adapter, $q) {
|
var SOURCE = "rems.source";
|
||||||
this.adapter = adapter;
|
|
||||||
this.$q = $q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
function RemsTelemetryProvider(adapter, $q) {
|
||||||
* Retrieve telemetry from this telemetry source.
|
this.adapter = adapter;
|
||||||
* @memberOf example/msl
|
this.$q = $q;
|
||||||
* @param {Array<TelemetryRequest>} requests An array of all request
|
}
|
||||||
* objects (which needs to be filtered to only those relevant to this
|
|
||||||
* source)
|
|
||||||
* @returns {Promise} A {@link Promise} resolved with a {@link RemsTelemetrySeries}
|
|
||||||
* object that wraps the telemetry returned from the telemetry source.
|
|
||||||
*/
|
|
||||||
RemsTelemetryProvider.prototype.requestTelemetry = function (requests) {
|
|
||||||
var packaged = {},
|
|
||||||
relevantReqs,
|
|
||||||
adapter = this.adapter;
|
|
||||||
|
|
||||||
function matchesSource(request) {
|
/**
|
||||||
return (request.source === SOURCE);
|
* Retrieve telemetry from this telemetry source.
|
||||||
}
|
* @memberOf example/msl
|
||||||
|
* @param {Array<TelemetryRequest>} requests An array of all request
|
||||||
|
* objects (which needs to be filtered to only those relevant to this
|
||||||
|
* source)
|
||||||
|
* @returns {Promise} A {@link Promise} resolved with a {@link RemsTelemetrySeries}
|
||||||
|
* object that wraps the telemetry returned from the telemetry source.
|
||||||
|
*/
|
||||||
|
RemsTelemetryProvider.prototype.requestTelemetry = function (requests) {
|
||||||
|
var packaged = {},
|
||||||
|
relevantReqs,
|
||||||
|
adapter = this.adapter;
|
||||||
|
|
||||||
function addToPackage(history) {
|
function matchesSource(request) {
|
||||||
packaged[SOURCE][history.id] =
|
return (request.source === SOURCE);
|
||||||
new RemsTelemetrySeries(history.values);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleRequest(request) {
|
|
||||||
return adapter.history(request).then(addToPackage);
|
|
||||||
}
|
|
||||||
|
|
||||||
relevantReqs = requests.filter(matchesSource);
|
|
||||||
packaged[SOURCE] = {};
|
|
||||||
|
|
||||||
return this.$q.all(relevantReqs.map(handleRequest))
|
|
||||||
.then(function () {
|
|
||||||
return packaged;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This data source does not support real-time subscriptions
|
|
||||||
*/
|
|
||||||
RemsTelemetryProvider.prototype.subscribe = function (callback, requests) {
|
|
||||||
return function () {};
|
|
||||||
};
|
|
||||||
|
|
||||||
RemsTelemetryProvider.prototype.unsubscribe = function (callback, requests) {
|
|
||||||
return function () {};
|
|
||||||
};
|
|
||||||
|
|
||||||
return RemsTelemetryProvider;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function addToPackage(history) {
|
||||||
|
packaged[SOURCE][history.id] =
|
||||||
|
new RemsTelemetrySeries(history.values);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleRequest(request) {
|
||||||
|
return adapter.history(request).then(addToPackage);
|
||||||
|
}
|
||||||
|
|
||||||
|
relevantReqs = requests.filter(matchesSource);
|
||||||
|
packaged[SOURCE] = {};
|
||||||
|
|
||||||
|
return this.$q.all(relevantReqs.map(handleRequest))
|
||||||
|
.then(function () {
|
||||||
|
return packaged;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This data source does not support real-time subscriptions
|
||||||
|
*/
|
||||||
|
RemsTelemetryProvider.prototype.subscribe = function (callback, requests) {
|
||||||
|
return function () {};
|
||||||
|
};
|
||||||
|
|
||||||
|
RemsTelemetryProvider.prototype.unsubscribe = function (callback, requests) {
|
||||||
|
return function () {};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RemsTelemetryProvider;
|
@ -19,66 +19,62 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
define(
|
"use strict";
|
||||||
function () {
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {Object} RemsTelemetryValue
|
* @typedef {Object} RemsTelemetryValue
|
||||||
* @memberOf example/msl
|
* @memberOf example/msl
|
||||||
* @property {number} date The date/time of the telemetry value. Constitutes the domain value of this value pair
|
* @property {number} date The date/time of the telemetry value. Constitutes the domain value of this value pair
|
||||||
* @property {number} value The value of this telemetry datum.
|
* @property {number} value The value of this telemetry datum.
|
||||||
* A floating point value representing some observable quantity (eg.
|
* A floating point value representing some observable quantity (eg.
|
||||||
* temperature, air pressure, etc.)
|
* temperature, air pressure, etc.)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A representation of a collection of telemetry data. The REMS
|
* A representation of a collection of telemetry data. The REMS
|
||||||
* telemetry data is time ordered, with the 'domain' value
|
* telemetry data is time ordered, with the 'domain' value
|
||||||
* constituting the time stamp of each data value and the
|
* constituting the time stamp of each data value and the
|
||||||
* 'range' being the value itself.
|
* 'range' being the value itself.
|
||||||
*
|
*
|
||||||
* TelemetrySeries will typically wrap an array of telemetry data,
|
* TelemetrySeries will typically wrap an array of telemetry data,
|
||||||
* and provide an interface for retrieving individual an telemetry
|
* and provide an interface for retrieving individual an telemetry
|
||||||
* value.
|
* value.
|
||||||
* @memberOf example/msl
|
* @memberOf example/msl
|
||||||
* @param {Array<RemsTelemetryValue>} data An array of telemetry values
|
* @param {Array<RemsTelemetryValue>} data An array of telemetry values
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function RemsTelemetrySeries(data) {
|
function RemsTelemetrySeries(data) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns {number} A count of the number of data values available in
|
* @returns {number} A count of the number of data values available in
|
||||||
* this series
|
* this series
|
||||||
*/
|
*/
|
||||||
RemsTelemetrySeries.prototype.getPointCount = function () {
|
RemsTelemetrySeries.prototype.getPointCount = function () {
|
||||||
return this.data.length;
|
return this.data.length;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The domain value at the given index. The Rems telemetry data is
|
* The domain value at the given index. The Rems telemetry data is
|
||||||
* time ordered, so the domain value is the time stamp of each data
|
* time ordered, so the domain value is the time stamp of each data
|
||||||
* value.
|
* value.
|
||||||
* @param index
|
* @param index
|
||||||
* @returns {number} the time value in ms since 1 January 1970
|
* @returns {number} the time value in ms since 1 January 1970
|
||||||
*/
|
*/
|
||||||
RemsTelemetrySeries.prototype.getDomainValue = function (index) {
|
RemsTelemetrySeries.prototype.getDomainValue = function (index) {
|
||||||
return this.data[index].date;
|
return this.data[index].date;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The range value of the REMS data set is the value of the thing
|
* The range value of the REMS data set is the value of the thing
|
||||||
* being measured, be it temperature, air pressure, etc.
|
* being measured, be it temperature, air pressure, etc.
|
||||||
* @param index The datum in the data series to return the range
|
* @param index The datum in the data series to return the range
|
||||||
* value of.
|
* value of.
|
||||||
* @returns {number} A floating point number
|
* @returns {number} A floating point number
|
||||||
*/
|
*/
|
||||||
RemsTelemetrySeries.prototype.getRangeValue = function (index) {
|
RemsTelemetrySeries.prototype.getRangeValue = function (index) {
|
||||||
return this.data[index].value;
|
return this.data[index].value;
|
||||||
};
|
};
|
||||||
|
|
||||||
return RemsTelemetrySeries;
|
export default RemsTelemetrySeries;
|
||||||
}
|
|
||||||
);
|
|
@ -21,125 +21,142 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*jslint es5: true */
|
/*jslint es5: true */
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./MSLDataDictionary",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"module"
|
* Administration. All rights reserved.
|
||||||
],
|
*
|
||||||
function (MSLDataDictionary, module) {
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
"use strict";
|
* "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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*jslint es5: true */
|
||||||
|
|
||||||
var TERRESTRIAL_DATE = "terrestrial_date",
|
import MSLDataDictionary from './MSLDataDictionary';
|
||||||
LOCAL_DATA = "../data/rems.json";
|
|
||||||
|
|
||||||
/**
|
import module from 'module';
|
||||||
* Fetches historical data from the REMS instrument on the Curiosity
|
"use strict";
|
||||||
* Rover.
|
|
||||||
* @memberOf example/msl
|
|
||||||
* @param $q
|
|
||||||
* @param $http
|
|
||||||
* @param REMS_WS_URL The location of the REMS telemetry data.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function RemsTelemetryServerAdapter($http, $log, REMS_WS_URL) {
|
|
||||||
this.localDataURI = module.uri.substring(0, module.uri.lastIndexOf('/') + 1) + LOCAL_DATA;
|
|
||||||
this.REMS_WS_URL = REMS_WS_URL;
|
|
||||||
this.$http = $http;
|
|
||||||
this.$log = $log;
|
|
||||||
this.promise = undefined;
|
|
||||||
|
|
||||||
this.dataTransforms = {
|
var TERRESTRIAL_DATE = "terrestrial_date",
|
||||||
//Convert from pascals to millibars
|
LOCAL_DATA = "../data/rems.json";
|
||||||
'pressure': function pascalsToMillibars(pascals) {
|
|
||||||
return pascals / 100;
|
/**
|
||||||
}
|
* Fetches historical data from the REMS instrument on the Curiosity
|
||||||
};
|
* Rover.
|
||||||
|
* @memberOf example/msl
|
||||||
|
* @param $q
|
||||||
|
* @param $http
|
||||||
|
* @param REMS_WS_URL The location of the REMS telemetry data.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function RemsTelemetryServerAdapter($http, $log, REMS_WS_URL) {
|
||||||
|
this.localDataURI = module.uri.substring(0, module.uri.lastIndexOf('/') + 1) + LOCAL_DATA;
|
||||||
|
this.REMS_WS_URL = REMS_WS_URL;
|
||||||
|
this.$http = $http;
|
||||||
|
this.$log = $log;
|
||||||
|
this.promise = undefined;
|
||||||
|
|
||||||
|
this.dataTransforms = {
|
||||||
|
//Convert from pascals to millibars
|
||||||
|
'pressure': function pascalsToMillibars(pascals) {
|
||||||
|
return pascals / 100;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The data dictionary for this data source.
|
* The data dictionary for this data source.
|
||||||
* @type {MSLDataDictionary}
|
* @type {MSLDataDictionary}
|
||||||
|
*/
|
||||||
|
RemsTelemetryServerAdapter.prototype.dictionary = MSLDataDictionary;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetches historical data from source, and associates it with the
|
||||||
|
* given request ID.
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
RemsTelemetryServerAdapter.prototype.requestHistory = function (request) {
|
||||||
|
var self = this,
|
||||||
|
id = request.key;
|
||||||
|
|
||||||
|
var dataTransforms = this.dataTransforms;
|
||||||
|
|
||||||
|
function processResponse(response) {
|
||||||
|
var data = [];
|
||||||
|
/*
|
||||||
|
* History data is organised by Sol. Iterate over sols...
|
||||||
*/
|
*/
|
||||||
RemsTelemetryServerAdapter.prototype.dictionary = MSLDataDictionary;
|
response.data.soles.forEach(function (solData) {
|
||||||
|
/*
|
||||||
/**
|
* Check that valid data exists
|
||||||
* Fetches historical data from source, and associates it with the
|
*/
|
||||||
* given request ID.
|
if (!isNaN(solData[id])) {
|
||||||
* @private
|
var dataTransform = dataTransforms[id];
|
||||||
*/
|
|
||||||
RemsTelemetryServerAdapter.prototype.requestHistory = function (request) {
|
|
||||||
var self = this,
|
|
||||||
id = request.key;
|
|
||||||
|
|
||||||
var dataTransforms = this.dataTransforms;
|
|
||||||
|
|
||||||
function processResponse(response) {
|
|
||||||
var data = [];
|
|
||||||
/*
|
/*
|
||||||
* History data is organised by Sol. Iterate over sols...
|
* Append each data point to the array of values
|
||||||
|
* for this data point property (min. temp, etc).
|
||||||
*/
|
*/
|
||||||
response.data.soles.forEach(function (solData) {
|
data.unshift({
|
||||||
/*
|
date: Date.parse(solData[TERRESTRIAL_DATE]),
|
||||||
* Check that valid data exists
|
value: dataTransform ? dataTransform(solData[id]) : solData[id]
|
||||||
*/
|
|
||||||
if (!isNaN(solData[id])) {
|
|
||||||
var dataTransform = dataTransforms[id];
|
|
||||||
/*
|
|
||||||
* Append each data point to the array of values
|
|
||||||
* for this data point property (min. temp, etc).
|
|
||||||
*/
|
|
||||||
data.unshift({
|
|
||||||
date: Date.parse(solData[TERRESTRIAL_DATE]),
|
|
||||||
value: dataTransform ? dataTransform(solData[id]) : solData[id]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
function fallbackToLocal() {
|
|
||||||
self.$log.warn("Loading REMS data failed, probably due to"
|
|
||||||
+ " cross origin policy. Falling back to local data");
|
|
||||||
|
|
||||||
return self.$http.get(self.localDataURI);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Filter results to match request parameters
|
|
||||||
function filterResults(results) {
|
|
||||||
return results.filter(function (result) {
|
|
||||||
return result.date >= (request.start || Number.MIN_VALUE)
|
|
||||||
&& result.date <= (request.end || Number.MAX_VALUE);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
function packageAndResolve(results) {
|
return data;
|
||||||
return {
|
|
||||||
id: id,
|
|
||||||
values: results
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return (this.promise = this.promise || this.$http.get(this.REMS_WS_URL))
|
|
||||||
.catch(fallbackToLocal)
|
|
||||||
.then(processResponse)
|
|
||||||
.then(filterResults)
|
|
||||||
.then(packageAndResolve);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Requests historical telemetry for the named data attribute. In
|
|
||||||
* the case of REMS, this data source exposes multiple different
|
|
||||||
* data variables from the REMS instrument, including temperature
|
|
||||||
* and others
|
|
||||||
* @param id The telemetry data point key to be queried.
|
|
||||||
* @returns {Promise | Array<RemsTelemetryValue>} that resolves with an Array of {@link RemsTelemetryValue} objects for the request data key.
|
|
||||||
*/
|
|
||||||
RemsTelemetryServerAdapter.prototype.history = function (request) {
|
|
||||||
return this.requestHistory(request);
|
|
||||||
};
|
|
||||||
|
|
||||||
return RemsTelemetryServerAdapter;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
|
function fallbackToLocal() {
|
||||||
|
self.$log.warn("Loading REMS data failed, probably due to"
|
||||||
|
+ " cross origin policy. Falling back to local data");
|
||||||
|
|
||||||
|
return self.$http.get(self.localDataURI);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Filter results to match request parameters
|
||||||
|
function filterResults(results) {
|
||||||
|
return results.filter(function (result) {
|
||||||
|
return result.date >= (request.start || Number.MIN_VALUE)
|
||||||
|
&& result.date <= (request.end || Number.MAX_VALUE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function packageAndResolve(results) {
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
values: results
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return (this.promise = this.promise || this.$http.get(this.REMS_WS_URL))
|
||||||
|
.catch(fallbackToLocal)
|
||||||
|
.then(processResponse)
|
||||||
|
.then(filterResults)
|
||||||
|
.then(packageAndResolve);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests historical telemetry for the named data attribute. In
|
||||||
|
* the case of REMS, this data source exposes multiple different
|
||||||
|
* data variables from the REMS instrument, including temperature
|
||||||
|
* and others
|
||||||
|
* @param id The telemetry data point key to be queried.
|
||||||
|
* @returns {Promise | Array<RemsTelemetryValue>} that resolves with an Array of {@link RemsTelemetryValue} objects for the request data key.
|
||||||
|
*/
|
||||||
|
RemsTelemetryServerAdapter.prototype.history = function (request) {
|
||||||
|
return this.requestHistory(request);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RemsTelemetryServerAdapter;
|
@ -20,71 +20,84 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/DialogLaunchController",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/NotificationLaunchController",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"./src/DialogLaunchIndicator",
|
* Administration. All rights reserved.
|
||||||
"./src/NotificationLaunchIndicator",
|
*
|
||||||
"./res/dialog-launch.html",
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
"./res/notification-launch.html"
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
], function (
|
* You may obtain a copy of the License at
|
||||||
DialogLaunchController,
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
NotificationLaunchController,
|
*
|
||||||
DialogLaunchIndicator,
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
NotificationLaunchIndicator,
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
DialogLaunch,
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
NotificationLaunch
|
* License for the specific language governing permissions and limitations
|
||||||
) {
|
* under the License.
|
||||||
"use strict";
|
*
|
||||||
|
* Open MCT 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import DialogLaunchController from './src/DialogLaunchController';
|
||||||
name: "example/notifications",
|
|
||||||
definition: {
|
import NotificationLaunchController from './src/NotificationLaunchController';
|
||||||
"extensions": {
|
import DialogLaunchIndicator from './src/DialogLaunchIndicator';
|
||||||
"templates": [
|
import NotificationLaunchIndicator from './src/NotificationLaunchIndicator';
|
||||||
{
|
import DialogLaunch from './res/dialog-launch.html';
|
||||||
"key": "dialogLaunchTemplate",
|
import NotificationLaunch from './res/notification-launch.html';
|
||||||
"template": DialogLaunch
|
"use strict";
|
||||||
},
|
|
||||||
{
|
export default {
|
||||||
"key": "notificationLaunchTemplate",
|
name: "example/notifications",
|
||||||
"template": NotificationLaunch
|
definition: {
|
||||||
}
|
"extensions": {
|
||||||
],
|
"templates": [
|
||||||
"controllers": [
|
{
|
||||||
{
|
"key": "dialogLaunchTemplate",
|
||||||
"key": "DialogLaunchController",
|
"template": DialogLaunch
|
||||||
"implementation": DialogLaunchController,
|
},
|
||||||
"depends": [
|
{
|
||||||
"$scope",
|
"key": "notificationLaunchTemplate",
|
||||||
"$timeout",
|
"template": NotificationLaunch
|
||||||
"$log",
|
}
|
||||||
"dialogService",
|
],
|
||||||
"notificationService"
|
"controllers": [
|
||||||
]
|
{
|
||||||
},
|
"key": "DialogLaunchController",
|
||||||
{
|
"implementation": DialogLaunchController,
|
||||||
"key": "NotificationLaunchController",
|
"depends": [
|
||||||
"implementation": NotificationLaunchController,
|
"$scope",
|
||||||
"depends": [
|
"$timeout",
|
||||||
"$scope",
|
"$log",
|
||||||
"$timeout",
|
"dialogService",
|
||||||
"$log",
|
"notificationService"
|
||||||
"notificationService"
|
]
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
],
|
"key": "NotificationLaunchController",
|
||||||
"indicators": [
|
"implementation": NotificationLaunchController,
|
||||||
{
|
"depends": [
|
||||||
"implementation": DialogLaunchIndicator,
|
"$scope",
|
||||||
"priority": "fallback"
|
"$timeout",
|
||||||
},
|
"$log",
|
||||||
{
|
"notificationService"
|
||||||
"implementation": NotificationLaunchIndicator,
|
]
|
||||||
"priority": "fallback"
|
}
|
||||||
}
|
],
|
||||||
]
|
"indicators": [
|
||||||
}
|
{
|
||||||
|
"implementation": DialogLaunchIndicator,
|
||||||
|
"priority": "fallback"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"implementation": NotificationLaunchIndicator,
|
||||||
|
"priority": "fallback"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,138 +20,155 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
"use strict";
|
||||||
* A controller for the dialog launch view. This view allows manual
|
|
||||||
* launching of dialogs for demonstration and testing purposes. It
|
|
||||||
* also demonstrates the use of the DialogService.
|
|
||||||
* @param $scope
|
|
||||||
* @param $timeout
|
|
||||||
* @param $log
|
|
||||||
* @param dialogService
|
|
||||||
* @param notificationService
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function DialogLaunchController($scope, $timeout, $log, dialogService, notificationService) {
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Demonstrates launching a progress dialog and updating it
|
* A controller for the dialog launch view. This view allows manual
|
||||||
periodically with the progress of an ongoing process.
|
* launching of dialogs for demonstration and testing purposes. It
|
||||||
*/
|
* also demonstrates the use of the DialogService.
|
||||||
$scope.launchProgress = function (knownProgress) {
|
* @param $scope
|
||||||
var dialog,
|
* @param $timeout
|
||||||
model = {
|
* @param $log
|
||||||
title: "Progress Dialog Example",
|
* @param dialogService
|
||||||
progress: 0,
|
* @param notificationService
|
||||||
hint: "Do not navigate away from this page or close this browser tab while this operation is in progress.",
|
* @constructor
|
||||||
actionText: "Calculating...",
|
*/
|
||||||
unknownProgress: !knownProgress,
|
function DialogLaunchController($scope, $timeout, $log, dialogService, notificationService) {
|
||||||
unknownDuration: false,
|
|
||||||
severity: "info",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: "Cancel Operation",
|
|
||||||
callback: function () {
|
|
||||||
$log.debug("Operation cancelled");
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Do something else...",
|
|
||||||
callback: function () {
|
|
||||||
$log.debug("Something else pressed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
|
|
||||||
function incrementProgress() {
|
/*
|
||||||
model.progress = Math.min(100, Math.floor(model.progress + Math.random() * 30));
|
Demonstrates launching a progress dialog and updating it
|
||||||
model.progressText = ["Estimated time remaining: about ", 60 - Math.floor((model.progress / 100) * 60), " seconds"].join(" ");
|
periodically with the progress of an ongoing process.
|
||||||
if (model.progress < 100) {
|
*/
|
||||||
$timeout(incrementProgress, 1000);
|
$scope.launchProgress = function (knownProgress) {
|
||||||
}
|
var dialog,
|
||||||
}
|
model = {
|
||||||
|
title: "Progress Dialog Example",
|
||||||
dialog = dialogService.showBlockingMessage(model);
|
progress: 0,
|
||||||
|
hint: "Do not navigate away from this page or close this browser tab while this operation is in progress.",
|
||||||
if (dialog) {
|
actionText: "Calculating...",
|
||||||
//Do processing here
|
unknownProgress: !knownProgress,
|
||||||
model.actionText = "Processing 100 objects...";
|
unknownDuration: false,
|
||||||
if (knownProgress) {
|
severity: "info",
|
||||||
$timeout(incrementProgress, 1000);
|
options: [
|
||||||
}
|
{
|
||||||
} else {
|
label: "Cancel Operation",
|
||||||
$log.error("Could not display modal dialog");
|
callback: function () {
|
||||||
}
|
$log.debug("Operation cancelled");
|
||||||
};
|
dialog.dismiss();
|
||||||
|
|
||||||
/*
|
|
||||||
Demonstrates launching an error dialog
|
|
||||||
*/
|
|
||||||
$scope.launchError = function () {
|
|
||||||
var dialog,
|
|
||||||
model = {
|
|
||||||
title: "Error Dialog Example",
|
|
||||||
actionText: "Something happened, and it was not good.",
|
|
||||||
severity: "error",
|
|
||||||
options: [
|
|
||||||
{
|
|
||||||
label: "Try Again",
|
|
||||||
callback: function () {
|
|
||||||
$log.debug("Try Again Pressed");
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: "Cancel",
|
|
||||||
callback: function () {
|
|
||||||
$log.debug("Cancel Pressed");
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
dialog = dialogService.showBlockingMessage(model);
|
|
||||||
|
|
||||||
if (!dialog) {
|
|
||||||
$log.error("Could not display modal dialog");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
Demonstrates launching an error dialog
|
|
||||||
*/
|
|
||||||
$scope.launchInfo = function () {
|
|
||||||
var dialog,
|
|
||||||
model = {
|
|
||||||
title: "Info Dialog Example",
|
|
||||||
actionText: "This is an example of a blocking info"
|
|
||||||
+ " dialog. This dialog can be used to draw the user's"
|
|
||||||
+ " attention to an event.",
|
|
||||||
severity: "info",
|
|
||||||
primaryOption: {
|
|
||||||
label: "OK",
|
|
||||||
callback: function () {
|
|
||||||
$log.debug("OK Pressed");
|
|
||||||
dialog.dismiss();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
},
|
||||||
|
{
|
||||||
dialog = dialogService.showBlockingMessage(model);
|
label: "Do something else...",
|
||||||
|
callback: function () {
|
||||||
if (!dialog) {
|
$log.debug("Something else pressed");
|
||||||
$log.error("Could not display modal dialog");
|
}
|
||||||
}
|
}
|
||||||
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function incrementProgress() {
|
||||||
|
model.progress = Math.min(100, Math.floor(model.progress + Math.random() * 30));
|
||||||
|
model.progressText = ["Estimated time remaining: about ", 60 - Math.floor((model.progress / 100) * 60), " seconds"].join(" ");
|
||||||
|
if (model.progress < 100) {
|
||||||
|
$timeout(incrementProgress, 1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return DialogLaunchController;
|
dialog = dialogService.showBlockingMessage(model);
|
||||||
}
|
|
||||||
);
|
if (dialog) {
|
||||||
|
//Do processing here
|
||||||
|
model.actionText = "Processing 100 objects...";
|
||||||
|
if (knownProgress) {
|
||||||
|
$timeout(incrementProgress, 1000);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$log.error("Could not display modal dialog");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Demonstrates launching an error dialog
|
||||||
|
*/
|
||||||
|
$scope.launchError = function () {
|
||||||
|
var dialog,
|
||||||
|
model = {
|
||||||
|
title: "Error Dialog Example",
|
||||||
|
actionText: "Something happened, and it was not good.",
|
||||||
|
severity: "error",
|
||||||
|
options: [
|
||||||
|
{
|
||||||
|
label: "Try Again",
|
||||||
|
callback: function () {
|
||||||
|
$log.debug("Try Again Pressed");
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Cancel",
|
||||||
|
callback: function () {
|
||||||
|
$log.debug("Cancel Pressed");
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
dialog = dialogService.showBlockingMessage(model);
|
||||||
|
|
||||||
|
if (!dialog) {
|
||||||
|
$log.error("Could not display modal dialog");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Demonstrates launching an error dialog
|
||||||
|
*/
|
||||||
|
$scope.launchInfo = function () {
|
||||||
|
var dialog,
|
||||||
|
model = {
|
||||||
|
title: "Info Dialog Example",
|
||||||
|
actionText: "This is an example of a blocking info"
|
||||||
|
+ " dialog. This dialog can be used to draw the user's"
|
||||||
|
+ " attention to an event.",
|
||||||
|
severity: "info",
|
||||||
|
primaryOption: {
|
||||||
|
label: "OK",
|
||||||
|
callback: function () {
|
||||||
|
$log.debug("OK Pressed");
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dialog = dialogService.showBlockingMessage(model);
|
||||||
|
|
||||||
|
if (!dialog) {
|
||||||
|
$log.error("Could not display modal dialog");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DialogLaunchController;
|
@ -20,36 +20,53 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
"use strict";
|
||||||
* A tool for manually invoking dialogs. When included this
|
|
||||||
* indicator will allow for dialogs of different types to be
|
|
||||||
* launched for demonstration and testing purposes.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
function DialogLaunchIndicator() {
|
/**
|
||||||
|
* A tool for manually invoking dialogs. When included this
|
||||||
|
* indicator will allow for dialogs of different types to be
|
||||||
|
* launched for demonstration and testing purposes.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
function DialogLaunchIndicator() {
|
||||||
|
|
||||||
DialogLaunchIndicator.template = 'dialogLaunchTemplate';
|
}
|
||||||
|
|
||||||
DialogLaunchIndicator.prototype.getGlyphClass = function () {
|
DialogLaunchIndicator.template = 'dialogLaunchTemplate';
|
||||||
return 'ok';
|
|
||||||
};
|
|
||||||
|
|
||||||
DialogLaunchIndicator.prototype.getText = function () {
|
DialogLaunchIndicator.prototype.getGlyphClass = function () {
|
||||||
return "Launch test dialog";
|
return 'ok';
|
||||||
};
|
};
|
||||||
|
|
||||||
DialogLaunchIndicator.prototype.getDescription = function () {
|
DialogLaunchIndicator.prototype.getText = function () {
|
||||||
return "Launch test dialog";
|
return "Launch test dialog";
|
||||||
};
|
};
|
||||||
|
|
||||||
return DialogLaunchIndicator;
|
DialogLaunchIndicator.prototype.getDescription = function () {
|
||||||
}
|
return "Launch test dialog";
|
||||||
);
|
};
|
||||||
|
|
||||||
|
export default DialogLaunchIndicator;
|
@ -20,107 +20,124 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows launching of notification messages for the purposes of
|
||||||
|
* demonstration and testing. Also demonstrates use of
|
||||||
|
* the NotificationService. Notifications are non-blocking messages that
|
||||||
|
* appear at the bottom of the screen to inform the user of events
|
||||||
|
* in a non-intrusive way. For more information see the
|
||||||
|
* {@link NotificationService}
|
||||||
|
* @param $scope
|
||||||
|
* @param $timeout
|
||||||
|
* @param $log
|
||||||
|
* @param notificationService
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function NotificationLaunchController($scope, $timeout, $log, notificationService) {
|
||||||
|
var messageCounter = 1;
|
||||||
|
|
||||||
|
function getExampleActionText() {
|
||||||
|
var actionTexts = [
|
||||||
|
"Adipiscing turpis mauris in enim elementu hac, enim aliquam etiam.",
|
||||||
|
"Eros turpis, pulvinar turpis eros eu",
|
||||||
|
"Lundium nascetur a, lectus montes ac, parturient in natoque, duis risus risus pulvinar pid rhoncus, habitasse auctor natoque!"
|
||||||
|
];
|
||||||
|
|
||||||
|
return actionTexts[Math.floor(Math.random() * 3)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch a new notification with a severity level of 'Error'.
|
||||||
|
*/
|
||||||
|
$scope.newError = function () {
|
||||||
|
notificationService.notify({
|
||||||
|
title: "Example error notification " + messageCounter++,
|
||||||
|
hint: "An error has occurred",
|
||||||
|
severity: "error"
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch a new notification with a severity of 'Alert'.
|
||||||
|
*/
|
||||||
|
$scope.newAlert = function () {
|
||||||
|
notificationService.notify({
|
||||||
|
title: "Alert notification " + (messageCounter++),
|
||||||
|
hint: "This is an alert message",
|
||||||
|
severity: "alert",
|
||||||
|
autoDismiss: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch a new notification with a progress bar that is updated
|
||||||
|
* periodically, tracking an ongoing process.
|
||||||
|
*/
|
||||||
|
$scope.newProgress = function () {
|
||||||
|
let progress = 0;
|
||||||
|
var notificationModel = {
|
||||||
|
title: "Progress notification example",
|
||||||
|
severity: "info",
|
||||||
|
progress: progress,
|
||||||
|
actionText: getExampleActionText()
|
||||||
|
};
|
||||||
|
let notification;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows launching of notification messages for the purposes of
|
* Simulate an ongoing process and update the progress bar.
|
||||||
* demonstration and testing. Also demonstrates use of
|
* @param notification
|
||||||
* the NotificationService. Notifications are non-blocking messages that
|
|
||||||
* appear at the bottom of the screen to inform the user of events
|
|
||||||
* in a non-intrusive way. For more information see the
|
|
||||||
* {@link NotificationService}
|
|
||||||
* @param $scope
|
|
||||||
* @param $timeout
|
|
||||||
* @param $log
|
|
||||||
* @param notificationService
|
|
||||||
* @constructor
|
|
||||||
*/
|
*/
|
||||||
function NotificationLaunchController($scope, $timeout, $log, notificationService) {
|
function incrementProgress() {
|
||||||
var messageCounter = 1;
|
progress = Math.min(100, Math.floor(progress + Math.random() * 30));
|
||||||
|
let progressText = ["Estimated time"
|
||||||
|
+ " remaining:"
|
||||||
|
+ " about ", 60 - Math.floor((progress / 100) * 60), " seconds"].join(" ");
|
||||||
|
notification.progress(progress, progressText);
|
||||||
|
|
||||||
function getExampleActionText() {
|
if (progress < 100) {
|
||||||
var actionTexts = [
|
$timeout(function () {
|
||||||
"Adipiscing turpis mauris in enim elementu hac, enim aliquam etiam.",
|
incrementProgress(notificationModel);
|
||||||
"Eros turpis, pulvinar turpis eros eu",
|
}, 1000);
|
||||||
"Lundium nascetur a, lectus montes ac, parturient in natoque, duis risus risus pulvinar pid rhoncus, habitasse auctor natoque!"
|
|
||||||
];
|
|
||||||
|
|
||||||
return actionTexts[Math.floor(Math.random() * 3)];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch a new notification with a severity level of 'Error'.
|
|
||||||
*/
|
|
||||||
$scope.newError = function () {
|
|
||||||
notificationService.notify({
|
|
||||||
title: "Example error notification " + messageCounter++,
|
|
||||||
hint: "An error has occurred",
|
|
||||||
severity: "error"
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch a new notification with a severity of 'Alert'.
|
|
||||||
*/
|
|
||||||
$scope.newAlert = function () {
|
|
||||||
notificationService.notify({
|
|
||||||
title: "Alert notification " + (messageCounter++),
|
|
||||||
hint: "This is an alert message",
|
|
||||||
severity: "alert",
|
|
||||||
autoDismiss: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch a new notification with a progress bar that is updated
|
|
||||||
* periodically, tracking an ongoing process.
|
|
||||||
*/
|
|
||||||
$scope.newProgress = function () {
|
|
||||||
let progress = 0;
|
|
||||||
var notificationModel = {
|
|
||||||
title: "Progress notification example",
|
|
||||||
severity: "info",
|
|
||||||
progress: progress,
|
|
||||||
actionText: getExampleActionText()
|
|
||||||
};
|
|
||||||
let notification;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simulate an ongoing process and update the progress bar.
|
|
||||||
* @param notification
|
|
||||||
*/
|
|
||||||
function incrementProgress() {
|
|
||||||
progress = Math.min(100, Math.floor(progress + Math.random() * 30));
|
|
||||||
let progressText = ["Estimated time"
|
|
||||||
+ " remaining:"
|
|
||||||
+ " about ", 60 - Math.floor((progress / 100) * 60), " seconds"].join(" ");
|
|
||||||
notification.progress(progress, progressText);
|
|
||||||
|
|
||||||
if (progress < 100) {
|
|
||||||
$timeout(function () {
|
|
||||||
incrementProgress(notificationModel);
|
|
||||||
}, 1000);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
notification = notificationService.notify(notificationModel);
|
|
||||||
incrementProgress();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Launch a new notification with severity level of INFO.
|
|
||||||
*/
|
|
||||||
$scope.newInfo = function () {
|
|
||||||
notificationService.info({
|
|
||||||
title: "Example Info notification " + messageCounter++
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NotificationLaunchController;
|
notification = notificationService.notify(notificationModel);
|
||||||
}
|
incrementProgress();
|
||||||
);
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch a new notification with severity level of INFO.
|
||||||
|
*/
|
||||||
|
$scope.newInfo = function () {
|
||||||
|
notificationService.info({
|
||||||
|
title: "Example Info notification " + messageCounter++
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default NotificationLaunchController;
|
@ -20,36 +20,53 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
"use strict";
|
||||||
* A tool for manually invoking notifications. When included this
|
|
||||||
* indicator will allow for notifications of different types to be
|
|
||||||
* launched for demonstration and testing purposes.
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
|
|
||||||
function NotificationLaunchIndicator() {
|
/**
|
||||||
|
* A tool for manually invoking notifications. When included this
|
||||||
|
* indicator will allow for notifications of different types to be
|
||||||
|
* launched for demonstration and testing purposes.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
|
||||||
}
|
function NotificationLaunchIndicator() {
|
||||||
|
|
||||||
NotificationLaunchIndicator.template = 'notificationLaunchTemplate';
|
}
|
||||||
|
|
||||||
NotificationLaunchIndicator.prototype.getGlyphClass = function () {
|
NotificationLaunchIndicator.template = 'notificationLaunchTemplate';
|
||||||
return 'ok';
|
|
||||||
};
|
|
||||||
|
|
||||||
NotificationLaunchIndicator.prototype.getText = function () {
|
NotificationLaunchIndicator.prototype.getGlyphClass = function () {
|
||||||
return "Launch notification";
|
return 'ok';
|
||||||
};
|
};
|
||||||
|
|
||||||
NotificationLaunchIndicator.prototype.getDescription = function () {
|
NotificationLaunchIndicator.prototype.getText = function () {
|
||||||
return "Launch notification";
|
return "Launch notification";
|
||||||
};
|
};
|
||||||
|
|
||||||
return NotificationLaunchIndicator;
|
NotificationLaunchIndicator.prototype.getDescription = function () {
|
||||||
}
|
return "Launch notification";
|
||||||
);
|
};
|
||||||
|
|
||||||
|
export default NotificationLaunchIndicator;
|
@ -20,35 +20,53 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/BrowserPersistenceProvider"
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
BrowserPersistenceProvider
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
"use strict";
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import BrowserPersistenceProvider from './src/BrowserPersistenceProvider';
|
||||||
name: "example/persistence",
|
|
||||||
definition: {
|
"use strict";
|
||||||
"extensions": {
|
|
||||||
"components": [
|
export default {
|
||||||
{
|
name: "example/persistence",
|
||||||
"provides": "persistenceService",
|
definition: {
|
||||||
"type": "provider",
|
"extensions": {
|
||||||
"implementation": BrowserPersistenceProvider,
|
"components": [
|
||||||
"depends": [
|
{
|
||||||
"$q",
|
"provides": "persistenceService",
|
||||||
"PERSISTENCE_SPACE"
|
"type": "provider",
|
||||||
]
|
"implementation": BrowserPersistenceProvider,
|
||||||
}
|
"depends": [
|
||||||
],
|
"$q",
|
||||||
"constants": [
|
"PERSISTENCE_SPACE"
|
||||||
{
|
]
|
||||||
"key": "PERSISTENCE_SPACE",
|
}
|
||||||
"value": "mct"
|
],
|
||||||
}
|
"constants": [
|
||||||
]
|
{
|
||||||
}
|
"key": "PERSISTENCE_SPACE",
|
||||||
|
"value": "mct"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -24,79 +24,100 @@
|
|||||||
* Stubbed implementation of a persistence provider,
|
* Stubbed implementation of a persistence provider,
|
||||||
* to permit objects to be created, saved, etc.
|
* to permit objects to be created, saved, etc.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
'use strict';
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
function BrowserPersistenceProvider($q, SPACE) {
|
/**
|
||||||
var spaces = SPACE ? [SPACE] : [],
|
* Stubbed implementation of a persistence provider,
|
||||||
caches = {},
|
* to permit objects to be created, saved, etc.
|
||||||
promises = {
|
*/
|
||||||
as: function (value) {
|
'use strict';
|
||||||
return $q.when(value);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
spaces.forEach(function (space) {
|
function BrowserPersistenceProvider($q, SPACE) {
|
||||||
caches[space] = {};
|
var spaces = SPACE ? [SPACE] : [],
|
||||||
});
|
caches = {},
|
||||||
|
promises = {
|
||||||
|
as: function (value) {
|
||||||
|
return $q.when(value);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return {
|
spaces.forEach(function (space) {
|
||||||
listSpaces: function () {
|
caches[space] = {};
|
||||||
return promises.as(spaces);
|
});
|
||||||
},
|
|
||||||
listObjects: function (space) {
|
|
||||||
var cache = caches[space];
|
|
||||||
|
|
||||||
return promises.as(
|
return {
|
||||||
cache ? Object.keys(cache) : null
|
listSpaces: function () {
|
||||||
);
|
return promises.as(spaces);
|
||||||
},
|
},
|
||||||
createObject: function (space, key, value) {
|
listObjects: function (space) {
|
||||||
var cache = caches[space];
|
var cache = caches[space];
|
||||||
|
|
||||||
if (!cache || cache[key]) {
|
return promises.as(
|
||||||
return promises.as(null);
|
cache ? Object.keys(cache) : null
|
||||||
}
|
);
|
||||||
|
},
|
||||||
|
createObject: function (space, key, value) {
|
||||||
|
var cache = caches[space];
|
||||||
|
|
||||||
cache[key] = value;
|
if (!cache || cache[key]) {
|
||||||
|
return promises.as(null);
|
||||||
|
}
|
||||||
|
|
||||||
return promises.as(true);
|
cache[key] = value;
|
||||||
},
|
|
||||||
readObject: function (space, key) {
|
|
||||||
var cache = caches[space];
|
|
||||||
|
|
||||||
return promises.as(
|
return promises.as(true);
|
||||||
cache ? cache[key] : null
|
},
|
||||||
);
|
readObject: function (space, key) {
|
||||||
},
|
var cache = caches[space];
|
||||||
updateObject: function (space, key, value) {
|
|
||||||
var cache = caches[space];
|
|
||||||
|
|
||||||
if (!cache || !cache[key]) {
|
return promises.as(
|
||||||
return promises.as(null);
|
cache ? cache[key] : null
|
||||||
}
|
);
|
||||||
|
},
|
||||||
|
updateObject: function (space, key, value) {
|
||||||
|
var cache = caches[space];
|
||||||
|
|
||||||
cache[key] = value;
|
if (!cache || !cache[key]) {
|
||||||
|
return promises.as(null);
|
||||||
|
}
|
||||||
|
|
||||||
return promises.as(true);
|
cache[key] = value;
|
||||||
},
|
|
||||||
deleteObject: function (space, key, value) {
|
|
||||||
var cache = caches[space];
|
|
||||||
|
|
||||||
if (!cache || !cache[key]) {
|
return promises.as(true);
|
||||||
return promises.as(null);
|
},
|
||||||
}
|
deleteObject: function (space, key, value) {
|
||||||
|
var cache = caches[space];
|
||||||
|
|
||||||
delete cache[key];
|
if (!cache || !cache[key]) {
|
||||||
|
return promises.as(null);
|
||||||
|
}
|
||||||
|
|
||||||
return promises.as(true);
|
delete cache[key];
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
return promises.as(true);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return BrowserPersistenceProvider;
|
}
|
||||||
}
|
|
||||||
);
|
export default BrowserPersistenceProvider;
|
@ -20,26 +20,44 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/ExamplePolicy"
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
ExamplePolicy
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
"use strict";
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import ExamplePolicy from './src/ExamplePolicy';
|
||||||
name: "example/policy",
|
|
||||||
definition: {
|
"use strict";
|
||||||
"name": "Example Policy",
|
|
||||||
"description": "Provides an example of using policies to prohibit actions.",
|
export default {
|
||||||
"extensions": {
|
name: "example/policy",
|
||||||
"policies": [
|
definition: {
|
||||||
{
|
"name": "Example Policy",
|
||||||
"implementation": ExamplePolicy,
|
"description": "Provides an example of using policies to prohibit actions.",
|
||||||
"category": "action"
|
"extensions": {
|
||||||
}
|
"policies": [
|
||||||
]
|
{
|
||||||
}
|
"implementation": ExamplePolicy,
|
||||||
|
"category": "action"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,28 +20,45 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
function ExamplePolicy() {
|
"use strict";
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Disallow the Remove action on objects whose name contains
|
|
||||||
* "foo."
|
|
||||||
*/
|
|
||||||
allow: function (action, context) {
|
|
||||||
var domainObject = (context || {}).domainObject,
|
|
||||||
model = (domainObject && domainObject.getModel()) || {},
|
|
||||||
name = model.name || "",
|
|
||||||
metadata = action.getMetadata() || {};
|
|
||||||
|
|
||||||
return metadata.key !== 'remove' || name.indexOf('foo') < 0;
|
function ExamplePolicy() {
|
||||||
}
|
return {
|
||||||
};
|
/**
|
||||||
|
* Disallow the Remove action on objects whose name contains
|
||||||
|
* "foo."
|
||||||
|
*/
|
||||||
|
allow: function (action, context) {
|
||||||
|
var domainObject = (context || {}).domainObject,
|
||||||
|
model = (domainObject && domainObject.getModel()) || {},
|
||||||
|
name = model.name || "",
|
||||||
|
metadata = action.getMetadata() || {};
|
||||||
|
|
||||||
|
return metadata.key !== 'remove' || name.indexOf('foo') < 0;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return ExamplePolicy;
|
export default ExamplePolicy;
|
||||||
}
|
|
||||||
);
|
|
@ -20,36 +20,53 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/WatchIndicator",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/DigestIndicator"
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
], function (
|
* Administration. All rights reserved.
|
||||||
WatchIndicator,
|
*
|
||||||
DigestIndicator
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
) {
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
"use strict";
|
* 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import WatchIndicator from './src/WatchIndicator';
|
||||||
name: "example/profiling",
|
|
||||||
definition: {
|
import DigestIndicator from './src/DigestIndicator';
|
||||||
"extensions": {
|
"use strict";
|
||||||
"indicators": [
|
|
||||||
{
|
export default {
|
||||||
"implementation": WatchIndicator,
|
name: "example/profiling",
|
||||||
"depends": [
|
definition: {
|
||||||
"$interval",
|
"extensions": {
|
||||||
"$rootScope"
|
"indicators": [
|
||||||
]
|
{
|
||||||
},
|
"implementation": WatchIndicator,
|
||||||
{
|
"depends": [
|
||||||
"implementation": DigestIndicator,
|
"$interval",
|
||||||
"depends": [
|
"$rootScope"
|
||||||
"$interval",
|
]
|
||||||
"$rootScope"
|
},
|
||||||
]
|
{
|
||||||
}
|
"implementation": DigestIndicator,
|
||||||
]
|
"depends": [
|
||||||
}
|
"$interval",
|
||||||
|
"$rootScope"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,63 +20,79 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
"use strict";
|
||||||
* Displays the number of digests that have occurred since the
|
|
||||||
* indicator was first instantiated.
|
|
||||||
* @constructor
|
|
||||||
* @param $interval Angular's $interval
|
|
||||||
* @implements {Indicator}
|
|
||||||
*/
|
|
||||||
function DigestIndicator($interval, $rootScope) {
|
|
||||||
var digests = 0,
|
|
||||||
displayed = 0,
|
|
||||||
start = Date.now();
|
|
||||||
|
|
||||||
function update() {
|
/**
|
||||||
var now = Date.now(),
|
* Displays the number of digests that have occurred since the
|
||||||
secs = (now - start) / 1000;
|
* indicator was first instantiated.
|
||||||
displayed = Math.round(digests / secs);
|
* @constructor
|
||||||
start = now;
|
* @param $interval Angular's $interval
|
||||||
digests = 0;
|
* @implements {Indicator}
|
||||||
}
|
*/
|
||||||
|
function DigestIndicator($interval, $rootScope) {
|
||||||
function increment() {
|
var digests = 0,
|
||||||
digests += 1;
|
displayed = 0,
|
||||||
}
|
start = Date.now();
|
||||||
|
|
||||||
$rootScope.$watch(increment);
|
|
||||||
|
|
||||||
// Update state every second
|
|
||||||
$interval(update, 1000);
|
|
||||||
|
|
||||||
// Provide initial state, too
|
|
||||||
update();
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Get the CSS class that defines the icon
|
|
||||||
* to display in this indicator. This will appear
|
|
||||||
* as a dataflow icon.
|
|
||||||
* @returns {string} the cssClass of the dataflow icon
|
|
||||||
*/
|
|
||||||
getCssClass: function () {
|
|
||||||
return "icon-connectivity";
|
|
||||||
},
|
|
||||||
getText: function () {
|
|
||||||
return displayed + " digests/sec";
|
|
||||||
},
|
|
||||||
getDescription: function () {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return DigestIndicator;
|
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
var now = Date.now(),
|
||||||
|
secs = (now - start) / 1000;
|
||||||
|
displayed = Math.round(digests / secs);
|
||||||
|
start = now;
|
||||||
|
digests = 0;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function increment() {
|
||||||
|
digests += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rootScope.$watch(increment);
|
||||||
|
|
||||||
|
// Update state every second
|
||||||
|
$interval(update, 1000);
|
||||||
|
|
||||||
|
// Provide initial state, too
|
||||||
|
update();
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Get the CSS class that defines the icon
|
||||||
|
* to display in this indicator. This will appear
|
||||||
|
* as a dataflow icon.
|
||||||
|
* @returns {string} the cssClass of the dataflow icon
|
||||||
|
*/
|
||||||
|
getCssClass: function () {
|
||||||
|
return "icon-connectivity";
|
||||||
|
},
|
||||||
|
getText: function () {
|
||||||
|
return displayed + " digests/sec";
|
||||||
|
},
|
||||||
|
getDescription: function () {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DigestIndicator;
|
@ -20,67 +20,83 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
"use strict";
|
||||||
* Updates a count of currently-active Angular watches.
|
|
||||||
* @constructor
|
|
||||||
* @param $interval Angular's $interval
|
|
||||||
*/
|
|
||||||
function WatchIndicator($interval, $rootScope) {
|
|
||||||
var watches = 0;
|
|
||||||
|
|
||||||
function count(scope) {
|
/**
|
||||||
if (scope) {
|
* Updates a count of currently-active Angular watches.
|
||||||
watches += (scope.$$watchers || []).length;
|
* @constructor
|
||||||
count(scope.$$childHead);
|
* @param $interval Angular's $interval
|
||||||
count(scope.$$nextSibling);
|
*/
|
||||||
}
|
function WatchIndicator($interval, $rootScope) {
|
||||||
}
|
var watches = 0;
|
||||||
|
|
||||||
function update() {
|
function count(scope) {
|
||||||
watches = 0;
|
if (scope) {
|
||||||
count($rootScope);
|
watches += (scope.$$watchers || []).length;
|
||||||
}
|
count(scope.$$childHead);
|
||||||
|
count(scope.$$nextSibling);
|
||||||
// Update state every second
|
|
||||||
$interval(update, 1000);
|
|
||||||
|
|
||||||
// Provide initial state, too
|
|
||||||
update();
|
|
||||||
|
|
||||||
return {
|
|
||||||
/**
|
|
||||||
* Get the CSS class (single character used as an icon)
|
|
||||||
* to display in this indicator. This will return ".",
|
|
||||||
* which should appear as a database icon.
|
|
||||||
* @returns {string} the character of the database icon
|
|
||||||
*/
|
|
||||||
getCssClass: function () {
|
|
||||||
return "icon-database";
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Get the text that should appear in the indicator.
|
|
||||||
* @returns {string} brief summary of connection status
|
|
||||||
*/
|
|
||||||
getText: function () {
|
|
||||||
return watches + " watches";
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Get a longer-form description of the current connection
|
|
||||||
* space, suitable for display in a tooltip
|
|
||||||
* @returns {string} longer summary of connection status
|
|
||||||
*/
|
|
||||||
getDescription: function () {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return WatchIndicator;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function update() {
|
||||||
|
watches = 0;
|
||||||
|
count($rootScope);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update state every second
|
||||||
|
$interval(update, 1000);
|
||||||
|
|
||||||
|
// Provide initial state, too
|
||||||
|
update();
|
||||||
|
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Get the CSS class (single character used as an icon)
|
||||||
|
* to display in this indicator. This will return ".",
|
||||||
|
* which should appear as a database icon.
|
||||||
|
* @returns {string} the character of the database icon
|
||||||
|
*/
|
||||||
|
getCssClass: function () {
|
||||||
|
return "icon-database";
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Get the text that should appear in the indicator.
|
||||||
|
* @returns {string} brief summary of connection status
|
||||||
|
*/
|
||||||
|
getText: function () {
|
||||||
|
return watches + " watches";
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* Get a longer-form description of the current connection
|
||||||
|
* space, suitable for display in a tooltip
|
||||||
|
* @returns {string} longer summary of connection status
|
||||||
|
*/
|
||||||
|
getDescription: function () {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WatchIndicator;
|
@ -20,44 +20,62 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/ScratchPersistenceProvider"
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
ScratchPersistenceProvider
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
"use strict";
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
return {
|
import ScratchPersistenceProvider from './src/ScratchPersistenceProvider';
|
||||||
name: "example/scratchpad",
|
|
||||||
definition: {
|
"use strict";
|
||||||
"extensions": {
|
|
||||||
"roots": [
|
export default {
|
||||||
{
|
name: "example/scratchpad",
|
||||||
"id": "scratch:root"
|
definition: {
|
||||||
}
|
"extensions": {
|
||||||
],
|
"roots": [
|
||||||
"models": [
|
{
|
||||||
{
|
"id": "scratch:root"
|
||||||
"id": "scratch:root",
|
}
|
||||||
"model": {
|
],
|
||||||
"type": "folder",
|
"models": [
|
||||||
"composition": [],
|
{
|
||||||
"name": "Scratchpad"
|
"id": "scratch:root",
|
||||||
},
|
"model": {
|
||||||
"priority": "preferred"
|
"type": "folder",
|
||||||
}
|
"composition": [],
|
||||||
],
|
"name": "Scratchpad"
|
||||||
"components": [
|
},
|
||||||
{
|
"priority": "preferred"
|
||||||
"provides": "persistenceService",
|
}
|
||||||
"type": "provider",
|
],
|
||||||
"implementation": ScratchPersistenceProvider,
|
"components": [
|
||||||
"depends": [
|
{
|
||||||
"$q"
|
"provides": "persistenceService",
|
||||||
]
|
"type": "provider",
|
||||||
}
|
"implementation": ScratchPersistenceProvider,
|
||||||
]
|
"depends": [
|
||||||
}
|
"$q"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,60 +20,77 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
'use strict';
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
'use strict';
|
||||||
* The ScratchPersistenceProvider keeps JSON documents in memory
|
|
||||||
* and provides a persistence interface, but changes are lost on reload.
|
|
||||||
* @memberof example/scratchpad
|
|
||||||
* @constructor
|
|
||||||
* @implements {PersistenceService}
|
|
||||||
* @param q Angular's $q, for promises
|
|
||||||
*/
|
|
||||||
function ScratchPersistenceProvider($q) {
|
|
||||||
this.$q = $q;
|
|
||||||
this.table = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
ScratchPersistenceProvider.prototype.listSpaces = function () {
|
/**
|
||||||
return this.$q.when(['scratch']);
|
* The ScratchPersistenceProvider keeps JSON documents in memory
|
||||||
};
|
* and provides a persistence interface, but changes are lost on reload.
|
||||||
|
* @memberof example/scratchpad
|
||||||
|
* @constructor
|
||||||
|
* @implements {PersistenceService}
|
||||||
|
* @param q Angular's $q, for promises
|
||||||
|
*/
|
||||||
|
function ScratchPersistenceProvider($q) {
|
||||||
|
this.$q = $q;
|
||||||
|
this.table = {};
|
||||||
|
}
|
||||||
|
|
||||||
ScratchPersistenceProvider.prototype.listObjects = function (space) {
|
ScratchPersistenceProvider.prototype.listSpaces = function () {
|
||||||
return this.$q.when(
|
return this.$q.when(['scratch']);
|
||||||
space === 'scratch' ? Object.keys(this.table) : []
|
};
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ScratchPersistenceProvider.prototype.createObject = function (space, key, value) {
|
ScratchPersistenceProvider.prototype.listObjects = function (space) {
|
||||||
if (space === 'scratch') {
|
return this.$q.when(
|
||||||
this.table[key] = JSON.stringify(value);
|
space === 'scratch' ? Object.keys(this.table) : []
|
||||||
}
|
);
|
||||||
|
};
|
||||||
|
|
||||||
return this.$q.when(space === 'scratch');
|
ScratchPersistenceProvider.prototype.createObject = function (space, key, value) {
|
||||||
};
|
if (space === 'scratch') {
|
||||||
|
this.table[key] = JSON.stringify(value);
|
||||||
ScratchPersistenceProvider.prototype.readObject = function (space, key) {
|
|
||||||
return this.$q.when(
|
|
||||||
(space === 'scratch' && this.table[key])
|
|
||||||
? JSON.parse(this.table[key]) : undefined
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
ScratchPersistenceProvider.prototype.deleteObject = function (space, key, value) {
|
|
||||||
if (space === 'scratch') {
|
|
||||||
delete this.table[key];
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.$q.when(space === 'scratch');
|
|
||||||
};
|
|
||||||
|
|
||||||
ScratchPersistenceProvider.prototype.updateObject =
|
|
||||||
ScratchPersistenceProvider.prototype.createObject;
|
|
||||||
|
|
||||||
return ScratchPersistenceProvider;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return this.$q.when(space === 'scratch');
|
||||||
|
};
|
||||||
|
|
||||||
|
ScratchPersistenceProvider.prototype.readObject = function (space, key) {
|
||||||
|
return this.$q.when(
|
||||||
|
(space === 'scratch' && this.table[key])
|
||||||
|
? JSON.parse(this.table[key]) : undefined
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
ScratchPersistenceProvider.prototype.deleteObject = function (space, key, value) {
|
||||||
|
if (space === 'scratch') {
|
||||||
|
delete this.table[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.$q.when(space === 'scratch');
|
||||||
|
};
|
||||||
|
|
||||||
|
ScratchPersistenceProvider.prototype.updateObject =
|
||||||
|
ScratchPersistenceProvider.prototype.createObject;
|
||||||
|
|
||||||
|
export default ScratchPersistenceProvider;
|
@ -1,188 +1,175 @@
|
|||||||
define([
|
import ExampleStyleGuideModelProvider from './src/ExampleStyleGuideModelProvider';
|
||||||
"./src/ExampleStyleGuideModelProvider",
|
import MCTExample from './src/MCTExample';
|
||||||
"./src/MCTExample",
|
import introTemplate from './res/templates/intro.html';
|
||||||
"./res/templates/intro.html",
|
import standardsTemplate from './res/templates/standards.html';
|
||||||
"./res/templates/standards.html",
|
import colorsTemplate from './res/templates/colors.html';
|
||||||
"./res/templates/colors.html",
|
import statusTemplate from './res/templates/status.html';
|
||||||
"./res/templates/status.html",
|
import glyphsTemplate from './res/templates/glyphs.html';
|
||||||
"./res/templates/glyphs.html",
|
import controlsTemplate from './res/templates/controls.html';
|
||||||
"./res/templates/controls.html",
|
import inputTemplate from './res/templates/input.html';
|
||||||
"./res/templates/input.html",
|
import menusTemplate from './res/templates/menus.html';
|
||||||
"./res/templates/menus.html"
|
|
||||||
], function (
|
export default {
|
||||||
ExampleStyleGuideModelProvider,
|
name: "example/styleguide",
|
||||||
MCTExample,
|
definition: {
|
||||||
introTemplate,
|
"name": "Open MCT Style Guide",
|
||||||
standardsTemplate,
|
"description": "Examples and documentation illustrating UI styles in use in Open MCT.",
|
||||||
colorsTemplate,
|
"extensions":
|
||||||
statusTemplate,
|
{
|
||||||
glyphsTemplate,
|
"types": [
|
||||||
controlsTemplate,
|
{
|
||||||
inputTemplate,
|
"key": "styleguide.intro",
|
||||||
menusTemplate
|
"name": "Introduction",
|
||||||
) {
|
"cssClass": "icon-page",
|
||||||
return {
|
"description": "Introduction and overview to the style guide"
|
||||||
name: "example/styleguide",
|
},
|
||||||
definition: {
|
{
|
||||||
"name": "Open MCT Style Guide",
|
"key": "styleguide.standards",
|
||||||
"description": "Examples and documentation illustrating UI styles in use in Open MCT.",
|
"name": "Standards",
|
||||||
"extensions":
|
"cssClass": "icon-page",
|
||||||
{
|
"description": ""
|
||||||
"types": [
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.intro",
|
"key": "styleguide.colors",
|
||||||
"name": "Introduction",
|
"name": "Colors",
|
||||||
"cssClass": "icon-page",
|
"cssClass": "icon-page",
|
||||||
"description": "Introduction and overview to the style guide"
|
"description": ""
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.standards",
|
"key": "styleguide.status",
|
||||||
"name": "Standards",
|
"name": "status",
|
||||||
"cssClass": "icon-page",
|
"cssClass": "icon-page",
|
||||||
"description": ""
|
"description": "Limits, telemetry paused, etc."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.colors",
|
"key": "styleguide.glyphs",
|
||||||
"name": "Colors",
|
"name": "Glyphs",
|
||||||
"cssClass": "icon-page",
|
"cssClass": "icon-page",
|
||||||
"description": ""
|
"description": "Glyphs overview"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.status",
|
"key": "styleguide.controls",
|
||||||
"name": "status",
|
"name": "Controls",
|
||||||
"cssClass": "icon-page",
|
"cssClass": "icon-page",
|
||||||
"description": "Limits, telemetry paused, etc."
|
"description": "Buttons, selects, HTML controls"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.glyphs",
|
"key": "styleguide.input",
|
||||||
"name": "Glyphs",
|
"name": "Text Inputs",
|
||||||
"cssClass": "icon-page",
|
"cssClass": "icon-page",
|
||||||
"description": "Glyphs overview"
|
"description": "Various text inputs"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.controls",
|
"key": "styleguide.menus",
|
||||||
"name": "Controls",
|
"name": "Menus",
|
||||||
"cssClass": "icon-page",
|
"cssClass": "icon-page",
|
||||||
"description": "Buttons, selects, HTML controls"
|
"description": "Context menus, dropdowns"
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"key": "styleguide.input",
|
"views": [
|
||||||
"name": "Text Inputs",
|
{
|
||||||
"cssClass": "icon-page",
|
"key": "styleguide.intro",
|
||||||
"description": "Various text inputs"
|
"type": "styleguide.intro",
|
||||||
},
|
"template": introTemplate,
|
||||||
{
|
"editable": false
|
||||||
"key": "styleguide.menus",
|
},
|
||||||
"name": "Menus",
|
{
|
||||||
"cssClass": "icon-page",
|
"key": "styleguide.standards",
|
||||||
"description": "Context menus, dropdowns"
|
"type": "styleguide.standards",
|
||||||
}
|
"template": standardsTemplate,
|
||||||
],
|
"editable": false
|
||||||
"views": [
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.intro",
|
"key": "styleguide.colors",
|
||||||
"type": "styleguide.intro",
|
"type": "styleguide.colors",
|
||||||
"template": introTemplate,
|
"template": colorsTemplate,
|
||||||
"editable": false
|
"editable": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.standards",
|
"key": "styleguide.status",
|
||||||
"type": "styleguide.standards",
|
"type": "styleguide.status",
|
||||||
"template": standardsTemplate,
|
"template": statusTemplate,
|
||||||
"editable": false
|
"editable": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.colors",
|
"key": "styleguide.glyphs",
|
||||||
"type": "styleguide.colors",
|
"type": "styleguide.glyphs",
|
||||||
"template": colorsTemplate,
|
"template": glyphsTemplate,
|
||||||
"editable": false
|
"editable": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.status",
|
"key": "styleguide.controls",
|
||||||
"type": "styleguide.status",
|
"type": "styleguide.controls",
|
||||||
"template": statusTemplate,
|
"template": controlsTemplate,
|
||||||
"editable": false
|
"editable": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.glyphs",
|
"key": "styleguide.input",
|
||||||
"type": "styleguide.glyphs",
|
"type": "styleguide.input",
|
||||||
"template": glyphsTemplate,
|
"template": inputTemplate,
|
||||||
"editable": false
|
"editable": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "styleguide.controls",
|
"key": "styleguide.menus",
|
||||||
"type": "styleguide.controls",
|
"type": "styleguide.menus",
|
||||||
"template": controlsTemplate,
|
"template": menusTemplate,
|
||||||
"editable": false
|
"editable": false
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"key": "styleguide.input",
|
"roots": [
|
||||||
"type": "styleguide.input",
|
{
|
||||||
"template": inputTemplate,
|
"id": "styleguide:home"
|
||||||
"editable": false
|
}
|
||||||
},
|
],
|
||||||
{
|
"models": [
|
||||||
"key": "styleguide.menus",
|
{
|
||||||
"type": "styleguide.menus",
|
"id": "styleguide:home",
|
||||||
"template": menusTemplate,
|
"priority": "preferred",
|
||||||
"editable": false
|
"model": {
|
||||||
}
|
"type": "noneditable.folder",
|
||||||
],
|
"name": "Style Guide Home",
|
||||||
"roots": [
|
"location": "ROOT",
|
||||||
{
|
"composition": [
|
||||||
"id": "styleguide:home"
|
"intro",
|
||||||
}
|
"standards",
|
||||||
],
|
"colors",
|
||||||
"models": [
|
"status",
|
||||||
{
|
"glyphs",
|
||||||
"id": "styleguide:home",
|
"styleguide:ui-elements"
|
||||||
"priority": "preferred",
|
|
||||||
"model": {
|
|
||||||
"type": "noneditable.folder",
|
|
||||||
"name": "Style Guide Home",
|
|
||||||
"location": "ROOT",
|
|
||||||
"composition": [
|
|
||||||
"intro",
|
|
||||||
"standards",
|
|
||||||
"colors",
|
|
||||||
"status",
|
|
||||||
"glyphs",
|
|
||||||
"styleguide:ui-elements"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"id": "styleguide:ui-elements",
|
|
||||||
"priority": "preferred",
|
|
||||||
"model": {
|
|
||||||
"type": "noneditable.folder",
|
|
||||||
"name": "UI Elements",
|
|
||||||
"location": "styleguide:home",
|
|
||||||
"composition": [
|
|
||||||
"controls",
|
|
||||||
"input",
|
|
||||||
"menus"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"directives": [
|
|
||||||
{
|
|
||||||
"key": "mctExample",
|
|
||||||
"implementation": MCTExample
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"provides": "modelService",
|
|
||||||
"type": "provider",
|
|
||||||
"implementation": ExampleStyleGuideModelProvider,
|
|
||||||
"depends": [
|
|
||||||
"$q"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
}
|
"id": "styleguide:ui-elements",
|
||||||
};
|
"priority": "preferred",
|
||||||
});
|
"model": {
|
||||||
|
"type": "noneditable.folder",
|
||||||
|
"name": "UI Elements",
|
||||||
|
"location": "styleguide:home",
|
||||||
|
"composition": [
|
||||||
|
"controls",
|
||||||
|
"input",
|
||||||
|
"menus"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"directives": [
|
||||||
|
{
|
||||||
|
"key": "mctExample",
|
||||||
|
"implementation": MCTExample
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"components": [
|
||||||
|
{
|
||||||
|
"provides": "modelService",
|
||||||
|
"type": "provider",
|
||||||
|
"implementation": ExampleStyleGuideModelProvider,
|
||||||
|
"depends": [
|
||||||
|
"$q"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
@ -20,63 +20,80 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"use strict";
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
function ExampleStyleGuideModelProvider($q) {
|
"use strict";
|
||||||
var pages = {};
|
|
||||||
|
|
||||||
// Add pages
|
function ExampleStyleGuideModelProvider($q) {
|
||||||
pages.intro = {
|
var pages = {};
|
||||||
name: "Introduction",
|
|
||||||
type: "styleguide.intro",
|
|
||||||
location: "styleguide:home"
|
|
||||||
};
|
|
||||||
pages.standards = {
|
|
||||||
name: "Standards",
|
|
||||||
type: "styleguide.standards",
|
|
||||||
location: "styleguide:home"
|
|
||||||
};
|
|
||||||
pages.colors = {
|
|
||||||
name: "Colors",
|
|
||||||
type: "styleguide.colors",
|
|
||||||
location: "styleguide:home"
|
|
||||||
};
|
|
||||||
pages.glyphs = {
|
|
||||||
name: "Glyphs",
|
|
||||||
type: "styleguide.glyphs",
|
|
||||||
location: "styleguide:home"
|
|
||||||
};
|
|
||||||
pages.status = {
|
|
||||||
name: "Status Indication",
|
|
||||||
type: "styleguide.status",
|
|
||||||
location: "styleguide:home"
|
|
||||||
};
|
|
||||||
pages.controls = {
|
|
||||||
name: "Controls",
|
|
||||||
type: "styleguide.controls",
|
|
||||||
location: "styleguide:ui-elements"
|
|
||||||
};
|
|
||||||
pages.input = {
|
|
||||||
name: "Text Inputs",
|
|
||||||
type: "styleguide.input",
|
|
||||||
location: "styleguide:ui-elements"
|
|
||||||
};
|
|
||||||
pages.menus = {
|
|
||||||
name: "Menus",
|
|
||||||
type: "styleguide.menus",
|
|
||||||
location: "styleguide:ui-elements"
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
// Add pages
|
||||||
getModels: function () {
|
pages.intro = {
|
||||||
return $q.when(pages);
|
name: "Introduction",
|
||||||
}
|
type: "styleguide.intro",
|
||||||
};
|
location: "styleguide:home"
|
||||||
|
};
|
||||||
|
pages.standards = {
|
||||||
|
name: "Standards",
|
||||||
|
type: "styleguide.standards",
|
||||||
|
location: "styleguide:home"
|
||||||
|
};
|
||||||
|
pages.colors = {
|
||||||
|
name: "Colors",
|
||||||
|
type: "styleguide.colors",
|
||||||
|
location: "styleguide:home"
|
||||||
|
};
|
||||||
|
pages.glyphs = {
|
||||||
|
name: "Glyphs",
|
||||||
|
type: "styleguide.glyphs",
|
||||||
|
location: "styleguide:home"
|
||||||
|
};
|
||||||
|
pages.status = {
|
||||||
|
name: "Status Indication",
|
||||||
|
type: "styleguide.status",
|
||||||
|
location: "styleguide:home"
|
||||||
|
};
|
||||||
|
pages.controls = {
|
||||||
|
name: "Controls",
|
||||||
|
type: "styleguide.controls",
|
||||||
|
location: "styleguide:ui-elements"
|
||||||
|
};
|
||||||
|
pages.input = {
|
||||||
|
name: "Text Inputs",
|
||||||
|
type: "styleguide.input",
|
||||||
|
location: "styleguide:ui-elements"
|
||||||
|
};
|
||||||
|
pages.menus = {
|
||||||
|
name: "Menus",
|
||||||
|
type: "styleguide.menus",
|
||||||
|
location: "styleguide:ui-elements"
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
getModels: function () {
|
||||||
|
return $q.when(pages);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return ExampleStyleGuideModelProvider;
|
export default ExampleStyleGuideModelProvider;
|
||||||
}
|
|
||||||
);
|
|
@ -1,30 +1,25 @@
|
|||||||
define([
|
import MCTExampleTemplate from '../res/templates/mct-example.html';
|
||||||
'../res/templates/mct-example.html'
|
|
||||||
], function (
|
|
||||||
MCTExampleTemplate
|
|
||||||
) {
|
|
||||||
|
|
||||||
function MCTExample() {
|
function MCTExample() {
|
||||||
function link($scope, $element, $attrs, controller, $transclude) {
|
function link($scope, $element, $attrs, controller, $transclude) {
|
||||||
var codeEl = $element.find('pre');
|
var codeEl = $element.find('pre');
|
||||||
var exampleEl = $element.find('div');
|
var exampleEl = $element.find('div');
|
||||||
|
|
||||||
$transclude(function (clone) {
|
$transclude(function (clone) {
|
||||||
exampleEl.append(clone);
|
exampleEl.append(clone);
|
||||||
codeEl.text(exampleEl.html()
|
codeEl.text(exampleEl.html()
|
||||||
.replace(/ class="ng-scope"/g, "")
|
.replace(/ class="ng-scope"/g, "")
|
||||||
.replace(/ ng-scope"/g, '"'));
|
.replace(/ ng-scope"/g, '"'));
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
restrict: "E",
|
|
||||||
template: MCTExampleTemplate,
|
|
||||||
transclude: true,
|
|
||||||
link: link,
|
|
||||||
replace: true
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MCTExample;
|
return {
|
||||||
});
|
restrict: "E",
|
||||||
|
template: MCTExampleTemplate,
|
||||||
|
transclude: true,
|
||||||
|
link: link,
|
||||||
|
replace: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MCTExample;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
"@percy/cli": "^1.0.0-beta.70",
|
"@percy/cli": "^1.0.0-beta.70",
|
||||||
"@percy/playwright": "^1.0.1",
|
"@percy/playwright": "^1.0.1",
|
||||||
"@playwright/test": "^1.16.3",
|
"@playwright/test": "^1.16.3",
|
||||||
|
"5to6-codemod": "^1.8.0",
|
||||||
"allure-playwright": "^2.0.0-beta.14",
|
"allure-playwright": "^2.0.0-beta.14",
|
||||||
"angular": ">=1.8.0",
|
"angular": ">=1.8.0",
|
||||||
"angular-route": "1.4.14",
|
"angular-route": "1.4.14",
|
||||||
@ -36,6 +37,7 @@
|
|||||||
"imports-loader": "^0.8.0",
|
"imports-loader": "^0.8.0",
|
||||||
"istanbul-instrumenter-loader": "^3.0.1",
|
"istanbul-instrumenter-loader": "^3.0.1",
|
||||||
"jasmine-core": "^3.7.1",
|
"jasmine-core": "^3.7.1",
|
||||||
|
"jscodeshift": "^0.13.0",
|
||||||
"jsdoc": "^3.3.2",
|
"jsdoc": "^3.3.2",
|
||||||
"karma": "6.3.9",
|
"karma": "6.3.9",
|
||||||
"karma-chrome-launcher": "3.1.0",
|
"karma-chrome-launcher": "3.1.0",
|
||||||
|
@ -20,139 +20,147 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/navigation/NavigationService",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/navigation/NavigateAction",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"./src/navigation/OrphanNavigationHandler",
|
* Administration. All rights reserved.
|
||||||
"./res/templates/browse.html",
|
*
|
||||||
"./res/templates/browse-object.html",
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
"./res/templates/browse/object-header.html",
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
"./res/templates/browse/object-header-frame.html",
|
* You may obtain a copy of the License at
|
||||||
"./res/templates/menu-arrow.html",
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
"./res/templates/back-arrow.html",
|
*
|
||||||
"./res/templates/browse/object-properties.html",
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
"./res/templates/browse/inspector-region.html"
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
], function (
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
NavigationService,
|
* License for the specific language governing permissions and limitations
|
||||||
NavigateAction,
|
* under the License.
|
||||||
OrphanNavigationHandler,
|
*
|
||||||
browseTemplate,
|
* Open MCT includes source code licensed under additional open source
|
||||||
browseObjectTemplate,
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
objectHeaderTemplate,
|
* this source code distribution or the Licensing information page available
|
||||||
objectHeaderFrameTemplate,
|
* at runtime from the About dialog for additional information.
|
||||||
menuArrowTemplate,
|
*****************************************************************************/
|
||||||
backArrowTemplate,
|
|
||||||
objectPropertiesTemplate,
|
|
||||||
inspectorRegionTemplate
|
|
||||||
) {
|
|
||||||
|
|
||||||
return {
|
import NavigationService from './src/navigation/NavigationService';
|
||||||
name: "platform/commonUI/browse",
|
|
||||||
definition: {
|
import NavigateAction from './src/navigation/NavigateAction';
|
||||||
"extensions": {
|
import OrphanNavigationHandler from './src/navigation/OrphanNavigationHandler';
|
||||||
"routes": [
|
import browseTemplate from './res/templates/browse.html';
|
||||||
],
|
import browseObjectTemplate from './res/templates/browse-object.html';
|
||||||
"constants": [
|
import objectHeaderTemplate from './res/templates/browse/object-header.html';
|
||||||
{
|
import objectHeaderFrameTemplate from './res/templates/browse/object-header-frame.html';
|
||||||
"key": "DEFAULT_PATH",
|
import menuArrowTemplate from './res/templates/menu-arrow.html';
|
||||||
"value": "mine",
|
import backArrowTemplate from './res/templates/back-arrow.html';
|
||||||
"priority": "fallback"
|
import objectPropertiesTemplate from './res/templates/browse/object-properties.html';
|
||||||
}
|
import inspectorRegionTemplate from './res/templates/browse/inspector-region.html';
|
||||||
],
|
|
||||||
"representations": [
|
export default {
|
||||||
{
|
name: "platform/commonUI/browse",
|
||||||
"key": "browse-object",
|
definition: {
|
||||||
"template": browseObjectTemplate,
|
"extensions": {
|
||||||
"gestures": [
|
"routes": [
|
||||||
"drop"
|
],
|
||||||
],
|
"constants": [
|
||||||
"uses": [
|
{
|
||||||
"view"
|
"key": "DEFAULT_PATH",
|
||||||
]
|
"value": "mine",
|
||||||
},
|
"priority": "fallback"
|
||||||
{
|
}
|
||||||
"key": "object-header",
|
],
|
||||||
"template": objectHeaderTemplate,
|
"representations": [
|
||||||
"uses": [
|
{
|
||||||
"type"
|
"key": "browse-object",
|
||||||
]
|
"template": browseObjectTemplate,
|
||||||
},
|
"gestures": [
|
||||||
{
|
"drop"
|
||||||
"key": "object-header-frame",
|
],
|
||||||
"template": objectHeaderFrameTemplate,
|
"uses": [
|
||||||
"uses": [
|
"view"
|
||||||
"type"
|
]
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "object-header",
|
||||||
"key": "menu-arrow",
|
"template": objectHeaderTemplate,
|
||||||
"template": menuArrowTemplate,
|
"uses": [
|
||||||
"uses": [
|
"type"
|
||||||
"action"
|
]
|
||||||
],
|
},
|
||||||
"gestures": [
|
{
|
||||||
"menu"
|
"key": "object-header-frame",
|
||||||
]
|
"template": objectHeaderFrameTemplate,
|
||||||
},
|
"uses": [
|
||||||
{
|
"type"
|
||||||
"key": "back-arrow",
|
]
|
||||||
"uses": [
|
},
|
||||||
"context"
|
{
|
||||||
],
|
"key": "menu-arrow",
|
||||||
"template": backArrowTemplate
|
"template": menuArrowTemplate,
|
||||||
},
|
"uses": [
|
||||||
{
|
"action"
|
||||||
"key": "object-properties",
|
],
|
||||||
"template": objectPropertiesTemplate
|
"gestures": [
|
||||||
},
|
"menu"
|
||||||
{
|
]
|
||||||
"key": "inspector-region",
|
},
|
||||||
"template": inspectorRegionTemplate
|
{
|
||||||
}
|
"key": "back-arrow",
|
||||||
],
|
"uses": [
|
||||||
"services": [
|
"context"
|
||||||
{
|
],
|
||||||
"key": "navigationService",
|
"template": backArrowTemplate
|
||||||
"implementation": NavigationService,
|
},
|
||||||
"depends": [
|
{
|
||||||
"$window"
|
"key": "object-properties",
|
||||||
]
|
"template": objectPropertiesTemplate
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"actions": [
|
"key": "inspector-region",
|
||||||
{
|
"template": inspectorRegionTemplate
|
||||||
"key": "navigate",
|
}
|
||||||
"implementation": NavigateAction,
|
],
|
||||||
"depends": [
|
"services": [
|
||||||
"navigationService"
|
{
|
||||||
]
|
"key": "navigationService",
|
||||||
}
|
"implementation": NavigationService,
|
||||||
],
|
"depends": [
|
||||||
"runs": [
|
"$window"
|
||||||
{
|
]
|
||||||
"implementation": OrphanNavigationHandler,
|
}
|
||||||
"depends": [
|
],
|
||||||
"throttle",
|
"actions": [
|
||||||
"topic",
|
{
|
||||||
"navigationService"
|
"key": "navigate",
|
||||||
]
|
"implementation": NavigateAction,
|
||||||
}
|
"depends": [
|
||||||
],
|
"navigationService"
|
||||||
"templates": [
|
]
|
||||||
{
|
}
|
||||||
key: "browseRoot",
|
],
|
||||||
template: browseTemplate
|
"runs": [
|
||||||
},
|
{
|
||||||
{
|
"implementation": OrphanNavigationHandler,
|
||||||
key: "browseObject",
|
"depends": [
|
||||||
template: browseObjectTemplate
|
"throttle",
|
||||||
},
|
"topic",
|
||||||
{
|
"navigationService"
|
||||||
key: "inspectorRegion",
|
]
|
||||||
template: inspectorRegionTemplate
|
}
|
||||||
}
|
],
|
||||||
]
|
"templates": [
|
||||||
}
|
{
|
||||||
|
key: "browseRoot",
|
||||||
|
template: browseTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "browseObject",
|
||||||
|
template: browseObjectTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "inspectorRegion",
|
||||||
|
template: inspectorRegionTemplate
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,48 +20,64 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
'../../regions/src/Region'
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
],
|
* Administration. All rights reserved.
|
||||||
function (Region) {
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
import Region from '../../regions/src/Region';
|
||||||
* Defines the a default Inspector region. Captured in a class to
|
|
||||||
* allow for modular extension and customization of regions based on
|
|
||||||
* the typical case.
|
|
||||||
* @memberOf platform/commonUI/regions
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function InspectorRegion() {
|
|
||||||
Region.call(this, {'name': 'Inspector'});
|
|
||||||
|
|
||||||
this.buildRegion();
|
/**
|
||||||
|
* Defines the a default Inspector region. Captured in a class to
|
||||||
|
* allow for modular extension and customization of regions based on
|
||||||
|
* the typical case.
|
||||||
|
* @memberOf platform/commonUI/regions
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function InspectorRegion() {
|
||||||
|
Region.call(this, {'name': 'Inspector'});
|
||||||
|
|
||||||
|
this.buildRegion();
|
||||||
|
}
|
||||||
|
|
||||||
|
InspectorRegion.prototype = Object.create(Region.prototype);
|
||||||
|
InspectorRegion.prototype.constructor = Region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
InspectorRegion.prototype.buildRegion = function () {
|
||||||
|
var metadataRegion = {
|
||||||
|
name: 'metadata',
|
||||||
|
title: 'Metadata Region',
|
||||||
|
// Which modes should the region part be visible in? If
|
||||||
|
// nothing provided here, then assumed that part is visible
|
||||||
|
// in both. The visibility or otherwise of a region part
|
||||||
|
// should be decided by a policy. In this case, 'modes' is a
|
||||||
|
// shortcut that is used by the EditableRegionPolicy.
|
||||||
|
modes: ['browse', 'edit'],
|
||||||
|
content: {
|
||||||
|
key: 'object-properties'
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
this.addRegion(new Region(metadataRegion), 0);
|
||||||
|
};
|
||||||
|
|
||||||
InspectorRegion.prototype = Object.create(Region.prototype);
|
export default InspectorRegion;
|
||||||
InspectorRegion.prototype.constructor = Region;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
InspectorRegion.prototype.buildRegion = function () {
|
|
||||||
var metadataRegion = {
|
|
||||||
name: 'metadata',
|
|
||||||
title: 'Metadata Region',
|
|
||||||
// Which modes should the region part be visible in? If
|
|
||||||
// nothing provided here, then assumed that part is visible
|
|
||||||
// in both. The visibility or otherwise of a region part
|
|
||||||
// should be decided by a policy. In this case, 'modes' is a
|
|
||||||
// shortcut that is used by the EditableRegionPolicy.
|
|
||||||
modes: ['browse', 'edit'],
|
|
||||||
content: {
|
|
||||||
key: 'object-properties'
|
|
||||||
}
|
|
||||||
};
|
|
||||||
this.addRegion(new Region(metadataRegion), 0);
|
|
||||||
};
|
|
||||||
|
|
||||||
return InspectorRegion;
|
|
||||||
}
|
|
||||||
);
|
|
@ -23,47 +23,60 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining NavigateAction. Created by vwoeltje on 11/10/14.
|
* Module defining NavigateAction. Created by vwoeltje on 11/10/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The navigate action navigates to a specific domain object.
|
* Module defining NavigateAction. Created by vwoeltje on 11/10/14.
|
||||||
* @memberof platform/commonUI/browse
|
*/
|
||||||
* @constructor
|
function NavigateAction(navigationService, context) {
|
||||||
* @implements {Action}
|
this.domainObject = context.domainObject;
|
||||||
*/
|
this.navigationService = navigationService;
|
||||||
function NavigateAction(navigationService, context) {
|
}
|
||||||
this.domainObject = context.domainObject;
|
|
||||||
this.navigationService = navigationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigate to the object described in the context.
|
* Navigate to the object described in the context.
|
||||||
* @returns {Promise} a promise that is resolved once the
|
* @returns {Promise} a promise that is resolved once the
|
||||||
* navigation has been updated
|
* navigation has been updated
|
||||||
*/
|
*/
|
||||||
NavigateAction.prototype.perform = function () {
|
NavigateAction.prototype.perform = function () {
|
||||||
if (this.navigationService.shouldNavigate()) {
|
if (this.navigationService.shouldNavigate()) {
|
||||||
this.navigationService.setNavigation(this.domainObject, true);
|
this.navigationService.setNavigation(this.domainObject, true);
|
||||||
|
|
||||||
return Promise.resolve({});
|
return Promise.resolve({});
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.reject('Navigation Prevented by User');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigate as an action is only applicable when a domain object
|
|
||||||
* is described in the action context.
|
|
||||||
* @param {ActionContext} context the context in which the action
|
|
||||||
* will be performed
|
|
||||||
* @returns {boolean} true if applicable
|
|
||||||
*/
|
|
||||||
NavigateAction.appliesTo = function (context) {
|
|
||||||
return context.domainObject !== undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
return NavigateAction;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return Promise.reject('Navigation Prevented by User');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Navigate as an action is only applicable when a domain object
|
||||||
|
* is described in the action context.
|
||||||
|
* @param {ActionContext} context the context in which the action
|
||||||
|
* will be performed
|
||||||
|
* @returns {boolean} true if applicable
|
||||||
|
*/
|
||||||
|
NavigateAction.appliesTo = function (context) {
|
||||||
|
return context.domainObject !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NavigateAction;
|
@ -23,181 +23,193 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining NavigationService. Created by vwoeltje on 11/10/14.
|
* Module defining NavigationService. Created by vwoeltje on 11/10/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The navigation service maintains the application's current
|
* Module defining NavigationService. Created by vwoeltje on 11/10/14.
|
||||||
* navigation state, and allows listening for changes thereto.
|
*/
|
||||||
*
|
function NavigationService($window) {
|
||||||
* @memberof platform/commonUI/browse
|
this.navigated = undefined;
|
||||||
* @constructor
|
this.callbacks = [];
|
||||||
*/
|
this.checks = [];
|
||||||
function NavigationService($window) {
|
this.$window = $window;
|
||||||
this.navigated = undefined;
|
|
||||||
this.callbacks = [];
|
|
||||||
this.checks = [];
|
|
||||||
this.$window = $window;
|
|
||||||
|
|
||||||
this.oldUnload = $window.onbeforeunload;
|
this.oldUnload = $window.onbeforeunload;
|
||||||
$window.onbeforeunload = this.onBeforeUnload.bind(this);
|
$window.onbeforeunload = this.onBeforeUnload.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current navigation state.
|
* Get the current navigation state.
|
||||||
*
|
*
|
||||||
* @returns {DomainObject} the object that is navigated-to
|
* @returns {DomainObject} the object that is navigated-to
|
||||||
*/
|
*/
|
||||||
NavigationService.prototype.getNavigation = function () {
|
NavigationService.prototype.getNavigation = function () {
|
||||||
return this.navigated;
|
return this.navigated;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Navigate to a specified object. If navigation checks exist and
|
* Navigate to a specified object. If navigation checks exist and
|
||||||
* return reasons to prevent navigation, it will prompt the user before
|
* return reasons to prevent navigation, it will prompt the user before
|
||||||
* continuing. Trying to navigate to the currently navigated object will
|
* continuing. Trying to navigate to the currently navigated object will
|
||||||
* do nothing.
|
* do nothing.
|
||||||
*
|
*
|
||||||
* If a truthy value is passed for `force`, it will skip navigation
|
* If a truthy value is passed for `force`, it will skip navigation
|
||||||
* and will not prevent navigation to an already selected object.
|
* and will not prevent navigation to an already selected object.
|
||||||
*
|
*
|
||||||
* @param {DomainObject} domainObject the domain object to navigate to
|
* @param {DomainObject} domainObject the domain object to navigate to
|
||||||
* @param {Boolean} force if true, force navigation to occur.
|
* @param {Boolean} force if true, force navigation to occur.
|
||||||
* @returns {Boolean} true if navigation occurred, otherwise false.
|
* @returns {Boolean} true if navigation occurred, otherwise false.
|
||||||
*/
|
*/
|
||||||
NavigationService.prototype.setNavigation = function (domainObject, force) {
|
NavigationService.prototype.setNavigation = function (domainObject, force) {
|
||||||
if (force) {
|
if (force) {
|
||||||
this.doNavigation(domainObject);
|
this.doNavigation(domainObject);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
if (this.navigated === domainObject) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
var doNotNavigate = this.shouldWarnBeforeNavigate();
|
|
||||||
if (doNotNavigate && !this.$window.confirm(doNotNavigate)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.doNavigation(domainObject);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listen for changes in navigation. The passed callback will
|
|
||||||
* be invoked with the new domain object of navigation when
|
|
||||||
* this changes.
|
|
||||||
*
|
|
||||||
* @param {function} callback the callback to invoke when
|
|
||||||
* navigation state changes
|
|
||||||
*/
|
|
||||||
NavigationService.prototype.addListener = function (callback) {
|
|
||||||
this.callbacks.push(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stop listening for changes in navigation state.
|
|
||||||
*
|
|
||||||
* @param {function} callback the callback which should
|
|
||||||
* no longer be invoked when navigation state
|
|
||||||
* changes
|
|
||||||
*/
|
|
||||||
NavigationService.prototype.removeListener = function (callback) {
|
|
||||||
this.callbacks = this.callbacks.filter(function (cb) {
|
|
||||||
return cb !== callback;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if navigation should proceed. May prompt a user for input
|
|
||||||
* if any checkFns return messages. Returns true if the user wishes to
|
|
||||||
* navigate, otherwise false. If using this prior to calling
|
|
||||||
* `setNavigation`, you should call `setNavigation` with `force=true`
|
|
||||||
* to prevent duplicate dialogs being displayed to the user.
|
|
||||||
*
|
|
||||||
* @returns {Boolean} true if the user wishes to navigate, otherwise false.
|
|
||||||
*/
|
|
||||||
NavigationService.prototype.shouldNavigate = function () {
|
|
||||||
var doNotNavigate = this.shouldWarnBeforeNavigate();
|
|
||||||
|
|
||||||
return !doNotNavigate || this.$window.confirm(doNotNavigate);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a check function to be called before any navigation occurs.
|
|
||||||
* Check functions should return a human readable "message" if
|
|
||||||
* there are any reasons to prevent navigation. Otherwise, they should
|
|
||||||
* return falsy. Returns a function which can be called to remove the
|
|
||||||
* check function.
|
|
||||||
*
|
|
||||||
* @param {Function} checkFn a function to call before navigation occurs.
|
|
||||||
* @returns {Function} removeCheck call to remove check
|
|
||||||
*/
|
|
||||||
NavigationService.prototype.checkBeforeNavigation = function (checkFn) {
|
|
||||||
this.checks.push(checkFn);
|
|
||||||
|
|
||||||
return function removeCheck() {
|
|
||||||
this.checks = this.checks.filter(function (fn) {
|
|
||||||
return checkFn !== fn;
|
|
||||||
});
|
|
||||||
}.bind(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Private method to actually perform navigation.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
NavigationService.prototype.doNavigation = function (value) {
|
|
||||||
this.navigated = value;
|
|
||||||
this.callbacks.forEach(function (callback) {
|
|
||||||
callback(value);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns either a false value, or a string that should be displayed
|
|
||||||
* to the user before navigation is allowed.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
NavigationService.prototype.shouldWarnBeforeNavigate = function () {
|
|
||||||
var reasons = [];
|
|
||||||
this.checks.forEach(function (checkFn) {
|
|
||||||
var reason = checkFn();
|
|
||||||
if (reason) {
|
|
||||||
reasons.push(reason);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (reasons.length) {
|
|
||||||
return reasons.join('\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listener for window on before unload event-- will warn before
|
|
||||||
* navigation is allowed.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
NavigationService.prototype.onBeforeUnload = function () {
|
|
||||||
var shouldWarnBeforeNavigate = this.shouldWarnBeforeNavigate();
|
|
||||||
if (shouldWarnBeforeNavigate) {
|
|
||||||
return shouldWarnBeforeNavigate;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.oldUnload) {
|
|
||||||
return this.oldUnload.apply(undefined, [].slice.apply(arguments));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return NavigationService;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
if (this.navigated === domainObject) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var doNotNavigate = this.shouldWarnBeforeNavigate();
|
||||||
|
if (doNotNavigate && !this.$window.confirm(doNotNavigate)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.doNavigation(domainObject);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listen for changes in navigation. The passed callback will
|
||||||
|
* be invoked with the new domain object of navigation when
|
||||||
|
* this changes.
|
||||||
|
*
|
||||||
|
* @param {function} callback the callback to invoke when
|
||||||
|
* navigation state changes
|
||||||
|
*/
|
||||||
|
NavigationService.prototype.addListener = function (callback) {
|
||||||
|
this.callbacks.push(callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stop listening for changes in navigation state.
|
||||||
|
*
|
||||||
|
* @param {function} callback the callback which should
|
||||||
|
* no longer be invoked when navigation state
|
||||||
|
* changes
|
||||||
|
*/
|
||||||
|
NavigationService.prototype.removeListener = function (callback) {
|
||||||
|
this.callbacks = this.callbacks.filter(function (cb) {
|
||||||
|
return cb !== callback;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if navigation should proceed. May prompt a user for input
|
||||||
|
* if any checkFns return messages. Returns true if the user wishes to
|
||||||
|
* navigate, otherwise false. If using this prior to calling
|
||||||
|
* `setNavigation`, you should call `setNavigation` with `force=true`
|
||||||
|
* to prevent duplicate dialogs being displayed to the user.
|
||||||
|
*
|
||||||
|
* @returns {Boolean} true if the user wishes to navigate, otherwise false.
|
||||||
|
*/
|
||||||
|
NavigationService.prototype.shouldNavigate = function () {
|
||||||
|
var doNotNavigate = this.shouldWarnBeforeNavigate();
|
||||||
|
|
||||||
|
return !doNotNavigate || this.$window.confirm(doNotNavigate);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a check function to be called before any navigation occurs.
|
||||||
|
* Check functions should return a human readable "message" if
|
||||||
|
* there are any reasons to prevent navigation. Otherwise, they should
|
||||||
|
* return falsy. Returns a function which can be called to remove the
|
||||||
|
* check function.
|
||||||
|
*
|
||||||
|
* @param {Function} checkFn a function to call before navigation occurs.
|
||||||
|
* @returns {Function} removeCheck call to remove check
|
||||||
|
*/
|
||||||
|
NavigationService.prototype.checkBeforeNavigation = function (checkFn) {
|
||||||
|
this.checks.push(checkFn);
|
||||||
|
|
||||||
|
return function removeCheck() {
|
||||||
|
this.checks = this.checks.filter(function (fn) {
|
||||||
|
return checkFn !== fn;
|
||||||
|
});
|
||||||
|
}.bind(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private method to actually perform navigation.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
NavigationService.prototype.doNavigation = function (value) {
|
||||||
|
this.navigated = value;
|
||||||
|
this.callbacks.forEach(function (callback) {
|
||||||
|
callback(value);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns either a false value, or a string that should be displayed
|
||||||
|
* to the user before navigation is allowed.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
NavigationService.prototype.shouldWarnBeforeNavigate = function () {
|
||||||
|
var reasons = [];
|
||||||
|
this.checks.forEach(function (checkFn) {
|
||||||
|
var reason = checkFn();
|
||||||
|
if (reason) {
|
||||||
|
reasons.push(reason);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (reasons.length) {
|
||||||
|
return reasons.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener for window on before unload event-- will warn before
|
||||||
|
* navigation is allowed.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
NavigationService.prototype.onBeforeUnload = function () {
|
||||||
|
var shouldWarnBeforeNavigate = this.shouldWarnBeforeNavigate();
|
||||||
|
if (shouldWarnBeforeNavigate) {
|
||||||
|
return shouldWarnBeforeNavigate;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.oldUnload) {
|
||||||
|
return this.oldUnload.apply(undefined, [].slice.apply(arguments));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NavigationService;
|
@ -20,57 +20,63 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([], function () {
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function OrphanNavigationHandler(throttle, topic, navigationService) {
|
||||||
* Navigates away from orphan objects whenever they are detected.
|
var throttledCheckNavigation;
|
||||||
*
|
|
||||||
* An orphan object is an object whose apparent parent does not
|
|
||||||
* actually contain it. This may occur in certain circumstances, such
|
|
||||||
* as when persistence succeeds for a newly-created object but fails
|
|
||||||
* for its parent.
|
|
||||||
*
|
|
||||||
* @param throttle the `throttle` service
|
|
||||||
* @param topic the `topic` service
|
|
||||||
* @param navigationService the `navigationService`
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function OrphanNavigationHandler(throttle, topic, navigationService) {
|
|
||||||
var throttledCheckNavigation;
|
|
||||||
|
|
||||||
function getParent(domainObject) {
|
function getParent(domainObject) {
|
||||||
var context = domainObject.getCapability('context');
|
var context = domainObject.getCapability('context');
|
||||||
|
|
||||||
return context.getParent();
|
return context.getParent();
|
||||||
}
|
|
||||||
|
|
||||||
function preventOrphanNavigation(domainObject) {
|
|
||||||
var parent = getParent(domainObject);
|
|
||||||
parent.useCapability('composition')
|
|
||||||
.then(function (composees) {
|
|
||||||
var isOrphan = composees.every(function (c) {
|
|
||||||
return c.getId() !== domainObject.getId();
|
|
||||||
});
|
|
||||||
if (isOrphan) {
|
|
||||||
parent.getCapability('action').perform('navigate');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkNavigation() {
|
|
||||||
var navigatedObject = navigationService.getNavigation();
|
|
||||||
if (navigatedObject && navigatedObject.hasCapability('context')) {
|
|
||||||
if (!navigatedObject.getCapability('editor').isEditContextRoot()) {
|
|
||||||
preventOrphanNavigation(navigatedObject);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throttledCheckNavigation = throttle(checkNavigation);
|
|
||||||
|
|
||||||
navigationService.addListener(throttledCheckNavigation);
|
|
||||||
topic('mutation').listen(throttledCheckNavigation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return OrphanNavigationHandler;
|
function preventOrphanNavigation(domainObject) {
|
||||||
});
|
var parent = getParent(domainObject);
|
||||||
|
parent.useCapability('composition')
|
||||||
|
.then(function (composees) {
|
||||||
|
var isOrphan = composees.every(function (c) {
|
||||||
|
return c.getId() !== domainObject.getId();
|
||||||
|
});
|
||||||
|
if (isOrphan) {
|
||||||
|
parent.getCapability('action').perform('navigate');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkNavigation() {
|
||||||
|
var navigatedObject = navigationService.getNavigation();
|
||||||
|
if (navigatedObject && navigatedObject.hasCapability('context')) {
|
||||||
|
if (!navigatedObject.getCapability('editor').isEditContextRoot()) {
|
||||||
|
preventOrphanNavigation(navigatedObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throttledCheckNavigation = throttle(checkNavigation);
|
||||||
|
|
||||||
|
navigationService.addListener(throttledCheckNavigation);
|
||||||
|
topic('mutation').listen(throttledCheckNavigation);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default OrphanNavigationHandler;
|
@ -23,21 +23,42 @@
|
|||||||
/**
|
/**
|
||||||
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../src/InspectorRegion"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (InspectorRegion) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The inspector region", function () {
|
/**
|
||||||
var inspectorRegion;
|
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
||||||
|
*/
|
||||||
|
import InspectorRegion from '../src/InspectorRegion';
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The inspector region", function () {
|
||||||
inspectorRegion = new InspectorRegion();
|
var inspectorRegion;
|
||||||
});
|
|
||||||
|
|
||||||
it("creates default region parts", function () {
|
beforeEach(function () {
|
||||||
expect(inspectorRegion.regions.length).toBe(1);
|
inspectorRegion = new InspectorRegion();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
it("creates default region parts", function () {
|
||||||
}
|
expect(inspectorRegion.regions.length).toBe(1);
|
||||||
);
|
});
|
||||||
|
|
||||||
|
});
|
@ -23,63 +23,83 @@
|
|||||||
/**
|
/**
|
||||||
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
|
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
|
||||||
*/
|
*/
|
||||||
define([
|
/*****************************************************************************
|
||||||
"../../src/navigation/NavigateAction"
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
NavigateAction
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The navigate action", function () {
|
/**
|
||||||
var mockNavigationService,
|
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
|
||||||
mockDomainObject,
|
*/
|
||||||
action;
|
import NavigateAction from '../../src/navigation/NavigateAction';
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The navigate action", function () {
|
||||||
mockNavigationService = jasmine.createSpyObj(
|
var mockNavigationService,
|
||||||
"navigationService",
|
mockDomainObject,
|
||||||
[
|
action;
|
||||||
"shouldNavigate",
|
|
||||||
"setNavigation"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
mockDomainObject = {};
|
beforeEach(function () {
|
||||||
|
mockNavigationService = jasmine.createSpyObj(
|
||||||
|
"navigationService",
|
||||||
|
[
|
||||||
|
"shouldNavigate",
|
||||||
|
"setNavigation"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
action = new NavigateAction(
|
mockDomainObject = {};
|
||||||
mockNavigationService,
|
|
||||||
{ domainObject: mockDomainObject }
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("sets navigation if it is allowed", function () {
|
|
||||||
mockNavigationService.shouldNavigate.and.returnValue(true);
|
|
||||||
|
|
||||||
return action.perform()
|
|
||||||
.then(function () {
|
|
||||||
expect(mockNavigationService.setNavigation)
|
|
||||||
.toHaveBeenCalledWith(mockDomainObject, true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not set navigation if it is not allowed", function () {
|
|
||||||
mockNavigationService.shouldNavigate.and.returnValue(false);
|
|
||||||
var onSuccess = jasmine.createSpy('onSuccess');
|
|
||||||
|
|
||||||
return action.perform()
|
|
||||||
.then(onSuccess, function () {
|
|
||||||
expect(onSuccess).not.toHaveBeenCalled();
|
|
||||||
expect(mockNavigationService.setNavigation)
|
|
||||||
.not
|
|
||||||
.toHaveBeenCalledWith(mockDomainObject);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("is only applicable when a domain object is in context", function () {
|
|
||||||
expect(NavigateAction.appliesTo({})).toBeFalsy();
|
|
||||||
expect(NavigateAction.appliesTo({
|
|
||||||
domainObject: mockDomainObject
|
|
||||||
})).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
action = new NavigateAction(
|
||||||
|
mockNavigationService,
|
||||||
|
{ domainObject: mockDomainObject }
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
it("sets navigation if it is allowed", function () {
|
||||||
|
mockNavigationService.shouldNavigate.and.returnValue(true);
|
||||||
|
|
||||||
|
return action.perform()
|
||||||
|
.then(function () {
|
||||||
|
expect(mockNavigationService.setNavigation)
|
||||||
|
.toHaveBeenCalledWith(mockDomainObject, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not set navigation if it is not allowed", function () {
|
||||||
|
mockNavigationService.shouldNavigate.and.returnValue(false);
|
||||||
|
var onSuccess = jasmine.createSpy('onSuccess');
|
||||||
|
|
||||||
|
return action.perform()
|
||||||
|
.then(onSuccess, function () {
|
||||||
|
expect(onSuccess).not.toHaveBeenCalled();
|
||||||
|
expect(mockNavigationService.setNavigation)
|
||||||
|
.not
|
||||||
|
.toHaveBeenCalledWith(mockDomainObject);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is only applicable when a domain object is in context", function () {
|
||||||
|
expect(NavigateAction.appliesTo({})).toBeFalsy();
|
||||||
|
expect(NavigateAction.appliesTo({
|
||||||
|
domainObject: mockDomainObject
|
||||||
|
})).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -23,66 +23,87 @@
|
|||||||
/**
|
/**
|
||||||
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
|
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/navigation/NavigationService"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (NavigationService) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The navigation service", function () {
|
/**
|
||||||
var $window,
|
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
|
||||||
navigationService;
|
*/
|
||||||
|
import NavigationService from '../../src/navigation/NavigationService';
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The navigation service", function () {
|
||||||
$window = jasmine.createSpyObj('$window', ['confirm']);
|
var $window,
|
||||||
navigationService = new NavigationService($window);
|
navigationService;
|
||||||
});
|
|
||||||
|
|
||||||
it("stores navigation state", function () {
|
beforeEach(function () {
|
||||||
var testObject = { someKey: 42 },
|
$window = jasmine.createSpyObj('$window', ['confirm']);
|
||||||
otherObject = { someKey: "some value" };
|
navigationService = new NavigationService($window);
|
||||||
expect(navigationService.getNavigation())
|
});
|
||||||
.toBeUndefined();
|
|
||||||
navigationService.setNavigation(testObject);
|
|
||||||
expect(navigationService.getNavigation())
|
|
||||||
.toBe(testObject);
|
|
||||||
expect(navigationService.getNavigation())
|
|
||||||
.toBe(testObject);
|
|
||||||
navigationService.setNavigation(otherObject);
|
|
||||||
expect(navigationService.getNavigation())
|
|
||||||
.toBe(otherObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("notifies listeners on change", function () {
|
it("stores navigation state", function () {
|
||||||
var testObject = { someKey: 42 },
|
var testObject = { someKey: 42 },
|
||||||
callback = jasmine.createSpy("callback");
|
otherObject = { someKey: "some value" };
|
||||||
|
expect(navigationService.getNavigation())
|
||||||
|
.toBeUndefined();
|
||||||
|
navigationService.setNavigation(testObject);
|
||||||
|
expect(navigationService.getNavigation())
|
||||||
|
.toBe(testObject);
|
||||||
|
expect(navigationService.getNavigation())
|
||||||
|
.toBe(testObject);
|
||||||
|
navigationService.setNavigation(otherObject);
|
||||||
|
expect(navigationService.getNavigation())
|
||||||
|
.toBe(otherObject);
|
||||||
|
});
|
||||||
|
|
||||||
navigationService.addListener(callback);
|
it("notifies listeners on change", function () {
|
||||||
expect(callback).not.toHaveBeenCalled();
|
var testObject = { someKey: 42 },
|
||||||
|
callback = jasmine.createSpy("callback");
|
||||||
|
|
||||||
navigationService.setNavigation(testObject);
|
navigationService.addListener(callback);
|
||||||
expect(callback).toHaveBeenCalledWith(testObject);
|
expect(callback).not.toHaveBeenCalled();
|
||||||
});
|
|
||||||
|
|
||||||
it("does not notify listeners when no changes occur", function () {
|
navigationService.setNavigation(testObject);
|
||||||
var testObject = { someKey: 42 },
|
expect(callback).toHaveBeenCalledWith(testObject);
|
||||||
callback = jasmine.createSpy("callback");
|
});
|
||||||
|
|
||||||
navigationService.addListener(callback);
|
it("does not notify listeners when no changes occur", function () {
|
||||||
navigationService.setNavigation(testObject);
|
var testObject = { someKey: 42 },
|
||||||
navigationService.setNavigation(testObject);
|
callback = jasmine.createSpy("callback");
|
||||||
expect(callback.calls.count()).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("stops notifying listeners after removal", function () {
|
navigationService.addListener(callback);
|
||||||
var testObject = { someKey: 42 },
|
navigationService.setNavigation(testObject);
|
||||||
callback = jasmine.createSpy("callback");
|
navigationService.setNavigation(testObject);
|
||||||
|
expect(callback.calls.count()).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
navigationService.addListener(callback);
|
it("stops notifying listeners after removal", function () {
|
||||||
navigationService.removeListener(callback);
|
var testObject = { someKey: 42 },
|
||||||
|
callback = jasmine.createSpy("callback");
|
||||||
|
|
||||||
navigationService.setNavigation(testObject);
|
navigationService.addListener(callback);
|
||||||
expect(callback).not.toHaveBeenCalled();
|
navigationService.removeListener(callback);
|
||||||
});
|
|
||||||
|
|
||||||
});
|
navigationService.setNavigation(testObject);
|
||||||
}
|
expect(callback).not.toHaveBeenCalled();
|
||||||
);
|
});
|
||||||
|
|
||||||
|
});
|
@ -20,163 +20,182 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
'../../src/navigation/OrphanNavigationHandler'
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (OrphanNavigationHandler) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
describe("OrphanNavigationHandler", function () {
|
* Administration. All rights reserved.
|
||||||
var mockTopic,
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import OrphanNavigationHandler from '../../src/navigation/OrphanNavigationHandler';
|
||||||
|
|
||||||
|
describe("OrphanNavigationHandler", function () {
|
||||||
|
var mockTopic,
|
||||||
|
mockThrottle,
|
||||||
|
mockMutationTopic,
|
||||||
|
mockNavigationService,
|
||||||
|
mockDomainObject,
|
||||||
|
mockParentObject,
|
||||||
|
mockContext,
|
||||||
|
mockActionCapability,
|
||||||
|
mockEditor,
|
||||||
|
testParentComposition,
|
||||||
|
testId,
|
||||||
|
mockThrottledFns;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
testId = 'some-identifier';
|
||||||
|
|
||||||
|
mockThrottledFns = [];
|
||||||
|
|
||||||
|
mockTopic = jasmine.createSpy('topic');
|
||||||
|
mockThrottle = jasmine.createSpy('throttle');
|
||||||
|
mockNavigationService = jasmine.createSpyObj('navigationService', [
|
||||||
|
'getNavigation',
|
||||||
|
'addListener'
|
||||||
|
]);
|
||||||
|
mockMutationTopic = jasmine.createSpyObj('mutationTopic', [
|
||||||
|
'listen'
|
||||||
|
]);
|
||||||
|
mockDomainObject = jasmine.createSpyObj('domainObject', [
|
||||||
|
'getId',
|
||||||
|
'getCapability',
|
||||||
|
'hasCapability'
|
||||||
|
]);
|
||||||
|
mockParentObject = jasmine.createSpyObj('domainObject', [
|
||||||
|
'getId',
|
||||||
|
'getCapability',
|
||||||
|
'useCapability'
|
||||||
|
]);
|
||||||
|
mockContext = jasmine.createSpyObj('context', ['getParent']);
|
||||||
|
mockActionCapability = jasmine.createSpyObj('action', ['perform']);
|
||||||
|
mockEditor = jasmine.createSpyObj('editor', ['isEditContextRoot']);
|
||||||
|
|
||||||
|
mockThrottle.and.callFake(function (fn) {
|
||||||
|
var mockThrottledFn =
|
||||||
|
jasmine.createSpy('throttled-' + mockThrottledFns.length);
|
||||||
|
mockThrottledFn.and.callFake(fn);
|
||||||
|
mockThrottledFns.push(mockThrottledFn);
|
||||||
|
|
||||||
|
return mockThrottledFn;
|
||||||
|
});
|
||||||
|
mockTopic.and.returnValue(mockMutationTopic);
|
||||||
|
mockDomainObject.getId.and.returnValue(testId);
|
||||||
|
mockDomainObject.getCapability.and.callFake(function (c) {
|
||||||
|
return {
|
||||||
|
context: mockContext,
|
||||||
|
editor: mockEditor
|
||||||
|
}[c];
|
||||||
|
});
|
||||||
|
mockDomainObject.hasCapability.and.callFake(function (c) {
|
||||||
|
return Boolean(mockDomainObject.getCapability(c));
|
||||||
|
});
|
||||||
|
mockParentObject.getCapability.and.callFake(function (c) {
|
||||||
|
return {
|
||||||
|
action: mockActionCapability
|
||||||
|
}[c];
|
||||||
|
});
|
||||||
|
testParentComposition = [];
|
||||||
|
mockParentObject.useCapability.and.returnValue(Promise.resolve(testParentComposition));
|
||||||
|
|
||||||
|
mockContext.getParent.and.returnValue(mockParentObject);
|
||||||
|
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
|
||||||
|
mockEditor.isEditContextRoot.and.returnValue(false);
|
||||||
|
|
||||||
|
return new OrphanNavigationHandler(
|
||||||
mockThrottle,
|
mockThrottle,
|
||||||
mockMutationTopic,
|
mockTopic,
|
||||||
mockNavigationService,
|
mockNavigationService
|
||||||
mockDomainObject,
|
);
|
||||||
mockParentObject,
|
|
||||||
mockContext,
|
|
||||||
mockActionCapability,
|
|
||||||
mockEditor,
|
|
||||||
testParentComposition,
|
|
||||||
testId,
|
|
||||||
mockThrottledFns;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
testId = 'some-identifier';
|
|
||||||
|
|
||||||
mockThrottledFns = [];
|
|
||||||
|
|
||||||
mockTopic = jasmine.createSpy('topic');
|
|
||||||
mockThrottle = jasmine.createSpy('throttle');
|
|
||||||
mockNavigationService = jasmine.createSpyObj('navigationService', [
|
|
||||||
'getNavigation',
|
|
||||||
'addListener'
|
|
||||||
]);
|
|
||||||
mockMutationTopic = jasmine.createSpyObj('mutationTopic', [
|
|
||||||
'listen'
|
|
||||||
]);
|
|
||||||
mockDomainObject = jasmine.createSpyObj('domainObject', [
|
|
||||||
'getId',
|
|
||||||
'getCapability',
|
|
||||||
'hasCapability'
|
|
||||||
]);
|
|
||||||
mockParentObject = jasmine.createSpyObj('domainObject', [
|
|
||||||
'getId',
|
|
||||||
'getCapability',
|
|
||||||
'useCapability'
|
|
||||||
]);
|
|
||||||
mockContext = jasmine.createSpyObj('context', ['getParent']);
|
|
||||||
mockActionCapability = jasmine.createSpyObj('action', ['perform']);
|
|
||||||
mockEditor = jasmine.createSpyObj('editor', ['isEditContextRoot']);
|
|
||||||
|
|
||||||
mockThrottle.and.callFake(function (fn) {
|
|
||||||
var mockThrottledFn =
|
|
||||||
jasmine.createSpy('throttled-' + mockThrottledFns.length);
|
|
||||||
mockThrottledFn.and.callFake(fn);
|
|
||||||
mockThrottledFns.push(mockThrottledFn);
|
|
||||||
|
|
||||||
return mockThrottledFn;
|
|
||||||
});
|
|
||||||
mockTopic.and.returnValue(mockMutationTopic);
|
|
||||||
mockDomainObject.getId.and.returnValue(testId);
|
|
||||||
mockDomainObject.getCapability.and.callFake(function (c) {
|
|
||||||
return {
|
|
||||||
context: mockContext,
|
|
||||||
editor: mockEditor
|
|
||||||
}[c];
|
|
||||||
});
|
|
||||||
mockDomainObject.hasCapability.and.callFake(function (c) {
|
|
||||||
return Boolean(mockDomainObject.getCapability(c));
|
|
||||||
});
|
|
||||||
mockParentObject.getCapability.and.callFake(function (c) {
|
|
||||||
return {
|
|
||||||
action: mockActionCapability
|
|
||||||
}[c];
|
|
||||||
});
|
|
||||||
testParentComposition = [];
|
|
||||||
mockParentObject.useCapability.and.returnValue(Promise.resolve(testParentComposition));
|
|
||||||
|
|
||||||
mockContext.getParent.and.returnValue(mockParentObject);
|
|
||||||
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
|
|
||||||
mockEditor.isEditContextRoot.and.returnValue(false);
|
|
||||||
|
|
||||||
return new OrphanNavigationHandler(
|
|
||||||
mockThrottle,
|
|
||||||
mockTopic,
|
|
||||||
mockNavigationService
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("listens for mutation with a throttled function", function () {
|
|
||||||
expect(mockMutationTopic.listen)
|
|
||||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
|
||||||
expect(mockThrottledFns.indexOf(
|
|
||||||
mockMutationTopic.listen.calls.mostRecent().args[0]
|
|
||||||
)).not.toEqual(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("listens for navigation changes with a throttled function", function () {
|
|
||||||
expect(mockNavigationService.addListener)
|
|
||||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
|
||||||
expect(mockThrottledFns.indexOf(
|
|
||||||
mockNavigationService.addListener.calls.mostRecent().args[0]
|
|
||||||
)).not.toEqual(-1);
|
|
||||||
});
|
|
||||||
|
|
||||||
[false, true].forEach(function (isOrphan) {
|
|
||||||
var prefix = isOrphan ? "" : "non-";
|
|
||||||
describe("for " + prefix + "orphan objects", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
if (!isOrphan) {
|
|
||||||
testParentComposition.push(mockDomainObject);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
[false, true].forEach(function (isEditRoot) {
|
|
||||||
var caseName = isEditRoot
|
|
||||||
? "that are being edited" : "that are not being edited";
|
|
||||||
|
|
||||||
function itNavigatesAsExpected() {
|
|
||||||
if (isOrphan && !isEditRoot) {
|
|
||||||
it("navigates to the parent", function () {
|
|
||||||
return Promise.resolve().then(function () {
|
|
||||||
expect(mockActionCapability.perform)
|
|
||||||
.toHaveBeenCalledWith('navigate');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
it("does nothing", function () {
|
|
||||||
return Promise.resolve().then(function () {
|
|
||||||
expect(mockActionCapability.perform)
|
|
||||||
.not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
describe(caseName, function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
mockEditor.isEditContextRoot.and.returnValue(isEditRoot);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when navigation changes", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
mockNavigationService.addListener.calls.mostRecent()
|
|
||||||
.args[0](mockDomainObject);
|
|
||||||
});
|
|
||||||
itNavigatesAsExpected();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when mutation occurs", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
mockMutationTopic.listen.calls.mostRecent()
|
|
||||||
.args[0](mockParentObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
itNavigatesAsExpected();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
it("listens for mutation with a throttled function", function () {
|
||||||
|
expect(mockMutationTopic.listen)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
expect(mockThrottledFns.indexOf(
|
||||||
|
mockMutationTopic.listen.calls.mostRecent().args[0]
|
||||||
|
)).not.toEqual(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("listens for navigation changes with a throttled function", function () {
|
||||||
|
expect(mockNavigationService.addListener)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
expect(mockThrottledFns.indexOf(
|
||||||
|
mockNavigationService.addListener.calls.mostRecent().args[0]
|
||||||
|
)).not.toEqual(-1);
|
||||||
|
});
|
||||||
|
|
||||||
|
[false, true].forEach(function (isOrphan) {
|
||||||
|
var prefix = isOrphan ? "" : "non-";
|
||||||
|
describe("for " + prefix + "orphan objects", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
if (!isOrphan) {
|
||||||
|
testParentComposition.push(mockDomainObject);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
[false, true].forEach(function (isEditRoot) {
|
||||||
|
var caseName = isEditRoot
|
||||||
|
? "that are being edited" : "that are not being edited";
|
||||||
|
|
||||||
|
function itNavigatesAsExpected() {
|
||||||
|
if (isOrphan && !isEditRoot) {
|
||||||
|
it("navigates to the parent", function () {
|
||||||
|
return Promise.resolve().then(function () {
|
||||||
|
expect(mockActionCapability.perform)
|
||||||
|
.toHaveBeenCalledWith('navigate');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
it("does nothing", function () {
|
||||||
|
return Promise.resolve().then(function () {
|
||||||
|
expect(mockActionCapability.perform)
|
||||||
|
.not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe(caseName, function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
mockEditor.isEditContextRoot.and.returnValue(isEditRoot);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when navigation changes", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
mockNavigationService.addListener.calls.mostRecent()
|
||||||
|
.args[0](mockDomainObject);
|
||||||
|
});
|
||||||
|
itNavigatesAsExpected();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when mutation occurs", function () {
|
||||||
|
beforeEach(function () {
|
||||||
|
mockMutationTopic.listen.calls.mostRecent()
|
||||||
|
.args[0](mockParentObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
itNavigatesAsExpected();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -20,93 +20,102 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/DialogService",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/OverlayService",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"./res/templates/overlay-dialog.html",
|
* Administration. All rights reserved.
|
||||||
"./res/templates/overlay-options.html",
|
*
|
||||||
"./res/templates/dialog.html",
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
"./res/templates/overlay-blocking-message.html",
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
"./res/templates/message.html",
|
* You may obtain a copy of the License at
|
||||||
"./res/templates/notification-message.html",
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
"./res/templates/overlay-message-list.html",
|
*
|
||||||
"./res/templates/overlay.html"
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
], function (
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
DialogService,
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
OverlayService,
|
* License for the specific language governing permissions and limitations
|
||||||
overlayDialogTemplate,
|
* under the License.
|
||||||
overlayOptionsTemplate,
|
*
|
||||||
dialogTemplate,
|
* Open MCT includes source code licensed under additional open source
|
||||||
overlayBlockingMessageTemplate,
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
messageTemplate,
|
* this source code distribution or the Licensing information page available
|
||||||
notificationMessageTemplate,
|
* at runtime from the About dialog for additional information.
|
||||||
overlayMessageListTemplate,
|
*****************************************************************************/
|
||||||
overlayTemplate
|
|
||||||
) {
|
|
||||||
|
|
||||||
return {
|
import DialogService from './src/DialogService';
|
||||||
name: "platform/commonUI/dialog",
|
|
||||||
definition: {
|
import OverlayService from './src/OverlayService';
|
||||||
"extensions": {
|
import overlayDialogTemplate from './res/templates/overlay-dialog.html';
|
||||||
"services": [
|
import overlayOptionsTemplate from './res/templates/overlay-options.html';
|
||||||
{
|
import dialogTemplate from './res/templates/dialog.html';
|
||||||
"key": "dialogService",
|
import overlayBlockingMessageTemplate from './res/templates/overlay-blocking-message.html';
|
||||||
"implementation": DialogService,
|
import messageTemplate from './res/templates/message.html';
|
||||||
"depends": [
|
import notificationMessageTemplate from './res/templates/notification-message.html';
|
||||||
"overlayService",
|
import overlayMessageListTemplate from './res/templates/overlay-message-list.html';
|
||||||
"$q",
|
import overlayTemplate from './res/templates/overlay.html';
|
||||||
"$log",
|
|
||||||
"$document"
|
export default {
|
||||||
]
|
name: "platform/commonUI/dialog",
|
||||||
},
|
definition: {
|
||||||
{
|
"extensions": {
|
||||||
"key": "overlayService",
|
"services": [
|
||||||
"implementation": OverlayService,
|
{
|
||||||
"depends": [
|
"key": "dialogService",
|
||||||
"$document",
|
"implementation": DialogService,
|
||||||
"$compile",
|
"depends": [
|
||||||
"$rootScope",
|
"overlayService",
|
||||||
"$timeout"
|
"$q",
|
||||||
]
|
"$log",
|
||||||
}
|
"$document"
|
||||||
],
|
]
|
||||||
"templates": [
|
},
|
||||||
{
|
{
|
||||||
"key": "overlay-dialog",
|
"key": "overlayService",
|
||||||
"template": overlayDialogTemplate
|
"implementation": OverlayService,
|
||||||
},
|
"depends": [
|
||||||
{
|
"$document",
|
||||||
"key": "overlay-options",
|
"$compile",
|
||||||
"template": overlayOptionsTemplate
|
"$rootScope",
|
||||||
},
|
"$timeout"
|
||||||
{
|
]
|
||||||
"key": "form-dialog",
|
}
|
||||||
"template": dialogTemplate
|
],
|
||||||
},
|
"templates": [
|
||||||
{
|
{
|
||||||
"key": "overlay-blocking-message",
|
"key": "overlay-dialog",
|
||||||
"template": overlayBlockingMessageTemplate
|
"template": overlayDialogTemplate
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "message",
|
"key": "overlay-options",
|
||||||
"template": messageTemplate
|
"template": overlayOptionsTemplate
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "notification-message",
|
"key": "form-dialog",
|
||||||
"template": notificationMessageTemplate
|
"template": dialogTemplate
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "overlay-message-list",
|
"key": "overlay-blocking-message",
|
||||||
"template": overlayMessageListTemplate
|
"template": overlayBlockingMessageTemplate
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"containers": [
|
"key": "message",
|
||||||
{
|
"template": messageTemplate
|
||||||
"key": "overlay",
|
},
|
||||||
"template": overlayTemplate
|
{
|
||||||
}
|
"key": "notification-message",
|
||||||
]
|
"template": notificationMessageTemplate
|
||||||
}
|
},
|
||||||
|
{
|
||||||
|
"key": "overlay-message-list",
|
||||||
|
"template": overlayMessageListTemplate
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"containers": [
|
||||||
|
{
|
||||||
|
"key": "overlay",
|
||||||
|
"template": overlayTemplate
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -25,247 +25,262 @@
|
|||||||
* launch dialogs for user input & notifications.
|
* launch dialogs for user input & notifications.
|
||||||
* @namespace platform/commonUI/dialog
|
* @namespace platform/commonUI/dialog
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
/**
|
* Administration. All rights reserved.
|
||||||
* The dialog service is responsible for handling window-modal
|
*
|
||||||
* communication with the user, such as displaying forms for user
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
* input.
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
* @memberof platform/commonUI/dialog
|
* You may obtain a copy of the License at
|
||||||
* @constructor
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
*/
|
*
|
||||||
function DialogService(overlayService, $q, $log, $document) {
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
this.overlayService = overlayService;
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
this.$q = $q;
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
this.$log = $log;
|
* License for the specific language governing permissions and limitations
|
||||||
this.activeOverlay = undefined;
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
this.findBody = function () {
|
/**
|
||||||
return $document.find('body');
|
* This bundle implements the dialog service, which can be used to
|
||||||
};
|
* launch dialogs for user input & notifications.
|
||||||
}
|
* @namespace platform/commonUI/dialog
|
||||||
|
*/
|
||||||
|
function DialogService(overlayService, $q, $log, $document) {
|
||||||
|
this.overlayService = overlayService;
|
||||||
|
this.$q = $q;
|
||||||
|
this.$log = $log;
|
||||||
|
this.activeOverlay = undefined;
|
||||||
|
|
||||||
/**
|
this.findBody = function () {
|
||||||
* @private
|
return $document.find('body');
|
||||||
*/
|
};
|
||||||
DialogService.prototype.dismissOverlay = function (overlay) {
|
}
|
||||||
//Dismiss the overlay
|
|
||||||
overlay.dismiss();
|
|
||||||
|
|
||||||
//If dialog is the current active one, dismiss it
|
/**
|
||||||
if (overlay === this.activeOverlay) {
|
* @private
|
||||||
this.activeOverlay = undefined;
|
*/
|
||||||
}
|
DialogService.prototype.dismissOverlay = function (overlay) {
|
||||||
};
|
//Dismiss the overlay
|
||||||
|
overlay.dismiss();
|
||||||
|
|
||||||
DialogService.prototype.getDialogResponse = function (key, model, resultGetter, typeClass) {
|
//If dialog is the current active one, dismiss it
|
||||||
// We will return this result as a promise, because user
|
if (overlay === this.activeOverlay) {
|
||||||
// input is asynchronous.
|
this.activeOverlay = undefined;
|
||||||
var deferred = this.$q.defer(),
|
|
||||||
self = this,
|
|
||||||
overlay,
|
|
||||||
handleEscKeydown;
|
|
||||||
|
|
||||||
// Confirm function; this will be passed in to the
|
|
||||||
// overlay-dialog template and associated with a
|
|
||||||
// OK button click
|
|
||||||
function confirm(value) {
|
|
||||||
// Pass along the result
|
|
||||||
deferred.resolve(resultGetter ? resultGetter() : value);
|
|
||||||
self.dismissOverlay(overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cancel function; this will be passed in to the
|
|
||||||
// overlay-dialog template and associated with a
|
|
||||||
// Cancel or X button click
|
|
||||||
function cancel() {
|
|
||||||
deferred.reject();
|
|
||||||
self.findBody().off('keydown', handleEscKeydown);
|
|
||||||
self.dismissOverlay(overlay);
|
|
||||||
}
|
|
||||||
|
|
||||||
handleEscKeydown = function (event) {
|
|
||||||
if (event.keyCode === 27) {
|
|
||||||
cancel();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Add confirm/cancel callbacks
|
|
||||||
model.confirm = confirm;
|
|
||||||
model.cancel = cancel;
|
|
||||||
|
|
||||||
this.findBody().on('keydown', handleEscKeydown);
|
|
||||||
|
|
||||||
if (this.canShowDialog(model)) {
|
|
||||||
// Add the overlay using the OverlayService, which
|
|
||||||
// will handle actual insertion into the DOM
|
|
||||||
overlay = this.activeOverlay = this.overlayService.createOverlay(
|
|
||||||
key,
|
|
||||||
model,
|
|
||||||
typeClass || "t-dialog"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
deferred.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
return deferred.promise;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request user input via a window-modal dialog.
|
|
||||||
*
|
|
||||||
* @param {FormModel} formModel a description of the form
|
|
||||||
* to be shown (see platform/forms)
|
|
||||||
* @param {object} value the initial state of the form
|
|
||||||
* @returns {Promise} a promise for the form value that the
|
|
||||||
* user has supplied; this may be rejected if
|
|
||||||
* user input cannot be obtained (for instance,
|
|
||||||
* because the user cancelled the dialog)
|
|
||||||
*/
|
|
||||||
DialogService.prototype.getUserInput = function (formModel, value) {
|
|
||||||
var overlayModel = {
|
|
||||||
title: formModel.name,
|
|
||||||
message: formModel.message,
|
|
||||||
structure: formModel,
|
|
||||||
value: value
|
|
||||||
};
|
|
||||||
|
|
||||||
// Provide result from the model
|
|
||||||
function resultGetter() {
|
|
||||||
return overlayModel.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show the overlay-dialog
|
|
||||||
return this.getDialogResponse(
|
|
||||||
"overlay-dialog",
|
|
||||||
overlayModel,
|
|
||||||
resultGetter
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request that the user chooses from a set of options,
|
|
||||||
* which will be shown as buttons.
|
|
||||||
*
|
|
||||||
* @param dialogModel a description of the dialog to show
|
|
||||||
* @return {Promise} a promise for the user's choice
|
|
||||||
*/
|
|
||||||
DialogService.prototype.getUserChoice = function (dialogModel) {
|
|
||||||
// Show the overlay-options dialog
|
|
||||||
return this.getDialogResponse(
|
|
||||||
"overlay-options",
|
|
||||||
{ dialog: dialogModel }
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests if a dialog can be displayed. A modal dialog may only be
|
|
||||||
* displayed if one is not already visible.
|
|
||||||
* Will log a warning message if it can't display a dialog.
|
|
||||||
* @returns {boolean} true if dialog is currently visible, false
|
|
||||||
* otherwise
|
|
||||||
*/
|
|
||||||
DialogService.prototype.canShowDialog = function (dialogModel) {
|
|
||||||
if (this.activeOverlay) {
|
|
||||||
// Only one dialog should be shown at a time.
|
|
||||||
// The application design should be such that
|
|
||||||
// we never even try to do this.
|
|
||||||
this.$log.warn([
|
|
||||||
"Dialog already showing; ",
|
|
||||||
"unable to show ",
|
|
||||||
dialogModel.title
|
|
||||||
].join(""));
|
|
||||||
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A user action that can be performed from a blocking dialog. These
|
|
||||||
* actions will be rendered as buttons within a blocking dialog.
|
|
||||||
*
|
|
||||||
* @typedef DialogOption
|
|
||||||
* @property {string} label a label to be displayed as the button
|
|
||||||
* text for this action
|
|
||||||
* @property {function} callback a function to be called when the
|
|
||||||
* button is clicked
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @typedef DialogHandle
|
|
||||||
* @property {function} dismiss a function to dismiss the given dialog
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A description of the model options that may be passed to the
|
|
||||||
* showBlockingMessage method. Note that the DialogModel described
|
|
||||||
* here is shared with the Notifications framework.
|
|
||||||
* @see NotificationService
|
|
||||||
*
|
|
||||||
* @typedef DialogModel
|
|
||||||
* @property {string} title the title to use for the dialog
|
|
||||||
* @property {string} severity the severity level of this message.
|
|
||||||
* These are defined in a bundle constant with key 'dialogSeverity'
|
|
||||||
* @property {string} hint the 'hint' message to show below the title
|
|
||||||
* @property {string} actionText text that indicates a current action,
|
|
||||||
* shown above a progress bar to indicate what's happening.
|
|
||||||
* @property {number} progress a percentage value (1-100)
|
|
||||||
* indicating the completion of the blocking task
|
|
||||||
* @property {boolean} delay adds a brief delay before loading
|
|
||||||
* the dialog. Useful for removing the dialog flicker when the
|
|
||||||
* conditions for displaying the dialog change rapidly.
|
|
||||||
* @property {string} progressText the message to show below a
|
|
||||||
* progress bar to indicate progress. For example, this might be
|
|
||||||
* used to indicate time remaining, or items still to process.
|
|
||||||
* @property {boolean} unknownProgress some tasks may be
|
|
||||||
* impossible to provide an estimate for. Providing a true value for
|
|
||||||
* this attribute will indicate to the user that the progress and
|
|
||||||
* duration cannot be estimated.
|
|
||||||
* @property {DialogOption} primaryOption an action that will
|
|
||||||
* be added to the dialog as a button. The primary action can be
|
|
||||||
* used as the suggested course of action for the user. Making it
|
|
||||||
* distinct from other actions allows it to be styled differently,
|
|
||||||
* and treated preferentially in banner mode.
|
|
||||||
* @property {DialogOption[]} options a list of actions that will
|
|
||||||
* be added to the dialog as buttons.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a blocking (modal) dialog. This dialog can be used for
|
|
||||||
* displaying messages that require the user's
|
|
||||||
* immediate attention. The message may include an indication of
|
|
||||||
* progress, as well as a series of actions that
|
|
||||||
* the user can take if necessary
|
|
||||||
* @param {DialogModel} dialogModel defines options for the dialog
|
|
||||||
* @param {typeClass} string tells overlayService that this overlay should use appropriate CSS class
|
|
||||||
* @returns {boolean | {DialogHandle}}
|
|
||||||
*/
|
|
||||||
DialogService.prototype.showBlockingMessage = function (dialogModel) {
|
|
||||||
if (this.canShowDialog(dialogModel)) {
|
|
||||||
// Add the overlay using the OverlayService, which
|
|
||||||
// will handle actual insertion into the DOM
|
|
||||||
var self = this,
|
|
||||||
overlay = this.overlayService.createOverlay(
|
|
||||||
"overlay-blocking-message",
|
|
||||||
dialogModel,
|
|
||||||
"t-dialog-sm"
|
|
||||||
);
|
|
||||||
|
|
||||||
this.activeOverlay = overlay;
|
|
||||||
|
|
||||||
return {
|
|
||||||
dismiss: function () {
|
|
||||||
self.dismissOverlay(overlay);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return DialogService;
|
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
|
|
||||||
|
DialogService.prototype.getDialogResponse = function (key, model, resultGetter, typeClass) {
|
||||||
|
// We will return this result as a promise, because user
|
||||||
|
// input is asynchronous.
|
||||||
|
var deferred = this.$q.defer(),
|
||||||
|
self = this,
|
||||||
|
overlay,
|
||||||
|
handleEscKeydown;
|
||||||
|
|
||||||
|
// Confirm function; this will be passed in to the
|
||||||
|
// overlay-dialog template and associated with a
|
||||||
|
// OK button click
|
||||||
|
function confirm(value) {
|
||||||
|
// Pass along the result
|
||||||
|
deferred.resolve(resultGetter ? resultGetter() : value);
|
||||||
|
self.dismissOverlay(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cancel function; this will be passed in to the
|
||||||
|
// overlay-dialog template and associated with a
|
||||||
|
// Cancel or X button click
|
||||||
|
function cancel() {
|
||||||
|
deferred.reject();
|
||||||
|
self.findBody().off('keydown', handleEscKeydown);
|
||||||
|
self.dismissOverlay(overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleEscKeydown = function (event) {
|
||||||
|
if (event.keyCode === 27) {
|
||||||
|
cancel();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add confirm/cancel callbacks
|
||||||
|
model.confirm = confirm;
|
||||||
|
model.cancel = cancel;
|
||||||
|
|
||||||
|
this.findBody().on('keydown', handleEscKeydown);
|
||||||
|
|
||||||
|
if (this.canShowDialog(model)) {
|
||||||
|
// Add the overlay using the OverlayService, which
|
||||||
|
// will handle actual insertion into the DOM
|
||||||
|
overlay = this.activeOverlay = this.overlayService.createOverlay(
|
||||||
|
key,
|
||||||
|
model,
|
||||||
|
typeClass || "t-dialog"
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
deferred.reject();
|
||||||
|
}
|
||||||
|
|
||||||
|
return deferred.promise;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request user input via a window-modal dialog.
|
||||||
|
*
|
||||||
|
* @param {FormModel} formModel a description of the form
|
||||||
|
* to be shown (see platform/forms)
|
||||||
|
* @param {object} value the initial state of the form
|
||||||
|
* @returns {Promise} a promise for the form value that the
|
||||||
|
* user has supplied; this may be rejected if
|
||||||
|
* user input cannot be obtained (for instance,
|
||||||
|
* because the user cancelled the dialog)
|
||||||
|
*/
|
||||||
|
DialogService.prototype.getUserInput = function (formModel, value) {
|
||||||
|
var overlayModel = {
|
||||||
|
title: formModel.name,
|
||||||
|
message: formModel.message,
|
||||||
|
structure: formModel,
|
||||||
|
value: value
|
||||||
|
};
|
||||||
|
|
||||||
|
// Provide result from the model
|
||||||
|
function resultGetter() {
|
||||||
|
return overlayModel.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the overlay-dialog
|
||||||
|
return this.getDialogResponse(
|
||||||
|
"overlay-dialog",
|
||||||
|
overlayModel,
|
||||||
|
resultGetter
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request that the user chooses from a set of options,
|
||||||
|
* which will be shown as buttons.
|
||||||
|
*
|
||||||
|
* @param dialogModel a description of the dialog to show
|
||||||
|
* @return {Promise} a promise for the user's choice
|
||||||
|
*/
|
||||||
|
DialogService.prototype.getUserChoice = function (dialogModel) {
|
||||||
|
// Show the overlay-options dialog
|
||||||
|
return this.getDialogResponse(
|
||||||
|
"overlay-options",
|
||||||
|
{ dialog: dialogModel }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests if a dialog can be displayed. A modal dialog may only be
|
||||||
|
* displayed if one is not already visible.
|
||||||
|
* Will log a warning message if it can't display a dialog.
|
||||||
|
* @returns {boolean} true if dialog is currently visible, false
|
||||||
|
* otherwise
|
||||||
|
*/
|
||||||
|
DialogService.prototype.canShowDialog = function (dialogModel) {
|
||||||
|
if (this.activeOverlay) {
|
||||||
|
// Only one dialog should be shown at a time.
|
||||||
|
// The application design should be such that
|
||||||
|
// we never even try to do this.
|
||||||
|
this.$log.warn([
|
||||||
|
"Dialog already showing; ",
|
||||||
|
"unable to show ",
|
||||||
|
dialogModel.title
|
||||||
|
].join(""));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user action that can be performed from a blocking dialog. These
|
||||||
|
* actions will be rendered as buttons within a blocking dialog.
|
||||||
|
*
|
||||||
|
* @typedef DialogOption
|
||||||
|
* @property {string} label a label to be displayed as the button
|
||||||
|
* text for this action
|
||||||
|
* @property {function} callback a function to be called when the
|
||||||
|
* button is clicked
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef DialogHandle
|
||||||
|
* @property {function} dismiss a function to dismiss the given dialog
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A description of the model options that may be passed to the
|
||||||
|
* showBlockingMessage method. Note that the DialogModel described
|
||||||
|
* here is shared with the Notifications framework.
|
||||||
|
* @see NotificationService
|
||||||
|
*
|
||||||
|
* @typedef DialogModel
|
||||||
|
* @property {string} title the title to use for the dialog
|
||||||
|
* @property {string} severity the severity level of this message.
|
||||||
|
* These are defined in a bundle constant with key 'dialogSeverity'
|
||||||
|
* @property {string} hint the 'hint' message to show below the title
|
||||||
|
* @property {string} actionText text that indicates a current action,
|
||||||
|
* shown above a progress bar to indicate what's happening.
|
||||||
|
* @property {number} progress a percentage value (1-100)
|
||||||
|
* indicating the completion of the blocking task
|
||||||
|
* @property {boolean} delay adds a brief delay before loading
|
||||||
|
* the dialog. Useful for removing the dialog flicker when the
|
||||||
|
* conditions for displaying the dialog change rapidly.
|
||||||
|
* @property {string} progressText the message to show below a
|
||||||
|
* progress bar to indicate progress. For example, this might be
|
||||||
|
* used to indicate time remaining, or items still to process.
|
||||||
|
* @property {boolean} unknownProgress some tasks may be
|
||||||
|
* impossible to provide an estimate for. Providing a true value for
|
||||||
|
* this attribute will indicate to the user that the progress and
|
||||||
|
* duration cannot be estimated.
|
||||||
|
* @property {DialogOption} primaryOption an action that will
|
||||||
|
* be added to the dialog as a button. The primary action can be
|
||||||
|
* used as the suggested course of action for the user. Making it
|
||||||
|
* distinct from other actions allows it to be styled differently,
|
||||||
|
* and treated preferentially in banner mode.
|
||||||
|
* @property {DialogOption[]} options a list of actions that will
|
||||||
|
* be added to the dialog as buttons.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a blocking (modal) dialog. This dialog can be used for
|
||||||
|
* displaying messages that require the user's
|
||||||
|
* immediate attention. The message may include an indication of
|
||||||
|
* progress, as well as a series of actions that
|
||||||
|
* the user can take if necessary
|
||||||
|
* @param {DialogModel} dialogModel defines options for the dialog
|
||||||
|
* @param {typeClass} string tells overlayService that this overlay should use appropriate CSS class
|
||||||
|
* @returns {boolean | {DialogHandle}}
|
||||||
|
*/
|
||||||
|
DialogService.prototype.showBlockingMessage = function (dialogModel) {
|
||||||
|
if (this.canShowDialog(dialogModel)) {
|
||||||
|
// Add the overlay using the OverlayService, which
|
||||||
|
// will handle actual insertion into the DOM
|
||||||
|
var self = this,
|
||||||
|
overlay = this.overlayService.createOverlay(
|
||||||
|
"overlay-blocking-message",
|
||||||
|
dialogModel,
|
||||||
|
"t-dialog-sm"
|
||||||
|
);
|
||||||
|
|
||||||
|
this.activeOverlay = overlay;
|
||||||
|
|
||||||
|
return {
|
||||||
|
dismiss: function () {
|
||||||
|
self.dismissOverlay(overlay);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DialogService;
|
@ -20,94 +20,108 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
// Template to inject into the DOM to show the dialog; really just points to
|
var TEMPLATE = '<mct-include ng-model="overlay" key="key" ng-class="typeClass"></mct-include>';
|
||||||
// the a specific template that can be included via mct-include
|
|
||||||
var TEMPLATE = '<mct-include ng-model="overlay" key="key" ng-class="typeClass"></mct-include>';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The OverlayService is responsible for pre-pending templates to
|
* The OverlayService is responsible for pre-pending templates to
|
||||||
* the body of the document, which is useful for displaying templates
|
* the body of the document, which is useful for displaying templates
|
||||||
* which need to block the full screen.
|
* which need to block the full screen.
|
||||||
*
|
*
|
||||||
* This is intended to be used by the DialogService; by design, it
|
* This is intended to be used by the DialogService; by design, it
|
||||||
* does not have any protections in place to prevent multiple overlays
|
* does not have any protections in place to prevent multiple overlays
|
||||||
* from being shown at once. (The DialogService does have these
|
* from being shown at once. (The DialogService does have these
|
||||||
* protections, and should be used for most overlay-type interactions,
|
* protections, and should be used for most overlay-type interactions,
|
||||||
* particularly where a multiple-overlay effect is not specifically
|
* particularly where a multiple-overlay effect is not specifically
|
||||||
* desired).
|
* desired).
|
||||||
*
|
*
|
||||||
* @memberof platform/commonUI/dialog
|
* @memberof platform/commonUI/dialog
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function OverlayService($document, $compile, $rootScope, $timeout) {
|
function OverlayService($document, $compile, $rootScope, $timeout) {
|
||||||
this.$compile = $compile;
|
this.$compile = $compile;
|
||||||
this.$timeout = $timeout;
|
this.$timeout = $timeout;
|
||||||
|
|
||||||
// Don't include $document and $rootScope directly;
|
// Don't include $document and $rootScope directly;
|
||||||
// avoids https://docs.angularjs.org/error/ng/cpws
|
// avoids https://docs.angularjs.org/error/ng/cpws
|
||||||
this.findBody = function () {
|
this.findBody = function () {
|
||||||
return $document.find('body');
|
return $document.find('body');
|
||||||
};
|
};
|
||||||
|
|
||||||
this.newScope = function () {
|
this.newScope = function () {
|
||||||
return $rootScope.$new();
|
return $rootScope.$new();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a new overlay to the document. This will be
|
* Add a new overlay to the document. This will be
|
||||||
* prepended to the document body; the overlay's
|
* prepended to the document body; the overlay's
|
||||||
* template (as pointed to by the `key` argument) is
|
* template (as pointed to by the `key` argument) is
|
||||||
* responsible for having a useful z-order, and for
|
* responsible for having a useful z-order, and for
|
||||||
* blocking user interactions if appropriate.
|
* blocking user interactions if appropriate.
|
||||||
*
|
*
|
||||||
* @param {string} key the symbolic key which identifies
|
* @param {string} key the symbolic key which identifies
|
||||||
* the template of the overlay to be shown
|
* the template of the overlay to be shown
|
||||||
* @param {object} overlayModel the model to pass to the
|
* @param {object} overlayModel the model to pass to the
|
||||||
* included overlay template (this will be passed
|
* included overlay template (this will be passed
|
||||||
* in via ng-model)
|
* in via ng-model)
|
||||||
* @param {string} typeClass the element class to use in rendering
|
* @param {string} typeClass the element class to use in rendering
|
||||||
* the overlay. Can be specified to provide custom styling of
|
* the overlay. Can be specified to provide custom styling of
|
||||||
* overlays
|
* overlays
|
||||||
*/
|
*/
|
||||||
OverlayService.prototype.createOverlay = function (key, overlayModel, typeClass) {
|
OverlayService.prototype.createOverlay = function (key, overlayModel, typeClass) {
|
||||||
// Create a new scope for this overlay
|
// Create a new scope for this overlay
|
||||||
var scope = this.newScope(),
|
var scope = this.newScope(),
|
||||||
element;
|
element;
|
||||||
|
|
||||||
// Stop showing the overlay; additionally, release the scope
|
// Stop showing the overlay; additionally, release the scope
|
||||||
// that it uses.
|
// that it uses.
|
||||||
function dismiss() {
|
function dismiss() {
|
||||||
scope.$destroy();
|
scope.$destroy();
|
||||||
element.remove();
|
element.remove();
|
||||||
}
|
|
||||||
|
|
||||||
// If no model is supplied, just fill in a default "cancel"
|
|
||||||
overlayModel = overlayModel || { cancel: dismiss };
|
|
||||||
|
|
||||||
// Populate the scope; will be passed directly to the template
|
|
||||||
scope.overlay = overlayModel;
|
|
||||||
scope.key = key;
|
|
||||||
scope.typeClass = typeClass || 't-dialog';
|
|
||||||
|
|
||||||
this.$timeout(() => {
|
|
||||||
// Create the overlay element and add it to the document's body
|
|
||||||
element = this.$compile(TEMPLATE)(scope);
|
|
||||||
|
|
||||||
// Append so that most recent dialog is last in DOM. This means the most recent dialog will be on top when
|
|
||||||
// multiple overlays with the same z-index are active.
|
|
||||||
this.findBody().append(element);
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
dismiss: dismiss
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
return OverlayService;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// If no model is supplied, just fill in a default "cancel"
|
||||||
|
overlayModel = overlayModel || { cancel: dismiss };
|
||||||
|
|
||||||
|
// Populate the scope; will be passed directly to the template
|
||||||
|
scope.overlay = overlayModel;
|
||||||
|
scope.key = key;
|
||||||
|
scope.typeClass = typeClass || 't-dialog';
|
||||||
|
|
||||||
|
this.$timeout(() => {
|
||||||
|
// Create the overlay element and add it to the document's body
|
||||||
|
element = this.$compile(TEMPLATE)(scope);
|
||||||
|
|
||||||
|
// Append so that most recent dialog is last in DOM. This means the most recent dialog will be on top when
|
||||||
|
// multiple overlays with the same z-index are active.
|
||||||
|
this.findBody().append(element);
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
dismiss: dismiss
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default OverlayService;
|
@ -23,192 +23,213 @@
|
|||||||
/**
|
/**
|
||||||
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../src/DialogService"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (DialogService) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The dialog service", function () {
|
/**
|
||||||
var mockOverlayService,
|
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
||||||
mockQ,
|
*/
|
||||||
mockLog,
|
import DialogService from '../src/DialogService';
|
||||||
mockOverlay,
|
|
||||||
mockDeferred,
|
|
||||||
mockDocument,
|
|
||||||
mockBody,
|
|
||||||
dialogService;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The dialog service", function () {
|
||||||
mockOverlayService = jasmine.createSpyObj(
|
var mockOverlayService,
|
||||||
"overlayService",
|
mockQ,
|
||||||
["createOverlay"]
|
mockLog,
|
||||||
);
|
mockOverlay,
|
||||||
mockQ = jasmine.createSpyObj(
|
mockDeferred,
|
||||||
"$q",
|
mockDocument,
|
||||||
["defer"]
|
mockBody,
|
||||||
);
|
dialogService;
|
||||||
mockLog = jasmine.createSpyObj(
|
|
||||||
"$log",
|
|
||||||
["warn", "info", "debug"]
|
|
||||||
);
|
|
||||||
mockOverlay = jasmine.createSpyObj(
|
|
||||||
"overlay",
|
|
||||||
["dismiss"]
|
|
||||||
);
|
|
||||||
mockDeferred = jasmine.createSpyObj(
|
|
||||||
"deferred",
|
|
||||||
["resolve", "reject"]
|
|
||||||
);
|
|
||||||
mockDocument = jasmine.createSpyObj(
|
|
||||||
"$document",
|
|
||||||
["find"]
|
|
||||||
);
|
|
||||||
mockBody = jasmine.createSpyObj('body', ['on', 'off']);
|
|
||||||
mockDocument.find.and.returnValue(mockBody);
|
|
||||||
|
|
||||||
mockDeferred.promise = "mock promise";
|
beforeEach(function () {
|
||||||
|
mockOverlayService = jasmine.createSpyObj(
|
||||||
|
"overlayService",
|
||||||
|
["createOverlay"]
|
||||||
|
);
|
||||||
|
mockQ = jasmine.createSpyObj(
|
||||||
|
"$q",
|
||||||
|
["defer"]
|
||||||
|
);
|
||||||
|
mockLog = jasmine.createSpyObj(
|
||||||
|
"$log",
|
||||||
|
["warn", "info", "debug"]
|
||||||
|
);
|
||||||
|
mockOverlay = jasmine.createSpyObj(
|
||||||
|
"overlay",
|
||||||
|
["dismiss"]
|
||||||
|
);
|
||||||
|
mockDeferred = jasmine.createSpyObj(
|
||||||
|
"deferred",
|
||||||
|
["resolve", "reject"]
|
||||||
|
);
|
||||||
|
mockDocument = jasmine.createSpyObj(
|
||||||
|
"$document",
|
||||||
|
["find"]
|
||||||
|
);
|
||||||
|
mockBody = jasmine.createSpyObj('body', ['on', 'off']);
|
||||||
|
mockDocument.find.and.returnValue(mockBody);
|
||||||
|
|
||||||
mockQ.defer.and.returnValue(mockDeferred);
|
mockDeferred.promise = "mock promise";
|
||||||
mockOverlayService.createOverlay.and.returnValue(mockOverlay);
|
|
||||||
|
|
||||||
dialogService = new DialogService(
|
mockQ.defer.and.returnValue(mockDeferred);
|
||||||
mockOverlayService,
|
mockOverlayService.createOverlay.and.returnValue(mockOverlay);
|
||||||
mockQ,
|
|
||||||
mockLog,
|
|
||||||
mockDocument
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("adds an overlay when user input is requested", function () {
|
dialogService = new DialogService(
|
||||||
dialogService.getUserInput({}, {});
|
mockOverlayService,
|
||||||
expect(mockOverlayService.createOverlay).toHaveBeenCalled();
|
mockQ,
|
||||||
});
|
mockLog,
|
||||||
|
mockDocument
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("allows user input to be canceled", function () {
|
it("adds an overlay when user input is requested", function () {
|
||||||
dialogService.getUserInput({}, { someKey: "some value" });
|
dialogService.getUserInput({}, {});
|
||||||
mockOverlayService.createOverlay.calls.mostRecent().args[1].cancel();
|
expect(mockOverlayService.createOverlay).toHaveBeenCalled();
|
||||||
expect(mockDeferred.reject).toHaveBeenCalled();
|
});
|
||||||
expect(mockDeferred.resolve).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("passes back the result of user input when confirmed", function () {
|
it("allows user input to be canceled", function () {
|
||||||
var value = { someKey: 42 };
|
dialogService.getUserInput({}, { someKey: "some value" });
|
||||||
dialogService.getUserInput({}, value);
|
mockOverlayService.createOverlay.calls.mostRecent().args[1].cancel();
|
||||||
mockOverlayService.createOverlay.calls.mostRecent().args[1].confirm();
|
expect(mockDeferred.reject).toHaveBeenCalled();
|
||||||
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
expect(mockDeferred.resolve).not.toHaveBeenCalled();
|
||||||
expect(mockDeferred.resolve).toHaveBeenCalledWith(value);
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("logs a warning when a dialog is already showing", function () {
|
it("passes back the result of user input when confirmed", function () {
|
||||||
dialogService.getUserInput({}, {});
|
var value = { someKey: 42 };
|
||||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
dialogService.getUserInput({}, value);
|
||||||
dialogService.getUserInput({}, {});
|
mockOverlayService.createOverlay.calls.mostRecent().args[1].confirm();
|
||||||
expect(mockLog.warn).toHaveBeenCalled();
|
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
||||||
expect(mockDeferred.reject).toHaveBeenCalled();
|
expect(mockDeferred.resolve).toHaveBeenCalledWith(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("can show multiple dialogs if prior ones are dismissed", function () {
|
it("logs a warning when a dialog is already showing", function () {
|
||||||
dialogService.getUserInput({}, {});
|
dialogService.getUserInput({}, {});
|
||||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||||
mockOverlayService.createOverlay.calls.mostRecent().args[1].confirm();
|
dialogService.getUserInput({}, {});
|
||||||
dialogService.getUserInput({}, {});
|
expect(mockLog.warn).toHaveBeenCalled();
|
||||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
expect(mockDeferred.reject).toHaveBeenCalled();
|
||||||
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
});
|
||||||
});
|
|
||||||
|
|
||||||
it("provides an options dialogs", function () {
|
it("can show multiple dialogs if prior ones are dismissed", function () {
|
||||||
var dialogModel = {};
|
dialogService.getUserInput({}, {});
|
||||||
dialogService.getUserChoice(dialogModel);
|
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||||
expect(mockOverlayService.createOverlay).toHaveBeenCalledWith(
|
mockOverlayService.createOverlay.calls.mostRecent().args[1].confirm();
|
||||||
'overlay-options',
|
dialogService.getUserInput({}, {});
|
||||||
{
|
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||||
dialog: dialogModel,
|
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
||||||
confirm: jasmine.any(Function),
|
});
|
||||||
cancel: jasmine.any(Function)
|
|
||||||
},
|
|
||||||
't-dialog'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("invokes the overlay service with the correct parameters when"
|
it("provides an options dialogs", function () {
|
||||||
+ " a blocking dialog is requested", function () {
|
var dialogModel = {};
|
||||||
var dialogModel = {};
|
dialogService.getUserChoice(dialogModel);
|
||||||
expect(dialogService.showBlockingMessage(dialogModel)).not.toBe(false);
|
expect(mockOverlayService.createOverlay).toHaveBeenCalledWith(
|
||||||
expect(mockOverlayService.createOverlay).toHaveBeenCalledWith(
|
'overlay-options',
|
||||||
"overlay-blocking-message",
|
{
|
||||||
dialogModel,
|
dialog: dialogModel,
|
||||||
"t-dialog-sm"
|
confirm: jasmine.any(Function),
|
||||||
);
|
cancel: jasmine.any(Function)
|
||||||
});
|
},
|
||||||
|
't-dialog'
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("adds a keydown event listener to the body", function () {
|
it("invokes the overlay service with the correct parameters when"
|
||||||
dialogService.getUserInput({}, {});
|
+ " a blocking dialog is requested", function () {
|
||||||
expect(mockDocument.find).toHaveBeenCalledWith("body");
|
var dialogModel = {};
|
||||||
expect(mockBody.on).toHaveBeenCalledWith("keydown", jasmine.any(Function));
|
expect(dialogService.showBlockingMessage(dialogModel)).not.toBe(false);
|
||||||
});
|
expect(mockOverlayService.createOverlay).toHaveBeenCalledWith(
|
||||||
|
"overlay-blocking-message",
|
||||||
|
dialogModel,
|
||||||
|
"t-dialog-sm"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("destroys the event listener when the dialog is cancelled", function () {
|
it("adds a keydown event listener to the body", function () {
|
||||||
dialogService.getUserInput({}, {});
|
dialogService.getUserInput({}, {});
|
||||||
mockOverlayService.createOverlay.calls.mostRecent().args[1].cancel();
|
expect(mockDocument.find).toHaveBeenCalledWith("body");
|
||||||
expect(mockBody.off).toHaveBeenCalledWith("keydown", jasmine.any(Function));
|
expect(mockBody.on).toHaveBeenCalledWith("keydown", jasmine.any(Function));
|
||||||
});
|
});
|
||||||
|
|
||||||
it("cancels the dialog when an escape keydown event is triggered", function () {
|
it("destroys the event listener when the dialog is cancelled", function () {
|
||||||
dialogService.getUserInput({}, {});
|
dialogService.getUserInput({}, {});
|
||||||
mockBody.on.calls.mostRecent().args[1]({
|
mockOverlayService.createOverlay.calls.mostRecent().args[1].cancel();
|
||||||
keyCode: 27
|
expect(mockBody.off).toHaveBeenCalledWith("keydown", jasmine.any(Function));
|
||||||
});
|
});
|
||||||
expect(mockDeferred.reject).toHaveBeenCalled();
|
|
||||||
expect(mockDeferred.resolve).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("ignores non escape keydown events", function () {
|
|
||||||
dialogService.getUserInput({}, {});
|
|
||||||
mockBody.on.calls.mostRecent().args[1]({
|
|
||||||
keyCode: 13
|
|
||||||
});
|
|
||||||
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
|
||||||
expect(mockDeferred.resolve).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("the blocking message dialog", function () {
|
|
||||||
var dialogModel = {};
|
|
||||||
var dialogHandle;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
dialogHandle = dialogService.showBlockingMessage(dialogModel);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns a handle to the dialog", function () {
|
|
||||||
expect(dialogHandle).not.toBe(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("dismissing the dialog dismisses the overlay", function () {
|
|
||||||
dialogHandle.dismiss();
|
|
||||||
expect(mockOverlay.dismiss).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("individual dialogs can be dismissed", function () {
|
|
||||||
var secondDialogHandle,
|
|
||||||
secondMockOverlay;
|
|
||||||
|
|
||||||
dialogHandle.dismiss();
|
|
||||||
|
|
||||||
secondMockOverlay = jasmine.createSpyObj(
|
|
||||||
"overlay",
|
|
||||||
["dismiss"]
|
|
||||||
);
|
|
||||||
mockOverlayService.createOverlay.and.returnValue(secondMockOverlay);
|
|
||||||
secondDialogHandle = dialogService.showBlockingMessage(dialogModel);
|
|
||||||
|
|
||||||
//Dismiss the first dialog. It should only dismiss if it
|
|
||||||
// is active
|
|
||||||
dialogHandle.dismiss();
|
|
||||||
expect(secondMockOverlay.dismiss).not.toHaveBeenCalled();
|
|
||||||
secondDialogHandle.dismiss();
|
|
||||||
expect(secondMockOverlay.dismiss).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
|
it("cancels the dialog when an escape keydown event is triggered", function () {
|
||||||
|
dialogService.getUserInput({}, {});
|
||||||
|
mockBody.on.calls.mostRecent().args[1]({
|
||||||
|
keyCode: 27
|
||||||
});
|
});
|
||||||
}
|
expect(mockDeferred.reject).toHaveBeenCalled();
|
||||||
);
|
expect(mockDeferred.resolve).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ignores non escape keydown events", function () {
|
||||||
|
dialogService.getUserInput({}, {});
|
||||||
|
mockBody.on.calls.mostRecent().args[1]({
|
||||||
|
keyCode: 13
|
||||||
|
});
|
||||||
|
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
||||||
|
expect(mockDeferred.resolve).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("the blocking message dialog", function () {
|
||||||
|
var dialogModel = {};
|
||||||
|
var dialogHandle;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
dialogHandle = dialogService.showBlockingMessage(dialogModel);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns a handle to the dialog", function () {
|
||||||
|
expect(dialogHandle).not.toBe(undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("dismissing the dialog dismisses the overlay", function () {
|
||||||
|
dialogHandle.dismiss();
|
||||||
|
expect(mockOverlay.dismiss).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("individual dialogs can be dismissed", function () {
|
||||||
|
var secondDialogHandle,
|
||||||
|
secondMockOverlay;
|
||||||
|
|
||||||
|
dialogHandle.dismiss();
|
||||||
|
|
||||||
|
secondMockOverlay = jasmine.createSpyObj(
|
||||||
|
"overlay",
|
||||||
|
["dismiss"]
|
||||||
|
);
|
||||||
|
mockOverlayService.createOverlay.and.returnValue(secondMockOverlay);
|
||||||
|
secondDialogHandle = dialogService.showBlockingMessage(dialogModel);
|
||||||
|
|
||||||
|
//Dismiss the first dialog. It should only dismiss if it
|
||||||
|
// is active
|
||||||
|
dialogHandle.dismiss();
|
||||||
|
expect(secondMockOverlay.dismiss).not.toHaveBeenCalled();
|
||||||
|
secondDialogHandle.dismiss();
|
||||||
|
expect(secondMockOverlay.dismiss).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -23,82 +23,103 @@
|
|||||||
/**
|
/**
|
||||||
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../src/OverlayService"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (OverlayService) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The overlay service", function () {
|
/**
|
||||||
var mockDocument,
|
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
|
||||||
mockCompile,
|
*/
|
||||||
mockRootScope,
|
import OverlayService from '../src/OverlayService';
|
||||||
mockBody,
|
|
||||||
mockTemplate,
|
|
||||||
mockElement,
|
|
||||||
mockScope,
|
|
||||||
mockTimeout,
|
|
||||||
overlayService;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The overlay service", function () {
|
||||||
mockDocument = jasmine.createSpyObj("$document", ["find"]);
|
var mockDocument,
|
||||||
mockCompile = jasmine.createSpy("$compile");
|
mockCompile,
|
||||||
mockRootScope = jasmine.createSpyObj("$rootScope", ["$new"]);
|
mockRootScope,
|
||||||
mockBody = jasmine.createSpyObj("body", ["append"]);
|
mockBody,
|
||||||
mockTemplate = jasmine.createSpy("template");
|
mockTemplate,
|
||||||
mockElement = jasmine.createSpyObj("element", ["remove"]);
|
mockElement,
|
||||||
mockScope = jasmine.createSpyObj("scope", ["$destroy"]);
|
mockScope,
|
||||||
mockTimeout = function (callback) {
|
mockTimeout,
|
||||||
callback();
|
overlayService;
|
||||||
};
|
|
||||||
|
|
||||||
mockDocument.find.and.returnValue(mockBody);
|
beforeEach(function () {
|
||||||
mockCompile.and.returnValue(mockTemplate);
|
mockDocument = jasmine.createSpyObj("$document", ["find"]);
|
||||||
mockRootScope.$new.and.returnValue(mockScope);
|
mockCompile = jasmine.createSpy("$compile");
|
||||||
mockTemplate.and.returnValue(mockElement);
|
mockRootScope = jasmine.createSpyObj("$rootScope", ["$new"]);
|
||||||
|
mockBody = jasmine.createSpyObj("body", ["append"]);
|
||||||
|
mockTemplate = jasmine.createSpy("template");
|
||||||
|
mockElement = jasmine.createSpyObj("element", ["remove"]);
|
||||||
|
mockScope = jasmine.createSpyObj("scope", ["$destroy"]);
|
||||||
|
mockTimeout = function (callback) {
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
overlayService = new OverlayService(
|
mockDocument.find.and.returnValue(mockBody);
|
||||||
mockDocument,
|
mockCompile.and.returnValue(mockTemplate);
|
||||||
mockCompile,
|
mockRootScope.$new.and.returnValue(mockScope);
|
||||||
mockRootScope,
|
mockTemplate.and.returnValue(mockElement);
|
||||||
mockTimeout
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("prepends an mct-include to create overlays", function () {
|
overlayService = new OverlayService(
|
||||||
overlayService.createOverlay("test", {});
|
mockDocument,
|
||||||
expect(mockCompile).toHaveBeenCalled();
|
mockCompile,
|
||||||
expect(mockCompile.calls.mostRecent().args[0].indexOf("mct-include"))
|
mockRootScope,
|
||||||
.not.toEqual(-1);
|
mockTimeout
|
||||||
});
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it("adds the templated element to the body", function () {
|
it("prepends an mct-include to create overlays", function () {
|
||||||
overlayService.createOverlay("test", {});
|
overlayService.createOverlay("test", {});
|
||||||
expect(mockBody.append).toHaveBeenCalledWith(mockElement);
|
expect(mockCompile).toHaveBeenCalled();
|
||||||
});
|
expect(mockCompile.calls.mostRecent().args[0].indexOf("mct-include"))
|
||||||
|
.not.toEqual(-1);
|
||||||
|
});
|
||||||
|
|
||||||
it("places the provided model/key in its template's scope", function () {
|
it("adds the templated element to the body", function () {
|
||||||
overlayService.createOverlay("test", { someKey: 42 });
|
overlayService.createOverlay("test", {});
|
||||||
expect(mockScope.overlay).toEqual({ someKey: 42 });
|
expect(mockBody.append).toHaveBeenCalledWith(mockElement);
|
||||||
expect(mockScope.key).toEqual("test");
|
});
|
||||||
|
|
||||||
// Make sure this is actually what was rendered, too
|
it("places the provided model/key in its template's scope", function () {
|
||||||
expect(mockTemplate).toHaveBeenCalledWith(mockScope);
|
overlayService.createOverlay("test", { someKey: 42 });
|
||||||
});
|
expect(mockScope.overlay).toEqual({ someKey: 42 });
|
||||||
|
expect(mockScope.key).toEqual("test");
|
||||||
|
|
||||||
it("removes the prepended element on request", function () {
|
// Make sure this is actually what was rendered, too
|
||||||
var overlay = overlayService.createOverlay("test", {});
|
expect(mockTemplate).toHaveBeenCalledWith(mockScope);
|
||||||
|
});
|
||||||
|
|
||||||
// Verify precondition
|
it("removes the prepended element on request", function () {
|
||||||
expect(mockElement.remove).not.toHaveBeenCalled();
|
var overlay = overlayService.createOverlay("test", {});
|
||||||
expect(mockScope.$destroy).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
// Dismiss the overlay
|
// Verify precondition
|
||||||
overlay.dismiss();
|
expect(mockElement.remove).not.toHaveBeenCalled();
|
||||||
|
expect(mockScope.$destroy).not.toHaveBeenCalled();
|
||||||
|
|
||||||
// Now it should have been removed, and the scope destroyed
|
// Dismiss the overlay
|
||||||
expect(mockElement.remove).toHaveBeenCalled();
|
overlay.dismiss();
|
||||||
expect(mockScope.$destroy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
// Now it should have been removed, and the scope destroyed
|
||||||
}
|
expect(mockElement.remove).toHaveBeenCalled();
|
||||||
);
|
expect(mockScope.$destroy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -20,190 +20,195 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/controllers/EditActionController",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/controllers/EditPanesController",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"./src/controllers/EditObjectController",
|
* Administration. All rights reserved.
|
||||||
"./src/actions/EditAndComposeAction",
|
*
|
||||||
"./src/actions/EditAction",
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
"./src/actions/SaveAction",
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
"./src/actions/SaveAndStopEditingAction",
|
* You may obtain a copy of the License at
|
||||||
"./src/actions/CancelAction",
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
"./src/policies/EditPersistableObjectsPolicy",
|
*
|
||||||
"./src/representers/EditRepresenter",
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
"./src/capabilities/EditorCapability",
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
"./res/templates/library.html",
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
"./res/templates/edit-object.html",
|
* License for the specific language governing permissions and limitations
|
||||||
"./res/templates/edit-action-buttons.html",
|
* under the License.
|
||||||
"./res/templates/topbar-edit.html"
|
*
|
||||||
], function (
|
* Open MCT includes source code licensed under additional open source
|
||||||
EditActionController,
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
EditPanesController,
|
* this source code distribution or the Licensing information page available
|
||||||
EditObjectController,
|
* at runtime from the About dialog for additional information.
|
||||||
EditAndComposeAction,
|
*****************************************************************************/
|
||||||
EditAction,
|
|
||||||
SaveAction,
|
import EditActionController from './src/controllers/EditActionController';
|
||||||
SaveAndStopEditingAction,
|
|
||||||
CancelAction,
|
import EditPanesController from './src/controllers/EditPanesController';
|
||||||
EditPersistableObjectsPolicy,
|
import EditObjectController from './src/controllers/EditObjectController';
|
||||||
EditRepresenter,
|
import EditAndComposeAction from './src/actions/EditAndComposeAction';
|
||||||
EditorCapability,
|
import EditAction from './src/actions/EditAction';
|
||||||
libraryTemplate,
|
import SaveAction from './src/actions/SaveAction';
|
||||||
editObjectTemplate,
|
import SaveAndStopEditingAction from './src/actions/SaveAndStopEditingAction';
|
||||||
editActionButtonsTemplate,
|
import CancelAction from './src/actions/CancelAction';
|
||||||
topbarEditTemplate
|
import EditPersistableObjectsPolicy from './src/policies/EditPersistableObjectsPolicy';
|
||||||
) {
|
import EditRepresenter from './src/representers/EditRepresenter';
|
||||||
return {
|
import EditorCapability from './src/capabilities/EditorCapability';
|
||||||
name: "platform/commonUI/edit",
|
import libraryTemplate from './res/templates/library.html';
|
||||||
definition: {
|
import editObjectTemplate from './res/templates/edit-object.html';
|
||||||
"extensions": {
|
import editActionButtonsTemplate from './res/templates/edit-action-buttons.html';
|
||||||
"controllers": [
|
import topbarEditTemplate from './res/templates/topbar-edit.html';
|
||||||
{
|
|
||||||
"key": "EditActionController",
|
export default {
|
||||||
"implementation": EditActionController,
|
name: "platform/commonUI/edit",
|
||||||
"depends": [
|
definition: {
|
||||||
"$scope"
|
"extensions": {
|
||||||
]
|
"controllers": [
|
||||||
},
|
{
|
||||||
{
|
"key": "EditActionController",
|
||||||
"key": "EditPanesController",
|
"implementation": EditActionController,
|
||||||
"implementation": EditPanesController,
|
"depends": [
|
||||||
"depends": [
|
"$scope"
|
||||||
"$scope"
|
]
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "EditPanesController",
|
||||||
"key": "EditObjectController",
|
"implementation": EditPanesController,
|
||||||
"implementation": EditObjectController,
|
"depends": [
|
||||||
"depends": [
|
"$scope"
|
||||||
"$scope",
|
]
|
||||||
"$location",
|
},
|
||||||
"navigationService"
|
{
|
||||||
]
|
"key": "EditObjectController",
|
||||||
|
"implementation": EditObjectController,
|
||||||
|
"depends": [
|
||||||
|
"$scope",
|
||||||
|
"$location",
|
||||||
|
"navigationService"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"key": "compose",
|
||||||
|
"implementation": EditAndComposeAction
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "edit",
|
||||||
|
"implementation": EditAction,
|
||||||
|
"depends": [
|
||||||
|
"$location",
|
||||||
|
"navigationService",
|
||||||
|
"$log"
|
||||||
|
],
|
||||||
|
"description": "Edit",
|
||||||
|
"category": "view-control",
|
||||||
|
"cssClass": "major icon-pencil",
|
||||||
|
"group": "action",
|
||||||
|
"priority": 10
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "save-and-stop-editing",
|
||||||
|
"category": "save",
|
||||||
|
"implementation": SaveAndStopEditingAction,
|
||||||
|
"name": "Save and Finish Editing",
|
||||||
|
"cssClass": "icon-save labeled",
|
||||||
|
"description": "Save changes made to these objects.",
|
||||||
|
"depends": [
|
||||||
|
"dialogService",
|
||||||
|
"notificationService"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "save",
|
||||||
|
"category": "save",
|
||||||
|
"implementation": SaveAction,
|
||||||
|
"name": "Save and Continue Editing",
|
||||||
|
"cssClass": "icon-save labeled",
|
||||||
|
"description": "Save changes made to these objects.",
|
||||||
|
"depends": [
|
||||||
|
"dialogService",
|
||||||
|
"notificationService"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "cancel",
|
||||||
|
"category": "conclude-editing",
|
||||||
|
"implementation": CancelAction,
|
||||||
|
// Because we use the name as label for edit buttons and mct-control buttons need
|
||||||
|
// the label to be set to undefined in order to not apply the labeled CSS rule.
|
||||||
|
"name": undefined,
|
||||||
|
"cssClass": "icon-x no-label",
|
||||||
|
"description": "Discard changes made to these objects.",
|
||||||
|
"depends": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"policies": [
|
||||||
|
{
|
||||||
|
"category": "action",
|
||||||
|
"implementation": EditPersistableObjectsPolicy,
|
||||||
|
"depends": ["openmct"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"templates": [
|
||||||
|
{
|
||||||
|
"key": "edit-library",
|
||||||
|
"template": libraryTemplate
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"representations": [
|
||||||
|
{
|
||||||
|
"key": "edit-object",
|
||||||
|
"template": editObjectTemplate,
|
||||||
|
"uses": [
|
||||||
|
"view"
|
||||||
|
],
|
||||||
|
"gestures": [
|
||||||
|
"drop"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "edit-action-buttons",
|
||||||
|
"template": editActionButtonsTemplate,
|
||||||
|
"uses": [
|
||||||
|
"action"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "topbar-edit",
|
||||||
|
"template": topbarEditTemplate
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"representers": [
|
||||||
|
{
|
||||||
|
"implementation": EditRepresenter,
|
||||||
|
"depends": [
|
||||||
|
"$log"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"capabilities": [
|
||||||
|
{
|
||||||
|
"key": "editor",
|
||||||
|
"name": "Editor Capability",
|
||||||
|
"description": "Provides transactional editing capabilities",
|
||||||
|
"implementation": EditorCapability,
|
||||||
|
"depends": [
|
||||||
|
"openmct"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
depends: [
|
||||||
|
"toolbars[]",
|
||||||
|
"openmct"
|
||||||
|
],
|
||||||
|
implementation: function (toolbars, openmct) {
|
||||||
|
toolbars.forEach(openmct.toolbars.addProvider, openmct.toolbars);
|
||||||
}
|
}
|
||||||
],
|
}
|
||||||
"actions": [
|
]
|
||||||
{
|
|
||||||
"key": "compose",
|
|
||||||
"implementation": EditAndComposeAction
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "edit",
|
|
||||||
"implementation": EditAction,
|
|
||||||
"depends": [
|
|
||||||
"$location",
|
|
||||||
"navigationService",
|
|
||||||
"$log"
|
|
||||||
],
|
|
||||||
"description": "Edit",
|
|
||||||
"category": "view-control",
|
|
||||||
"cssClass": "major icon-pencil",
|
|
||||||
"group": "action",
|
|
||||||
"priority": 10
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "save-and-stop-editing",
|
|
||||||
"category": "save",
|
|
||||||
"implementation": SaveAndStopEditingAction,
|
|
||||||
"name": "Save and Finish Editing",
|
|
||||||
"cssClass": "icon-save labeled",
|
|
||||||
"description": "Save changes made to these objects.",
|
|
||||||
"depends": [
|
|
||||||
"dialogService",
|
|
||||||
"notificationService"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "save",
|
|
||||||
"category": "save",
|
|
||||||
"implementation": SaveAction,
|
|
||||||
"name": "Save and Continue Editing",
|
|
||||||
"cssClass": "icon-save labeled",
|
|
||||||
"description": "Save changes made to these objects.",
|
|
||||||
"depends": [
|
|
||||||
"dialogService",
|
|
||||||
"notificationService"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "cancel",
|
|
||||||
"category": "conclude-editing",
|
|
||||||
"implementation": CancelAction,
|
|
||||||
// Because we use the name as label for edit buttons and mct-control buttons need
|
|
||||||
// the label to be set to undefined in order to not apply the labeled CSS rule.
|
|
||||||
"name": undefined,
|
|
||||||
"cssClass": "icon-x no-label",
|
|
||||||
"description": "Discard changes made to these objects.",
|
|
||||||
"depends": []
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"policies": [
|
|
||||||
{
|
|
||||||
"category": "action",
|
|
||||||
"implementation": EditPersistableObjectsPolicy,
|
|
||||||
"depends": ["openmct"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"templates": [
|
|
||||||
{
|
|
||||||
"key": "edit-library",
|
|
||||||
"template": libraryTemplate
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"representations": [
|
|
||||||
{
|
|
||||||
"key": "edit-object",
|
|
||||||
"template": editObjectTemplate,
|
|
||||||
"uses": [
|
|
||||||
"view"
|
|
||||||
],
|
|
||||||
"gestures": [
|
|
||||||
"drop"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "edit-action-buttons",
|
|
||||||
"template": editActionButtonsTemplate,
|
|
||||||
"uses": [
|
|
||||||
"action"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"key": "topbar-edit",
|
|
||||||
"template": topbarEditTemplate
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"representers": [
|
|
||||||
{
|
|
||||||
"implementation": EditRepresenter,
|
|
||||||
"depends": [
|
|
||||||
"$log"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"capabilities": [
|
|
||||||
{
|
|
||||||
"key": "editor",
|
|
||||||
"name": "Editor Capability",
|
|
||||||
"description": "Provides transactional editing capabilities",
|
|
||||||
"implementation": EditorCapability,
|
|
||||||
"depends": [
|
|
||||||
"openmct"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"runs": [
|
|
||||||
{
|
|
||||||
depends: [
|
|
||||||
"toolbars[]",
|
|
||||||
"openmct"
|
|
||||||
],
|
|
||||||
implementation: function (toolbars, openmct) {
|
|
||||||
toolbars.forEach(openmct.toolbars.addProvider, openmct.toolbars);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,71 +20,66 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/**
|
||||||
function () {
|
* The "Cancel" action; the action triggered by clicking Cancel from
|
||||||
|
* Edit Mode. Exits the editing user interface and invokes object
|
||||||
|
* capabilities to persist the changes that have been made.
|
||||||
|
* @constructor
|
||||||
|
* @memberof platform/commonUI/edit
|
||||||
|
* @implements {Action}
|
||||||
|
*/
|
||||||
|
function CancelAction(context) {
|
||||||
|
this.domainObject = context.domainObject;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "Cancel" action; the action triggered by clicking Cancel from
|
* Cancel editing.
|
||||||
* Edit Mode. Exits the editing user interface and invokes object
|
*
|
||||||
* capabilities to persist the changes that have been made.
|
* @returns {Promise} a promise that will be fulfilled when
|
||||||
* @constructor
|
* cancellation has completed
|
||||||
* @memberof platform/commonUI/edit
|
*/
|
||||||
* @implements {Action}
|
CancelAction.prototype.perform = function () {
|
||||||
*/
|
var domainObject = this.domainObject;
|
||||||
function CancelAction(context) {
|
|
||||||
this.domainObject = context.domainObject;
|
function returnToBrowse() {
|
||||||
|
var parent;
|
||||||
|
|
||||||
|
//If the object existed already, navigate to refresh view
|
||||||
|
// with previous object state.
|
||||||
|
if (domainObject.getModel().persisted) {
|
||||||
|
return domainObject.getCapability("action").perform("navigate");
|
||||||
|
} else {
|
||||||
|
//If the object was new, and user has cancelled, then
|
||||||
|
//navigate back to parent because nothing to show.
|
||||||
|
return domainObject.getCapability("location").getOriginal().then(function (original) {
|
||||||
|
parent = original.getCapability("context").getParent();
|
||||||
|
|
||||||
|
return parent.getCapability("action").perform("navigate");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Cancel editing.
|
|
||||||
*
|
|
||||||
* @returns {Promise} a promise that will be fulfilled when
|
|
||||||
* cancellation has completed
|
|
||||||
*/
|
|
||||||
CancelAction.prototype.perform = function () {
|
|
||||||
var domainObject = this.domainObject;
|
|
||||||
|
|
||||||
function returnToBrowse() {
|
|
||||||
var parent;
|
|
||||||
|
|
||||||
//If the object existed already, navigate to refresh view
|
|
||||||
// with previous object state.
|
|
||||||
if (domainObject.getModel().persisted) {
|
|
||||||
return domainObject.getCapability("action").perform("navigate");
|
|
||||||
} else {
|
|
||||||
//If the object was new, and user has cancelled, then
|
|
||||||
//navigate back to parent because nothing to show.
|
|
||||||
return domainObject.getCapability("location").getOriginal().then(function (original) {
|
|
||||||
parent = original.getCapability("context").getParent();
|
|
||||||
|
|
||||||
return parent.getCapability("action").perform("navigate");
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function cancel() {
|
|
||||||
return domainObject.getCapability("editor").finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Do navigation first in order to trigger unsaved changes dialog
|
|
||||||
return returnToBrowse()
|
|
||||||
.then(cancel);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this action is applicable in a given context.
|
|
||||||
* This will ensure that a domain object is present in the context,
|
|
||||||
* and that this domain object is in Edit mode.
|
|
||||||
* @returns {boolean} true if applicable
|
|
||||||
*/
|
|
||||||
CancelAction.appliesTo = function (context) {
|
|
||||||
var domainObject = (context || {}).domainObject;
|
|
||||||
|
|
||||||
return domainObject !== undefined
|
|
||||||
&& domainObject.hasCapability('editor')
|
|
||||||
&& domainObject.getCapability('editor').isEditContextRoot();
|
|
||||||
};
|
|
||||||
|
|
||||||
return CancelAction;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function cancel() {
|
||||||
|
return domainObject.getCapability("editor").finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Do navigation first in order to trigger unsaved changes dialog
|
||||||
|
return returnToBrowse()
|
||||||
|
.then(cancel);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this action is applicable in a given context.
|
||||||
|
* This will ensure that a domain object is present in the context,
|
||||||
|
* and that this domain object is in Edit mode.
|
||||||
|
* @returns {boolean} true if applicable
|
||||||
|
*/
|
||||||
|
CancelAction.appliesTo = function (context) {
|
||||||
|
var domainObject = (context || {}).domainObject;
|
||||||
|
|
||||||
|
return domainObject !== undefined
|
||||||
|
&& domainObject.hasCapability('editor')
|
||||||
|
&& domainObject.getCapability('editor').isEditContextRoot();
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CancelAction;
|
@ -23,79 +23,96 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining EditAction. Created by vwoeltje on 11/14/14.
|
* Module defining EditAction. Created by vwoeltje on 11/14/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
// A no-op action to return in the event that the action cannot
|
/**
|
||||||
// be completed.
|
* Module defining EditAction. Created by vwoeltje on 11/14/14.
|
||||||
var NULL_ACTION = {
|
*/
|
||||||
perform: function () {
|
var NULL_ACTION = {
|
||||||
return undefined;
|
perform: function () {
|
||||||
}
|
return undefined;
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Edit action is performed when the user wishes to enter Edit
|
|
||||||
* mode (typically triggered by the Edit button.) This will
|
|
||||||
* show the user interface for editing (by way of a change in
|
|
||||||
* route)
|
|
||||||
* @memberof platform/commonUI/edit
|
|
||||||
* @constructor
|
|
||||||
* @implements {Action}
|
|
||||||
*/
|
|
||||||
function EditAction($location, navigationService, $log, context) {
|
|
||||||
var domainObject = (context || {}).domainObject;
|
|
||||||
|
|
||||||
// We cannot enter Edit mode if we have no domain object to
|
|
||||||
// edit, so verify that one was defined as part of the
|
|
||||||
// context. (This is also verified in appliesTo, so this
|
|
||||||
// would indicate abnormal behavior.)
|
|
||||||
if (!domainObject) {
|
|
||||||
$log.warn([
|
|
||||||
"No domain object to edit; ",
|
|
||||||
"edit action is not valid."
|
|
||||||
].join(""));
|
|
||||||
|
|
||||||
return NULL_ACTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.domainObject = domainObject;
|
|
||||||
this.$location = $location;
|
|
||||||
this.navigationService = navigationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enter edit mode.
|
|
||||||
*/
|
|
||||||
EditAction.prototype.perform = function () {
|
|
||||||
|
|
||||||
//If this is not the currently navigated object, then navigate
|
|
||||||
// to it.
|
|
||||||
if (this.navigationService.getNavigation() !== this.domainObject) {
|
|
||||||
this.navigationService.setNavigation(this.domainObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.domainObject.useCapability("editor");
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check for applicability; verify that a domain object is present
|
|
||||||
* for this action to be performed upon.
|
|
||||||
* @param {ActionContext} context the context in which this action
|
|
||||||
* will be performed; should contain a `domainObject` property
|
|
||||||
*/
|
|
||||||
EditAction.appliesTo = function (context) {
|
|
||||||
var domainObject = (context || {}).domainObject,
|
|
||||||
type = domainObject && domainObject.getCapability('type');
|
|
||||||
|
|
||||||
// Only allow editing of types that support it and are not already
|
|
||||||
// being edited
|
|
||||||
return type && type.hasFeature('creation')
|
|
||||||
&& domainObject.hasCapability('editor')
|
|
||||||
&& !domainObject.getCapability('editor').isEditContextRoot();
|
|
||||||
};
|
|
||||||
|
|
||||||
return EditAction;
|
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Edit action is performed when the user wishes to enter Edit
|
||||||
|
* mode (typically triggered by the Edit button.) This will
|
||||||
|
* show the user interface for editing (by way of a change in
|
||||||
|
* route)
|
||||||
|
* @memberof platform/commonUI/edit
|
||||||
|
* @constructor
|
||||||
|
* @implements {Action}
|
||||||
|
*/
|
||||||
|
function EditAction($location, navigationService, $log, context) {
|
||||||
|
var domainObject = (context || {}).domainObject;
|
||||||
|
|
||||||
|
// We cannot enter Edit mode if we have no domain object to
|
||||||
|
// edit, so verify that one was defined as part of the
|
||||||
|
// context. (This is also verified in appliesTo, so this
|
||||||
|
// would indicate abnormal behavior.)
|
||||||
|
if (!domainObject) {
|
||||||
|
$log.warn([
|
||||||
|
"No domain object to edit; ",
|
||||||
|
"edit action is not valid."
|
||||||
|
].join(""));
|
||||||
|
|
||||||
|
return NULL_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.domainObject = domainObject;
|
||||||
|
this.$location = $location;
|
||||||
|
this.navigationService = navigationService;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enter edit mode.
|
||||||
|
*/
|
||||||
|
EditAction.prototype.perform = function () {
|
||||||
|
|
||||||
|
//If this is not the currently navigated object, then navigate
|
||||||
|
// to it.
|
||||||
|
if (this.navigationService.getNavigation() !== this.domainObject) {
|
||||||
|
this.navigationService.setNavigation(this.domainObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.domainObject.useCapability("editor");
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check for applicability; verify that a domain object is present
|
||||||
|
* for this action to be performed upon.
|
||||||
|
* @param {ActionContext} context the context in which this action
|
||||||
|
* will be performed; should contain a `domainObject` property
|
||||||
|
*/
|
||||||
|
EditAction.appliesTo = function (context) {
|
||||||
|
var domainObject = (context || {}).domainObject,
|
||||||
|
type = domainObject && domainObject.getCapability('type');
|
||||||
|
|
||||||
|
// Only allow editing of types that support it and are not already
|
||||||
|
// being edited
|
||||||
|
return type && type.hasFeature('creation')
|
||||||
|
&& domainObject.hasCapability('editor')
|
||||||
|
&& !domainObject.getCapability('editor').isEditContextRoot();
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditAction;
|
@ -20,40 +20,50 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function EditAndComposeAction(context) {
|
||||||
* Add one domain object to another's composition.
|
this.domainObject = (context || {}).domainObject;
|
||||||
* @constructor
|
this.selectedObject = (context || {}).selectedObject;
|
||||||
* @memberof platform/commonUI/edit
|
}
|
||||||
* @implements {Action}
|
|
||||||
*/
|
|
||||||
function EditAndComposeAction(context) {
|
|
||||||
this.domainObject = (context || {}).domainObject;
|
|
||||||
this.selectedObject = (context || {}).selectedObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditAndComposeAction.prototype.perform = function () {
|
EditAndComposeAction.prototype.perform = function () {
|
||||||
var self = this,
|
var self = this,
|
||||||
editAction = this.domainObject.getCapability('action').getActions("edit")[0];
|
editAction = this.domainObject.getCapability('action').getActions("edit")[0];
|
||||||
|
|
||||||
// Link these objects
|
// Link these objects
|
||||||
function doLink() {
|
function doLink() {
|
||||||
var composition = self.domainObject
|
var composition = self.domainObject
|
||||||
&& self.domainObject.getCapability('composition');
|
&& self.domainObject.getCapability('composition');
|
||||||
|
|
||||||
return composition && composition.add(self.selectedObject);
|
return composition && composition.add(self.selectedObject);
|
||||||
}
|
|
||||||
|
|
||||||
if (editAction) {
|
|
||||||
editAction.perform();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.selectedObject && doLink();
|
|
||||||
};
|
|
||||||
|
|
||||||
return EditAndComposeAction;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
if (editAction) {
|
||||||
|
editAction.perform();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.selectedObject && doLink();
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditAndComposeAction;
|
@ -20,79 +20,97 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
['./SaveInProgressDialog'],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (SaveInProgressDialog) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
import SaveInProgressDialog from './SaveInProgressDialog';
|
||||||
* The "Save" action; it invokes object capabilities to persist
|
|
||||||
* the changes that have been made.
|
|
||||||
* @constructor
|
|
||||||
* @implements {Action}
|
|
||||||
* @memberof platform/commonUI/edit
|
|
||||||
*/
|
|
||||||
function SaveAction(
|
|
||||||
dialogService,
|
|
||||||
notificationService,
|
|
||||||
context
|
|
||||||
) {
|
|
||||||
this.domainObject = (context || {}).domainObject;
|
|
||||||
this.dialogService = dialogService;
|
|
||||||
this.notificationService = notificationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save changes.
|
* The "Save" action; it invokes object capabilities to persist
|
||||||
*
|
* the changes that have been made.
|
||||||
* @returns {Promise} a promise that will be fulfilled when
|
* @constructor
|
||||||
* cancellation has completed
|
* @implements {Action}
|
||||||
* @memberof platform/commonUI/edit.SaveAction#
|
* @memberof platform/commonUI/edit
|
||||||
*/
|
*/
|
||||||
SaveAction.prototype.perform = function () {
|
function SaveAction(
|
||||||
var self = this,
|
dialogService,
|
||||||
domainObject = this.domainObject,
|
notificationService,
|
||||||
dialog = new SaveInProgressDialog(this.dialogService);
|
context
|
||||||
|
) {
|
||||||
|
this.domainObject = (context || {}).domainObject;
|
||||||
|
this.dialogService = dialogService;
|
||||||
|
this.notificationService = notificationService;
|
||||||
|
}
|
||||||
|
|
||||||
// Invoke any save behavior introduced by the editor capability;
|
/**
|
||||||
// this is introduced by EditableDomainObject which is
|
* Save changes.
|
||||||
// used to insulate underlying objects from changes made
|
*
|
||||||
// during editing.
|
* @returns {Promise} a promise that will be fulfilled when
|
||||||
function doSave() {
|
* cancellation has completed
|
||||||
return domainObject.getCapability("editor").save();
|
* @memberof platform/commonUI/edit.SaveAction#
|
||||||
}
|
*/
|
||||||
|
SaveAction.prototype.perform = function () {
|
||||||
|
var self = this,
|
||||||
|
domainObject = this.domainObject,
|
||||||
|
dialog = new SaveInProgressDialog(this.dialogService);
|
||||||
|
|
||||||
function onSuccess() {
|
// Invoke any save behavior introduced by the editor capability;
|
||||||
dialog.hide();
|
// this is introduced by EditableDomainObject which is
|
||||||
self.notificationService.info("Save Succeeded");
|
// used to insulate underlying objects from changes made
|
||||||
}
|
// during editing.
|
||||||
|
function doSave() {
|
||||||
function onFailure() {
|
return domainObject.getCapability("editor").save();
|
||||||
dialog.hide();
|
|
||||||
self.notificationService.error("Save Failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog.show();
|
|
||||||
|
|
||||||
return doSave()
|
|
||||||
.then(onSuccess)
|
|
||||||
.catch(onFailure);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this action is applicable in a given context.
|
|
||||||
* This will ensure that a domain object is present in the context,
|
|
||||||
* and that this domain object is in Edit mode.
|
|
||||||
* @returns true if applicable
|
|
||||||
*/
|
|
||||||
SaveAction.appliesTo = function (context) {
|
|
||||||
var domainObject = (context || {}).domainObject;
|
|
||||||
|
|
||||||
return domainObject !== undefined
|
|
||||||
&& domainObject.hasCapability('editor')
|
|
||||||
&& domainObject.getCapability('editor').isEditContextRoot()
|
|
||||||
&& domainObject.getModel().persisted !== undefined;
|
|
||||||
};
|
|
||||||
|
|
||||||
return SaveAction;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function onSuccess() {
|
||||||
|
dialog.hide();
|
||||||
|
self.notificationService.info("Save Succeeded");
|
||||||
|
}
|
||||||
|
|
||||||
|
function onFailure() {
|
||||||
|
dialog.hide();
|
||||||
|
self.notificationService.error("Save Failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
|
||||||
|
return doSave()
|
||||||
|
.then(onSuccess)
|
||||||
|
.catch(onFailure);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this action is applicable in a given context.
|
||||||
|
* This will ensure that a domain object is present in the context,
|
||||||
|
* and that this domain object is in Edit mode.
|
||||||
|
* @returns true if applicable
|
||||||
|
*/
|
||||||
|
SaveAction.appliesTo = function (context) {
|
||||||
|
var domainObject = (context || {}).domainObject;
|
||||||
|
|
||||||
|
return domainObject !== undefined
|
||||||
|
&& domainObject.hasCapability('editor')
|
||||||
|
&& domainObject.getCapability('editor').isEditContextRoot()
|
||||||
|
&& domainObject.getModel().persisted !== undefined;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SaveAction;
|
@ -20,56 +20,74 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["./SaveAction"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (SaveAction) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
import SaveAction from './SaveAction';
|
||||||
* The "Save and Stop Editing" action performs a [Save action]{@link SaveAction}
|
|
||||||
* on the object under edit followed by exiting the edit user interface.
|
|
||||||
* @constructor
|
|
||||||
* @implements {Action}
|
|
||||||
* @memberof platform/commonUI/edit
|
|
||||||
*/
|
|
||||||
function SaveAndStopEditingAction(
|
|
||||||
dialogService,
|
|
||||||
notificationService,
|
|
||||||
context
|
|
||||||
) {
|
|
||||||
this.context = context;
|
|
||||||
this.domainObject = (context || {}).domainObject;
|
|
||||||
this.dialogService = dialogService;
|
|
||||||
this.notificationService = notificationService;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Trigger a save operation and exit edit mode.
|
* The "Save and Stop Editing" action performs a [Save action]{@link SaveAction}
|
||||||
*
|
* on the object under edit followed by exiting the edit user interface.
|
||||||
* @returns {Promise} a promise that will be fulfilled when
|
* @constructor
|
||||||
* cancellation has completed
|
* @implements {Action}
|
||||||
* @memberof platform/commonUI/edit.SaveAndStopEditingAction#
|
* @memberof platform/commonUI/edit
|
||||||
*/
|
*/
|
||||||
SaveAndStopEditingAction.prototype.perform = function () {
|
function SaveAndStopEditingAction(
|
||||||
var domainObject = this.domainObject,
|
dialogService,
|
||||||
saveAction = new SaveAction(this.dialogService, this.notificationService, this.context);
|
notificationService,
|
||||||
|
context
|
||||||
|
) {
|
||||||
|
this.context = context;
|
||||||
|
this.domainObject = (context || {}).domainObject;
|
||||||
|
this.dialogService = dialogService;
|
||||||
|
this.notificationService = notificationService;
|
||||||
|
}
|
||||||
|
|
||||||
function closeEditor() {
|
/**
|
||||||
return domainObject.getCapability("editor").finish();
|
* Trigger a save operation and exit edit mode.
|
||||||
}
|
*
|
||||||
|
* @returns {Promise} a promise that will be fulfilled when
|
||||||
|
* cancellation has completed
|
||||||
|
* @memberof platform/commonUI/edit.SaveAndStopEditingAction#
|
||||||
|
*/
|
||||||
|
SaveAndStopEditingAction.prototype.perform = function () {
|
||||||
|
var domainObject = this.domainObject,
|
||||||
|
saveAction = new SaveAction(this.dialogService, this.notificationService, this.context);
|
||||||
|
|
||||||
return saveAction.perform()
|
function closeEditor() {
|
||||||
.then(closeEditor)
|
return domainObject.getCapability("editor").finish();
|
||||||
.catch(closeEditor);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this action is applicable in a given context.
|
|
||||||
* This will ensure that a domain object is present in the context,
|
|
||||||
* and that this domain object is in Edit mode.
|
|
||||||
* @returns true if applicable
|
|
||||||
*/
|
|
||||||
SaveAndStopEditingAction.appliesTo = SaveAction.appliesTo;
|
|
||||||
|
|
||||||
return SaveAndStopEditingAction;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return saveAction.perform()
|
||||||
|
.then(closeEditor)
|
||||||
|
.catch(closeEditor);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this action is applicable in a given context.
|
||||||
|
* This will ensure that a domain object is present in the context,
|
||||||
|
* and that this domain object is in Edit mode.
|
||||||
|
* @returns true if applicable
|
||||||
|
*/
|
||||||
|
SaveAndStopEditingAction.appliesTo = SaveAction.appliesTo;
|
||||||
|
|
||||||
|
export default SaveAndStopEditingAction;
|
@ -1,24 +1,22 @@
|
|||||||
define([], function () {
|
function SaveInProgressDialog(dialogService) {
|
||||||
function SaveInProgressDialog(dialogService) {
|
this.dialogService = dialogService;
|
||||||
this.dialogService = dialogService;
|
this.dialog = undefined;
|
||||||
this.dialog = undefined;
|
}
|
||||||
|
|
||||||
|
SaveInProgressDialog.prototype.show = function () {
|
||||||
|
this.dialog = this.dialogService.showBlockingMessage({
|
||||||
|
title: "Saving",
|
||||||
|
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
|
||||||
|
unknownProgress: true,
|
||||||
|
severity: "info",
|
||||||
|
delay: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
SaveInProgressDialog.prototype.hide = function () {
|
||||||
|
if (this.dialog) {
|
||||||
|
this.dialog.dismiss();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
SaveInProgressDialog.prototype.show = function () {
|
export default SaveInProgressDialog;
|
||||||
this.dialog = this.dialogService.showBlockingMessage({
|
|
||||||
title: "Saving",
|
|
||||||
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
|
|
||||||
unknownProgress: true,
|
|
||||||
severity: "info",
|
|
||||||
delay: true
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
SaveInProgressDialog.prototype.hide = function () {
|
|
||||||
if (this.dialog) {
|
|
||||||
this.dialog.dismiss();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return SaveInProgressDialog;
|
|
||||||
});
|
|
||||||
|
@ -20,45 +20,52 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function EditorCapability(
|
||||||
* A capability that implements an editing 'session' for a domain
|
openmct,
|
||||||
* object. An editing session is initiated via a call to .edit().
|
domainObject
|
||||||
* Once initiated, any persist operations will be queued pending a
|
) {
|
||||||
* subsequent call to [.save()](@link #save) or [.finish()](@link
|
this.openmct = openmct;
|
||||||
* #finish).
|
this.domainObject = domainObject;
|
||||||
* @param domainObject
|
}
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function EditorCapability(
|
|
||||||
openmct,
|
|
||||||
domainObject
|
|
||||||
) {
|
|
||||||
this.openmct = openmct;
|
|
||||||
this.domainObject = domainObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether this object, or any of its ancestors are
|
* Determines whether this object, or any of its ancestors are
|
||||||
* currently being edited.
|
* currently being edited.
|
||||||
* @returns boolean
|
* @returns boolean
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.inEditContext = function () {
|
EditorCapability.prototype.inEditContext = function () {
|
||||||
return this.openmct.editor.isEditing();
|
return this.openmct.editor.isEditing();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this the root editing object (ie. the object that the user
|
* Is this the root editing object (ie. the object that the user
|
||||||
* clicked 'edit' on)?
|
* clicked 'edit' on)?
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.isEditContextRoot = function () {
|
EditorCapability.prototype.isEditContextRoot = function () {
|
||||||
return this.openmct.editor.isEditing();
|
return this.openmct.editor.isEditing();
|
||||||
};
|
};
|
||||||
|
|
||||||
return EditorCapability;
|
export default EditorCapability;
|
||||||
}
|
|
||||||
);
|
|
@ -23,57 +23,76 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining EditActionController. Created by vwoeltje on 11/17/14.
|
* Module defining EditActionController. Created by vwoeltje on 11/17/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var SAVE_ACTION_CONTEXT = { category: 'save' };
|
/**
|
||||||
var OTHERS_ACTION_CONTEXT = { category: 'conclude-editing' };
|
* Module defining EditActionController. Created by vwoeltje on 11/17/14.
|
||||||
|
*/
|
||||||
|
var SAVE_ACTION_CONTEXT = { category: 'save' };
|
||||||
|
var OTHERS_ACTION_CONTEXT = { category: 'conclude-editing' };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller which supplies action instances for Save/Cancel.
|
* Controller which supplies action instances for Save/Cancel.
|
||||||
* @memberof platform/commonUI/edit
|
* @memberof platform/commonUI/edit
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function EditActionController($scope) {
|
function EditActionController($scope) {
|
||||||
|
|
||||||
function actionToMenuOption(action) {
|
function actionToMenuOption(action) {
|
||||||
return {
|
return {
|
||||||
key: action,
|
key: action,
|
||||||
name: action.getMetadata().name,
|
name: action.getMetadata().name,
|
||||||
cssClass: action.getMetadata().cssClass
|
cssClass: action.getMetadata().cssClass
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// Maintain all "conclude-editing" and "save" actions in the
|
|
||||||
// present context.
|
|
||||||
function updateActions() {
|
|
||||||
$scope.saveActions = $scope.action
|
|
||||||
? $scope.action.getActions(SAVE_ACTION_CONTEXT)
|
|
||||||
: [];
|
|
||||||
|
|
||||||
$scope.saveActionsAsMenuOptions = $scope.saveActions.map(actionToMenuOption);
|
|
||||||
|
|
||||||
$scope.saveActionMenuClickHandler = function (clickedAction) {
|
|
||||||
clickedAction.perform();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.otherEditActions = $scope.action
|
|
||||||
? $scope.action.getActions(OTHERS_ACTION_CONTEXT)
|
|
||||||
: [];
|
|
||||||
|
|
||||||
// Required because Angular does not allow 'bind'
|
|
||||||
// in expressions.
|
|
||||||
$scope.actionPerformer = function (action) {
|
|
||||||
return action.perform.bind(action);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update set of actions whenever the action capability
|
|
||||||
// changes or becomes available.
|
|
||||||
$scope.$watch("action", updateActions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return EditActionController;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Maintain all "conclude-editing" and "save" actions in the
|
||||||
|
// present context.
|
||||||
|
function updateActions() {
|
||||||
|
$scope.saveActions = $scope.action
|
||||||
|
? $scope.action.getActions(SAVE_ACTION_CONTEXT)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
$scope.saveActionsAsMenuOptions = $scope.saveActions.map(actionToMenuOption);
|
||||||
|
|
||||||
|
$scope.saveActionMenuClickHandler = function (clickedAction) {
|
||||||
|
clickedAction.perform();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.otherEditActions = $scope.action
|
||||||
|
? $scope.action.getActions(OTHERS_ACTION_CONTEXT)
|
||||||
|
: [];
|
||||||
|
|
||||||
|
// Required because Angular does not allow 'bind'
|
||||||
|
// in expressions.
|
||||||
|
$scope.actionPerformer = function (action) {
|
||||||
|
return action.perform.bind(action);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update set of actions whenever the action capability
|
||||||
|
// changes or becomes available.
|
||||||
|
$scope.$watch("action", updateActions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditActionController;
|
@ -24,63 +24,83 @@
|
|||||||
* This bundle implements Edit mode.
|
* This bundle implements Edit mode.
|
||||||
* @namespace platform/commonUI/edit
|
* @namespace platform/commonUI/edit
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
function cancelEditing(domainObject) {
|
/**
|
||||||
var navigatedObject = domainObject,
|
* This bundle implements Edit mode.
|
||||||
editorCapability = navigatedObject
|
* @namespace platform/commonUI/edit
|
||||||
&& navigatedObject.getCapability("editor");
|
*/
|
||||||
|
function cancelEditing(domainObject) {
|
||||||
|
var navigatedObject = domainObject,
|
||||||
|
editorCapability = navigatedObject
|
||||||
|
&& navigatedObject.getCapability("editor");
|
||||||
|
|
||||||
return editorCapability
|
return editorCapability
|
||||||
&& editorCapability.finish();
|
&& editorCapability.finish();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller which is responsible for populating the scope for
|
* Controller which is responsible for populating the scope for
|
||||||
* Edit mode
|
* Edit mode
|
||||||
* @memberof platform/commonUI/edit
|
* @memberof platform/commonUI/edit
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function EditObjectController($scope, $location, navigationService) {
|
function EditObjectController($scope, $location, navigationService) {
|
||||||
this.scope = $scope;
|
this.scope = $scope;
|
||||||
var domainObject = $scope.domainObject;
|
var domainObject = $scope.domainObject;
|
||||||
|
|
||||||
var removeCheck = navigationService
|
var removeCheck = navigationService
|
||||||
.checkBeforeNavigation(function () {
|
.checkBeforeNavigation(function () {
|
||||||
return "Continuing will cause the loss of any unsaved changes.";
|
return "Continuing will cause the loss of any unsaved changes.";
|
||||||
});
|
});
|
||||||
|
|
||||||
$scope.$on('$destroy', function () {
|
$scope.$on('$destroy', function () {
|
||||||
removeCheck();
|
removeCheck();
|
||||||
cancelEditing(domainObject);
|
cancelEditing(domainObject);
|
||||||
});
|
});
|
||||||
|
|
||||||
function setViewForDomainObject() {
|
function setViewForDomainObject() {
|
||||||
|
|
||||||
var locationViewKey = $location.search().view;
|
var locationViewKey = $location.search().view;
|
||||||
|
|
||||||
function selectViewIfMatching(view) {
|
function selectViewIfMatching(view) {
|
||||||
if (view.key === locationViewKey) {
|
if (view.key === locationViewKey) {
|
||||||
$scope.representation = $scope.representation || {};
|
$scope.representation = $scope.representation || {};
|
||||||
$scope.representation.selected = view;
|
$scope.representation.selected = view;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (locationViewKey) {
|
|
||||||
((domainObject && domainObject.useCapability('view')) || [])
|
|
||||||
.forEach(selectViewIfMatching);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setViewForDomainObject();
|
|
||||||
|
|
||||||
$scope.doAction = function (action) {
|
|
||||||
return $scope[action] && $scope[action]();
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return EditObjectController;
|
if (locationViewKey) {
|
||||||
|
((domainObject && domainObject.useCapability('view')) || [])
|
||||||
|
.forEach(selectViewIfMatching);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
setViewForDomainObject();
|
||||||
|
|
||||||
|
$scope.doAction = function (action) {
|
||||||
|
return $scope[action] && $scope[action]();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default EditObjectController;
|
@ -20,47 +20,58 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function EditPanesController($scope) {
|
||||||
* Supports the Library and Elements panes in Edit mode.
|
var self = this;
|
||||||
* @memberof platform/commonUI/edit
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function EditPanesController($scope) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
// Update root object based on represented object
|
// Update root object based on represented object
|
||||||
function updateRoot(domainObject) {
|
function updateRoot(domainObject) {
|
||||||
var root = self.rootDomainObject,
|
var root = self.rootDomainObject,
|
||||||
context = domainObject
|
context = domainObject
|
||||||
&& domainObject.getCapability('context'),
|
&& domainObject.getCapability('context'),
|
||||||
newRoot = context && context.getTrueRoot(),
|
newRoot = context && context.getTrueRoot(),
|
||||||
oldId = root && root.getId(),
|
oldId = root && root.getId(),
|
||||||
newId = newRoot && newRoot.getId();
|
newId = newRoot && newRoot.getId();
|
||||||
|
|
||||||
// Only update if this has actually changed,
|
// Only update if this has actually changed,
|
||||||
// to avoid excessive refreshing.
|
// to avoid excessive refreshing.
|
||||||
if (oldId !== newId) {
|
if (oldId !== newId) {
|
||||||
self.rootDomainObject = newRoot;
|
self.rootDomainObject = newRoot;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update root when represented object changes
|
|
||||||
$scope.$watch('domainObject', updateRoot);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the root-level domain object, as reported by the
|
|
||||||
* represented domain object.
|
|
||||||
* @returns {DomainObject} the root object
|
|
||||||
*/
|
|
||||||
EditPanesController.prototype.getRoot = function () {
|
|
||||||
return this.rootDomainObject;
|
|
||||||
};
|
|
||||||
|
|
||||||
return EditPanesController;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Update root when represented object changes
|
||||||
|
$scope.$watch('domainObject', updateRoot);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the root-level domain object, as reported by the
|
||||||
|
* represented domain object.
|
||||||
|
* @returns {DomainObject} the root object
|
||||||
|
*/
|
||||||
|
EditPanesController.prototype.getRoot = function () {
|
||||||
|
return this.rootDomainObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditPanesController;
|
@ -20,38 +20,56 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
['objectUtils'],
|
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||||
function (objectUtils) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
import objectUtils from 'objectUtils';
|
||||||
* Policy that prevents editing of any object from a provider that does not
|
|
||||||
* support persistence (ie. the 'save' operation). Editing is prevented
|
|
||||||
* as a subsequent save would fail, causing the loss of a user's changes.
|
|
||||||
* @param openmct
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function EditPersistableObjectsPolicy(openmct) {
|
|
||||||
this.openmct = openmct;
|
|
||||||
}
|
|
||||||
|
|
||||||
EditPersistableObjectsPolicy.prototype.allow = function (action, context) {
|
/**
|
||||||
var domainObject = context.domainObject;
|
* Policy that prevents editing of any object from a provider that does not
|
||||||
var key = action.getMetadata().key;
|
* support persistence (ie. the 'save' operation). Editing is prevented
|
||||||
var category = (context || {}).category;
|
* as a subsequent save would fail, causing the loss of a user's changes.
|
||||||
|
* @param openmct
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function EditPersistableObjectsPolicy(openmct) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
}
|
||||||
|
|
||||||
// Use category to selectively block edit from the view. Edit action
|
EditPersistableObjectsPolicy.prototype.allow = function (action, context) {
|
||||||
// is also invoked during the create process which should be allowed,
|
var domainObject = context.domainObject;
|
||||||
// because it may be saved elsewhere
|
var key = action.getMetadata().key;
|
||||||
if ((key === 'edit' && category === 'view-control') || key === 'properties') {
|
var category = (context || {}).category;
|
||||||
let identifier = this.openmct.objects.parseKeyString(domainObject.getId());
|
|
||||||
|
|
||||||
return this.openmct.objects.isPersistable(identifier);
|
// Use category to selectively block edit from the view. Edit action
|
||||||
}
|
// is also invoked during the create process which should be allowed,
|
||||||
|
// because it may be saved elsewhere
|
||||||
|
if ((key === 'edit' && category === 'view-control') || key === 'properties') {
|
||||||
|
let identifier = this.openmct.objects.parseKeyString(domainObject.getId());
|
||||||
|
|
||||||
return true;
|
return this.openmct.objects.isPersistable(identifier);
|
||||||
};
|
|
||||||
|
|
||||||
return EditPersistableObjectsPolicy;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditPersistableObjectsPolicy;
|
@ -20,80 +20,77 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function EditRepresenter($log, $scope) {
|
||||||
* The EditRepresenter is responsible for implementing
|
this.$log = $log;
|
||||||
* representation-level behavior relevant to Edit mode.
|
this.$scope = $scope;
|
||||||
* Specifically, this listens for changes to view configuration
|
|
||||||
* or to domain object models, and triggers persistence when
|
|
||||||
* these are detected.
|
|
||||||
*
|
|
||||||
* This is exposed as an extension of category `representers`,
|
|
||||||
* which mct-representation will utilize to add additional
|
|
||||||
* behavior to each representation.
|
|
||||||
*
|
|
||||||
* This will be called once per mct-representation directive,
|
|
||||||
* and may be reused for different domain objects and/or
|
|
||||||
* representations resulting from changes there.
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/edit
|
|
||||||
* @implements {Representer}
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function EditRepresenter($log, $scope) {
|
|
||||||
this.$log = $log;
|
|
||||||
this.$scope = $scope;
|
|
||||||
|
|
||||||
this.$scope.commit = this.commit.bind(this);
|
this.$scope.commit = this.commit.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Commit any changes made to the in-scope model to the domain object.
|
||||||
|
* Also commits any changes made to $scope.configuration to the proper
|
||||||
|
* configuration value for the current representation.
|
||||||
|
*
|
||||||
|
* @param {String} message a message to log with the commit message.
|
||||||
|
*/
|
||||||
|
EditRepresenter.prototype.commit = function (message) {
|
||||||
|
var model = this.$scope.model,
|
||||||
|
configuration = this.$scope.configuration,
|
||||||
|
domainObject = this.domainObject;
|
||||||
|
|
||||||
|
this.$log.debug([
|
||||||
|
"Committing ",
|
||||||
|
domainObject && domainObject.getModel().name,
|
||||||
|
"(" + (domainObject && domainObject.getId()) + "):",
|
||||||
|
message
|
||||||
|
].join(" "));
|
||||||
|
|
||||||
|
if (this.domainObject) {
|
||||||
|
if (this.key && configuration) {
|
||||||
|
model.configuration = model.configuration || {};
|
||||||
|
model.configuration[this.key] = configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
domainObject.useCapability('mutation', function () {
|
||||||
* Commit any changes made to the in-scope model to the domain object.
|
return model;
|
||||||
* Also commits any changes made to $scope.configuration to the proper
|
});
|
||||||
* configuration value for the current representation.
|
|
||||||
*
|
|
||||||
* @param {String} message a message to log with the commit message.
|
|
||||||
*/
|
|
||||||
EditRepresenter.prototype.commit = function (message) {
|
|
||||||
var model = this.$scope.model,
|
|
||||||
configuration = this.$scope.configuration,
|
|
||||||
domainObject = this.domainObject;
|
|
||||||
|
|
||||||
this.$log.debug([
|
|
||||||
"Committing ",
|
|
||||||
domainObject && domainObject.getModel().name,
|
|
||||||
"(" + (domainObject && domainObject.getId()) + "):",
|
|
||||||
message
|
|
||||||
].join(" "));
|
|
||||||
|
|
||||||
if (this.domainObject) {
|
|
||||||
if (this.key && configuration) {
|
|
||||||
model.configuration = model.configuration || {};
|
|
||||||
model.configuration[this.key] = configuration;
|
|
||||||
}
|
|
||||||
|
|
||||||
domainObject.useCapability('mutation', function () {
|
|
||||||
return model;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Handle a specific representation of a specific domain object
|
|
||||||
EditRepresenter.prototype.represent = function (representation, representedObject) {
|
|
||||||
this.domainObject = representedObject;
|
|
||||||
if (representation) {
|
|
||||||
this.key = representation.key;
|
|
||||||
} else {
|
|
||||||
delete this.key;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Respond to the destruction of the current representation.
|
|
||||||
EditRepresenter.prototype.destroy = function () {};
|
|
||||||
|
|
||||||
return EditRepresenter;
|
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
|
|
||||||
|
// Handle a specific representation of a specific domain object
|
||||||
|
EditRepresenter.prototype.represent = function (representation, representedObject) {
|
||||||
|
this.domainObject = representedObject;
|
||||||
|
if (representation) {
|
||||||
|
this.key = representation.key;
|
||||||
|
} else {
|
||||||
|
delete this.key;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Respond to the destruction of the current representation.
|
||||||
|
EditRepresenter.prototype.destroy = function () {};
|
||||||
|
|
||||||
|
export default EditRepresenter;
|
@ -20,136 +20,154 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/actions/CancelAction"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (CancelAction) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Cancel action", function () {
|
import CancelAction from '../../src/actions/CancelAction';
|
||||||
var mockDomainObject,
|
|
||||||
mockParentObject,
|
|
||||||
capabilities = {},
|
|
||||||
parentCapabilities = {},
|
|
||||||
actionContext,
|
|
||||||
action;
|
|
||||||
|
|
||||||
function mockPromise(value) {
|
describe("The Cancel action", function () {
|
||||||
return {
|
var mockDomainObject,
|
||||||
then: function (callback) {
|
mockParentObject,
|
||||||
return mockPromise(callback(value));
|
capabilities = {},
|
||||||
}
|
parentCapabilities = {},
|
||||||
};
|
actionContext,
|
||||||
|
action;
|
||||||
|
|
||||||
|
function mockPromise(value) {
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
return mockPromise(callback(value));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
beforeEach(function () {
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
|
||||||
[
|
|
||||||
"getCapability",
|
|
||||||
"hasCapability",
|
|
||||||
"getModel"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
mockDomainObject.getModel.and.returnValue({});
|
|
||||||
|
|
||||||
mockParentObject = jasmine.createSpyObj(
|
|
||||||
"parentObject",
|
|
||||||
[
|
|
||||||
"getCapability"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
mockParentObject.getCapability.and.callFake(function (name) {
|
|
||||||
return parentCapabilities[name];
|
|
||||||
});
|
|
||||||
|
|
||||||
capabilities.editor = jasmine.createSpyObj(
|
|
||||||
"editor",
|
|
||||||
["save", "finish", "isEditContextRoot"]
|
|
||||||
);
|
|
||||||
capabilities.action = jasmine.createSpyObj(
|
|
||||||
"actionCapability",
|
|
||||||
[
|
|
||||||
"perform"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
capabilities.location = jasmine.createSpyObj(
|
|
||||||
"locationCapability",
|
|
||||||
[
|
|
||||||
"getOriginal"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
capabilities.location.getOriginal.and.returnValue(mockPromise(mockDomainObject));
|
|
||||||
capabilities.context = jasmine.createSpyObj(
|
|
||||||
"contextCapability",
|
|
||||||
[
|
|
||||||
"getParent"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
capabilities.context.getParent.and.returnValue(mockParentObject);
|
|
||||||
|
|
||||||
parentCapabilities.action = jasmine.createSpyObj(
|
|
||||||
"actionCapability",
|
|
||||||
[
|
|
||||||
"perform"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
actionContext = {
|
|
||||||
domainObject: mockDomainObject
|
|
||||||
};
|
|
||||||
|
|
||||||
mockDomainObject.getCapability.and.callFake(function (name) {
|
|
||||||
return capabilities[name];
|
|
||||||
});
|
|
||||||
|
|
||||||
mockDomainObject.hasCapability.and.callFake(function (name) {
|
|
||||||
return Boolean(capabilities[name]);
|
|
||||||
});
|
|
||||||
|
|
||||||
capabilities.editor.finish.and.returnValue(mockPromise(true));
|
|
||||||
|
|
||||||
action = new CancelAction(actionContext);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it("only applies to domain object that is being edited", function () {
|
|
||||||
capabilities.editor.isEditContextRoot.and.returnValue(true);
|
|
||||||
expect(CancelAction.appliesTo(actionContext)).toBeTruthy();
|
|
||||||
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
|
||||||
|
|
||||||
capabilities.editor.isEditContextRoot.and.returnValue(false);
|
|
||||||
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
|
|
||||||
|
|
||||||
mockDomainObject.hasCapability.and.returnValue(false);
|
|
||||||
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("invokes the editor capability's cancel functionality when"
|
|
||||||
+ " performed", function () {
|
|
||||||
mockDomainObject.getModel.and.returnValue({persisted: 1});
|
|
||||||
//Return true from navigate action
|
|
||||||
capabilities.action.perform.and.returnValue(mockPromise(true));
|
|
||||||
action.perform();
|
|
||||||
|
|
||||||
// Should have called finish
|
|
||||||
expect(capabilities.editor.finish).toHaveBeenCalled();
|
|
||||||
|
|
||||||
// Definitely shouldn't call save!
|
|
||||||
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("navigates to object if existing using navigate action", function () {
|
|
||||||
mockDomainObject.getModel.and.returnValue({persisted: 1});
|
|
||||||
//Return true from navigate action
|
|
||||||
capabilities.action.perform.and.returnValue(mockPromise(true));
|
|
||||||
action.perform();
|
|
||||||
expect(capabilities.action.perform).toHaveBeenCalledWith("navigate");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("navigates to parent if new using navigate action", function () {
|
|
||||||
mockDomainObject.getModel.and.returnValue({persisted: undefined});
|
|
||||||
action.perform();
|
|
||||||
expect(parentCapabilities.action.perform).toHaveBeenCalledWith("navigate");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[
|
||||||
|
"getCapability",
|
||||||
|
"hasCapability",
|
||||||
|
"getModel"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockDomainObject.getModel.and.returnValue({});
|
||||||
|
|
||||||
|
mockParentObject = jasmine.createSpyObj(
|
||||||
|
"parentObject",
|
||||||
|
[
|
||||||
|
"getCapability"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockParentObject.getCapability.and.callFake(function (name) {
|
||||||
|
return parentCapabilities[name];
|
||||||
|
});
|
||||||
|
|
||||||
|
capabilities.editor = jasmine.createSpyObj(
|
||||||
|
"editor",
|
||||||
|
["save", "finish", "isEditContextRoot"]
|
||||||
|
);
|
||||||
|
capabilities.action = jasmine.createSpyObj(
|
||||||
|
"actionCapability",
|
||||||
|
[
|
||||||
|
"perform"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
capabilities.location = jasmine.createSpyObj(
|
||||||
|
"locationCapability",
|
||||||
|
[
|
||||||
|
"getOriginal"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
capabilities.location.getOriginal.and.returnValue(mockPromise(mockDomainObject));
|
||||||
|
capabilities.context = jasmine.createSpyObj(
|
||||||
|
"contextCapability",
|
||||||
|
[
|
||||||
|
"getParent"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
capabilities.context.getParent.and.returnValue(mockParentObject);
|
||||||
|
|
||||||
|
parentCapabilities.action = jasmine.createSpyObj(
|
||||||
|
"actionCapability",
|
||||||
|
[
|
||||||
|
"perform"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
actionContext = {
|
||||||
|
domainObject: mockDomainObject
|
||||||
|
};
|
||||||
|
|
||||||
|
mockDomainObject.getCapability.and.callFake(function (name) {
|
||||||
|
return capabilities[name];
|
||||||
|
});
|
||||||
|
|
||||||
|
mockDomainObject.hasCapability.and.callFake(function (name) {
|
||||||
|
return Boolean(capabilities[name]);
|
||||||
|
});
|
||||||
|
|
||||||
|
capabilities.editor.finish.and.returnValue(mockPromise(true));
|
||||||
|
|
||||||
|
action = new CancelAction(actionContext);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("only applies to domain object that is being edited", function () {
|
||||||
|
capabilities.editor.isEditContextRoot.and.returnValue(true);
|
||||||
|
expect(CancelAction.appliesTo(actionContext)).toBeTruthy();
|
||||||
|
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
||||||
|
|
||||||
|
capabilities.editor.isEditContextRoot.and.returnValue(false);
|
||||||
|
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
|
||||||
|
|
||||||
|
mockDomainObject.hasCapability.and.returnValue(false);
|
||||||
|
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("invokes the editor capability's cancel functionality when"
|
||||||
|
+ " performed", function () {
|
||||||
|
mockDomainObject.getModel.and.returnValue({persisted: 1});
|
||||||
|
//Return true from navigate action
|
||||||
|
capabilities.action.perform.and.returnValue(mockPromise(true));
|
||||||
|
action.perform();
|
||||||
|
|
||||||
|
// Should have called finish
|
||||||
|
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||||
|
|
||||||
|
// Definitely shouldn't call save!
|
||||||
|
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("navigates to object if existing using navigate action", function () {
|
||||||
|
mockDomainObject.getModel.and.returnValue({persisted: 1});
|
||||||
|
//Return true from navigate action
|
||||||
|
capabilities.action.perform.and.returnValue(mockPromise(true));
|
||||||
|
action.perform();
|
||||||
|
expect(capabilities.action.perform).toHaveBeenCalledWith("navigate");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("navigates to parent if new using navigate action", function () {
|
||||||
|
mockDomainObject.getModel.and.returnValue({persisted: undefined});
|
||||||
|
action.perform();
|
||||||
|
expect(parentCapabilities.action.perform).toHaveBeenCalledWith("navigate");
|
||||||
|
});
|
||||||
|
});
|
@ -20,89 +20,107 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/actions/EditAction"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (EditAction) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Edit action", function () {
|
import EditAction from '../../src/actions/EditAction';
|
||||||
var mockLocation,
|
|
||||||
mockNavigationService,
|
|
||||||
mockLog,
|
|
||||||
mockDomainObject,
|
|
||||||
mockType,
|
|
||||||
mockEditor,
|
|
||||||
actionContext,
|
|
||||||
capabilities,
|
|
||||||
action;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The Edit action", function () {
|
||||||
mockLocation = jasmine.createSpyObj(
|
var mockLocation,
|
||||||
"$location",
|
mockNavigationService,
|
||||||
["path"]
|
mockLog,
|
||||||
);
|
mockDomainObject,
|
||||||
mockNavigationService = jasmine.createSpyObj(
|
mockType,
|
||||||
"navigationService",
|
mockEditor,
|
||||||
["setNavigation", "getNavigation", "addListener", "removeListener"]
|
actionContext,
|
||||||
);
|
capabilities,
|
||||||
mockLog = jasmine.createSpyObj(
|
action;
|
||||||
"$log",
|
|
||||||
["error", "warn", "info", "debug"]
|
|
||||||
);
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
|
||||||
["getId", "getModel", "getCapability", "hasCapability", "useCapability"]
|
|
||||||
);
|
|
||||||
mockType = jasmine.createSpyObj(
|
|
||||||
"type",
|
|
||||||
["hasFeature"]
|
|
||||||
);
|
|
||||||
mockEditor = jasmine.createSpyObj(
|
|
||||||
"editorCapability",
|
|
||||||
["edit", "isEditContextRoot"]
|
|
||||||
);
|
|
||||||
|
|
||||||
capabilities = {
|
beforeEach(function () {
|
||||||
type: mockType,
|
mockLocation = jasmine.createSpyObj(
|
||||||
editor: mockEditor
|
"$location",
|
||||||
};
|
["path"]
|
||||||
|
);
|
||||||
|
mockNavigationService = jasmine.createSpyObj(
|
||||||
|
"navigationService",
|
||||||
|
["setNavigation", "getNavigation", "addListener", "removeListener"]
|
||||||
|
);
|
||||||
|
mockLog = jasmine.createSpyObj(
|
||||||
|
"$log",
|
||||||
|
["error", "warn", "info", "debug"]
|
||||||
|
);
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
["getId", "getModel", "getCapability", "hasCapability", "useCapability"]
|
||||||
|
);
|
||||||
|
mockType = jasmine.createSpyObj(
|
||||||
|
"type",
|
||||||
|
["hasFeature"]
|
||||||
|
);
|
||||||
|
mockEditor = jasmine.createSpyObj(
|
||||||
|
"editorCapability",
|
||||||
|
["edit", "isEditContextRoot"]
|
||||||
|
);
|
||||||
|
|
||||||
mockDomainObject.getCapability.and.callFake(function (name) {
|
capabilities = {
|
||||||
return capabilities[name];
|
type: mockType,
|
||||||
});
|
editor: mockEditor
|
||||||
mockDomainObject.hasCapability.and.returnValue(true);
|
};
|
||||||
mockType.hasFeature.and.returnValue(true);
|
|
||||||
|
|
||||||
actionContext = { domainObject: mockDomainObject };
|
|
||||||
|
|
||||||
action = new EditAction(
|
|
||||||
mockLocation,
|
|
||||||
mockNavigationService,
|
|
||||||
mockLog,
|
|
||||||
actionContext
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("is only applicable when an editable domain object is present", function () {
|
|
||||||
expect(EditAction.appliesTo(actionContext)).toBeTruthy();
|
|
||||||
expect(EditAction.appliesTo({})).toBeFalsy();
|
|
||||||
|
|
||||||
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith('editor');
|
|
||||||
// Should have checked for creatability
|
|
||||||
expect(mockType.hasFeature).toHaveBeenCalledWith('creation');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("is only applicable to objects not already in edit mode", function () {
|
|
||||||
mockEditor.isEditContextRoot.and.returnValue(false);
|
|
||||||
expect(EditAction.appliesTo(actionContext)).toBe(true);
|
|
||||||
mockEditor.isEditContextRoot.and.returnValue(true);
|
|
||||||
expect(EditAction.appliesTo(actionContext)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it ("invokes the Edit capability on the object", function () {
|
|
||||||
action.perform();
|
|
||||||
expect(mockDomainObject.useCapability).toHaveBeenCalledWith("editor");
|
|
||||||
});
|
|
||||||
|
|
||||||
|
mockDomainObject.getCapability.and.callFake(function (name) {
|
||||||
|
return capabilities[name];
|
||||||
});
|
});
|
||||||
}
|
mockDomainObject.hasCapability.and.returnValue(true);
|
||||||
);
|
mockType.hasFeature.and.returnValue(true);
|
||||||
|
|
||||||
|
actionContext = { domainObject: mockDomainObject };
|
||||||
|
|
||||||
|
action = new EditAction(
|
||||||
|
mockLocation,
|
||||||
|
mockNavigationService,
|
||||||
|
mockLog,
|
||||||
|
actionContext
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is only applicable when an editable domain object is present", function () {
|
||||||
|
expect(EditAction.appliesTo(actionContext)).toBeTruthy();
|
||||||
|
expect(EditAction.appliesTo({})).toBeFalsy();
|
||||||
|
|
||||||
|
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith('editor');
|
||||||
|
// Should have checked for creatability
|
||||||
|
expect(mockType.hasFeature).toHaveBeenCalledWith('creation');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("is only applicable to objects not already in edit mode", function () {
|
||||||
|
mockEditor.isEditContextRoot.and.returnValue(false);
|
||||||
|
expect(EditAction.appliesTo(actionContext)).toBe(true);
|
||||||
|
mockEditor.isEditContextRoot.and.returnValue(true);
|
||||||
|
expect(EditAction.appliesTo(actionContext)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it ("invokes the Edit capability on the object", function () {
|
||||||
|
action.perform();
|
||||||
|
expect(mockDomainObject.useCapability).toHaveBeenCalledWith("editor");
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -20,100 +20,118 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/actions/EditAndComposeAction"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (EditAndComposeAction) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Link action", function () {
|
import EditAndComposeAction from '../../src/actions/EditAndComposeAction';
|
||||||
var mockDomainObject,
|
|
||||||
mockParent,
|
|
||||||
mockContext,
|
|
||||||
mockComposition,
|
|
||||||
mockActionCapability,
|
|
||||||
mockEditAction,
|
|
||||||
mockType,
|
|
||||||
actionContext,
|
|
||||||
model,
|
|
||||||
capabilities,
|
|
||||||
action;
|
|
||||||
|
|
||||||
function mockPromise(value) {
|
describe("The Link action", function () {
|
||||||
return {
|
var mockDomainObject,
|
||||||
then: function (callback) {
|
mockParent,
|
||||||
return mockPromise(callback(value));
|
mockContext,
|
||||||
}
|
mockComposition,
|
||||||
};
|
mockActionCapability,
|
||||||
|
mockEditAction,
|
||||||
|
mockType,
|
||||||
|
actionContext,
|
||||||
|
model,
|
||||||
|
capabilities,
|
||||||
|
action;
|
||||||
|
|
||||||
|
function mockPromise(value) {
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
return mockPromise(callback(value));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
beforeEach(function () {
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
|
||||||
["getId", "getCapability"]
|
|
||||||
);
|
|
||||||
mockParent = {
|
|
||||||
getModel: function () {
|
|
||||||
return model;
|
|
||||||
},
|
|
||||||
getCapability: function (k) {
|
|
||||||
return capabilities[k];
|
|
||||||
},
|
|
||||||
useCapability: function (k, v) {
|
|
||||||
return capabilities[k].invoke(v);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
mockContext = jasmine.createSpyObj("context", ["getParent"]);
|
|
||||||
mockComposition = jasmine.createSpyObj("composition", ["invoke", "add"]);
|
|
||||||
mockType = jasmine.createSpyObj("type", ["hasFeature", "getKey"]);
|
|
||||||
mockActionCapability = jasmine.createSpyObj("actionCapability", ["getActions"]);
|
|
||||||
mockEditAction = jasmine.createSpyObj("editAction", ["perform"]);
|
|
||||||
|
|
||||||
mockDomainObject.getId.and.returnValue("test");
|
|
||||||
mockDomainObject.getCapability.and.returnValue(mockContext);
|
|
||||||
mockContext.getParent.and.returnValue(mockParent);
|
|
||||||
mockType.hasFeature.and.returnValue(true);
|
|
||||||
mockType.getKey.and.returnValue("layout");
|
|
||||||
mockComposition.invoke.and.returnValue(mockPromise(true));
|
|
||||||
mockComposition.add.and.returnValue(mockPromise(true));
|
|
||||||
mockActionCapability.getActions.and.returnValue([]);
|
|
||||||
|
|
||||||
capabilities = {
|
|
||||||
composition: mockComposition,
|
|
||||||
action: mockActionCapability,
|
|
||||||
type: mockType
|
|
||||||
};
|
|
||||||
model = {
|
|
||||||
composition: ["a", "b", "c"]
|
|
||||||
};
|
|
||||||
|
|
||||||
actionContext = {
|
|
||||||
domainObject: mockParent,
|
|
||||||
selectedObject: mockDomainObject
|
|
||||||
};
|
|
||||||
|
|
||||||
action = new EditAndComposeAction(actionContext);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("adds to the parent's composition when performed", function () {
|
|
||||||
action.perform();
|
|
||||||
expect(mockComposition.add)
|
|
||||||
.toHaveBeenCalledWith(mockDomainObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("enables edit mode for objects that have an edit action", function () {
|
|
||||||
mockActionCapability.getActions.and.returnValue([mockEditAction]);
|
|
||||||
action.perform();
|
|
||||||
expect(mockEditAction.perform).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("Does not enable edit mode for objects that do not have an"
|
|
||||||
+ " edit action", function () {
|
|
||||||
mockActionCapability.getActions.and.returnValue([]);
|
|
||||||
action.perform();
|
|
||||||
expect(mockEditAction.perform).not.toHaveBeenCalled();
|
|
||||||
expect(mockComposition.add)
|
|
||||||
.toHaveBeenCalledWith(mockDomainObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
["getId", "getCapability"]
|
||||||
|
);
|
||||||
|
mockParent = {
|
||||||
|
getModel: function () {
|
||||||
|
return model;
|
||||||
|
},
|
||||||
|
getCapability: function (k) {
|
||||||
|
return capabilities[k];
|
||||||
|
},
|
||||||
|
useCapability: function (k, v) {
|
||||||
|
return capabilities[k].invoke(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mockContext = jasmine.createSpyObj("context", ["getParent"]);
|
||||||
|
mockComposition = jasmine.createSpyObj("composition", ["invoke", "add"]);
|
||||||
|
mockType = jasmine.createSpyObj("type", ["hasFeature", "getKey"]);
|
||||||
|
mockActionCapability = jasmine.createSpyObj("actionCapability", ["getActions"]);
|
||||||
|
mockEditAction = jasmine.createSpyObj("editAction", ["perform"]);
|
||||||
|
|
||||||
|
mockDomainObject.getId.and.returnValue("test");
|
||||||
|
mockDomainObject.getCapability.and.returnValue(mockContext);
|
||||||
|
mockContext.getParent.and.returnValue(mockParent);
|
||||||
|
mockType.hasFeature.and.returnValue(true);
|
||||||
|
mockType.getKey.and.returnValue("layout");
|
||||||
|
mockComposition.invoke.and.returnValue(mockPromise(true));
|
||||||
|
mockComposition.add.and.returnValue(mockPromise(true));
|
||||||
|
mockActionCapability.getActions.and.returnValue([]);
|
||||||
|
|
||||||
|
capabilities = {
|
||||||
|
composition: mockComposition,
|
||||||
|
action: mockActionCapability,
|
||||||
|
type: mockType
|
||||||
|
};
|
||||||
|
model = {
|
||||||
|
composition: ["a", "b", "c"]
|
||||||
|
};
|
||||||
|
|
||||||
|
actionContext = {
|
||||||
|
domainObject: mockParent,
|
||||||
|
selectedObject: mockDomainObject
|
||||||
|
};
|
||||||
|
|
||||||
|
action = new EditAndComposeAction(actionContext);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds to the parent's composition when performed", function () {
|
||||||
|
action.perform();
|
||||||
|
expect(mockComposition.add)
|
||||||
|
.toHaveBeenCalledWith(mockDomainObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("enables edit mode for objects that have an edit action", function () {
|
||||||
|
mockActionCapability.getActions.and.returnValue([mockEditAction]);
|
||||||
|
action.perform();
|
||||||
|
expect(mockEditAction.perform).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Does not enable edit mode for objects that do not have an"
|
||||||
|
+ " edit action", function () {
|
||||||
|
mockActionCapability.getActions.and.returnValue([]);
|
||||||
|
action.perform();
|
||||||
|
expect(mockEditAction.perform).not.toHaveBeenCalled();
|
||||||
|
expect(mockComposition.add)
|
||||||
|
.toHaveBeenCalledWith(mockDomainObject);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -20,140 +20,158 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/actions/SaveAction"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (SaveAction) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Save action", function () {
|
import SaveAction from '../../src/actions/SaveAction';
|
||||||
var mockDomainObject,
|
|
||||||
mockEditorCapability,
|
|
||||||
actionContext,
|
|
||||||
mockDialogService,
|
|
||||||
mockNotificationService,
|
|
||||||
mockActionCapability,
|
|
||||||
capabilities = {},
|
|
||||||
action;
|
|
||||||
|
|
||||||
function mockPromise(value) {
|
describe("The Save action", function () {
|
||||||
return {
|
var mockDomainObject,
|
||||||
then: function (callback) {
|
mockEditorCapability,
|
||||||
return mockPromise(callback(value));
|
actionContext,
|
||||||
},
|
mockDialogService,
|
||||||
catch: function (callback) {
|
mockNotificationService,
|
||||||
return mockPromise(callback(value));
|
mockActionCapability,
|
||||||
}
|
capabilities = {},
|
||||||
};
|
action;
|
||||||
|
|
||||||
|
function mockPromise(value) {
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
return mockPromise(callback(value));
|
||||||
|
},
|
||||||
|
catch: function (callback) {
|
||||||
|
return mockPromise(callback(value));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
"domainObject",
|
"domainObject",
|
||||||
[
|
[
|
||||||
"getCapability",
|
"getCapability",
|
||||||
"hasCapability",
|
"hasCapability",
|
||||||
"getModel",
|
"getModel",
|
||||||
"getOriginalObject"
|
"getOriginalObject"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
mockEditorCapability = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "isEditContextRoot"]
|
["save", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
mockActionCapability = jasmine.createSpyObj(
|
mockActionCapability = jasmine.createSpyObj(
|
||||||
"actionCapability",
|
"actionCapability",
|
||||||
["perform"]
|
["perform"]
|
||||||
);
|
);
|
||||||
capabilities.editor = mockEditorCapability;
|
capabilities.editor = mockEditorCapability;
|
||||||
capabilities.action = mockActionCapability;
|
capabilities.action = mockActionCapability;
|
||||||
|
|
||||||
actionContext = {
|
actionContext = {
|
||||||
domainObject: mockDomainObject
|
domainObject: mockDomainObject
|
||||||
};
|
};
|
||||||
|
|
||||||
mockDialogService = jasmine.createSpyObj(
|
mockDialogService = jasmine.createSpyObj(
|
||||||
"dialogService",
|
"dialogService",
|
||||||
["showBlockingMessage"]
|
["showBlockingMessage"]
|
||||||
);
|
);
|
||||||
|
|
||||||
mockNotificationService = jasmine.createSpyObj(
|
mockNotificationService = jasmine.createSpyObj(
|
||||||
"notificationService",
|
"notificationService",
|
||||||
["info", "error"]
|
["info", "error"]
|
||||||
);
|
);
|
||||||
|
|
||||||
mockDomainObject.hasCapability.and.returnValue(true);
|
mockDomainObject.hasCapability.and.returnValue(true);
|
||||||
mockDomainObject.getCapability.and.callFake(function (capability) {
|
mockDomainObject.getCapability.and.callFake(function (capability) {
|
||||||
return capabilities[capability];
|
return capabilities[capability];
|
||||||
});
|
});
|
||||||
mockDomainObject.getModel.and.returnValue({persisted: 0});
|
mockDomainObject.getModel.and.returnValue({persisted: 0});
|
||||||
mockEditorCapability.save.and.returnValue(mockPromise(true));
|
mockEditorCapability.save.and.returnValue(mockPromise(true));
|
||||||
mockEditorCapability.isEditContextRoot.and.returnValue(true);
|
mockEditorCapability.isEditContextRoot.and.returnValue(true);
|
||||||
|
|
||||||
action = new SaveAction(mockDialogService, mockNotificationService, actionContext);
|
action = new SaveAction(mockDialogService, mockNotificationService, actionContext);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("only applies to domain object with an editor capability", function () {
|
it("only applies to domain object with an editor capability", function () {
|
||||||
expect(SaveAction.appliesTo(actionContext)).toBe(true);
|
expect(SaveAction.appliesTo(actionContext)).toBe(true);
|
||||||
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
||||||
|
|
||||||
mockDomainObject.hasCapability.and.returnValue(false);
|
mockDomainObject.hasCapability.and.returnValue(false);
|
||||||
mockDomainObject.getCapability.and.returnValue(undefined);
|
mockDomainObject.getCapability.and.returnValue(undefined);
|
||||||
expect(SaveAction.appliesTo(actionContext)).toBe(false);
|
expect(SaveAction.appliesTo(actionContext)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("only applies to domain object that has already been persisted",
|
it("only applies to domain object that has already been persisted",
|
||||||
function () {
|
function () {
|
||||||
mockDomainObject.getModel.and.returnValue({persisted: undefined});
|
mockDomainObject.getModel.and.returnValue({persisted: undefined});
|
||||||
expect(SaveAction.appliesTo(actionContext)).toBe(false);
|
expect(SaveAction.appliesTo(actionContext)).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses the editor capability to save the object",
|
it("uses the editor capability to save the object",
|
||||||
function () {
|
function () {
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("in order to keep the user in the loop", function () {
|
describe("in order to keep the user in the loop", function () {
|
||||||
var mockDialogHandle;
|
var mockDialogHandle;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockDialogHandle = jasmine.createSpyObj("dialogHandle", ["dismiss"]);
|
mockDialogHandle = jasmine.createSpyObj("dialogHandle", ["dismiss"]);
|
||||||
mockDialogService.showBlockingMessage.and.returnValue(mockDialogHandle);
|
mockDialogService.showBlockingMessage.and.returnValue(mockDialogHandle);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("shows a dialog while saving", function () {
|
it("shows a dialog while saving", function () {
|
||||||
mockEditorCapability.save.and.returnValue(new Promise(function () {
|
mockEditorCapability.save.and.returnValue(new Promise(function () {
|
||||||
}));
|
}));
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
|
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
|
||||||
expect(mockDialogHandle.dismiss).not.toHaveBeenCalled();
|
expect(mockDialogHandle.dismiss).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("hides the dialog when saving is complete", function () {
|
it("hides the dialog when saving is complete", function () {
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
|
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
|
||||||
expect(mockDialogHandle.dismiss).toHaveBeenCalled();
|
expect(mockDialogHandle.dismiss).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("notifies if saving succeeded", function () {
|
it("notifies if saving succeeded", function () {
|
||||||
var mockCallback = jasmine.createSpy("callback");
|
var mockCallback = jasmine.createSpy("callback");
|
||||||
mockEditorCapability.save.and.returnValue(Promise.resolve());
|
mockEditorCapability.save.and.returnValue(Promise.resolve());
|
||||||
|
|
||||||
return action.perform().then(mockCallback).then(function () {
|
return action.perform().then(mockCallback).then(function () {
|
||||||
expect(mockNotificationService.info).toHaveBeenCalled();
|
expect(mockNotificationService.info).toHaveBeenCalled();
|
||||||
expect(mockNotificationService.error).not.toHaveBeenCalled();
|
expect(mockNotificationService.error).not.toHaveBeenCalled();
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("notifies if saving failed", function () {
|
|
||||||
var mockCallback = jasmine.createSpy("callback");
|
|
||||||
mockEditorCapability.save.and.returnValue(Promise.reject("some failure reason"));
|
|
||||||
|
|
||||||
return action.perform().then(mockCallback).then(function () {
|
|
||||||
expect(mockNotificationService.error).toHaveBeenCalled();
|
|
||||||
expect(mockNotificationService.info).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
);
|
it("notifies if saving failed", function () {
|
||||||
|
var mockCallback = jasmine.createSpy("callback");
|
||||||
|
mockEditorCapability.save.and.returnValue(Promise.reject("some failure reason"));
|
||||||
|
|
||||||
|
return action.perform().then(mockCallback).then(function () {
|
||||||
|
expect(mockNotificationService.error).toHaveBeenCalled();
|
||||||
|
expect(mockNotificationService.info).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@ -20,109 +20,127 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/actions/SaveAndStopEditingAction"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (SaveAndStopEditingAction) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Save and Stop Editing action", function () {
|
import SaveAndStopEditingAction from '../../src/actions/SaveAndStopEditingAction';
|
||||||
|
|
||||||
// Some mocks appear unused because the
|
describe("The Save and Stop Editing action", function () {
|
||||||
// underlying SaveAction that this action
|
|
||||||
// depends on is not mocked, so we mock some
|
|
||||||
// of SaveAction's own dependencies to make
|
|
||||||
// it run.
|
|
||||||
var mockDomainObject,
|
|
||||||
mockEditorCapability,
|
|
||||||
actionContext,
|
|
||||||
dialogService,
|
|
||||||
notificationService,
|
|
||||||
mockActionCapability,
|
|
||||||
capabilities = {},
|
|
||||||
action;
|
|
||||||
|
|
||||||
function mockPromise(value) {
|
// Some mocks appear unused because the
|
||||||
return {
|
// underlying SaveAction that this action
|
||||||
then: function (callback) {
|
// depends on is not mocked, so we mock some
|
||||||
return mockPromise(callback(value));
|
// of SaveAction's own dependencies to make
|
||||||
},
|
// it run.
|
||||||
catch: function (callback) {
|
var mockDomainObject,
|
||||||
return mockPromise(callback(value));
|
mockEditorCapability,
|
||||||
}
|
actionContext,
|
||||||
};
|
dialogService,
|
||||||
|
notificationService,
|
||||||
|
mockActionCapability,
|
||||||
|
capabilities = {},
|
||||||
|
action;
|
||||||
|
|
||||||
|
function mockPromise(value) {
|
||||||
|
return {
|
||||||
|
then: function (callback) {
|
||||||
|
return mockPromise(callback(value));
|
||||||
|
},
|
||||||
|
catch: function (callback) {
|
||||||
|
return mockPromise(callback(value));
|
||||||
}
|
}
|
||||||
|
};
|
||||||
beforeEach(function () {
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
|
||||||
[
|
|
||||||
"getCapability",
|
|
||||||
"hasCapability",
|
|
||||||
"getModel",
|
|
||||||
"getOriginalObject"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
|
||||||
"editor",
|
|
||||||
["save", "finish", "isEditContextRoot"]
|
|
||||||
);
|
|
||||||
mockActionCapability = jasmine.createSpyObj(
|
|
||||||
"actionCapability",
|
|
||||||
["perform"]
|
|
||||||
);
|
|
||||||
capabilities.editor = mockEditorCapability;
|
|
||||||
capabilities.action = mockActionCapability;
|
|
||||||
|
|
||||||
actionContext = {
|
|
||||||
domainObject: mockDomainObject
|
|
||||||
};
|
|
||||||
dialogService = jasmine.createSpyObj(
|
|
||||||
"dialogService",
|
|
||||||
["showBlockingMessage"]
|
|
||||||
);
|
|
||||||
|
|
||||||
notificationService = jasmine.createSpyObj(
|
|
||||||
"notificationService",
|
|
||||||
["info", "error"]
|
|
||||||
);
|
|
||||||
|
|
||||||
mockDomainObject.hasCapability.and.returnValue(true);
|
|
||||||
mockDomainObject.getCapability.and.callFake(function (capability) {
|
|
||||||
return capabilities[capability];
|
|
||||||
});
|
|
||||||
mockDomainObject.getModel.and.returnValue({ persisted: 0 });
|
|
||||||
mockEditorCapability.save.and.returnValue(mockPromise(true));
|
|
||||||
mockEditorCapability.isEditContextRoot.and.returnValue(true);
|
|
||||||
|
|
||||||
action = new SaveAndStopEditingAction(dialogService, notificationService, actionContext);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("only applies to domain object with an editor capability", function () {
|
|
||||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(true);
|
|
||||||
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
|
||||||
|
|
||||||
mockDomainObject.hasCapability.and.returnValue(false);
|
|
||||||
mockDomainObject.getCapability.and.returnValue(undefined);
|
|
||||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("only applies to domain object that has already been persisted", function () {
|
|
||||||
mockDomainObject.getModel.and.returnValue({ persisted: undefined });
|
|
||||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not close the editor before completing the save", function () {
|
|
||||||
mockEditorCapability.save.and.returnValue(new Promise(function () {
|
|
||||||
}));
|
|
||||||
action.perform();
|
|
||||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
|
||||||
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("closes the editor after saving", function () {
|
|
||||||
action.perform();
|
|
||||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
|
||||||
expect(mockEditorCapability.finish).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[
|
||||||
|
"getCapability",
|
||||||
|
"hasCapability",
|
||||||
|
"getModel",
|
||||||
|
"getOriginalObject"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockEditorCapability = jasmine.createSpyObj(
|
||||||
|
"editor",
|
||||||
|
["save", "finish", "isEditContextRoot"]
|
||||||
|
);
|
||||||
|
mockActionCapability = jasmine.createSpyObj(
|
||||||
|
"actionCapability",
|
||||||
|
["perform"]
|
||||||
|
);
|
||||||
|
capabilities.editor = mockEditorCapability;
|
||||||
|
capabilities.action = mockActionCapability;
|
||||||
|
|
||||||
|
actionContext = {
|
||||||
|
domainObject: mockDomainObject
|
||||||
|
};
|
||||||
|
dialogService = jasmine.createSpyObj(
|
||||||
|
"dialogService",
|
||||||
|
["showBlockingMessage"]
|
||||||
|
);
|
||||||
|
|
||||||
|
notificationService = jasmine.createSpyObj(
|
||||||
|
"notificationService",
|
||||||
|
["info", "error"]
|
||||||
|
);
|
||||||
|
|
||||||
|
mockDomainObject.hasCapability.and.returnValue(true);
|
||||||
|
mockDomainObject.getCapability.and.callFake(function (capability) {
|
||||||
|
return capabilities[capability];
|
||||||
|
});
|
||||||
|
mockDomainObject.getModel.and.returnValue({ persisted: 0 });
|
||||||
|
mockEditorCapability.save.and.returnValue(mockPromise(true));
|
||||||
|
mockEditorCapability.isEditContextRoot.and.returnValue(true);
|
||||||
|
|
||||||
|
action = new SaveAndStopEditingAction(dialogService, notificationService, actionContext);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("only applies to domain object with an editor capability", function () {
|
||||||
|
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(true);
|
||||||
|
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
||||||
|
|
||||||
|
mockDomainObject.hasCapability.and.returnValue(false);
|
||||||
|
mockDomainObject.getCapability.and.returnValue(undefined);
|
||||||
|
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("only applies to domain object that has already been persisted", function () {
|
||||||
|
mockDomainObject.getModel.and.returnValue({ persisted: undefined });
|
||||||
|
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("does not close the editor before completing the save", function () {
|
||||||
|
mockEditorCapability.save.and.returnValue(new Promise(function () {
|
||||||
|
}));
|
||||||
|
action.perform();
|
||||||
|
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||||
|
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("closes the editor after saving", function () {
|
||||||
|
action.perform();
|
||||||
|
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||||
|
expect(mockEditorCapability.finish).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
@ -20,87 +20,105 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/controllers/EditActionController"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (EditActionController) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Edit Action controller", function () {
|
import EditActionController from '../../src/controllers/EditActionController';
|
||||||
var mockSaveActionMetadata = {
|
|
||||||
name: "mocked-save-action",
|
|
||||||
cssClass: "mocked-save-action-css"
|
|
||||||
};
|
|
||||||
|
|
||||||
function fakeGetActions(actionContext) {
|
describe("The Edit Action controller", function () {
|
||||||
if (actionContext.category === "save") {
|
var mockSaveActionMetadata = {
|
||||||
var mockedSaveActions = [
|
name: "mocked-save-action",
|
||||||
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"]),
|
cssClass: "mocked-save-action-css"
|
||||||
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"])
|
};
|
||||||
];
|
|
||||||
mockedSaveActions.forEach(function (action) {
|
|
||||||
action.getMetadata.and.returnValue(mockSaveActionMetadata);
|
|
||||||
});
|
|
||||||
|
|
||||||
return mockedSaveActions;
|
function fakeGetActions(actionContext) {
|
||||||
} else if (actionContext.category === "conclude-editing") {
|
if (actionContext.category === "save") {
|
||||||
return ["a", "b", "c"];
|
var mockedSaveActions = [
|
||||||
} else {
|
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"]),
|
||||||
throw "EditActionController uses a context that's not covered by tests.";
|
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"])
|
||||||
}
|
];
|
||||||
}
|
mockedSaveActions.forEach(function (action) {
|
||||||
|
action.getMetadata.and.returnValue(mockSaveActionMetadata);
|
||||||
var mockScope,
|
|
||||||
mockActions,
|
|
||||||
controller;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
|
||||||
mockActions.getActions.and.callFake(fakeGetActions);
|
|
||||||
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
|
||||||
mockScope.action = mockActions;
|
|
||||||
controller = new EditActionController(mockScope);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function makeControllerUpdateActions() {
|
return mockedSaveActions;
|
||||||
mockScope.$watch.calls.mostRecent().args[1]();
|
} else if (actionContext.category === "conclude-editing") {
|
||||||
}
|
return ["a", "b", "c"];
|
||||||
|
} else {
|
||||||
it("watches scope that may change applicable actions", function () {
|
throw "EditActionController uses a context that's not covered by tests.";
|
||||||
// The action capability
|
}
|
||||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
|
||||||
"action",
|
|
||||||
jasmine.any(Function)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("populates the scope with 'save' actions", function () {
|
|
||||||
makeControllerUpdateActions();
|
|
||||||
expect(mockScope.saveActions.length).toEqual(2);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("converts 'save' actions to their menu counterparts", function () {
|
|
||||||
makeControllerUpdateActions();
|
|
||||||
var menuOptions = mockScope.saveActionsAsMenuOptions;
|
|
||||||
|
|
||||||
expect(menuOptions.length).toEqual(2);
|
|
||||||
expect(menuOptions[0].key).toEqual(mockScope.saveActions[0]);
|
|
||||||
expect(menuOptions[1].key).toEqual(mockScope.saveActions[1]);
|
|
||||||
menuOptions.forEach(function (option) {
|
|
||||||
expect(option.name).toEqual(mockSaveActionMetadata.name);
|
|
||||||
expect(option.cssClass).toEqual(mockSaveActionMetadata.cssClass);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("uses a click handler to perform the clicked action", function () {
|
|
||||||
makeControllerUpdateActions();
|
|
||||||
var sampleSaveAction = mockScope.saveActions[0];
|
|
||||||
mockScope.saveActionMenuClickHandler(sampleSaveAction);
|
|
||||||
expect(sampleSaveAction.perform).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("populates the scope with other editing actions", function () {
|
|
||||||
makeControllerUpdateActions();
|
|
||||||
expect(mockScope.otherEditActions).toEqual(["a", "b", "c"]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
var mockScope,
|
||||||
|
mockActions,
|
||||||
|
controller;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
||||||
|
mockActions.getActions.and.callFake(fakeGetActions);
|
||||||
|
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
||||||
|
mockScope.action = mockActions;
|
||||||
|
controller = new EditActionController(mockScope);
|
||||||
|
});
|
||||||
|
|
||||||
|
function makeControllerUpdateActions() {
|
||||||
|
mockScope.$watch.calls.mostRecent().args[1]();
|
||||||
|
}
|
||||||
|
|
||||||
|
it("watches scope that may change applicable actions", function () {
|
||||||
|
// The action capability
|
||||||
|
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||||
|
"action",
|
||||||
|
jasmine.any(Function)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("populates the scope with 'save' actions", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
expect(mockScope.saveActions.length).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("converts 'save' actions to their menu counterparts", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
var menuOptions = mockScope.saveActionsAsMenuOptions;
|
||||||
|
|
||||||
|
expect(menuOptions.length).toEqual(2);
|
||||||
|
expect(menuOptions[0].key).toEqual(mockScope.saveActions[0]);
|
||||||
|
expect(menuOptions[1].key).toEqual(mockScope.saveActions[1]);
|
||||||
|
menuOptions.forEach(function (option) {
|
||||||
|
expect(option.name).toEqual(mockSaveActionMetadata.name);
|
||||||
|
expect(option.cssClass).toEqual(mockSaveActionMetadata.cssClass);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("uses a click handler to perform the clicked action", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
var sampleSaveAction = mockScope.saveActions[0];
|
||||||
|
mockScope.saveActionMenuClickHandler(sampleSaveAction);
|
||||||
|
expect(sampleSaveAction.perform).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("populates the scope with other editing actions", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
expect(mockScope.otherEditActions).toEqual(["a", "b", "c"]);
|
||||||
|
});
|
||||||
|
});
|
@ -20,119 +20,137 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/controllers/EditObjectController"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (EditObjectController) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Edit Object controller", function () {
|
import EditObjectController from '../../src/controllers/EditObjectController';
|
||||||
var mockScope,
|
|
||||||
mockObject,
|
|
||||||
testViews,
|
|
||||||
mockEditorCapability,
|
|
||||||
mockLocation,
|
|
||||||
mockNavigationService,
|
|
||||||
removeCheck,
|
|
||||||
mockStatusCapability,
|
|
||||||
mockCapabilities,
|
|
||||||
controller;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The Edit Object controller", function () {
|
||||||
mockScope = jasmine.createSpyObj(
|
var mockScope,
|
||||||
"$scope",
|
mockObject,
|
||||||
["$on", "$watch"]
|
testViews,
|
||||||
);
|
mockEditorCapability,
|
||||||
mockObject = jasmine.createSpyObj(
|
mockLocation,
|
||||||
"domainObject",
|
mockNavigationService,
|
||||||
["getId", "getModel", "getCapability", "hasCapability", "useCapability"]
|
removeCheck,
|
||||||
);
|
mockStatusCapability,
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
mockCapabilities,
|
||||||
"mockEditorCapability",
|
controller;
|
||||||
["isEditContextRoot", "dirty", "finish"]
|
|
||||||
);
|
|
||||||
mockStatusCapability = jasmine.createSpyObj('statusCapability',
|
|
||||||
["get"]
|
|
||||||
);
|
|
||||||
|
|
||||||
mockCapabilities = {
|
beforeEach(function () {
|
||||||
"editor": mockEditorCapability,
|
mockScope = jasmine.createSpyObj(
|
||||||
"status": mockStatusCapability
|
"$scope",
|
||||||
};
|
["$on", "$watch"]
|
||||||
|
);
|
||||||
|
mockObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
["getId", "getModel", "getCapability", "hasCapability", "useCapability"]
|
||||||
|
);
|
||||||
|
mockEditorCapability = jasmine.createSpyObj(
|
||||||
|
"mockEditorCapability",
|
||||||
|
["isEditContextRoot", "dirty", "finish"]
|
||||||
|
);
|
||||||
|
mockStatusCapability = jasmine.createSpyObj('statusCapability',
|
||||||
|
["get"]
|
||||||
|
);
|
||||||
|
|
||||||
mockLocation = jasmine.createSpyObj('$location',
|
mockCapabilities = {
|
||||||
["search"]
|
"editor": mockEditorCapability,
|
||||||
);
|
"status": mockStatusCapability
|
||||||
mockLocation.search.and.returnValue({"view": "fixed"});
|
};
|
||||||
mockNavigationService = jasmine.createSpyObj('navigationService',
|
|
||||||
["checkBeforeNavigation"]
|
|
||||||
);
|
|
||||||
|
|
||||||
removeCheck = jasmine.createSpy('removeCheck');
|
mockLocation = jasmine.createSpyObj('$location',
|
||||||
mockNavigationService.checkBeforeNavigation.and.returnValue(removeCheck);
|
["search"]
|
||||||
|
);
|
||||||
|
mockLocation.search.and.returnValue({"view": "fixed"});
|
||||||
|
mockNavigationService = jasmine.createSpyObj('navigationService',
|
||||||
|
["checkBeforeNavigation"]
|
||||||
|
);
|
||||||
|
|
||||||
mockObject.getId.and.returnValue("test");
|
removeCheck = jasmine.createSpy('removeCheck');
|
||||||
mockObject.getModel.and.returnValue({ name: "Test object" });
|
mockNavigationService.checkBeforeNavigation.and.returnValue(removeCheck);
|
||||||
mockObject.getCapability.and.callFake(function (key) {
|
|
||||||
return mockCapabilities[key];
|
|
||||||
});
|
|
||||||
|
|
||||||
testViews = [
|
|
||||||
{ key: 'abc' },
|
|
||||||
{
|
|
||||||
key: 'def',
|
|
||||||
someKey: 'some value'
|
|
||||||
},
|
|
||||||
{ key: 'xyz' }
|
|
||||||
];
|
|
||||||
|
|
||||||
mockObject.useCapability.and.callFake(function (c) {
|
|
||||||
return (c === 'view') && testViews;
|
|
||||||
});
|
|
||||||
mockLocation.search.and.returnValue({ view: 'def' });
|
|
||||||
|
|
||||||
mockScope.domainObject = mockObject;
|
|
||||||
|
|
||||||
controller = new EditObjectController(
|
|
||||||
mockScope,
|
|
||||||
mockLocation,
|
|
||||||
mockNavigationService
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("adds a check before navigation", function () {
|
|
||||||
expect(mockNavigationService.checkBeforeNavigation)
|
|
||||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
|
||||||
|
|
||||||
var checkFn = mockNavigationService.checkBeforeNavigation.calls.mostRecent().args[0];
|
|
||||||
|
|
||||||
mockEditorCapability.isEditContextRoot.and.returnValue(false);
|
|
||||||
mockEditorCapability.dirty.and.returnValue(false);
|
|
||||||
|
|
||||||
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
|
|
||||||
|
|
||||||
mockEditorCapability.isEditContextRoot.and.returnValue(true);
|
|
||||||
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
|
|
||||||
|
|
||||||
mockEditorCapability.dirty.and.returnValue(true);
|
|
||||||
expect(checkFn())
|
|
||||||
.toBe("Continuing will cause the loss of any unsaved changes.");
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it("cleans up on destroy", function () {
|
|
||||||
expect(mockScope.$on)
|
|
||||||
.toHaveBeenCalledWith("$destroy", jasmine.any(Function));
|
|
||||||
|
|
||||||
mockScope.$on.calls.mostRecent().args[1]();
|
|
||||||
|
|
||||||
expect(mockEditorCapability.finish).toHaveBeenCalled();
|
|
||||||
expect(removeCheck).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("sets the active view from query parameters", function () {
|
|
||||||
expect(mockScope.representation.selected)
|
|
||||||
.toEqual(testViews[1]);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
mockObject.getId.and.returnValue("test");
|
||||||
|
mockObject.getModel.and.returnValue({ name: "Test object" });
|
||||||
|
mockObject.getCapability.and.callFake(function (key) {
|
||||||
|
return mockCapabilities[key];
|
||||||
});
|
});
|
||||||
}
|
|
||||||
);
|
testViews = [
|
||||||
|
{ key: 'abc' },
|
||||||
|
{
|
||||||
|
key: 'def',
|
||||||
|
someKey: 'some value'
|
||||||
|
},
|
||||||
|
{ key: 'xyz' }
|
||||||
|
];
|
||||||
|
|
||||||
|
mockObject.useCapability.and.callFake(function (c) {
|
||||||
|
return (c === 'view') && testViews;
|
||||||
|
});
|
||||||
|
mockLocation.search.and.returnValue({ view: 'def' });
|
||||||
|
|
||||||
|
mockScope.domainObject = mockObject;
|
||||||
|
|
||||||
|
controller = new EditObjectController(
|
||||||
|
mockScope,
|
||||||
|
mockLocation,
|
||||||
|
mockNavigationService
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("adds a check before navigation", function () {
|
||||||
|
expect(mockNavigationService.checkBeforeNavigation)
|
||||||
|
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||||
|
|
||||||
|
var checkFn = mockNavigationService.checkBeforeNavigation.calls.mostRecent().args[0];
|
||||||
|
|
||||||
|
mockEditorCapability.isEditContextRoot.and.returnValue(false);
|
||||||
|
mockEditorCapability.dirty.and.returnValue(false);
|
||||||
|
|
||||||
|
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
|
||||||
|
|
||||||
|
mockEditorCapability.isEditContextRoot.and.returnValue(true);
|
||||||
|
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
|
||||||
|
|
||||||
|
mockEditorCapability.dirty.and.returnValue(true);
|
||||||
|
expect(checkFn())
|
||||||
|
.toBe("Continuing will cause the loss of any unsaved changes.");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cleans up on destroy", function () {
|
||||||
|
expect(mockScope.$on)
|
||||||
|
.toHaveBeenCalledWith("$destroy", jasmine.any(Function));
|
||||||
|
|
||||||
|
mockScope.$on.calls.mostRecent().args[1]();
|
||||||
|
|
||||||
|
expect(mockEditorCapability.finish).toHaveBeenCalled();
|
||||||
|
expect(removeCheck).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets the active view from query parameters", function () {
|
||||||
|
expect(mockScope.representation.selected)
|
||||||
|
.toEqual(testViews[1]);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -20,95 +20,113 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/controllers/EditPanesController"],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (EditPanesController) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Edit Panes controller", function () {
|
import EditPanesController from '../../src/controllers/EditPanesController';
|
||||||
var mockScope,
|
|
||||||
mockDomainObject,
|
|
||||||
mockContext,
|
|
||||||
controller;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The Edit Panes controller", function () {
|
||||||
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
var mockScope,
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
mockDomainObject,
|
||||||
'domainObject',
|
mockContext,
|
||||||
['getId', 'getCapability']
|
controller;
|
||||||
);
|
|
||||||
mockContext = jasmine.createSpyObj(
|
|
||||||
'context',
|
|
||||||
['getTrueRoot']
|
|
||||||
);
|
|
||||||
|
|
||||||
mockDomainObject.getId.and.returnValue('test-id');
|
beforeEach(function () {
|
||||||
mockDomainObject.getCapability.and.returnValue(mockContext);
|
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
'domainObject',
|
||||||
|
['getId', 'getCapability']
|
||||||
|
);
|
||||||
|
mockContext = jasmine.createSpyObj(
|
||||||
|
'context',
|
||||||
|
['getTrueRoot']
|
||||||
|
);
|
||||||
|
|
||||||
// Return a new instance of the root object each time
|
mockDomainObject.getId.and.returnValue('test-id');
|
||||||
mockContext.getTrueRoot.and.callFake(function () {
|
mockDomainObject.getCapability.and.returnValue(mockContext);
|
||||||
var mockRoot = jasmine.createSpyObj('root', ['getId']);
|
|
||||||
mockRoot.getId.and.returnValue('root-id');
|
|
||||||
|
|
||||||
return mockRoot;
|
// Return a new instance of the root object each time
|
||||||
});
|
mockContext.getTrueRoot.and.callFake(function () {
|
||||||
|
var mockRoot = jasmine.createSpyObj('root', ['getId']);
|
||||||
|
mockRoot.getId.and.returnValue('root-id');
|
||||||
|
|
||||||
controller = new EditPanesController(mockScope);
|
return mockRoot;
|
||||||
});
|
|
||||||
|
|
||||||
it("watches for the domain object in view", function () {
|
|
||||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
|
||||||
"domainObject",
|
|
||||||
jasmine.any(Function)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("exposes the root object found via the object's context capability", function () {
|
|
||||||
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
|
||||||
|
|
||||||
// Verify that the correct capability was used
|
|
||||||
expect(mockDomainObject.getCapability)
|
|
||||||
.toHaveBeenCalledWith('context');
|
|
||||||
|
|
||||||
// Should have exposed the root from getRoot
|
|
||||||
expect(controller.getRoot().getId()).toEqual('root-id');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("preserves the same root instance to avoid excessive refreshing", function () {
|
|
||||||
var firstRoot;
|
|
||||||
// Expose the domain object
|
|
||||||
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
|
||||||
firstRoot = controller.getRoot();
|
|
||||||
// Update!
|
|
||||||
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
|
||||||
// Should still have the same object instance, to avoid
|
|
||||||
// triggering the watch used by the template we're supporting
|
|
||||||
expect(controller.getRoot()).toBe(firstRoot);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Complements the test above; the object pointed to should change
|
|
||||||
// when the actual root has changed (detected by identifier)
|
|
||||||
it("updates the root when it changes", function () {
|
|
||||||
var firstRoot;
|
|
||||||
// Expose the domain object
|
|
||||||
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
|
||||||
firstRoot = controller.getRoot();
|
|
||||||
|
|
||||||
// Change the exposed root
|
|
||||||
mockContext.getTrueRoot.and.callFake(function () {
|
|
||||||
var mockRoot = jasmine.createSpyObj('root', ['getId']);
|
|
||||||
mockRoot.getId.and.returnValue('other-root-id');
|
|
||||||
|
|
||||||
return mockRoot;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Update!
|
|
||||||
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
|
||||||
|
|
||||||
// Should still have the same object instance, to avoid
|
|
||||||
// triggering the watch used by the template we're supporting
|
|
||||||
expect(controller.getRoot()).not.toBe(firstRoot);
|
|
||||||
expect(controller.getRoot().getId()).toEqual('other-root-id');
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
|
||||||
);
|
controller = new EditPanesController(mockScope);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("watches for the domain object in view", function () {
|
||||||
|
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||||
|
"domainObject",
|
||||||
|
jasmine.any(Function)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("exposes the root object found via the object's context capability", function () {
|
||||||
|
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
||||||
|
|
||||||
|
// Verify that the correct capability was used
|
||||||
|
expect(mockDomainObject.getCapability)
|
||||||
|
.toHaveBeenCalledWith('context');
|
||||||
|
|
||||||
|
// Should have exposed the root from getRoot
|
||||||
|
expect(controller.getRoot().getId()).toEqual('root-id');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves the same root instance to avoid excessive refreshing", function () {
|
||||||
|
var firstRoot;
|
||||||
|
// Expose the domain object
|
||||||
|
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
||||||
|
firstRoot = controller.getRoot();
|
||||||
|
// Update!
|
||||||
|
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
||||||
|
// Should still have the same object instance, to avoid
|
||||||
|
// triggering the watch used by the template we're supporting
|
||||||
|
expect(controller.getRoot()).toBe(firstRoot);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Complements the test above; the object pointed to should change
|
||||||
|
// when the actual root has changed (detected by identifier)
|
||||||
|
it("updates the root when it changes", function () {
|
||||||
|
var firstRoot;
|
||||||
|
// Expose the domain object
|
||||||
|
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
||||||
|
firstRoot = controller.getRoot();
|
||||||
|
|
||||||
|
// Change the exposed root
|
||||||
|
mockContext.getTrueRoot.and.callFake(function () {
|
||||||
|
var mockRoot = jasmine.createSpyObj('root', ['getId']);
|
||||||
|
mockRoot.getId.and.returnValue('other-root-id');
|
||||||
|
|
||||||
|
return mockRoot;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Update!
|
||||||
|
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
|
||||||
|
|
||||||
|
// Should still have the same object instance, to avoid
|
||||||
|
// triggering the watch used by the template we're supporting
|
||||||
|
expect(controller.getRoot()).not.toBe(firstRoot);
|
||||||
|
expect(controller.getRoot().getId()).toEqual('other-root-id');
|
||||||
|
});
|
||||||
|
});
|
@ -20,83 +20,101 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
["../../src/policies/EditPersistableObjectsPolicy"],
|
* Open MCT, Copyright (c) 2014-2016, United States Government
|
||||||
function (EditPersistableObjectsPolicy) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
describe("The Edit persistable objects policy", function () {
|
import EditPersistableObjectsPolicy from '../../src/policies/EditPersistableObjectsPolicy';
|
||||||
var mockDomainObject,
|
|
||||||
mockEditAction,
|
|
||||||
mockPropertiesAction,
|
|
||||||
mockOtherAction,
|
|
||||||
mockAPI,
|
|
||||||
mockObjectAPI,
|
|
||||||
testContext,
|
|
||||||
policy;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The Edit persistable objects policy", function () {
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
var mockDomainObject,
|
||||||
'domainObject',
|
mockEditAction,
|
||||||
[
|
mockPropertiesAction,
|
||||||
'getId'
|
mockOtherAction,
|
||||||
]
|
mockAPI,
|
||||||
);
|
mockObjectAPI,
|
||||||
|
testContext,
|
||||||
|
policy;
|
||||||
|
|
||||||
mockObjectAPI = jasmine.createSpyObj('objectAPI', [
|
beforeEach(function () {
|
||||||
'isPersistable',
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
'parseKeyString'
|
'domainObject',
|
||||||
]);
|
[
|
||||||
|
'getId'
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
mockAPI = {
|
mockObjectAPI = jasmine.createSpyObj('objectAPI', [
|
||||||
objects: mockObjectAPI
|
'isPersistable',
|
||||||
};
|
'parseKeyString'
|
||||||
|
]);
|
||||||
|
|
||||||
mockEditAction = jasmine.createSpyObj('edit', ['getMetadata']);
|
mockAPI = {
|
||||||
mockPropertiesAction = jasmine.createSpyObj('properties', ['getMetadata']);
|
objects: mockObjectAPI
|
||||||
mockOtherAction = jasmine.createSpyObj('other', ['getMetadata']);
|
};
|
||||||
|
|
||||||
mockEditAction.getMetadata.and.returnValue({ key: 'edit' });
|
mockEditAction = jasmine.createSpyObj('edit', ['getMetadata']);
|
||||||
mockPropertiesAction.getMetadata.and.returnValue({ key: 'properties' });
|
mockPropertiesAction = jasmine.createSpyObj('properties', ['getMetadata']);
|
||||||
mockOtherAction.getMetadata.and.returnValue({key: 'other'});
|
mockOtherAction = jasmine.createSpyObj('other', ['getMetadata']);
|
||||||
|
|
||||||
mockDomainObject.getId.and.returnValue('test:testId');
|
mockEditAction.getMetadata.and.returnValue({ key: 'edit' });
|
||||||
|
mockPropertiesAction.getMetadata.and.returnValue({ key: 'properties' });
|
||||||
|
mockOtherAction.getMetadata.and.returnValue({key: 'other'});
|
||||||
|
|
||||||
testContext = {
|
mockDomainObject.getId.and.returnValue('test:testId');
|
||||||
domainObject: mockDomainObject,
|
|
||||||
category: 'view-control'
|
|
||||||
};
|
|
||||||
|
|
||||||
policy = new EditPersistableObjectsPolicy(mockAPI);
|
testContext = {
|
||||||
});
|
domainObject: mockDomainObject,
|
||||||
|
category: 'view-control'
|
||||||
|
};
|
||||||
|
|
||||||
it("Applies to edit action", function () {
|
policy = new EditPersistableObjectsPolicy(mockAPI);
|
||||||
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
});
|
||||||
|
|
||||||
policy.allow(mockEditAction, testContext);
|
it("Applies to edit action", function () {
|
||||||
expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
|
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
||||||
});
|
|
||||||
|
|
||||||
it("Applies to properties action", function () {
|
policy.allow(mockEditAction, testContext);
|
||||||
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
policy.allow(mockPropertiesAction, testContext);
|
it("Applies to properties action", function () {
|
||||||
expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
|
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
||||||
});
|
|
||||||
|
|
||||||
it("does not apply to other actions", function () {
|
policy.allow(mockPropertiesAction, testContext);
|
||||||
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
policy.allow(mockOtherAction, testContext);
|
it("does not apply to other actions", function () {
|
||||||
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
||||||
});
|
|
||||||
|
|
||||||
it("Tests object provider for editability", function () {
|
policy.allow(mockOtherAction, testContext);
|
||||||
mockObjectAPI.isPersistable.and.returnValue(false);
|
expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
|
||||||
expect(policy.allow(mockEditAction, testContext)).toBe(false);
|
});
|
||||||
expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
|
|
||||||
mockObjectAPI.isPersistable.and.returnValue(true);
|
it("Tests object provider for editability", function () {
|
||||||
expect(policy.allow(mockEditAction, testContext)).toBe(true);
|
mockObjectAPI.isPersistable.and.returnValue(false);
|
||||||
});
|
expect(policy.allow(mockEditAction, testContext)).toBe(false);
|
||||||
});
|
expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
|
||||||
}
|
mockObjectAPI.isPersistable.and.returnValue(true);
|
||||||
);
|
expect(policy.allow(mockEditAction, testContext)).toBe(true);
|
||||||
|
});
|
||||||
|
});
|
@ -20,68 +20,86 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
'../../src/representers/EditRepresenter'
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
EditRepresenter
|
* Administration. All rights reserved.
|
||||||
) {
|
*
|
||||||
describe('EditRepresenter', function () {
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
var $log,
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
$scope,
|
* You may obtain a copy of the License at
|
||||||
representer;
|
* 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import EditRepresenter from '../../src/representers/EditRepresenter';
|
||||||
|
|
||||||
|
describe('EditRepresenter', function () {
|
||||||
|
var $log,
|
||||||
|
$scope,
|
||||||
|
representer;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
$log = jasmine.createSpyObj('$log', ['debug']);
|
||||||
|
$scope = {};
|
||||||
|
representer = new EditRepresenter($log, $scope);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('injects a commit function in scope', function () {
|
||||||
|
expect($scope.commit).toEqual(jasmine.any(Function));
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('representation', function () {
|
||||||
|
var domainObject,
|
||||||
|
representation;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
$log = jasmine.createSpyObj('$log', ['debug']);
|
domainObject = jasmine.createSpyObj('domainObject', [
|
||||||
$scope = {};
|
'getId',
|
||||||
representer = new EditRepresenter($log, $scope);
|
'getModel',
|
||||||
|
'useCapability'
|
||||||
|
]);
|
||||||
|
|
||||||
|
domainObject.getId.and.returnValue('anId');
|
||||||
|
domainObject.getModel.and.returnValue({name: 'anObject'});
|
||||||
|
|
||||||
|
representation = {
|
||||||
|
key: 'someRepresentation'
|
||||||
|
};
|
||||||
|
$scope.model = {name: 'anotherName'};
|
||||||
|
$scope.configuration = {some: 'config'};
|
||||||
|
representer.represent(representation, domainObject);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('injects a commit function in scope', function () {
|
it('logs a message when commiting', function () {
|
||||||
expect($scope.commit).toEqual(jasmine.any(Function));
|
$scope.commit('Test Message');
|
||||||
|
expect($log.debug)
|
||||||
|
.toHaveBeenCalledWith('Committing anObject (anId): Test Message');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('representation', function () {
|
it('mutates the object when committing', function () {
|
||||||
var domainObject,
|
$scope.commit('Test Message');
|
||||||
representation;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
expect(domainObject.useCapability)
|
||||||
domainObject = jasmine.createSpyObj('domainObject', [
|
.toHaveBeenCalledWith('mutation', jasmine.any(Function));
|
||||||
'getId',
|
|
||||||
'getModel',
|
|
||||||
'useCapability'
|
|
||||||
]);
|
|
||||||
|
|
||||||
domainObject.getId.and.returnValue('anId');
|
var mutateValue = domainObject.useCapability.calls.all()[0].args[1]();
|
||||||
domainObject.getModel.and.returnValue({name: 'anObject'});
|
|
||||||
|
|
||||||
representation = {
|
|
||||||
key: 'someRepresentation'
|
|
||||||
};
|
|
||||||
$scope.model = {name: 'anotherName'};
|
|
||||||
$scope.configuration = {some: 'config'};
|
|
||||||
representer.represent(representation, domainObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('logs a message when commiting', function () {
|
|
||||||
$scope.commit('Test Message');
|
|
||||||
expect($log.debug)
|
|
||||||
.toHaveBeenCalledWith('Committing anObject (anId): Test Message');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('mutates the object when committing', function () {
|
|
||||||
$scope.commit('Test Message');
|
|
||||||
|
|
||||||
expect(domainObject.useCapability)
|
|
||||||
.toHaveBeenCalledWith('mutation', jasmine.any(Function));
|
|
||||||
|
|
||||||
var mutateValue = domainObject.useCapability.calls.all()[0].args[1]();
|
|
||||||
|
|
||||||
expect(mutateValue.configuration.someRepresentation)
|
|
||||||
.toEqual({some: 'config'});
|
|
||||||
expect(mutateValue.name).toEqual('anotherName');
|
|
||||||
});
|
|
||||||
|
|
||||||
|
expect(mutateValue.configuration.someRepresentation)
|
||||||
|
.toEqual({some: 'config'});
|
||||||
|
expect(mutateValue.name).toEqual('anotherName');
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
});
|
@ -20,53 +20,71 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/FormatProvider",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/DurationFormat"
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
], function (
|
* Administration. All rights reserved.
|
||||||
FormatProvider,
|
*
|
||||||
DurationFormat
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
) {
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
return {
|
* You may obtain a copy of the License at
|
||||||
name: "platform/commonUI/formats",
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
definition: {
|
*
|
||||||
"name": "Format Registry",
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
"description": "Provides a registry for formats, which allow parsing and formatting of values.",
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
"extensions": {
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
"components": [
|
* License for the specific language governing permissions and limitations
|
||||||
{
|
* under the License.
|
||||||
"provides": "formatService",
|
*
|
||||||
"type": "provider",
|
* Open MCT includes source code licensed under additional open source
|
||||||
"implementation": FormatProvider,
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
"depends": [
|
* this source code distribution or the Licensing information page available
|
||||||
"formats[]"
|
* at runtime from the About dialog for additional information.
|
||||||
]
|
*****************************************************************************/
|
||||||
}
|
|
||||||
],
|
import FormatProvider from './src/FormatProvider';
|
||||||
"formats": [
|
|
||||||
{
|
import DurationFormat from './src/DurationFormat';
|
||||||
"key": "duration",
|
|
||||||
"implementation": DurationFormat
|
export default {
|
||||||
}
|
name: "platform/commonUI/formats",
|
||||||
],
|
definition: {
|
||||||
"constants": [
|
"name": "Format Registry",
|
||||||
{
|
"description": "Provides a registry for formats, which allow parsing and formatting of values.",
|
||||||
"key": "DEFAULT_TIME_FORMAT",
|
"extensions": {
|
||||||
"value": "utc"
|
"components": [
|
||||||
}
|
{
|
||||||
],
|
"provides": "formatService",
|
||||||
"licenses": [
|
"type": "provider",
|
||||||
{
|
"implementation": FormatProvider,
|
||||||
"name": "d3",
|
"depends": [
|
||||||
"version": "3.0.0",
|
"formats[]"
|
||||||
"description": "Incorporates modified code from d3 Time Scales",
|
]
|
||||||
"author": "Mike Bostock",
|
}
|
||||||
"copyright": "Copyright 2010-2016 Mike Bostock. "
|
],
|
||||||
+ "All rights reserved.",
|
"formats": [
|
||||||
"link": "https://github.com/d3/d3/blob/master/LICENSE"
|
{
|
||||||
}
|
"key": "duration",
|
||||||
]
|
"implementation": DurationFormat
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"constants": [
|
||||||
|
{
|
||||||
|
"key": "DEFAULT_TIME_FORMAT",
|
||||||
|
"value": "utc"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"name": "d3",
|
||||||
|
"version": "3.0.0",
|
||||||
|
"description": "Incorporates modified code from d3 Time Scales",
|
||||||
|
"author": "Mike Bostock",
|
||||||
|
"copyright": "Copyright 2010-2016 Mike Bostock. "
|
||||||
|
+ "All rights reserved.",
|
||||||
|
"link": "https://github.com/d3/d3/blob/master/LICENSE"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,43 +20,60 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
'moment'
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
], function (
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
moment
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var DATE_FORMAT = "HH:mm:ss",
|
import moment from 'moment';
|
||||||
DATE_FORMATS = [
|
|
||||||
DATE_FORMAT
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
var DATE_FORMAT = "HH:mm:ss",
|
||||||
* Formatter for duration. Uses moment to produce a date from a given
|
DATE_FORMATS = [
|
||||||
* value, but output is formatted to display only time. Can be used for
|
DATE_FORMAT
|
||||||
* specifying a time duration. For specifying duration, it's best to
|
];
|
||||||
* specify a date of January 1, 1970, as the ms offset will equal the
|
|
||||||
* duration represented by the time.
|
|
||||||
*
|
|
||||||
* @implements {Format}
|
|
||||||
* @constructor
|
|
||||||
* @memberof platform/commonUI/formats
|
|
||||||
*/
|
|
||||||
function DurationFormat() {
|
|
||||||
this.key = "duration";
|
|
||||||
}
|
|
||||||
|
|
||||||
DurationFormat.prototype.format = function (value) {
|
/**
|
||||||
return moment.utc(value).format(DATE_FORMAT);
|
* Formatter for duration. Uses moment to produce a date from a given
|
||||||
};
|
* value, but output is formatted to display only time. Can be used for
|
||||||
|
* specifying a time duration. For specifying duration, it's best to
|
||||||
|
* specify a date of January 1, 1970, as the ms offset will equal the
|
||||||
|
* duration represented by the time.
|
||||||
|
*
|
||||||
|
* @implements {Format}
|
||||||
|
* @constructor
|
||||||
|
* @memberof platform/commonUI/formats
|
||||||
|
*/
|
||||||
|
function DurationFormat() {
|
||||||
|
this.key = "duration";
|
||||||
|
}
|
||||||
|
|
||||||
DurationFormat.prototype.parse = function (text) {
|
DurationFormat.prototype.format = function (value) {
|
||||||
return moment.duration(text).asMilliseconds();
|
return moment.utc(value).format(DATE_FORMAT);
|
||||||
};
|
};
|
||||||
|
|
||||||
DurationFormat.prototype.validate = function (text) {
|
DurationFormat.prototype.parse = function (text) {
|
||||||
return moment.utc(text, DATE_FORMATS, true).isValid();
|
return moment.duration(text).asMilliseconds();
|
||||||
};
|
};
|
||||||
|
|
||||||
return DurationFormat;
|
DurationFormat.prototype.validate = function (text) {
|
||||||
});
|
return moment.utc(text, DATE_FORMATS, true).isValid();
|
||||||
|
};
|
||||||
|
|
||||||
|
export default DurationFormat;
|
@ -20,104 +20,49 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
], function (
|
function FormatProvider(formats) {
|
||||||
|
var formatMap = {};
|
||||||
|
|
||||||
) {
|
function addToMap(Format) {
|
||||||
|
var key = Format.key;
|
||||||
/**
|
if (key && !formatMap[key]) {
|
||||||
* An object used to convert between numeric values and text values,
|
formatMap[key] = new Format();
|
||||||
* typically used to display these values to the user and to convert
|
|
||||||
* user input to a numeric format, particularly for time formats.
|
|
||||||
* @interface Format
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* Parse text (typically user input) to a numeric value.
|
|
||||||
* Behavior is undefined when the text cannot be parsed;
|
|
||||||
* `validate` should be called first if the text may be invalid.
|
|
||||||
* @method Format#parse
|
|
||||||
* @memberof Format#
|
|
||||||
* @param {string} text the text to parse
|
|
||||||
* @returns {number} the parsed numeric value
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @property {string} key A unique identifier for this formatter.
|
|
||||||
* @memberof Format#
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine whether or not some text (typically user input) can
|
|
||||||
* be parsed to a numeric value by this format.
|
|
||||||
* @method validate
|
|
||||||
* @memberof Format#
|
|
||||||
* @param {string} text the text to parse
|
|
||||||
* @returns {boolean} true if the text can be parsed
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert a numeric value to a text value for display using
|
|
||||||
* this format.
|
|
||||||
* @method format
|
|
||||||
* @memberof Format#
|
|
||||||
* @param {number} value the numeric value to format
|
|
||||||
* @param {number} [minValue] Contextual information for scaled formatting used in linear scales such as conductor
|
|
||||||
* and plot axes. Specifies the smallest number on the scale.
|
|
||||||
* @param {number} [maxValue] Contextual information for scaled formatting used in linear scales such as conductor
|
|
||||||
* and plot axes. Specifies the largest number on the scale
|
|
||||||
* @param {number} [count] Contextual information for scaled formatting used in linear scales such as conductor
|
|
||||||
* and plot axes. The number of labels on the scale.
|
|
||||||
* @returns {string} the text representation of the value
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides access to `Format` objects which can be used to
|
|
||||||
* convert values between human-readable text and numeric
|
|
||||||
* representations.
|
|
||||||
* @interface FormatService
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Look up a format by its symbolic identifier.
|
|
||||||
* @method getFormat
|
|
||||||
* @memberof FormatService#
|
|
||||||
* @param {string} key the identifier for this format
|
|
||||||
* @returns {Format} the format
|
|
||||||
* @throws {Error} errors when the requested format is unrecognized
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides formats from the `formats` extension category.
|
|
||||||
* @constructor
|
|
||||||
* @implements {FormatService}
|
|
||||||
* @memberof platform/commonUI/formats
|
|
||||||
* @param {Array.<function(new : Format)>} format constructors,
|
|
||||||
* from the `formats` extension category.
|
|
||||||
*/
|
|
||||||
function FormatProvider(formats) {
|
|
||||||
var formatMap = {};
|
|
||||||
|
|
||||||
function addToMap(Format) {
|
|
||||||
var key = Format.key;
|
|
||||||
if (key && !formatMap[key]) {
|
|
||||||
formatMap[key] = new Format();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
formats.forEach(addToMap);
|
|
||||||
this.formatMap = formatMap;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FormatProvider.prototype.getFormat = function (key) {
|
formats.forEach(addToMap);
|
||||||
var format = this.formatMap[key];
|
this.formatMap = formatMap;
|
||||||
if (!format) {
|
}
|
||||||
throw new Error("FormatProvider: No format found for " + key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return format;
|
FormatProvider.prototype.getFormat = function (key) {
|
||||||
};
|
var format = this.formatMap[key];
|
||||||
|
if (!format) {
|
||||||
|
throw new Error("FormatProvider: No format found for " + key);
|
||||||
|
}
|
||||||
|
|
||||||
return FormatProvider;
|
return format;
|
||||||
|
};
|
||||||
|
|
||||||
});
|
export default FormatProvider;
|
@ -20,50 +20,68 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
['../src/FormatProvider'],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (FormatProvider) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var KEYS = ['a', 'b', 'c'];
|
import FormatProvider from '../src/FormatProvider';
|
||||||
|
|
||||||
describe("The FormatProvider", function () {
|
var KEYS = ['a', 'b', 'c'];
|
||||||
var mockFormats,
|
|
||||||
mockFormatInstances,
|
|
||||||
provider;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
describe("The FormatProvider", function () {
|
||||||
mockFormatInstances = KEYS.map(function (k) {
|
var mockFormats,
|
||||||
return jasmine.createSpyObj(
|
mockFormatInstances,
|
||||||
'format-' + k,
|
provider;
|
||||||
['parse', 'validate', 'format']
|
|
||||||
);
|
|
||||||
});
|
|
||||||
// Return constructors
|
|
||||||
mockFormats = KEYS.map(function (k, i) {
|
|
||||||
function MockFormat() {
|
|
||||||
return mockFormatInstances[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
MockFormat.key = k;
|
|
||||||
|
|
||||||
return MockFormat;
|
|
||||||
});
|
|
||||||
provider = new FormatProvider(mockFormats);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("looks up formats by key", function () {
|
|
||||||
KEYS.forEach(function (k, i) {
|
|
||||||
expect(provider.getFormat(k))
|
|
||||||
.toEqual(mockFormatInstances[i]);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("throws an error about unknown formats", function () {
|
|
||||||
expect(function () {
|
|
||||||
provider.getFormat('some-unknown-format');
|
|
||||||
}).toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockFormatInstances = KEYS.map(function (k) {
|
||||||
|
return jasmine.createSpyObj(
|
||||||
|
'format-' + k,
|
||||||
|
['parse', 'validate', 'format']
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
// Return constructors
|
||||||
);
|
mockFormats = KEYS.map(function (k, i) {
|
||||||
|
function MockFormat() {
|
||||||
|
return mockFormatInstances[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
MockFormat.key = k;
|
||||||
|
|
||||||
|
return MockFormat;
|
||||||
|
});
|
||||||
|
provider = new FormatProvider(mockFormats);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("looks up formats by key", function () {
|
||||||
|
KEYS.forEach(function (k, i) {
|
||||||
|
expect(provider.getFormat(k))
|
||||||
|
.toEqual(mockFormatInstances[i]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("throws an error about unknown formats", function () {
|
||||||
|
expect(function () {
|
||||||
|
provider.getFormat('some-unknown-format');
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
@ -20,510 +20,483 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
"./src/services/UrlService",
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
"./src/services/PopupService",
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
"./src/SplashScreenManager",
|
* Administration. All rights reserved.
|
||||||
"./src/StyleSheetLoader",
|
*
|
||||||
"./src/controllers/TimeRangeController",
|
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||||
"./src/controllers/DateTimePickerController",
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
"./src/controllers/DateTimeFieldController",
|
* You may obtain a copy of the License at
|
||||||
"./src/controllers/TreeNodeController",
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
"./src/controllers/ActionGroupController",
|
*
|
||||||
"./src/controllers/ToggleController",
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
"./src/controllers/ClickAwayController",
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
"./src/controllers/ViewSwitcherController",
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
"./src/controllers/GetterSetterController",
|
* License for the specific language governing permissions and limitations
|
||||||
"./src/controllers/SelectorController",
|
* under the License.
|
||||||
"./src/controllers/ObjectInspectorController",
|
*
|
||||||
"./src/controllers/BannerController",
|
* Open MCT includes source code licensed under additional open source
|
||||||
"./src/directives/MCTContainer",
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
"./src/directives/MCTDrag",
|
* this source code distribution or the Licensing information page available
|
||||||
"./src/directives/MCTSelectable",
|
* at runtime from the About dialog for additional information.
|
||||||
"./src/directives/MCTClickElsewhere",
|
*****************************************************************************/
|
||||||
"./src/directives/MCTResize",
|
|
||||||
"./src/directives/MCTPopup",
|
|
||||||
"./src/directives/MCTScroll",
|
|
||||||
"./src/directives/MCTSplitPane",
|
|
||||||
"./src/directives/MCTSplitter",
|
|
||||||
"./src/directives/MCTTree",
|
|
||||||
"./src/directives/MCTIndicators",
|
|
||||||
"./src/filters/ReverseFilter",
|
|
||||||
"./res/templates/bottombar.html",
|
|
||||||
"./res/templates/controls/action-button.html",
|
|
||||||
"./res/templates/controls/input-filter.html",
|
|
||||||
"./res/templates/angular-indicator.html",
|
|
||||||
"./res/templates/message-banner.html",
|
|
||||||
"./res/templates/progress-bar.html",
|
|
||||||
"./res/templates/controls/time-controller.html",
|
|
||||||
"./res/templates/containers/accordion.html",
|
|
||||||
"./res/templates/subtree.html",
|
|
||||||
"./res/templates/tree.html",
|
|
||||||
"./res/templates/tree-node.html",
|
|
||||||
"./res/templates/label.html",
|
|
||||||
"./res/templates/controls/action-group.html",
|
|
||||||
"./res/templates/controls/switcher.html",
|
|
||||||
"./res/templates/object-inspector.html",
|
|
||||||
"./res/templates/controls/selector.html",
|
|
||||||
"./res/templates/controls/datetime-picker.html",
|
|
||||||
"./res/templates/controls/datetime-field.html"
|
|
||||||
], function (
|
|
||||||
UrlService,
|
|
||||||
PopupService,
|
|
||||||
SplashScreenManager,
|
|
||||||
StyleSheetLoader,
|
|
||||||
TimeRangeController,
|
|
||||||
DateTimePickerController,
|
|
||||||
DateTimeFieldController,
|
|
||||||
TreeNodeController,
|
|
||||||
ActionGroupController,
|
|
||||||
ToggleController,
|
|
||||||
ClickAwayController,
|
|
||||||
ViewSwitcherController,
|
|
||||||
GetterSetterController,
|
|
||||||
SelectorController,
|
|
||||||
ObjectInspectorController,
|
|
||||||
BannerController,
|
|
||||||
MCTContainer,
|
|
||||||
MCTDrag,
|
|
||||||
MCTSelectable,
|
|
||||||
MCTClickElsewhere,
|
|
||||||
MCTResize,
|
|
||||||
MCTPopup,
|
|
||||||
MCTScroll,
|
|
||||||
MCTSplitPane,
|
|
||||||
MCTSplitter,
|
|
||||||
MCTTree,
|
|
||||||
MCTIndicators,
|
|
||||||
ReverseFilter,
|
|
||||||
bottombarTemplate,
|
|
||||||
actionButtonTemplate,
|
|
||||||
inputFilterTemplate,
|
|
||||||
indicatorTemplate,
|
|
||||||
messageBannerTemplate,
|
|
||||||
progressBarTemplate,
|
|
||||||
timeControllerTemplate,
|
|
||||||
accordionTemplate,
|
|
||||||
subtreeTemplate,
|
|
||||||
treeTemplate,
|
|
||||||
treeNodeTemplate,
|
|
||||||
labelTemplate,
|
|
||||||
actionGroupTemplate,
|
|
||||||
switcherTemplate,
|
|
||||||
objectInspectorTemplate,
|
|
||||||
selectorTemplate,
|
|
||||||
datetimePickerTemplate,
|
|
||||||
datetimeFieldTemplate
|
|
||||||
) {
|
|
||||||
|
|
||||||
return {
|
import UrlService from './src/services/UrlService';
|
||||||
name: "platform/commonUI/general",
|
|
||||||
definition: {
|
import PopupService from './src/services/PopupService';
|
||||||
"name": "General UI elements",
|
import SplashScreenManager from './src/SplashScreenManager';
|
||||||
"description": "General UI elements, meant to be reused across modes",
|
import StyleSheetLoader from './src/StyleSheetLoader';
|
||||||
"resources": "res",
|
import TimeRangeController from './src/controllers/TimeRangeController';
|
||||||
"extensions": {
|
import DateTimePickerController from './src/controllers/DateTimePickerController';
|
||||||
"services": [
|
import DateTimeFieldController from './src/controllers/DateTimeFieldController';
|
||||||
{
|
import TreeNodeController from './src/controllers/TreeNodeController';
|
||||||
"key": "urlService",
|
import ActionGroupController from './src/controllers/ActionGroupController';
|
||||||
"implementation": UrlService,
|
import ToggleController from './src/controllers/ToggleController';
|
||||||
"depends": [
|
import ClickAwayController from './src/controllers/ClickAwayController';
|
||||||
"$location"
|
import ViewSwitcherController from './src/controllers/ViewSwitcherController';
|
||||||
]
|
import GetterSetterController from './src/controllers/GetterSetterController';
|
||||||
},
|
import SelectorController from './src/controllers/SelectorController';
|
||||||
{
|
import ObjectInspectorController from './src/controllers/ObjectInspectorController';
|
||||||
"key": "popupService",
|
import BannerController from './src/controllers/BannerController';
|
||||||
"implementation": PopupService,
|
import MCTContainer from './src/directives/MCTContainer';
|
||||||
"depends": [
|
import MCTDrag from './src/directives/MCTDrag';
|
||||||
"$document",
|
import MCTSelectable from './src/directives/MCTSelectable';
|
||||||
"$window"
|
import MCTClickElsewhere from './src/directives/MCTClickElsewhere';
|
||||||
]
|
import MCTResize from './src/directives/MCTResize';
|
||||||
}
|
import MCTPopup from './src/directives/MCTPopup';
|
||||||
],
|
import MCTScroll from './src/directives/MCTScroll';
|
||||||
"runs": [
|
import MCTSplitPane from './src/directives/MCTSplitPane';
|
||||||
{
|
import MCTSplitter from './src/directives/MCTSplitter';
|
||||||
"implementation": StyleSheetLoader,
|
import MCTTree from './src/directives/MCTTree';
|
||||||
"depends": [
|
import MCTIndicators from './src/directives/MCTIndicators';
|
||||||
"stylesheets[]",
|
import ReverseFilter from './src/filters/ReverseFilter';
|
||||||
"$document",
|
import bottombarTemplate from './res/templates/bottombar.html';
|
||||||
"THEME",
|
import actionButtonTemplate from './res/templates/controls/action-button.html';
|
||||||
"ASSETS_PATH"
|
import inputFilterTemplate from './res/templates/controls/input-filter.html';
|
||||||
]
|
import indicatorTemplate from './res/templates/angular-indicator.html';
|
||||||
},
|
import messageBannerTemplate from './res/templates/message-banner.html';
|
||||||
{
|
import progressBarTemplate from './res/templates/progress-bar.html';
|
||||||
"implementation": SplashScreenManager,
|
import timeControllerTemplate from './res/templates/controls/time-controller.html';
|
||||||
"depends": [
|
import accordionTemplate from './res/templates/containers/accordion.html';
|
||||||
"$document"
|
import subtreeTemplate from './res/templates/subtree.html';
|
||||||
]
|
import treeTemplate from './res/templates/tree.html';
|
||||||
}
|
import treeNodeTemplate from './res/templates/tree-node.html';
|
||||||
],
|
import labelTemplate from './res/templates/label.html';
|
||||||
"filters": [
|
import actionGroupTemplate from './res/templates/controls/action-group.html';
|
||||||
{
|
import switcherTemplate from './res/templates/controls/switcher.html';
|
||||||
"implementation": ReverseFilter,
|
import objectInspectorTemplate from './res/templates/object-inspector.html';
|
||||||
"key": "reverse"
|
import selectorTemplate from './res/templates/controls/selector.html';
|
||||||
}
|
import datetimePickerTemplate from './res/templates/controls/datetime-picker.html';
|
||||||
],
|
import datetimeFieldTemplate from './res/templates/controls/datetime-field.html';
|
||||||
"templates": [
|
|
||||||
{
|
export default {
|
||||||
"key": "bottombar",
|
name: "platform/commonUI/general",
|
||||||
"template": bottombarTemplate
|
definition: {
|
||||||
},
|
"name": "General UI elements",
|
||||||
{
|
"description": "General UI elements, meant to be reused across modes",
|
||||||
"key": "action-button",
|
"resources": "res",
|
||||||
"template": actionButtonTemplate
|
"extensions": {
|
||||||
},
|
"services": [
|
||||||
{
|
{
|
||||||
"key": "input-filter",
|
"key": "urlService",
|
||||||
"template": inputFilterTemplate
|
"implementation": UrlService,
|
||||||
},
|
"depends": [
|
||||||
{
|
"$location"
|
||||||
"key": "indicator",
|
]
|
||||||
"template": indicatorTemplate
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "popupService",
|
||||||
"key": "message-banner",
|
"implementation": PopupService,
|
||||||
"template": messageBannerTemplate
|
"depends": [
|
||||||
},
|
"$document",
|
||||||
{
|
"$window"
|
||||||
"key": "progress-bar",
|
]
|
||||||
"template": progressBarTemplate
|
}
|
||||||
},
|
],
|
||||||
{
|
"runs": [
|
||||||
"key": "time-controller",
|
{
|
||||||
"template": timeControllerTemplate
|
"implementation": StyleSheetLoader,
|
||||||
}
|
"depends": [
|
||||||
],
|
"stylesheets[]",
|
||||||
"controllers": [
|
"$document",
|
||||||
{
|
"THEME",
|
||||||
"key": "TimeRangeController",
|
"ASSETS_PATH"
|
||||||
"implementation": TimeRangeController,
|
]
|
||||||
"depends": [
|
},
|
||||||
"$scope",
|
{
|
||||||
"$timeout",
|
"implementation": SplashScreenManager,
|
||||||
"formatService",
|
"depends": [
|
||||||
"DEFAULT_TIME_FORMAT",
|
"$document"
|
||||||
"now"
|
]
|
||||||
]
|
}
|
||||||
},
|
],
|
||||||
{
|
"filters": [
|
||||||
"key": "DateTimePickerController",
|
{
|
||||||
"implementation": DateTimePickerController,
|
"implementation": ReverseFilter,
|
||||||
"depends": [
|
"key": "reverse"
|
||||||
"$scope",
|
}
|
||||||
"now"
|
],
|
||||||
]
|
"templates": [
|
||||||
},
|
{
|
||||||
{
|
"key": "bottombar",
|
||||||
"key": "DateTimeFieldController",
|
"template": bottombarTemplate
|
||||||
"implementation": DateTimeFieldController,
|
},
|
||||||
"depends": [
|
{
|
||||||
"$scope",
|
"key": "action-button",
|
||||||
"formatService",
|
"template": actionButtonTemplate
|
||||||
"DEFAULT_TIME_FORMAT"
|
},
|
||||||
]
|
{
|
||||||
},
|
"key": "input-filter",
|
||||||
{
|
"template": inputFilterTemplate
|
||||||
"key": "TreeNodeController",
|
},
|
||||||
"implementation": TreeNodeController,
|
{
|
||||||
"depends": [
|
"key": "indicator",
|
||||||
"$scope",
|
"template": indicatorTemplate
|
||||||
"$timeout",
|
},
|
||||||
"navigationService"
|
{
|
||||||
]
|
"key": "message-banner",
|
||||||
},
|
"template": messageBannerTemplate
|
||||||
{
|
},
|
||||||
"key": "ActionGroupController",
|
{
|
||||||
"implementation": ActionGroupController,
|
"key": "progress-bar",
|
||||||
"depends": [
|
"template": progressBarTemplate
|
||||||
"$scope"
|
},
|
||||||
]
|
{
|
||||||
},
|
"key": "time-controller",
|
||||||
{
|
"template": timeControllerTemplate
|
||||||
"key": "ToggleController",
|
}
|
||||||
"implementation": ToggleController
|
],
|
||||||
},
|
"controllers": [
|
||||||
{
|
{
|
||||||
"key": "ClickAwayController",
|
"key": "TimeRangeController",
|
||||||
"implementation": ClickAwayController,
|
"implementation": TimeRangeController,
|
||||||
"depends": [
|
"depends": [
|
||||||
"$document",
|
"$scope",
|
||||||
"$timeout"
|
"$timeout",
|
||||||
]
|
"formatService",
|
||||||
},
|
"DEFAULT_TIME_FORMAT",
|
||||||
{
|
"now"
|
||||||
"key": "ViewSwitcherController",
|
]
|
||||||
"implementation": ViewSwitcherController,
|
},
|
||||||
"depends": [
|
{
|
||||||
"$scope",
|
"key": "DateTimePickerController",
|
||||||
"$timeout"
|
"implementation": DateTimePickerController,
|
||||||
]
|
"depends": [
|
||||||
},
|
"$scope",
|
||||||
{
|
"now"
|
||||||
"key": "GetterSetterController",
|
]
|
||||||
"implementation": GetterSetterController,
|
},
|
||||||
"depends": [
|
{
|
||||||
"$scope"
|
"key": "DateTimeFieldController",
|
||||||
]
|
"implementation": DateTimeFieldController,
|
||||||
},
|
"depends": [
|
||||||
{
|
"$scope",
|
||||||
"key": "SelectorController",
|
"formatService",
|
||||||
"implementation": SelectorController,
|
"DEFAULT_TIME_FORMAT"
|
||||||
"depends": [
|
]
|
||||||
"objectService",
|
},
|
||||||
"$scope"
|
{
|
||||||
]
|
"key": "TreeNodeController",
|
||||||
},
|
"implementation": TreeNodeController,
|
||||||
{
|
"depends": [
|
||||||
"key": "ObjectInspectorController",
|
"$scope",
|
||||||
"implementation": ObjectInspectorController,
|
"$timeout",
|
||||||
"depends": [
|
"navigationService"
|
||||||
"$scope",
|
]
|
||||||
"objectService"
|
},
|
||||||
]
|
{
|
||||||
},
|
"key": "ActionGroupController",
|
||||||
{
|
"implementation": ActionGroupController,
|
||||||
"key": "BannerController",
|
"depends": [
|
||||||
"implementation": BannerController,
|
"$scope"
|
||||||
"depends": [
|
]
|
||||||
"$scope",
|
},
|
||||||
"notificationService",
|
{
|
||||||
"dialogService"
|
"key": "ToggleController",
|
||||||
]
|
"implementation": ToggleController
|
||||||
}
|
},
|
||||||
],
|
{
|
||||||
"directives": [
|
"key": "ClickAwayController",
|
||||||
{
|
"implementation": ClickAwayController,
|
||||||
"key": "mctContainer",
|
"depends": [
|
||||||
"implementation": MCTContainer,
|
"$document",
|
||||||
"depends": [
|
"$timeout"
|
||||||
"containers[]"
|
]
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "ViewSwitcherController",
|
||||||
"key": "mctDrag",
|
"implementation": ViewSwitcherController,
|
||||||
"implementation": MCTDrag,
|
"depends": [
|
||||||
"depends": [
|
"$scope",
|
||||||
"$document",
|
"$timeout"
|
||||||
"agentService"
|
]
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "GetterSetterController",
|
||||||
"key": "mctSelectable",
|
"implementation": GetterSetterController,
|
||||||
"implementation": MCTSelectable,
|
"depends": [
|
||||||
"depends": [
|
"$scope"
|
||||||
"openmct"
|
]
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "SelectorController",
|
||||||
"key": "mctClickElsewhere",
|
"implementation": SelectorController,
|
||||||
"implementation": MCTClickElsewhere,
|
"depends": [
|
||||||
"depends": [
|
"objectService",
|
||||||
"$document"
|
"$scope"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "mctResize",
|
"key": "ObjectInspectorController",
|
||||||
"implementation": MCTResize,
|
"implementation": ObjectInspectorController,
|
||||||
"depends": [
|
"depends": [
|
||||||
"$timeout"
|
"$scope",
|
||||||
]
|
"objectService"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"key": "mctPopup",
|
{
|
||||||
"implementation": MCTPopup,
|
"key": "BannerController",
|
||||||
"depends": [
|
"implementation": BannerController,
|
||||||
"$compile",
|
"depends": [
|
||||||
"popupService"
|
"$scope",
|
||||||
]
|
"notificationService",
|
||||||
},
|
"dialogService"
|
||||||
{
|
]
|
||||||
"key": "mctScrollX",
|
}
|
||||||
"implementation": MCTScroll,
|
],
|
||||||
"depends": [
|
"directives": [
|
||||||
"$parse",
|
{
|
||||||
"MCT_SCROLL_X_PROPERTY",
|
"key": "mctContainer",
|
||||||
"MCT_SCROLL_X_ATTRIBUTE"
|
"implementation": MCTContainer,
|
||||||
]
|
"depends": [
|
||||||
},
|
"containers[]"
|
||||||
{
|
]
|
||||||
"key": "mctScrollY",
|
},
|
||||||
"implementation": MCTScroll,
|
{
|
||||||
"depends": [
|
"key": "mctDrag",
|
||||||
"$parse",
|
"implementation": MCTDrag,
|
||||||
"MCT_SCROLL_Y_PROPERTY",
|
"depends": [
|
||||||
"MCT_SCROLL_Y_ATTRIBUTE"
|
"$document",
|
||||||
]
|
"agentService"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"key": "mctSplitPane",
|
{
|
||||||
"implementation": MCTSplitPane,
|
"key": "mctSelectable",
|
||||||
"depends": [
|
"implementation": MCTSelectable,
|
||||||
"$parse",
|
"depends": [
|
||||||
"$log",
|
"openmct"
|
||||||
"$interval",
|
]
|
||||||
"$window"
|
},
|
||||||
]
|
{
|
||||||
},
|
"key": "mctClickElsewhere",
|
||||||
{
|
"implementation": MCTClickElsewhere,
|
||||||
"key": "mctSplitter",
|
"depends": [
|
||||||
"implementation": MCTSplitter
|
"$document"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"key": "mctTree",
|
{
|
||||||
"implementation": MCTTree,
|
"key": "mctResize",
|
||||||
"depends": ['gestureService', 'openmct']
|
"implementation": MCTResize,
|
||||||
},
|
"depends": [
|
||||||
{
|
"$timeout"
|
||||||
"key": "mctIndicators",
|
]
|
||||||
"implementation": MCTIndicators,
|
},
|
||||||
"depends": ['openmct']
|
{
|
||||||
}
|
"key": "mctPopup",
|
||||||
],
|
"implementation": MCTPopup,
|
||||||
"constants": [
|
"depends": [
|
||||||
{
|
"$compile",
|
||||||
"key": "MCT_SCROLL_X_PROPERTY",
|
"popupService"
|
||||||
"value": "scrollLeft"
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "MCT_SCROLL_X_ATTRIBUTE",
|
"key": "mctScrollX",
|
||||||
"value": "mctScrollX"
|
"implementation": MCTScroll,
|
||||||
},
|
"depends": [
|
||||||
{
|
"$parse",
|
||||||
"key": "MCT_SCROLL_Y_PROPERTY",
|
"MCT_SCROLL_X_PROPERTY",
|
||||||
"value": "scrollTop"
|
"MCT_SCROLL_X_ATTRIBUTE"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"key": "MCT_SCROLL_Y_ATTRIBUTE",
|
{
|
||||||
"value": "mctScrollY"
|
"key": "mctScrollY",
|
||||||
},
|
"implementation": MCTScroll,
|
||||||
{
|
"depends": [
|
||||||
"key": "THEME",
|
"$parse",
|
||||||
"value": "unspecified",
|
"MCT_SCROLL_Y_PROPERTY",
|
||||||
"priority": "fallback"
|
"MCT_SCROLL_Y_ATTRIBUTE"
|
||||||
},
|
]
|
||||||
{
|
},
|
||||||
"key": "ASSETS_PATH",
|
{
|
||||||
"value": ".",
|
"key": "mctSplitPane",
|
||||||
"priority": "fallback"
|
"implementation": MCTSplitPane,
|
||||||
}
|
"depends": [
|
||||||
],
|
"$parse",
|
||||||
"containers": [
|
"$log",
|
||||||
{
|
"$interval",
|
||||||
"key": "accordion",
|
"$window"
|
||||||
"template": accordionTemplate,
|
]
|
||||||
"attributes": [
|
},
|
||||||
"label"
|
{
|
||||||
]
|
"key": "mctSplitter",
|
||||||
}
|
"implementation": MCTSplitter
|
||||||
],
|
},
|
||||||
"representations": [
|
{
|
||||||
{
|
"key": "mctTree",
|
||||||
"key": "tree",
|
"implementation": MCTTree,
|
||||||
"template": subtreeTemplate,
|
"depends": ['gestureService', 'openmct']
|
||||||
"uses": [
|
},
|
||||||
"composition"
|
{
|
||||||
],
|
"key": "mctIndicators",
|
||||||
"type": "root",
|
"implementation": MCTIndicators,
|
||||||
"priority": "preferred"
|
"depends": ['openmct']
|
||||||
},
|
}
|
||||||
{
|
],
|
||||||
"key": "tree",
|
"constants": [
|
||||||
"template": treeTemplate
|
{
|
||||||
},
|
"key": "MCT_SCROLL_X_PROPERTY",
|
||||||
{
|
"value": "scrollLeft"
|
||||||
"key": "subtree",
|
},
|
||||||
"template": subtreeTemplate,
|
{
|
||||||
"uses": [
|
"key": "MCT_SCROLL_X_ATTRIBUTE",
|
||||||
"composition"
|
"value": "mctScrollX"
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "MCT_SCROLL_Y_PROPERTY",
|
||||||
"key": "tree-node",
|
"value": "scrollTop"
|
||||||
"template": treeNodeTemplate,
|
},
|
||||||
"uses": [
|
{
|
||||||
"action"
|
"key": "MCT_SCROLL_Y_ATTRIBUTE",
|
||||||
]
|
"value": "mctScrollY"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "label",
|
"key": "THEME",
|
||||||
"template": labelTemplate,
|
"value": "unspecified",
|
||||||
"uses": [
|
"priority": "fallback"
|
||||||
"type",
|
},
|
||||||
"location"
|
{
|
||||||
],
|
"key": "ASSETS_PATH",
|
||||||
"gestures": [
|
"value": ".",
|
||||||
"drag",
|
"priority": "fallback"
|
||||||
"menu",
|
}
|
||||||
"info"
|
],
|
||||||
]
|
"containers": [
|
||||||
},
|
{
|
||||||
{
|
"key": "accordion",
|
||||||
"key": "node",
|
"template": accordionTemplate,
|
||||||
"template": labelTemplate,
|
"attributes": [
|
||||||
"uses": [
|
"label"
|
||||||
"type"
|
]
|
||||||
],
|
}
|
||||||
"gestures": [
|
],
|
||||||
"drag",
|
"representations": [
|
||||||
"menu"
|
{
|
||||||
]
|
"key": "tree",
|
||||||
},
|
"template": subtreeTemplate,
|
||||||
{
|
"uses": [
|
||||||
"key": "action-group",
|
"composition"
|
||||||
"template": actionGroupTemplate,
|
],
|
||||||
"uses": [
|
"type": "root",
|
||||||
"action"
|
"priority": "preferred"
|
||||||
]
|
},
|
||||||
},
|
{
|
||||||
{
|
"key": "tree",
|
||||||
"key": "switcher",
|
"template": treeTemplate
|
||||||
"template": switcherTemplate,
|
},
|
||||||
"uses": [
|
{
|
||||||
"view"
|
"key": "subtree",
|
||||||
]
|
"template": subtreeTemplate,
|
||||||
},
|
"uses": [
|
||||||
{
|
"composition"
|
||||||
"key": "object-inspector",
|
]
|
||||||
"template": objectInspectorTemplate
|
},
|
||||||
}
|
{
|
||||||
],
|
"key": "tree-node",
|
||||||
"controls": [
|
"template": treeNodeTemplate,
|
||||||
{
|
"uses": [
|
||||||
"key": "selector",
|
"action"
|
||||||
"template": selectorTemplate
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "datetime-picker",
|
"key": "label",
|
||||||
"template": datetimePickerTemplate
|
"template": labelTemplate,
|
||||||
},
|
"uses": [
|
||||||
{
|
"type",
|
||||||
"key": "datetime-field",
|
"location"
|
||||||
"template": datetimeFieldTemplate
|
],
|
||||||
}
|
"gestures": [
|
||||||
],
|
"drag",
|
||||||
"licenses": [
|
"menu",
|
||||||
{
|
"info"
|
||||||
"name": "Normalize.css",
|
]
|
||||||
"version": "1.1.2",
|
},
|
||||||
"description": "Browser style normalization",
|
{
|
||||||
"author": "Nicolas Gallagher, Jonathan Neal",
|
"key": "node",
|
||||||
"website": "http://necolas.github.io/normalize.css/",
|
"template": labelTemplate,
|
||||||
"copyright": "Copyright (c) Nicolas Gallagher and Jonathan Neal",
|
"uses": [
|
||||||
"license": "license-mit",
|
"type"
|
||||||
"link": "https://github.com/necolas/normalize.css/blob/v1.1.2/LICENSE.md"
|
],
|
||||||
},
|
"gestures": [
|
||||||
{
|
"drag",
|
||||||
"name": "Zepto",
|
"menu"
|
||||||
"version": "1.1.6",
|
]
|
||||||
"description": "DOM manipulation",
|
},
|
||||||
"author": "Thomas Fuchs",
|
{
|
||||||
"website": "http://zeptojs.com/",
|
"key": "action-group",
|
||||||
"copyright": "Copyright (c) 2010-2016 Thomas Fuchs",
|
"template": actionGroupTemplate,
|
||||||
"license": "license-mit",
|
"uses": [
|
||||||
"link": "https://github.com/madrobby/zepto/blob/master/MIT-LICENSE"
|
"action"
|
||||||
}
|
]
|
||||||
]
|
},
|
||||||
}
|
{
|
||||||
|
"key": "switcher",
|
||||||
|
"template": switcherTemplate,
|
||||||
|
"uses": [
|
||||||
|
"view"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "object-inspector",
|
||||||
|
"template": objectInspectorTemplate
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"controls": [
|
||||||
|
{
|
||||||
|
"key": "selector",
|
||||||
|
"template": selectorTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "datetime-picker",
|
||||||
|
"template": datetimePickerTemplate
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "datetime-field",
|
||||||
|
"template": datetimeFieldTemplate
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"licenses": [
|
||||||
|
{
|
||||||
|
"name": "Normalize.css",
|
||||||
|
"version": "1.1.2",
|
||||||
|
"description": "Browser style normalization",
|
||||||
|
"author": "Nicolas Gallagher, Jonathan Neal",
|
||||||
|
"website": "http://necolas.github.io/normalize.css/",
|
||||||
|
"copyright": "Copyright (c) Nicolas Gallagher and Jonathan Neal",
|
||||||
|
"license": "license-mit",
|
||||||
|
"link": "https://github.com/necolas/normalize.css/blob/v1.1.2/LICENSE.md"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Zepto",
|
||||||
|
"version": "1.1.6",
|
||||||
|
"description": "DOM manipulation",
|
||||||
|
"author": "Thomas Fuchs",
|
||||||
|
"website": "http://zeptojs.com/",
|
||||||
|
"copyright": "Copyright (c) 2010-2016 Thomas Fuchs",
|
||||||
|
"license": "license-mit",
|
||||||
|
"link": "https://github.com/madrobby/zepto/blob/master/MIT-LICENSE"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
});
|
};
|
@ -20,25 +20,40 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
], function (
|
function SplashScreenManager($document) {
|
||||||
|
var splash;
|
||||||
) {
|
$document = $document[0];
|
||||||
|
splash = $document.querySelectorAll('.l-splash-holder')[0];
|
||||||
function SplashScreenManager($document) {
|
if (!splash) {
|
||||||
var splash;
|
return;
|
||||||
$document = $document[0];
|
|
||||||
splash = $document.querySelectorAll('.l-splash-holder')[0];
|
|
||||||
if (!splash) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
splash.className += ' fadeout';
|
|
||||||
splash.addEventListener('transitionend', function () {
|
|
||||||
splash.parentNode.removeChild(splash);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return SplashScreenManager;
|
splash.className += ' fadeout';
|
||||||
});
|
splash.addEventListener('transitionend', function () {
|
||||||
|
splash.parentNode.removeChild(splash);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SplashScreenManager;
|
@ -25,58 +25,68 @@
|
|||||||
* platform styling.
|
* platform styling.
|
||||||
* @namespace platform/commonUI/general
|
* @namespace platform/commonUI/general
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The StyleSheetLoader adds links to style sheets exposed from
|
* This bundle provides various general-purpose UI elements, including
|
||||||
* various bundles as extensions of category `stylesheets`.
|
* platform styling.
|
||||||
* @memberof platform/commonUI/general
|
* @namespace platform/commonUI/general
|
||||||
* @constructor
|
*/
|
||||||
* @param {object[]} stylesheets stylesheet extension definitions
|
function StyleSheetLoader(stylesheets, $document, activeTheme, assetPath) {
|
||||||
* @param $document Angular's jqLite-wrapped document element
|
var head = $document.find('head'),
|
||||||
* @param {string} activeTheme the theme in use
|
document = $document[0];
|
||||||
* @param {string} [assetPath] the directory relative to which
|
|
||||||
* stylesheets will be found
|
|
||||||
*/
|
|
||||||
function StyleSheetLoader(stylesheets, $document, activeTheme, assetPath) {
|
|
||||||
var head = $document.find('head'),
|
|
||||||
document = $document[0];
|
|
||||||
|
|
||||||
// Procedure for adding a single stylesheet
|
// Procedure for adding a single stylesheet
|
||||||
function addStyleSheet(stylesheet) {
|
function addStyleSheet(stylesheet) {
|
||||||
// Create a link element, and construct full path
|
// Create a link element, and construct full path
|
||||||
var link = document.createElement('link'),
|
var link = document.createElement('link'),
|
||||||
path = [
|
path = [
|
||||||
assetPath,
|
assetPath,
|
||||||
stylesheet.bundle.path,
|
stylesheet.bundle.path,
|
||||||
stylesheet.bundle.resources,
|
stylesheet.bundle.resources,
|
||||||
stylesheet.stylesheetUrl
|
stylesheet.stylesheetUrl
|
||||||
].join("/");
|
].join("/");
|
||||||
|
|
||||||
// Initialize attributes on the link
|
// Initialize attributes on the link
|
||||||
link.setAttribute("rel", "stylesheet");
|
link.setAttribute("rel", "stylesheet");
|
||||||
link.setAttribute("type", "text/css");
|
link.setAttribute("type", "text/css");
|
||||||
link.setAttribute("href", path);
|
link.setAttribute("href", path);
|
||||||
|
|
||||||
// Append the link to the head element
|
// Append the link to the head element
|
||||||
head.append(link);
|
head.append(link);
|
||||||
}
|
|
||||||
|
|
||||||
// Stylesheets which specify themes should only be applied
|
|
||||||
// when that theme has been declared.
|
|
||||||
function matchesTheme(stylesheet) {
|
|
||||||
return stylesheet.theme === undefined
|
|
||||||
|| stylesheet.theme === activeTheme;
|
|
||||||
}
|
|
||||||
|
|
||||||
assetPath = assetPath || ".";
|
|
||||||
|
|
||||||
// Add all stylesheets from extensions
|
|
||||||
stylesheets.filter(matchesTheme).forEach(addStyleSheet);
|
|
||||||
}
|
|
||||||
|
|
||||||
return StyleSheetLoader;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Stylesheets which specify themes should only be applied
|
||||||
|
// when that theme has been declared.
|
||||||
|
function matchesTheme(stylesheet) {
|
||||||
|
return stylesheet.theme === undefined
|
||||||
|
|| stylesheet.theme === activeTheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
assetPath = assetPath || ".";
|
||||||
|
|
||||||
|
// Add all stylesheets from extensions
|
||||||
|
stylesheets.filter(matchesTheme).forEach(addStyleSheet);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default StyleSheetLoader;
|
@ -23,82 +23,85 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining ActionGroupController. Created by vwoeltje on 11/14/14.
|
* Module defining ActionGroupController. Created by vwoeltje on 11/14/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller which keeps an up-to-date list of actions of
|
* Module defining ActionGroupController. Created by vwoeltje on 11/14/14.
|
||||||
* a certain category, and additionally bins them into
|
*/
|
||||||
* groups as described by their metadata. Used specifically
|
function ActionGroupController($scope) {
|
||||||
* to support button groups.
|
|
||||||
*
|
|
||||||
* This will maintain two fields in the scope:
|
|
||||||
* * `groups`: An array of arrays. Each element in the outer
|
|
||||||
* array corresponds to a group; the inner array contains
|
|
||||||
* the actions which are in that group.
|
|
||||||
* * `ungrouped`: All actions which did not have a defined
|
|
||||||
* group.
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function ActionGroupController($scope) {
|
|
||||||
|
|
||||||
// Separate out the actions that have been retrieved
|
// Separate out the actions that have been retrieved
|
||||||
// into groups, and populate scope with this.
|
// into groups, and populate scope with this.
|
||||||
function groupActions(actions) {
|
function groupActions(actions) {
|
||||||
var groups = {},
|
var groups = {},
|
||||||
ungrouped = [];
|
ungrouped = [];
|
||||||
|
|
||||||
function assignToGroup(action) {
|
function assignToGroup(action) {
|
||||||
var metadata = action.getMetadata(),
|
var metadata = action.getMetadata(),
|
||||||
group = metadata.group;
|
group = metadata.group;
|
||||||
if (group) {
|
if (group) {
|
||||||
groups[group] = groups[group] || [];
|
groups[group] = groups[group] || [];
|
||||||
groups[group].push(action);
|
groups[group].push(action);
|
||||||
} else {
|
} else {
|
||||||
ungrouped.push(action);
|
ungrouped.push(action);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
(actions || []).forEach(assignToGroup);
|
|
||||||
|
|
||||||
$scope.ungrouped = ungrouped;
|
|
||||||
$scope.groups = Object.keys(groups).sort().map(function (k) {
|
|
||||||
return groups[k];
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Callback for when state which might influence action groupings
|
|
||||||
// changes.
|
|
||||||
function updateGroups() {
|
|
||||||
var actionCapability = $scope.action,
|
|
||||||
params = $scope.parameters || {},
|
|
||||||
category = params.category;
|
|
||||||
|
|
||||||
if (actionCapability && category) {
|
|
||||||
// Get actions by capability, and group them
|
|
||||||
groupActions(actionCapability.getActions({
|
|
||||||
category: category
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
// We don't have enough information to get any actions.
|
|
||||||
groupActions([]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Changes to the represented object, to its action capability, or
|
|
||||||
// to the chosen action category may all require an update.
|
|
||||||
$scope.$watch("domainObject", updateGroups);
|
|
||||||
$scope.$watch("action", updateGroups);
|
|
||||||
$scope.$watch("parameters.category", updateGroups);
|
|
||||||
|
|
||||||
// Start with empty arrays.
|
|
||||||
$scope.ungrouped = [];
|
|
||||||
$scope.groups = [];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionGroupController;
|
(actions || []).forEach(assignToGroup);
|
||||||
|
|
||||||
|
$scope.ungrouped = ungrouped;
|
||||||
|
$scope.groups = Object.keys(groups).sort().map(function (k) {
|
||||||
|
return groups[k];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Callback for when state which might influence action groupings
|
||||||
|
// changes.
|
||||||
|
function updateGroups() {
|
||||||
|
var actionCapability = $scope.action,
|
||||||
|
params = $scope.parameters || {},
|
||||||
|
category = params.category;
|
||||||
|
|
||||||
|
if (actionCapability && category) {
|
||||||
|
// Get actions by capability, and group them
|
||||||
|
groupActions(actionCapability.getActions({
|
||||||
|
category: category
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
// We don't have enough information to get any actions.
|
||||||
|
groupActions([]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Changes to the represented object, to its action capability, or
|
||||||
|
// to the chosen action category may all require an update.
|
||||||
|
$scope.$watch("domainObject", updateGroups);
|
||||||
|
$scope.$watch("action", updateGroups);
|
||||||
|
$scope.$watch("parameters.category", updateGroups);
|
||||||
|
|
||||||
|
// Start with empty arrays.
|
||||||
|
$scope.ungrouped = [];
|
||||||
|
$scope.groups = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ActionGroupController;
|
@ -20,58 +20,62 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function BannerController($scope, notificationService, dialogService) {
|
||||||
* A controller for banner notifications. Banner notifications are a
|
$scope.active = notificationService.active;
|
||||||
* non-blocking way of drawing the user's attention to an event such
|
|
||||||
* as system errors, or the progress or successful completion of an
|
$scope.action = function (action, $event) {
|
||||||
* ongoing task. This controller provides scoped functions for
|
/*
|
||||||
* dismissing and 'maximizing' notifications. See {@link NotificationService}
|
Prevents default 'maximize' behaviour when clicking on
|
||||||
* for more details on Notifications.
|
notification button
|
||||||
*
|
|
||||||
* @param $scope
|
|
||||||
* @param notificationService
|
|
||||||
* @param dialogService
|
|
||||||
* @constructor
|
|
||||||
*/
|
*/
|
||||||
function BannerController($scope, notificationService, dialogService) {
|
$event.stopPropagation();
|
||||||
$scope.active = notificationService.active;
|
|
||||||
|
|
||||||
$scope.action = function (action, $event) {
|
return action();
|
||||||
/*
|
};
|
||||||
Prevents default 'maximize' behaviour when clicking on
|
|
||||||
notification button
|
|
||||||
*/
|
|
||||||
$event.stopPropagation();
|
|
||||||
|
|
||||||
return action();
|
$scope.dismiss = function (notification, $event) {
|
||||||
|
$event.stopPropagation();
|
||||||
|
notification.dismiss();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.maximize = function (notification) {
|
||||||
|
if (notification.model.severity !== "info") {
|
||||||
|
var dialog;
|
||||||
|
notification.model.cancel = function () {
|
||||||
|
dialog.dismiss();
|
||||||
};
|
};
|
||||||
|
|
||||||
$scope.dismiss = function (notification, $event) {
|
//If the notification is dismissed by the user, close
|
||||||
$event.stopPropagation();
|
// the dialog.
|
||||||
notification.dismiss();
|
notification.on('dismiss', function () {
|
||||||
};
|
dialog.dismiss();
|
||||||
|
});
|
||||||
|
|
||||||
$scope.maximize = function (notification) {
|
dialog = dialogService.showBlockingMessage(notification.model);
|
||||||
if (notification.model.severity !== "info") {
|
|
||||||
var dialog;
|
|
||||||
notification.model.cancel = function () {
|
|
||||||
dialog.dismiss();
|
|
||||||
};
|
|
||||||
|
|
||||||
//If the notification is dismissed by the user, close
|
|
||||||
// the dialog.
|
|
||||||
notification.on('dismiss', function () {
|
|
||||||
dialog.dismiss();
|
|
||||||
});
|
|
||||||
|
|
||||||
dialog = dialogService.showBlockingMessage(notification.model);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return BannerController;
|
export default BannerController;
|
||||||
});
|
|
@ -20,78 +20,84 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function ClickAwayController($document, $timeout) {
|
||||||
* A ClickAwayController is used to toggle things (such as context
|
var self = this;
|
||||||
* menus) where clicking elsewhere in the document while the toggle
|
|
||||||
* is in an active state is intended to dismiss the toggle.
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @constructor
|
|
||||||
* @param $scope the scope in which this controller is active
|
|
||||||
* @param $document the document element, injected by Angular
|
|
||||||
*/
|
|
||||||
function ClickAwayController($document, $timeout) {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
this.state = false;
|
this.state = false;
|
||||||
this.$document = $document;
|
this.$document = $document;
|
||||||
|
|
||||||
// Callback used by the document listener. Timeout ensures that
|
// Callback used by the document listener. Timeout ensures that
|
||||||
// `clickaway` action occurs after `toggle` if `toggle` is
|
// `clickaway` action occurs after `toggle` if `toggle` is
|
||||||
// triggered by a click/mouseup.
|
// triggered by a click/mouseup.
|
||||||
this.clickaway = function () {
|
this.clickaway = function () {
|
||||||
$timeout(function () {
|
$timeout(function () {
|
||||||
self.deactivate();
|
self.deactivate();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Track state, but also attach and detach a listener for
|
// Track state, but also attach and detach a listener for
|
||||||
// mouseup events on the document.
|
// mouseup events on the document.
|
||||||
ClickAwayController.prototype.deactivate = function () {
|
ClickAwayController.prototype.deactivate = function () {
|
||||||
this.state = false;
|
this.state = false;
|
||||||
this.$document.off("mouseup", this.clickaway);
|
this.$document.off("mouseup", this.clickaway);
|
||||||
};
|
};
|
||||||
|
|
||||||
ClickAwayController.prototype.activate = function () {
|
ClickAwayController.prototype.activate = function () {
|
||||||
this.state = true;
|
this.state = true;
|
||||||
this.$document.on("mouseup", this.clickaway);
|
this.$document.on("mouseup", this.clickaway);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current state of the toggle.
|
* Get the current state of the toggle.
|
||||||
* @return {boolean} true if active
|
* @return {boolean} true if active
|
||||||
*/
|
*/
|
||||||
ClickAwayController.prototype.isActive = function () {
|
ClickAwayController.prototype.isActive = function () {
|
||||||
return this.state;
|
return this.state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a new state for the toggle.
|
* Set a new state for the toggle.
|
||||||
* @return {boolean} true to activate
|
* @return {boolean} true to activate
|
||||||
*/
|
*/
|
||||||
ClickAwayController.prototype.setState = function (newState) {
|
ClickAwayController.prototype.setState = function (newState) {
|
||||||
if (this.state !== newState) {
|
if (this.state !== newState) {
|
||||||
this.toggle();
|
this.toggle();
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle the current state; activate if it is inactive,
|
|
||||||
* deactivate if it is active.
|
|
||||||
*/
|
|
||||||
ClickAwayController.prototype.toggle = function () {
|
|
||||||
if (this.state) {
|
|
||||||
this.deactivate();
|
|
||||||
} else {
|
|
||||||
this.activate();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return ClickAwayController;
|
|
||||||
}
|
}
|
||||||
);
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggle the current state; activate if it is inactive,
|
||||||
|
* deactivate if it is active.
|
||||||
|
*/
|
||||||
|
ClickAwayController.prototype.toggle = function () {
|
||||||
|
if (this.state) {
|
||||||
|
this.deactivate();
|
||||||
|
} else {
|
||||||
|
this.activate();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ClickAwayController;
|
@ -20,93 +20,92 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function DateTimeFieldController($scope, formatService, defaultFormat) {
|
||||||
* Controller to support the date-time entry field.
|
var formatter = formatService.getFormat(defaultFormat);
|
||||||
*
|
|
||||||
* Accepts a `format` property in the `structure` attribute
|
|
||||||
* which allows a date/time to be specified via its symbolic
|
|
||||||
* key (as will be used to look up said format from the
|
|
||||||
* `formatService`.)
|
|
||||||
*
|
|
||||||
* {@see FormatService}
|
|
||||||
* @constructor
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @param $scope the Angular scope for this controller
|
|
||||||
* @param {FormatService} formatService the service to user to format
|
|
||||||
* domain values
|
|
||||||
* @param {string} defaultFormat the format to request when no
|
|
||||||
* format has been otherwise specified
|
|
||||||
*/
|
|
||||||
function DateTimeFieldController($scope, formatService, defaultFormat) {
|
|
||||||
var formatter = formatService.getFormat(defaultFormat);
|
|
||||||
|
|
||||||
function updateFromModel(value) {
|
function updateFromModel(value) {
|
||||||
// Only reformat if the value is different from user
|
// Only reformat if the value is different from user
|
||||||
// input (to avoid reformatting valid input while typing.)
|
// input (to avoid reformatting valid input while typing.)
|
||||||
if (!formatter.validate($scope.textValue)
|
if (!formatter.validate($scope.textValue)
|
||||||
|| formatter.parse($scope.textValue) !== value) {
|
|| formatter.parse($scope.textValue) !== value) {
|
||||||
$scope.textValue = formatter.format(value);
|
$scope.textValue = formatter.format(value);
|
||||||
$scope.textInvalid = false;
|
$scope.textInvalid = false;
|
||||||
$scope.lastValidValue = $scope.textValue;
|
$scope.lastValidValue = $scope.textValue;
|
||||||
}
|
|
||||||
|
|
||||||
$scope.pickerModel = { value: value };
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateFromView(textValue) {
|
|
||||||
$scope.textInvalid = !formatter.validate(textValue);
|
|
||||||
if (!$scope.textInvalid) {
|
|
||||||
$scope.ngModel[$scope.field] =
|
|
||||||
formatter.parse(textValue);
|
|
||||||
$scope.lastValidValue = $scope.textValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateFromPicker(value) {
|
|
||||||
if (value !== $scope.ngModel[$scope.field]) {
|
|
||||||
$scope.ngModel[$scope.field] = value;
|
|
||||||
updateFromModel(value);
|
|
||||||
if ($scope.ngBlur) {
|
|
||||||
$scope.ngBlur();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If picker is active, dismiss it when valid value has been selected
|
|
||||||
// This 'if' is to avoid unnecessary validation if picker is not active
|
|
||||||
if ($scope.picker.active) {
|
|
||||||
if ($scope.structure.validate && $scope.structure.validate($scope.ngModel[$scope.field])) {
|
|
||||||
$scope.picker.active = false;
|
|
||||||
} else if (!$scope.structure.validate) {
|
|
||||||
//If picker visible, but no validation function, hide picker
|
|
||||||
$scope.picker.active = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function setFormat(format) {
|
|
||||||
formatter = formatService.getFormat(format || defaultFormat);
|
|
||||||
updateFromModel($scope.ngModel[$scope.field]);
|
|
||||||
}
|
|
||||||
|
|
||||||
function restoreTextValue() {
|
|
||||||
$scope.textValue = $scope.lastValidValue;
|
|
||||||
updateFromView($scope.textValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.restoreTextValue = restoreTextValue;
|
|
||||||
|
|
||||||
$scope.picker = { active: false };
|
|
||||||
|
|
||||||
$scope.$watch('structure.format', setFormat);
|
|
||||||
$scope.$watch('ngModel[field]', updateFromModel);
|
|
||||||
$scope.$watch('pickerModel.value', updateFromPicker);
|
|
||||||
$scope.$watch('textValue', updateFromView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DateTimeFieldController;
|
$scope.pickerModel = { value: value };
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function updateFromView(textValue) {
|
||||||
|
$scope.textInvalid = !formatter.validate(textValue);
|
||||||
|
if (!$scope.textInvalid) {
|
||||||
|
$scope.ngModel[$scope.field] =
|
||||||
|
formatter.parse(textValue);
|
||||||
|
$scope.lastValidValue = $scope.textValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFromPicker(value) {
|
||||||
|
if (value !== $scope.ngModel[$scope.field]) {
|
||||||
|
$scope.ngModel[$scope.field] = value;
|
||||||
|
updateFromModel(value);
|
||||||
|
if ($scope.ngBlur) {
|
||||||
|
$scope.ngBlur();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If picker is active, dismiss it when valid value has been selected
|
||||||
|
// This 'if' is to avoid unnecessary validation if picker is not active
|
||||||
|
if ($scope.picker.active) {
|
||||||
|
if ($scope.structure.validate && $scope.structure.validate($scope.ngModel[$scope.field])) {
|
||||||
|
$scope.picker.active = false;
|
||||||
|
} else if (!$scope.structure.validate) {
|
||||||
|
//If picker visible, but no validation function, hide picker
|
||||||
|
$scope.picker.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setFormat(format) {
|
||||||
|
formatter = formatService.getFormat(format || defaultFormat);
|
||||||
|
updateFromModel($scope.ngModel[$scope.field]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function restoreTextValue() {
|
||||||
|
$scope.textValue = $scope.lastValidValue;
|
||||||
|
updateFromView($scope.textValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.restoreTextValue = restoreTextValue;
|
||||||
|
|
||||||
|
$scope.picker = { active: false };
|
||||||
|
|
||||||
|
$scope.$watch('structure.format', setFormat);
|
||||||
|
$scope.$watch('ngModel[field]', updateFromModel);
|
||||||
|
$scope.$watch('pickerModel.value', updateFromPicker);
|
||||||
|
$scope.$watch('textValue', updateFromView);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DateTimeFieldController;
|
@ -20,188 +20,206 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
['moment'],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function (moment) {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var TIME_NAMES = {
|
import moment from 'moment';
|
||||||
'hours': "Hour",
|
|
||||||
'minutes': "Minute",
|
|
||||||
'seconds': "Second"
|
|
||||||
},
|
|
||||||
MONTHS = moment.months(),
|
|
||||||
TIME_OPTIONS = (function makeRanges() {
|
|
||||||
var arr = [];
|
|
||||||
while (arr.length < 60) {
|
|
||||||
arr.push(arr.length);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
var TIME_NAMES = {
|
||||||
hours: arr.slice(0, 24),
|
'hours': "Hour",
|
||||||
minutes: arr,
|
'minutes': "Minute",
|
||||||
seconds: arr
|
'seconds': "Second"
|
||||||
};
|
},
|
||||||
}());
|
MONTHS = moment.months(),
|
||||||
|
TIME_OPTIONS = (function makeRanges() {
|
||||||
/**
|
var arr = [];
|
||||||
* Controller to support the date-time picker.
|
while (arr.length < 60) {
|
||||||
*
|
arr.push(arr.length);
|
||||||
* Adds/uses the following properties in scope:
|
|
||||||
* * `year`: Year being displayed in picker
|
|
||||||
* * `month`: Month being displayed
|
|
||||||
* * `table`: Table being displayed; array of arrays of
|
|
||||||
* * `day`: Day of month
|
|
||||||
* * `dayOfYear`: Day of year
|
|
||||||
* * `month`: Month associated with the day
|
|
||||||
* * `year`: Year associated with the day.
|
|
||||||
* * `date`: Date chosen
|
|
||||||
* * `year`: Year selected
|
|
||||||
* * `month`: Month selected (0-indexed)
|
|
||||||
* * `day`: Day of month selected
|
|
||||||
* * `time`: Chosen time (hours/minutes/seconds)
|
|
||||||
* * `hours`: Hours chosen
|
|
||||||
* * `minutes`: Minutes chosen
|
|
||||||
* * `seconds`: Seconds chosen
|
|
||||||
*
|
|
||||||
* Months are zero-indexed, day-of-months are one-indexed.
|
|
||||||
*/
|
|
||||||
function DateTimePickerController($scope, now) {
|
|
||||||
var year,
|
|
||||||
month, // For picker state, not model state
|
|
||||||
interacted = false;
|
|
||||||
|
|
||||||
function generateTable() {
|
|
||||||
var m = moment.utc({
|
|
||||||
year: year,
|
|
||||||
month: month
|
|
||||||
}).day(0),
|
|
||||||
table = [],
|
|
||||||
row,
|
|
||||||
col;
|
|
||||||
|
|
||||||
for (row = 0; row < 6; row += 1) {
|
|
||||||
table.push([]);
|
|
||||||
for (col = 0; col < 7; col += 1) {
|
|
||||||
table[row].push({
|
|
||||||
year: m.year(),
|
|
||||||
month: m.month(),
|
|
||||||
day: m.date(),
|
|
||||||
dayOfYear: m.dayOfYear()
|
|
||||||
});
|
|
||||||
m.add(1, 'days'); // Next day!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateScopeForMonth() {
|
|
||||||
$scope.month = MONTHS[month];
|
|
||||||
$scope.year = year;
|
|
||||||
$scope.table = generateTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateFromModel(ngModel) {
|
|
||||||
var m;
|
|
||||||
|
|
||||||
m = moment.utc(ngModel);
|
|
||||||
|
|
||||||
$scope.date = {
|
|
||||||
year: m.year(),
|
|
||||||
month: m.month(),
|
|
||||||
day: m.date()
|
|
||||||
};
|
|
||||||
$scope.time = {
|
|
||||||
hours: m.hour(),
|
|
||||||
minutes: m.minute(),
|
|
||||||
seconds: m.second()
|
|
||||||
};
|
|
||||||
|
|
||||||
//window.alert($scope.date.day + " " + ngModel);
|
|
||||||
|
|
||||||
// Zoom to that date in the picker, but
|
|
||||||
// only if the user hasn't interacted with it yet.
|
|
||||||
if (!interacted) {
|
|
||||||
year = m.year();
|
|
||||||
month = m.month();
|
|
||||||
updateScopeForMonth();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateFromView() {
|
|
||||||
var m = moment.utc({
|
|
||||||
year: $scope.date.year,
|
|
||||||
month: $scope.date.month,
|
|
||||||
day: $scope.date.day,
|
|
||||||
hour: $scope.time.hours,
|
|
||||||
minute: $scope.time.minutes,
|
|
||||||
second: $scope.time.seconds
|
|
||||||
});
|
|
||||||
$scope.ngModel[$scope.field] = m.valueOf();
|
|
||||||
}
|
|
||||||
|
|
||||||
$scope.isInCurrentMonth = function (cell) {
|
|
||||||
return cell.month === month;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.isSelected = function (cell) {
|
|
||||||
var date = $scope.date || {};
|
|
||||||
|
|
||||||
return cell.day === date.day
|
|
||||||
&& cell.month === date.month
|
|
||||||
&& cell.year === date.year;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.select = function (cell) {
|
|
||||||
$scope.date = $scope.date || {};
|
|
||||||
$scope.date.month = cell.month;
|
|
||||||
$scope.date.year = cell.year;
|
|
||||||
$scope.date.day = cell.day;
|
|
||||||
updateFromView();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.dateEquals = function (d1, d2) {
|
|
||||||
return d1.year === d2.year
|
|
||||||
&& d1.month === d2.month
|
|
||||||
&& d1.day === d2.day;
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.changeMonth = function (delta) {
|
|
||||||
month += delta;
|
|
||||||
if (month > 11) {
|
|
||||||
month = 0;
|
|
||||||
year += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (month < 0) {
|
|
||||||
month = 11;
|
|
||||||
year -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
interacted = true;
|
|
||||||
updateScopeForMonth();
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.nameFor = function (key) {
|
|
||||||
return TIME_NAMES[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
$scope.optionsFor = function (key) {
|
|
||||||
return TIME_OPTIONS[key];
|
|
||||||
};
|
|
||||||
|
|
||||||
updateScopeForMonth();
|
|
||||||
|
|
||||||
// Ensure some useful default
|
|
||||||
$scope.ngModel[$scope.field] =
|
|
||||||
$scope.ngModel[$scope.field] === undefined
|
|
||||||
? now() : $scope.ngModel[$scope.field];
|
|
||||||
|
|
||||||
$scope.$watch('ngModel[field]', updateFromModel);
|
|
||||||
$scope.$watchCollection('date', updateFromView);
|
|
||||||
$scope.$watchCollection('time', updateFromView);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DateTimePickerController;
|
return {
|
||||||
|
hours: arr.slice(0, 24),
|
||||||
|
minutes: arr,
|
||||||
|
seconds: arr
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller to support the date-time picker.
|
||||||
|
*
|
||||||
|
* Adds/uses the following properties in scope:
|
||||||
|
* * `year`: Year being displayed in picker
|
||||||
|
* * `month`: Month being displayed
|
||||||
|
* * `table`: Table being displayed; array of arrays of
|
||||||
|
* * `day`: Day of month
|
||||||
|
* * `dayOfYear`: Day of year
|
||||||
|
* * `month`: Month associated with the day
|
||||||
|
* * `year`: Year associated with the day.
|
||||||
|
* * `date`: Date chosen
|
||||||
|
* * `year`: Year selected
|
||||||
|
* * `month`: Month selected (0-indexed)
|
||||||
|
* * `day`: Day of month selected
|
||||||
|
* * `time`: Chosen time (hours/minutes/seconds)
|
||||||
|
* * `hours`: Hours chosen
|
||||||
|
* * `minutes`: Minutes chosen
|
||||||
|
* * `seconds`: Seconds chosen
|
||||||
|
*
|
||||||
|
* Months are zero-indexed, day-of-months are one-indexed.
|
||||||
|
*/
|
||||||
|
function DateTimePickerController($scope, now) {
|
||||||
|
var year,
|
||||||
|
month, // For picker state, not model state
|
||||||
|
interacted = false;
|
||||||
|
|
||||||
|
function generateTable() {
|
||||||
|
var m = moment.utc({
|
||||||
|
year: year,
|
||||||
|
month: month
|
||||||
|
}).day(0),
|
||||||
|
table = [],
|
||||||
|
row,
|
||||||
|
col;
|
||||||
|
|
||||||
|
for (row = 0; row < 6; row += 1) {
|
||||||
|
table.push([]);
|
||||||
|
for (col = 0; col < 7; col += 1) {
|
||||||
|
table[row].push({
|
||||||
|
year: m.year(),
|
||||||
|
month: m.month(),
|
||||||
|
day: m.date(),
|
||||||
|
dayOfYear: m.dayOfYear()
|
||||||
|
});
|
||||||
|
m.add(1, 'days'); // Next day!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return table;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
function updateScopeForMonth() {
|
||||||
|
$scope.month = MONTHS[month];
|
||||||
|
$scope.year = year;
|
||||||
|
$scope.table = generateTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFromModel(ngModel) {
|
||||||
|
var m;
|
||||||
|
|
||||||
|
m = moment.utc(ngModel);
|
||||||
|
|
||||||
|
$scope.date = {
|
||||||
|
year: m.year(),
|
||||||
|
month: m.month(),
|
||||||
|
day: m.date()
|
||||||
|
};
|
||||||
|
$scope.time = {
|
||||||
|
hours: m.hour(),
|
||||||
|
minutes: m.minute(),
|
||||||
|
seconds: m.second()
|
||||||
|
};
|
||||||
|
|
||||||
|
//window.alert($scope.date.day + " " + ngModel);
|
||||||
|
|
||||||
|
// Zoom to that date in the picker, but
|
||||||
|
// only if the user hasn't interacted with it yet.
|
||||||
|
if (!interacted) {
|
||||||
|
year = m.year();
|
||||||
|
month = m.month();
|
||||||
|
updateScopeForMonth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateFromView() {
|
||||||
|
var m = moment.utc({
|
||||||
|
year: $scope.date.year,
|
||||||
|
month: $scope.date.month,
|
||||||
|
day: $scope.date.day,
|
||||||
|
hour: $scope.time.hours,
|
||||||
|
minute: $scope.time.minutes,
|
||||||
|
second: $scope.time.seconds
|
||||||
|
});
|
||||||
|
$scope.ngModel[$scope.field] = m.valueOf();
|
||||||
|
}
|
||||||
|
|
||||||
|
$scope.isInCurrentMonth = function (cell) {
|
||||||
|
return cell.month === month;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.isSelected = function (cell) {
|
||||||
|
var date = $scope.date || {};
|
||||||
|
|
||||||
|
return cell.day === date.day
|
||||||
|
&& cell.month === date.month
|
||||||
|
&& cell.year === date.year;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.select = function (cell) {
|
||||||
|
$scope.date = $scope.date || {};
|
||||||
|
$scope.date.month = cell.month;
|
||||||
|
$scope.date.year = cell.year;
|
||||||
|
$scope.date.day = cell.day;
|
||||||
|
updateFromView();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.dateEquals = function (d1, d2) {
|
||||||
|
return d1.year === d2.year
|
||||||
|
&& d1.month === d2.month
|
||||||
|
&& d1.day === d2.day;
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.changeMonth = function (delta) {
|
||||||
|
month += delta;
|
||||||
|
if (month > 11) {
|
||||||
|
month = 0;
|
||||||
|
year += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (month < 0) {
|
||||||
|
month = 11;
|
||||||
|
year -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
interacted = true;
|
||||||
|
updateScopeForMonth();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.nameFor = function (key) {
|
||||||
|
return TIME_NAMES[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.optionsFor = function (key) {
|
||||||
|
return TIME_OPTIONS[key];
|
||||||
|
};
|
||||||
|
|
||||||
|
updateScopeForMonth();
|
||||||
|
|
||||||
|
// Ensure some useful default
|
||||||
|
$scope.ngModel[$scope.field] =
|
||||||
|
$scope.ngModel[$scope.field] === undefined
|
||||||
|
? now() : $scope.ngModel[$scope.field];
|
||||||
|
|
||||||
|
$scope.$watch('ngModel[field]', updateFromModel);
|
||||||
|
$scope.$watchCollection('date', updateFromView);
|
||||||
|
$scope.$watchCollection('time', updateFromView);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DateTimePickerController;
|
@ -20,70 +20,53 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function GetterSetterController($scope) {
|
||||||
* This controller acts as an adapter to permit getter-setter
|
|
||||||
* functions to be used as ng-model arguments to controls,
|
|
||||||
* such as the input-filter. This is supported natively in
|
|
||||||
* Angular 1.3+ via `ng-model-options`, so this controller
|
|
||||||
* should be made obsolete after any upgrade to Angular 1.3.
|
|
||||||
*
|
|
||||||
* It expects to find in scope a value `ngModel` which is a
|
|
||||||
* function which, when called with no arguments, acts as a
|
|
||||||
* getter, and when called with one argument, acts as a setter.
|
|
||||||
*
|
|
||||||
* It also publishes into the scope a value `getterSetter.value`
|
|
||||||
* which is meant to be used as an assignable expression.
|
|
||||||
*
|
|
||||||
* This controller watches both of these; when one changes,
|
|
||||||
* it will update the other's value to match. Because of this,
|
|
||||||
* the `ngModel` function should be both stable and computationally
|
|
||||||
* inexpensive, as it will be invoked often.
|
|
||||||
*
|
|
||||||
* Getter-setter style models can be preferable when there
|
|
||||||
* is significant indirection between templates; "dotless"
|
|
||||||
* expressions in `ng-model` can behave unexpectedly due to the
|
|
||||||
* rules of scope, but dots are lost when passed in via `ng-model`
|
|
||||||
* (so if a control is internally implemented using regular
|
|
||||||
* form elements, it can't transparently pass through the `ng-model`
|
|
||||||
* parameter it received.) Getter-setter functions are never the
|
|
||||||
* target of a scope assignment and so avoid this problem.
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @constructor
|
|
||||||
* @param {Scope} $scope the controller's scope
|
|
||||||
*/
|
|
||||||
function GetterSetterController($scope) {
|
|
||||||
|
|
||||||
// Update internal assignable state based on changes
|
|
||||||
// to the getter-setter function.
|
|
||||||
function updateGetterSetter() {
|
|
||||||
if (typeof $scope.ngModel === 'function') {
|
|
||||||
$scope.getterSetter.value = $scope.ngModel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the external getter-setter based on changes
|
|
||||||
// to the assignable state.
|
|
||||||
function updateNgModel() {
|
|
||||||
if (typeof $scope.ngModel === 'function') {
|
|
||||||
$scope.ngModel($scope.getterSetter.value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Watch for changes to both expressions
|
|
||||||
$scope.$watch("ngModel()", updateGetterSetter);
|
|
||||||
$scope.$watch("getterSetter.value", updateNgModel);
|
|
||||||
|
|
||||||
// Publish an assignable field into scope.
|
|
||||||
$scope.getterSetter = {};
|
|
||||||
|
|
||||||
|
// Update internal assignable state based on changes
|
||||||
|
// to the getter-setter function.
|
||||||
|
function updateGetterSetter() {
|
||||||
|
if (typeof $scope.ngModel === 'function') {
|
||||||
|
$scope.getterSetter.value = $scope.ngModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetterSetterController;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Update the external getter-setter based on changes
|
||||||
|
// to the assignable state.
|
||||||
|
function updateNgModel() {
|
||||||
|
if (typeof $scope.ngModel === 'function') {
|
||||||
|
$scope.ngModel($scope.getterSetter.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch for changes to both expressions
|
||||||
|
$scope.$watch("ngModel()", updateGetterSetter);
|
||||||
|
$scope.$watch("getterSetter.value", updateNgModel);
|
||||||
|
|
||||||
|
// Publish an assignable field into scope.
|
||||||
|
$scope.getterSetter = {};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export default GetterSetterController;
|
@ -23,97 +23,110 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining ObjectInspectorController. Created by shale on 08/21/2015.
|
* Module defining ObjectInspectorController. Created by shale on 08/21/2015.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The ObjectInspectorController gets and formats the data for
|
* Module defining ObjectInspectorController. Created by shale on 08/21/2015.
|
||||||
* the inspector display
|
*/
|
||||||
*
|
function ObjectInspectorController($scope, objectService) {
|
||||||
* @constructor
|
$scope.primaryParents = [];
|
||||||
*/
|
$scope.contextutalParents = [];
|
||||||
function ObjectInspectorController($scope, objectService) {
|
//$scope.isLink = false;
|
||||||
$scope.primaryParents = [];
|
|
||||||
$scope.contextutalParents = [];
|
|
||||||
//$scope.isLink = false;
|
|
||||||
|
|
||||||
// Gets an array of the contextual parents/ancestors of the selected object
|
// Gets an array of the contextual parents/ancestors of the selected object
|
||||||
function getContextualPath() {
|
function getContextualPath() {
|
||||||
var currentObj = $scope.domainObject,
|
var currentObj = $scope.domainObject,
|
||||||
currentParent,
|
currentParent,
|
||||||
parents = [];
|
parents = [];
|
||||||
|
|
||||||
currentParent = currentObj
|
currentParent = currentObj
|
||||||
&& currentObj.hasCapability('context')
|
&& currentObj.hasCapability('context')
|
||||||
&& currentObj.getCapability('context').getParent();
|
&& currentObj.getCapability('context').getParent();
|
||||||
|
|
||||||
while (currentParent && currentParent.getModel().type !== 'root'
|
while (currentParent && currentParent.getModel().type !== 'root'
|
||||||
&& currentParent.hasCapability('context')) {
|
&& currentParent.hasCapability('context')) {
|
||||||
// Record this object
|
// Record this object
|
||||||
parents.unshift(currentParent);
|
parents.unshift(currentParent);
|
||||||
|
|
||||||
// Get the next one up the tree
|
// Get the next one up the tree
|
||||||
currentObj = currentParent;
|
currentObj = currentParent;
|
||||||
currentParent = currentObj.getCapability('context').getParent();
|
currentParent = currentObj.getCapability('context').getParent();
|
||||||
}
|
|
||||||
|
|
||||||
$scope.contextutalParents = parents;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets an array of the parents/ancestors of the selected object's
|
|
||||||
// primary location (locational of original non-link)
|
|
||||||
function getPrimaryPath(current) {
|
|
||||||
var location;
|
|
||||||
|
|
||||||
// If this the the initial call of this recursive function
|
|
||||||
if (!current) {
|
|
||||||
current = $scope.domainObject;
|
|
||||||
$scope.primaryParents = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
location = current.getModel().location;
|
|
||||||
|
|
||||||
if (location && location !== 'root') {
|
|
||||||
objectService.getObjects([location]).then(function (obj) {
|
|
||||||
var next = obj[location];
|
|
||||||
|
|
||||||
$scope.primaryParents.unshift(next);
|
|
||||||
getPrimaryPath(next);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the metadata for the selected object
|
|
||||||
function getMetadata() {
|
|
||||||
$scope.metadata = $scope.domainObject
|
|
||||||
&& $scope.domainObject.hasCapability('metadata')
|
|
||||||
&& $scope.domainObject.useCapability('metadata');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set scope variables when the selected object changes
|
|
||||||
$scope.$watch('domainObject', function () {
|
|
||||||
$scope.isLink = $scope.domainObject
|
|
||||||
&& $scope.domainObject.hasCapability('location')
|
|
||||||
&& $scope.domainObject.getCapability('location').isLink();
|
|
||||||
|
|
||||||
if ($scope.isLink) {
|
|
||||||
getPrimaryPath();
|
|
||||||
getContextualPath();
|
|
||||||
} else {
|
|
||||||
$scope.primaryParents = [];
|
|
||||||
getContextualPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
getMetadata();
|
|
||||||
});
|
|
||||||
|
|
||||||
var mutation = $scope.domainObject.getCapability('mutation');
|
|
||||||
var unlisten = mutation.listen(getMetadata);
|
|
||||||
$scope.$on('$destroy', unlisten);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ObjectInspectorController;
|
$scope.contextutalParents = parents;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Gets an array of the parents/ancestors of the selected object's
|
||||||
|
// primary location (locational of original non-link)
|
||||||
|
function getPrimaryPath(current) {
|
||||||
|
var location;
|
||||||
|
|
||||||
|
// If this the the initial call of this recursive function
|
||||||
|
if (!current) {
|
||||||
|
current = $scope.domainObject;
|
||||||
|
$scope.primaryParents = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
location = current.getModel().location;
|
||||||
|
|
||||||
|
if (location && location !== 'root') {
|
||||||
|
objectService.getObjects([location]).then(function (obj) {
|
||||||
|
var next = obj[location];
|
||||||
|
|
||||||
|
$scope.primaryParents.unshift(next);
|
||||||
|
getPrimaryPath(next);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the metadata for the selected object
|
||||||
|
function getMetadata() {
|
||||||
|
$scope.metadata = $scope.domainObject
|
||||||
|
&& $scope.domainObject.hasCapability('metadata')
|
||||||
|
&& $scope.domainObject.useCapability('metadata');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set scope variables when the selected object changes
|
||||||
|
$scope.$watch('domainObject', function () {
|
||||||
|
$scope.isLink = $scope.domainObject
|
||||||
|
&& $scope.domainObject.hasCapability('location')
|
||||||
|
&& $scope.domainObject.getCapability('location').isLink();
|
||||||
|
|
||||||
|
if ($scope.isLink) {
|
||||||
|
getPrimaryPath();
|
||||||
|
getContextualPath();
|
||||||
|
} else {
|
||||||
|
$scope.primaryParents = [];
|
||||||
|
getContextualPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
getMetadata();
|
||||||
|
});
|
||||||
|
|
||||||
|
var mutation = $scope.domainObject.getCapability('mutation');
|
||||||
|
var unlisten = mutation.listen(getMetadata);
|
||||||
|
$scope.$on('$destroy', unlisten);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ObjectInspectorController;
|
@ -20,145 +20,161 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
var ROOT_ID = "ROOT";
|
var ROOT_ID = "ROOT";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for the domain object selector control.
|
* Controller for the domain object selector control.
|
||||||
* @memberof platform/commonUI/general
|
* @memberof platform/commonUI/general
|
||||||
* @constructor
|
* @constructor
|
||||||
* @param {ObjectService} objectService service from which to
|
* @param {ObjectService} objectService service from which to
|
||||||
* read domain objects
|
* read domain objects
|
||||||
* @param $scope Angular scope for this controller
|
* @param $scope Angular scope for this controller
|
||||||
*/
|
*/
|
||||||
function SelectorController(objectService, $scope) {
|
function SelectorController(objectService, $scope) {
|
||||||
var treeModel = {},
|
var treeModel = {},
|
||||||
listModel = {},
|
listModel = {},
|
||||||
previousSelected,
|
previousSelected,
|
||||||
self = this;
|
self = this;
|
||||||
|
|
||||||
// For watch; look at the user's selection in the tree
|
// For watch; look at the user's selection in the tree
|
||||||
function getTreeSelection() {
|
function getTreeSelection() {
|
||||||
return treeModel.selectedObject;
|
return treeModel.selectedObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store root object for subsequent exposure to template
|
// Store root object for subsequent exposure to template
|
||||||
function storeRoot(objects) {
|
function storeRoot(objects) {
|
||||||
self.rootObject = objects[ROOT_ID];
|
self.rootObject = objects[ROOT_ID];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that a selection is of the valid type
|
// Check that a selection is of the valid type
|
||||||
function validateTreeSelection(selectedObject) {
|
function validateTreeSelection(selectedObject) {
|
||||||
var type = selectedObject
|
var type = selectedObject
|
||||||
&& selectedObject.getCapability('type');
|
&& selectedObject.getCapability('type');
|
||||||
|
|
||||||
// Delegate type-checking to the capability...
|
// Delegate type-checking to the capability...
|
||||||
if (!type || !type.instanceOf($scope.structure.type)) {
|
if (!type || !type.instanceOf($scope.structure.type)) {
|
||||||
treeModel.selectedObject = previousSelected;
|
treeModel.selectedObject = previousSelected;
|
||||||
}
|
|
||||||
|
|
||||||
// Track current selection to restore it if an invalid
|
|
||||||
// selection is made later.
|
|
||||||
previousSelected = treeModel.selectedObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the right-hand list of currently-selected objects
|
|
||||||
function updateList(ids) {
|
|
||||||
function updateSelectedObjects(objects) {
|
|
||||||
// Look up from the
|
|
||||||
function getObject(id) {
|
|
||||||
return objects[id];
|
|
||||||
}
|
|
||||||
|
|
||||||
self.selectedObjects =
|
|
||||||
ids.filter(getObject).map(getObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up objects by id, then populate right-hand list
|
|
||||||
objectService.getObjects(ids).then(updateSelectedObjects);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reject attempts to select objects of the wrong type
|
|
||||||
$scope.$watch(getTreeSelection, validateTreeSelection);
|
|
||||||
|
|
||||||
// Make sure right-hand list matches underlying model
|
|
||||||
$scope.$watchCollection(function () {
|
|
||||||
return self.getField();
|
|
||||||
}, updateList);
|
|
||||||
|
|
||||||
// Look up root object, then store it
|
|
||||||
objectService.getObjects([ROOT_ID]).then(storeRoot);
|
|
||||||
|
|
||||||
this.$scope = $scope;
|
|
||||||
this.selectedObjects = [];
|
|
||||||
|
|
||||||
// Expose tree/list model for use in template directly
|
|
||||||
this.treeModel = treeModel;
|
|
||||||
this.listModel = listModel;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the value of the field being edited
|
// Track current selection to restore it if an invalid
|
||||||
SelectorController.prototype.setField = function (value) {
|
// selection is made later.
|
||||||
this.$scope.ngModel[this.$scope.field] = value;
|
previousSelected = treeModel.selectedObject;
|
||||||
};
|
|
||||||
|
|
||||||
// Get the value of the field being edited
|
|
||||||
SelectorController.prototype.getField = function () {
|
|
||||||
return this.$scope.ngModel[this.$scope.field] || [];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the root object to show in the left-hand tree.
|
|
||||||
* @returns {DomainObject} the root object
|
|
||||||
*/
|
|
||||||
SelectorController.prototype.root = function () {
|
|
||||||
return this.rootObject;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a domain object to the list of selected objects.
|
|
||||||
* @param {DomainObject} the domain object to select
|
|
||||||
*/
|
|
||||||
SelectorController.prototype.select = function (domainObject) {
|
|
||||||
var id = domainObject && domainObject.getId(),
|
|
||||||
list = this.getField() || [];
|
|
||||||
// Only select if we have a valid id,
|
|
||||||
// and it isn't already selected
|
|
||||||
if (id && list.indexOf(id) === -1) {
|
|
||||||
this.setField(list.concat([id]));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a domain object from the list of selected objects.
|
|
||||||
* @param {DomainObject} the domain object to select
|
|
||||||
*/
|
|
||||||
SelectorController.prototype.deselect = function (domainObject) {
|
|
||||||
var id = domainObject && domainObject.getId(),
|
|
||||||
list = this.getField() || [];
|
|
||||||
// Only change if this was a valid id,
|
|
||||||
// for an object which was already selected
|
|
||||||
if (id && list.indexOf(id) !== -1) {
|
|
||||||
// Filter it out of the current field
|
|
||||||
this.setField(list.filter(function (otherId) {
|
|
||||||
return otherId !== id;
|
|
||||||
}));
|
|
||||||
// Clear the current list selection
|
|
||||||
delete this.listModel.selectedObject;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the currently-selected domain objects.
|
|
||||||
* @returns {DomainObject[]} the current selection
|
|
||||||
*/
|
|
||||||
SelectorController.prototype.selected = function () {
|
|
||||||
return this.selectedObjects;
|
|
||||||
};
|
|
||||||
|
|
||||||
return SelectorController;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Update the right-hand list of currently-selected objects
|
||||||
|
function updateList(ids) {
|
||||||
|
function updateSelectedObjects(objects) {
|
||||||
|
// Look up from the
|
||||||
|
function getObject(id) {
|
||||||
|
return objects[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.selectedObjects =
|
||||||
|
ids.filter(getObject).map(getObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look up objects by id, then populate right-hand list
|
||||||
|
objectService.getObjects(ids).then(updateSelectedObjects);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reject attempts to select objects of the wrong type
|
||||||
|
$scope.$watch(getTreeSelection, validateTreeSelection);
|
||||||
|
|
||||||
|
// Make sure right-hand list matches underlying model
|
||||||
|
$scope.$watchCollection(function () {
|
||||||
|
return self.getField();
|
||||||
|
}, updateList);
|
||||||
|
|
||||||
|
// Look up root object, then store it
|
||||||
|
objectService.getObjects([ROOT_ID]).then(storeRoot);
|
||||||
|
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.selectedObjects = [];
|
||||||
|
|
||||||
|
// Expose tree/list model for use in template directly
|
||||||
|
this.treeModel = treeModel;
|
||||||
|
this.listModel = listModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the value of the field being edited
|
||||||
|
SelectorController.prototype.setField = function (value) {
|
||||||
|
this.$scope.ngModel[this.$scope.field] = value;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get the value of the field being edited
|
||||||
|
SelectorController.prototype.getField = function () {
|
||||||
|
return this.$scope.ngModel[this.$scope.field] || [];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the root object to show in the left-hand tree.
|
||||||
|
* @returns {DomainObject} the root object
|
||||||
|
*/
|
||||||
|
SelectorController.prototype.root = function () {
|
||||||
|
return this.rootObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a domain object to the list of selected objects.
|
||||||
|
* @param {DomainObject} the domain object to select
|
||||||
|
*/
|
||||||
|
SelectorController.prototype.select = function (domainObject) {
|
||||||
|
var id = domainObject && domainObject.getId(),
|
||||||
|
list = this.getField() || [];
|
||||||
|
// Only select if we have a valid id,
|
||||||
|
// and it isn't already selected
|
||||||
|
if (id && list.indexOf(id) === -1) {
|
||||||
|
this.setField(list.concat([id]));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove a domain object from the list of selected objects.
|
||||||
|
* @param {DomainObject} the domain object to select
|
||||||
|
*/
|
||||||
|
SelectorController.prototype.deselect = function (domainObject) {
|
||||||
|
var id = domainObject && domainObject.getId(),
|
||||||
|
list = this.getField() || [];
|
||||||
|
// Only change if this was a valid id,
|
||||||
|
// for an object which was already selected
|
||||||
|
if (id && list.indexOf(id) !== -1) {
|
||||||
|
// Filter it out of the current field
|
||||||
|
this.setField(list.filter(function (otherId) {
|
||||||
|
return otherId !== id;
|
||||||
|
}));
|
||||||
|
// Clear the current list selection
|
||||||
|
delete this.listModel.selectedObject;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the currently-selected domain objects.
|
||||||
|
* @returns {DomainObject[]} the current selection
|
||||||
|
*/
|
||||||
|
SelectorController.prototype.selected = function () {
|
||||||
|
return this.selectedObjects;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SelectorController;
|
@ -20,294 +20,311 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define([
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
], function () {
|
var TICK_SPACING_PX = 150;
|
||||||
|
|
||||||
var TICK_SPACING_PX = 150;
|
/* format number as percent; 0.0-1.0 to "0%"-"100%" */
|
||||||
|
function toPercent(p) {
|
||||||
|
return (100 * p) + "%";
|
||||||
|
}
|
||||||
|
|
||||||
/* format number as percent; 0.0-1.0 to "0%"-"100%" */
|
function clamp(value, low, high) {
|
||||||
function toPercent(p) {
|
return Math.max(low, Math.min(high, value));
|
||||||
return (100 * p) + "%";
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function clamp(value, low, high) {
|
function copyBounds(bounds) {
|
||||||
return Math.max(low, Math.min(high, value));
|
return {
|
||||||
}
|
start: bounds.start,
|
||||||
|
end: bounds.end
|
||||||
function copyBounds(bounds) {
|
|
||||||
return {
|
|
||||||
start: bounds.start,
|
|
||||||
end: bounds.end
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Controller used by the `time-controller` template.
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @constructor
|
|
||||||
* @param $scope the Angular scope for this controller
|
|
||||||
* @param {FormatService} formatService the service to user to format
|
|
||||||
* domain values
|
|
||||||
* @param {string} defaultFormat the format to request when no
|
|
||||||
* format has been otherwise specified
|
|
||||||
* @param {Function} now a function to return current system time
|
|
||||||
*/
|
|
||||||
function TimeRangeController($scope, $timeout, formatService, defaultFormat, now) {
|
|
||||||
this.$scope = $scope;
|
|
||||||
this.formatService = formatService;
|
|
||||||
this.defaultFormat = defaultFormat;
|
|
||||||
this.now = now;
|
|
||||||
|
|
||||||
this.tickCount = 2;
|
|
||||||
this.innerMinimumSpan = 1000; // 1 second
|
|
||||||
this.outerMinimumSpan = 1000; // 1 second
|
|
||||||
this.initialDragValue = undefined;
|
|
||||||
this.formatter = formatService.getFormat(defaultFormat);
|
|
||||||
this.formStartChanged = false;
|
|
||||||
this.formEndChanged = false;
|
|
||||||
this.$timeout = $timeout;
|
|
||||||
|
|
||||||
this.$scope.ticks = [];
|
|
||||||
|
|
||||||
this.updateViewFromModel(this.$scope.ngModel);
|
|
||||||
this.updateFormModel();
|
|
||||||
|
|
||||||
[
|
|
||||||
'updateViewFromModel',
|
|
||||||
'updateSpanWidth',
|
|
||||||
'updateOuterStart',
|
|
||||||
'updateOuterEnd',
|
|
||||||
'updateFormat',
|
|
||||||
'validateStart',
|
|
||||||
'validateEnd',
|
|
||||||
'onFormStartChange',
|
|
||||||
'onFormEndChange'
|
|
||||||
].forEach(function (boundFn) {
|
|
||||||
this[boundFn] = this[boundFn].bind(this);
|
|
||||||
}, this);
|
|
||||||
|
|
||||||
this.$scope.$watchCollection("ngModel", this.updateViewFromModel);
|
|
||||||
this.$scope.$watch("spanWidth", this.updateSpanWidth);
|
|
||||||
this.$scope.$watch("ngModel.outer.start", this.updateOuterStart);
|
|
||||||
this.$scope.$watch("ngModel.outer.end", this.updateOuterEnd);
|
|
||||||
this.$scope.$watch("parameters.format", this.updateFormat);
|
|
||||||
this.$scope.$watch("formModel.start", this.onFormStartChange);
|
|
||||||
this.$scope.$watch("formModel.end", this.onFormEndChange);
|
|
||||||
}
|
|
||||||
|
|
||||||
TimeRangeController.prototype.formatTimestamp = function (ts) {
|
|
||||||
return this.formatter.format(ts);
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
TimeRangeController.prototype.updateTicks = function () {
|
/**
|
||||||
var i, p, ts, start, end, span;
|
* Controller used by the `time-controller` template.
|
||||||
end = this.$scope.ngModel.outer.end;
|
* @memberof platform/commonUI/general
|
||||||
start = this.$scope.ngModel.outer.start;
|
* @constructor
|
||||||
span = end - start;
|
* @param $scope the Angular scope for this controller
|
||||||
this.$scope.ticks = [];
|
* @param {FormatService} formatService the service to user to format
|
||||||
for (i = 0; i < this.tickCount; i += 1) {
|
* domain values
|
||||||
p = i / (this.tickCount - 1);
|
* @param {string} defaultFormat the format to request when no
|
||||||
ts = p * span + start;
|
* format has been otherwise specified
|
||||||
this.$scope.ticks.push(this.formatTimestamp(ts));
|
* @param {Function} now a function to return current system time
|
||||||
|
*/
|
||||||
|
function TimeRangeController($scope, $timeout, formatService, defaultFormat, now) {
|
||||||
|
this.$scope = $scope;
|
||||||
|
this.formatService = formatService;
|
||||||
|
this.defaultFormat = defaultFormat;
|
||||||
|
this.now = now;
|
||||||
|
|
||||||
|
this.tickCount = 2;
|
||||||
|
this.innerMinimumSpan = 1000; // 1 second
|
||||||
|
this.outerMinimumSpan = 1000; // 1 second
|
||||||
|
this.initialDragValue = undefined;
|
||||||
|
this.formatter = formatService.getFormat(defaultFormat);
|
||||||
|
this.formStartChanged = false;
|
||||||
|
this.formEndChanged = false;
|
||||||
|
this.$timeout = $timeout;
|
||||||
|
|
||||||
|
this.$scope.ticks = [];
|
||||||
|
|
||||||
|
this.updateViewFromModel(this.$scope.ngModel);
|
||||||
|
this.updateFormModel();
|
||||||
|
|
||||||
|
[
|
||||||
|
'updateViewFromModel',
|
||||||
|
'updateSpanWidth',
|
||||||
|
'updateOuterStart',
|
||||||
|
'updateOuterEnd',
|
||||||
|
'updateFormat',
|
||||||
|
'validateStart',
|
||||||
|
'validateEnd',
|
||||||
|
'onFormStartChange',
|
||||||
|
'onFormEndChange'
|
||||||
|
].forEach(function (boundFn) {
|
||||||
|
this[boundFn] = this[boundFn].bind(this);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
this.$scope.$watchCollection("ngModel", this.updateViewFromModel);
|
||||||
|
this.$scope.$watch("spanWidth", this.updateSpanWidth);
|
||||||
|
this.$scope.$watch("ngModel.outer.start", this.updateOuterStart);
|
||||||
|
this.$scope.$watch("ngModel.outer.end", this.updateOuterEnd);
|
||||||
|
this.$scope.$watch("parameters.format", this.updateFormat);
|
||||||
|
this.$scope.$watch("formModel.start", this.onFormStartChange);
|
||||||
|
this.$scope.$watch("formModel.end", this.onFormEndChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
TimeRangeController.prototype.formatTimestamp = function (ts) {
|
||||||
|
return this.formatter.format(ts);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateTicks = function () {
|
||||||
|
var i, p, ts, start, end, span;
|
||||||
|
end = this.$scope.ngModel.outer.end;
|
||||||
|
start = this.$scope.ngModel.outer.start;
|
||||||
|
span = end - start;
|
||||||
|
this.$scope.ticks = [];
|
||||||
|
for (i = 0; i < this.tickCount; i += 1) {
|
||||||
|
p = i / (this.tickCount - 1);
|
||||||
|
ts = p * span + start;
|
||||||
|
this.$scope.ticks.push(this.formatTimestamp(ts));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateSpanWidth = function (w) {
|
||||||
|
this.tickCount = Math.max(Math.floor(w / TICK_SPACING_PX), 2);
|
||||||
|
this.updateTicks();
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateViewForInnerSpanFromModel = function (
|
||||||
|
ngModel
|
||||||
|
) {
|
||||||
|
var span = ngModel.outer.end - ngModel.outer.start;
|
||||||
|
|
||||||
|
// Expose readable dates for the knobs
|
||||||
|
this.$scope.startInnerText = this.formatTimestamp(ngModel.inner.start);
|
||||||
|
this.$scope.endInnerText = this.formatTimestamp(ngModel.inner.end);
|
||||||
|
|
||||||
|
// And positions for the knobs
|
||||||
|
this.$scope.startInnerPct =
|
||||||
|
toPercent((ngModel.inner.start - ngModel.outer.start) / span);
|
||||||
|
this.$scope.endInnerPct =
|
||||||
|
toPercent((ngModel.outer.end - ngModel.inner.end) / span);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.defaultBounds = function () {
|
||||||
|
var t = this.now();
|
||||||
|
|
||||||
|
return {
|
||||||
|
start: t - 24 * 3600 * 1000, // One day
|
||||||
|
end: t
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateViewFromModel = function (ngModel) {
|
||||||
|
ngModel = ngModel || {};
|
||||||
|
ngModel.outer = ngModel.outer || this.defaultBounds();
|
||||||
|
ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
|
||||||
|
|
||||||
|
// Stick it back is scope (in case we just set defaults)
|
||||||
|
this.$scope.ngModel = ngModel;
|
||||||
|
|
||||||
|
this.updateViewForInnerSpanFromModel(ngModel);
|
||||||
|
this.updateTicks();
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.startLeftDrag = function () {
|
||||||
|
this.initialDragValue = this.$scope.ngModel.inner.start;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.startRightDrag = function () {
|
||||||
|
this.initialDragValue = this.$scope.ngModel.inner.end;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.startMiddleDrag = function () {
|
||||||
|
this.initialDragValue = {
|
||||||
|
start: this.$scope.ngModel.inner.start,
|
||||||
|
end: this.$scope.ngModel.inner.end
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.toMillis = function (pixels) {
|
||||||
|
var span =
|
||||||
|
this.$scope.ngModel.outer.end - this.$scope.ngModel.outer.start;
|
||||||
|
|
||||||
|
return (pixels / this.$scope.spanWidth) * span;
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.leftDrag = function (pixels) {
|
||||||
|
var delta = this.toMillis(pixels);
|
||||||
|
this.$scope.ngModel.inner.start = clamp(
|
||||||
|
this.initialDragValue + delta,
|
||||||
|
this.$scope.ngModel.outer.start,
|
||||||
|
this.$scope.ngModel.inner.end - this.innerMinimumSpan
|
||||||
|
);
|
||||||
|
this.updateViewFromModel(this.$scope.ngModel);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.rightDrag = function (pixels) {
|
||||||
|
var delta = this.toMillis(pixels);
|
||||||
|
this.$scope.ngModel.inner.end = clamp(
|
||||||
|
this.initialDragValue + delta,
|
||||||
|
this.$scope.ngModel.inner.start + this.innerMinimumSpan,
|
||||||
|
this.$scope.ngModel.outer.end
|
||||||
|
);
|
||||||
|
this.updateViewFromModel(this.$scope.ngModel);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.middleDrag = function (pixels) {
|
||||||
|
var delta = this.toMillis(pixels),
|
||||||
|
edge = delta < 0 ? 'start' : 'end',
|
||||||
|
opposite = delta < 0 ? 'end' : 'start';
|
||||||
|
|
||||||
|
// Adjust the position of the edge in the direction of drag
|
||||||
|
this.$scope.ngModel.inner[edge] = clamp(
|
||||||
|
this.initialDragValue[edge] + delta,
|
||||||
|
this.$scope.ngModel.outer.start,
|
||||||
|
this.$scope.ngModel.outer.end
|
||||||
|
);
|
||||||
|
// Adjust opposite knob to maintain span
|
||||||
|
this.$scope.ngModel.inner[opposite] =
|
||||||
|
this.$scope.ngModel.inner[edge]
|
||||||
|
+ this.initialDragValue[opposite]
|
||||||
|
- this.initialDragValue[edge];
|
||||||
|
|
||||||
|
this.updateViewFromModel(this.$scope.ngModel);
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateFormModel = function () {
|
||||||
|
this.$scope.formModel = {
|
||||||
|
start: ((this.$scope.ngModel || {}).outer || {}).start,
|
||||||
|
end: ((this.$scope.ngModel || {}).outer || {}).end
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateOuterStart = function () {
|
||||||
|
var ngModel = this.$scope.ngModel;
|
||||||
|
|
||||||
|
ngModel.inner.start =
|
||||||
|
Math.max(ngModel.outer.start, ngModel.inner.start);
|
||||||
|
ngModel.inner.end = Math.max(
|
||||||
|
ngModel.inner.start + this.innerMinimumSpan,
|
||||||
|
ngModel.inner.end
|
||||||
|
);
|
||||||
|
|
||||||
|
this.updateFormModel();
|
||||||
|
this.updateViewForInnerSpanFromModel(ngModel);
|
||||||
|
this.updateTicks();
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateOuterEnd = function () {
|
||||||
|
var ngModel = this.$scope.ngModel;
|
||||||
|
|
||||||
|
ngModel.inner.end =
|
||||||
|
Math.min(ngModel.outer.end, ngModel.inner.end);
|
||||||
|
ngModel.inner.start = Math.min(
|
||||||
|
ngModel.inner.end - this.innerMinimumSpan,
|
||||||
|
ngModel.inner.start
|
||||||
|
);
|
||||||
|
|
||||||
|
this.updateFormModel();
|
||||||
|
this.updateViewForInnerSpanFromModel(ngModel);
|
||||||
|
this.updateTicks();
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateFormat = function (key) {
|
||||||
|
this.formatter = this.formatService.getFormat(key || this.defaultFormat);
|
||||||
|
this.updateViewForInnerSpanFromModel(this.$scope.ngModel);
|
||||||
|
this.updateTicks();
|
||||||
|
};
|
||||||
|
|
||||||
|
TimeRangeController.prototype.updateBoundsFromForm = function () {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
//Allow Angular to trigger watches and determine whether values have changed.
|
||||||
|
this.$timeout(function () {
|
||||||
|
if (self.formStartChanged) {
|
||||||
|
self.$scope.ngModel.outer.start =
|
||||||
|
self.$scope.ngModel.inner.start =
|
||||||
|
self.$scope.formModel.start;
|
||||||
|
self.formStartChanged = false;
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.updateSpanWidth = function (w) {
|
if (self.formEndChanged) {
|
||||||
this.tickCount = Math.max(Math.floor(w / TICK_SPACING_PX), 2);
|
self.$scope.ngModel.outer.end =
|
||||||
this.updateTicks();
|
self.$scope.ngModel.inner.end =
|
||||||
};
|
self.$scope.formModel.end;
|
||||||
|
self.formEndChanged = false;
|
||||||
TimeRangeController.prototype.updateViewForInnerSpanFromModel = function (
|
|
||||||
ngModel
|
|
||||||
) {
|
|
||||||
var span = ngModel.outer.end - ngModel.outer.start;
|
|
||||||
|
|
||||||
// Expose readable dates for the knobs
|
|
||||||
this.$scope.startInnerText = this.formatTimestamp(ngModel.inner.start);
|
|
||||||
this.$scope.endInnerText = this.formatTimestamp(ngModel.inner.end);
|
|
||||||
|
|
||||||
// And positions for the knobs
|
|
||||||
this.$scope.startInnerPct =
|
|
||||||
toPercent((ngModel.inner.start - ngModel.outer.start) / span);
|
|
||||||
this.$scope.endInnerPct =
|
|
||||||
toPercent((ngModel.outer.end - ngModel.inner.end) / span);
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.defaultBounds = function () {
|
|
||||||
var t = this.now();
|
|
||||||
|
|
||||||
return {
|
|
||||||
start: t - 24 * 3600 * 1000, // One day
|
|
||||||
end: t
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.updateViewFromModel = function (ngModel) {
|
|
||||||
ngModel = ngModel || {};
|
|
||||||
ngModel.outer = ngModel.outer || this.defaultBounds();
|
|
||||||
ngModel.inner = ngModel.inner || copyBounds(ngModel.outer);
|
|
||||||
|
|
||||||
// Stick it back is scope (in case we just set defaults)
|
|
||||||
this.$scope.ngModel = ngModel;
|
|
||||||
|
|
||||||
this.updateViewForInnerSpanFromModel(ngModel);
|
|
||||||
this.updateTicks();
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.startLeftDrag = function () {
|
|
||||||
this.initialDragValue = this.$scope.ngModel.inner.start;
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.startRightDrag = function () {
|
|
||||||
this.initialDragValue = this.$scope.ngModel.inner.end;
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.startMiddleDrag = function () {
|
|
||||||
this.initialDragValue = {
|
|
||||||
start: this.$scope.ngModel.inner.start,
|
|
||||||
end: this.$scope.ngModel.inner.end
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.toMillis = function (pixels) {
|
|
||||||
var span =
|
|
||||||
this.$scope.ngModel.outer.end - this.$scope.ngModel.outer.start;
|
|
||||||
|
|
||||||
return (pixels / this.$scope.spanWidth) * span;
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.leftDrag = function (pixels) {
|
|
||||||
var delta = this.toMillis(pixels);
|
|
||||||
this.$scope.ngModel.inner.start = clamp(
|
|
||||||
this.initialDragValue + delta,
|
|
||||||
this.$scope.ngModel.outer.start,
|
|
||||||
this.$scope.ngModel.inner.end - this.innerMinimumSpan
|
|
||||||
);
|
|
||||||
this.updateViewFromModel(this.$scope.ngModel);
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.rightDrag = function (pixels) {
|
|
||||||
var delta = this.toMillis(pixels);
|
|
||||||
this.$scope.ngModel.inner.end = clamp(
|
|
||||||
this.initialDragValue + delta,
|
|
||||||
this.$scope.ngModel.inner.start + this.innerMinimumSpan,
|
|
||||||
this.$scope.ngModel.outer.end
|
|
||||||
);
|
|
||||||
this.updateViewFromModel(this.$scope.ngModel);
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.middleDrag = function (pixels) {
|
|
||||||
var delta = this.toMillis(pixels),
|
|
||||||
edge = delta < 0 ? 'start' : 'end',
|
|
||||||
opposite = delta < 0 ? 'end' : 'start';
|
|
||||||
|
|
||||||
// Adjust the position of the edge in the direction of drag
|
|
||||||
this.$scope.ngModel.inner[edge] = clamp(
|
|
||||||
this.initialDragValue[edge] + delta,
|
|
||||||
this.$scope.ngModel.outer.start,
|
|
||||||
this.$scope.ngModel.outer.end
|
|
||||||
);
|
|
||||||
// Adjust opposite knob to maintain span
|
|
||||||
this.$scope.ngModel.inner[opposite] =
|
|
||||||
this.$scope.ngModel.inner[edge]
|
|
||||||
+ this.initialDragValue[opposite]
|
|
||||||
- this.initialDragValue[edge];
|
|
||||||
|
|
||||||
this.updateViewFromModel(this.$scope.ngModel);
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.updateFormModel = function () {
|
|
||||||
this.$scope.formModel = {
|
|
||||||
start: ((this.$scope.ngModel || {}).outer || {}).start,
|
|
||||||
end: ((this.$scope.ngModel || {}).outer || {}).end
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.updateOuterStart = function () {
|
|
||||||
var ngModel = this.$scope.ngModel;
|
|
||||||
|
|
||||||
ngModel.inner.start =
|
|
||||||
Math.max(ngModel.outer.start, ngModel.inner.start);
|
|
||||||
ngModel.inner.end = Math.max(
|
|
||||||
ngModel.inner.start + this.innerMinimumSpan,
|
|
||||||
ngModel.inner.end
|
|
||||||
);
|
|
||||||
|
|
||||||
this.updateFormModel();
|
|
||||||
this.updateViewForInnerSpanFromModel(ngModel);
|
|
||||||
this.updateTicks();
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.updateOuterEnd = function () {
|
|
||||||
var ngModel = this.$scope.ngModel;
|
|
||||||
|
|
||||||
ngModel.inner.end =
|
|
||||||
Math.min(ngModel.outer.end, ngModel.inner.end);
|
|
||||||
ngModel.inner.start = Math.min(
|
|
||||||
ngModel.inner.end - this.innerMinimumSpan,
|
|
||||||
ngModel.inner.start
|
|
||||||
);
|
|
||||||
|
|
||||||
this.updateFormModel();
|
|
||||||
this.updateViewForInnerSpanFromModel(ngModel);
|
|
||||||
this.updateTicks();
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.updateFormat = function (key) {
|
|
||||||
this.formatter = this.formatService.getFormat(key || this.defaultFormat);
|
|
||||||
this.updateViewForInnerSpanFromModel(this.$scope.ngModel);
|
|
||||||
this.updateTicks();
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.updateBoundsFromForm = function () {
|
|
||||||
var self = this;
|
|
||||||
|
|
||||||
//Allow Angular to trigger watches and determine whether values have changed.
|
|
||||||
this.$timeout(function () {
|
|
||||||
if (self.formStartChanged) {
|
|
||||||
self.$scope.ngModel.outer.start =
|
|
||||||
self.$scope.ngModel.inner.start =
|
|
||||||
self.$scope.formModel.start;
|
|
||||||
self.formStartChanged = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (self.formEndChanged) {
|
|
||||||
self.$scope.ngModel.outer.end =
|
|
||||||
self.$scope.ngModel.inner.end =
|
|
||||||
self.$scope.formModel.end;
|
|
||||||
self.formEndChanged = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
TimeRangeController.prototype.onFormStartChange = function (
|
|
||||||
newValue,
|
|
||||||
oldValue
|
|
||||||
) {
|
|
||||||
if (!this.formStartChanged && newValue !== oldValue) {
|
|
||||||
this.formStartChanged = true;
|
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
};
|
||||||
|
|
||||||
TimeRangeController.prototype.onFormEndChange = function (
|
TimeRangeController.prototype.onFormStartChange = function (
|
||||||
newValue,
|
newValue,
|
||||||
oldValue
|
oldValue
|
||||||
) {
|
) {
|
||||||
if (!this.formEndChanged && newValue !== oldValue) {
|
if (!this.formStartChanged && newValue !== oldValue) {
|
||||||
this.formEndChanged = true;
|
this.formStartChanged = true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TimeRangeController.prototype.validateStart = function (startValue) {
|
TimeRangeController.prototype.onFormEndChange = function (
|
||||||
return startValue
|
newValue,
|
||||||
<= this.$scope.formModel.end - this.outerMinimumSpan;
|
oldValue
|
||||||
};
|
) {
|
||||||
|
if (!this.formEndChanged && newValue !== oldValue) {
|
||||||
|
this.formEndChanged = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
TimeRangeController.prototype.validateEnd = function (endValue) {
|
TimeRangeController.prototype.validateStart = function (startValue) {
|
||||||
return endValue
|
return startValue
|
||||||
>= this.$scope.formModel.start + this.outerMinimumSpan;
|
<= this.$scope.formModel.end - this.outerMinimumSpan;
|
||||||
};
|
};
|
||||||
|
|
||||||
return TimeRangeController;
|
TimeRangeController.prototype.validateEnd = function (endValue) {
|
||||||
});
|
return endValue
|
||||||
|
>= this.$scope.formModel.start + this.outerMinimumSpan;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TimeRangeController;
|
@ -20,47 +20,56 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function ToggleController() {
|
||||||
* A ToggleController is used to activate/deactivate things.
|
this.state = false;
|
||||||
* A common usage is for "twistie"
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function ToggleController() {
|
|
||||||
this.state = false;
|
|
||||||
|
|
||||||
this.setState = this.setState.bind(this);
|
this.setState = this.setState.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the current state of the toggle.
|
* Get the current state of the toggle.
|
||||||
* @return {boolean} true if active
|
* @return {boolean} true if active
|
||||||
*/
|
*/
|
||||||
ToggleController.prototype.isActive = function () {
|
ToggleController.prototype.isActive = function () {
|
||||||
return this.state;
|
return this.state;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a new state for the toggle.
|
* Set a new state for the toggle.
|
||||||
* @return {boolean} true to activate
|
* @return {boolean} true to activate
|
||||||
*/
|
*/
|
||||||
ToggleController.prototype.setState = function (newState) {
|
ToggleController.prototype.setState = function (newState) {
|
||||||
this.state = newState;
|
this.state = newState;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle the current state; activate if it is inactive,
|
* Toggle the current state; activate if it is inactive,
|
||||||
* deactivate if it is active.
|
* deactivate if it is active.
|
||||||
*/
|
*/
|
||||||
ToggleController.prototype.toggle = function () {
|
ToggleController.prototype.toggle = function () {
|
||||||
this.state = !this.state;
|
this.state = !this.state;
|
||||||
};
|
};
|
||||||
|
|
||||||
return ToggleController;
|
export default ToggleController;
|
||||||
}
|
|
||||||
);
|
|
@ -23,182 +23,170 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining TreeNodeController. Created by vwoeltje on 11/10/14.
|
* Module defining TreeNodeController. Created by vwoeltje on 11/10/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The TreeNodeController supports the tree node representation;
|
* Module defining TreeNodeController. Created by vwoeltje on 11/10/14.
|
||||||
* a tree node has a label for the current object as well as a
|
*/
|
||||||
* subtree which shows (and is not loaded until) the node is
|
function TreeNodeController($scope, $timeout) {
|
||||||
* expanded.
|
var self = this,
|
||||||
*
|
selectedObject = ($scope.ngModel || {}).selectedObject;
|
||||||
* This controller tracks the following, so that the tree node
|
|
||||||
* template may update its state accordingly:
|
|
||||||
*
|
|
||||||
* * Whether or not the tree node has ever been expanded (this
|
|
||||||
* is used to lazily load, exactly once, the subtree)
|
|
||||||
* * Whether or not the node is currently the domain object
|
|
||||||
* of navigation (this gets highlighted differently to
|
|
||||||
* provide the user with visual feedback.)
|
|
||||||
*
|
|
||||||
* Additionally, this controller will automatically trigger
|
|
||||||
* node expansion when this tree node's _subtree_ will contain
|
|
||||||
* the navigated object (recursively, this becomes an
|
|
||||||
* expand-to-show-navigated-object behavior.)
|
|
||||||
*
|
|
||||||
* Finally, if a `callback` property is passed in through the
|
|
||||||
* `parameters` attribute of the `tree-node`, that callback
|
|
||||||
* will be invoked whenever a user clicks in a manner which
|
|
||||||
* would result in a selection. This callback is invoked
|
|
||||||
* even if the selection does not change (if you are only
|
|
||||||
* interested in changes, watch the `selectedObject` property
|
|
||||||
* of the object passed in `ng-model` instead.)
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function TreeNodeController($scope, $timeout) {
|
|
||||||
var self = this,
|
|
||||||
selectedObject = ($scope.ngModel || {}).selectedObject;
|
|
||||||
|
|
||||||
// Look up the id for a domain object. A convenience
|
// Look up the id for a domain object. A convenience
|
||||||
// for mapping; additionally does some undefined-checking.
|
// for mapping; additionally does some undefined-checking.
|
||||||
function getId(obj) {
|
function getId(obj) {
|
||||||
return obj && obj.getId && obj.getId();
|
return obj && obj.getId && obj.getId();
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that id paths are equivalent, staring at
|
|
||||||
// index, ending at the end of the node path.
|
|
||||||
function checkPath(nodePath, navPath, index) {
|
|
||||||
index = index || 0;
|
|
||||||
|
|
||||||
// The paths overlap if we have made it past the
|
|
||||||
// end of the node's path; otherwise, check the
|
|
||||||
// id at the current index for equality and perform
|
|
||||||
// a recursive step for subsequent ids in the paths,
|
|
||||||
// until we exceed path length or hit a mismatch.
|
|
||||||
return (index >= nodePath.length)
|
|
||||||
|| ((navPath[index] === nodePath[index])
|
|
||||||
&& checkPath(nodePath, navPath, index + 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consider the currently-navigated object and update
|
|
||||||
// parameters which support display.
|
|
||||||
function checkSelection() {
|
|
||||||
var nodeObject = $scope.domainObject,
|
|
||||||
navObject = selectedObject,
|
|
||||||
nodeContext = nodeObject
|
|
||||||
&& nodeObject.getCapability('context'),
|
|
||||||
navContext = navObject
|
|
||||||
&& navObject.getCapability('context'),
|
|
||||||
nodePath,
|
|
||||||
navPath;
|
|
||||||
|
|
||||||
// Deselect; we will reselect below, iff we are
|
|
||||||
// exactly at the end of the path.
|
|
||||||
self.isSelectedFlag = false;
|
|
||||||
|
|
||||||
// Expand if necessary (if the navigated object will
|
|
||||||
// be in this node's subtree)
|
|
||||||
if (nodeContext && navContext) {
|
|
||||||
// Get the paths as arrays of identifiers
|
|
||||||
nodePath = nodeContext.getPath().map(getId);
|
|
||||||
navPath = navContext.getPath().map(getId);
|
|
||||||
|
|
||||||
// Check to see if the node's path lies entirely
|
|
||||||
// within the navigation path; otherwise, navigation
|
|
||||||
// has happened in some other subtree.
|
|
||||||
if (navPath.length >= nodePath.length
|
|
||||||
&& checkPath(nodePath, navPath)) {
|
|
||||||
|
|
||||||
// nodePath is along the navPath; if it's
|
|
||||||
// at the end of the path, highlight;
|
|
||||||
// otherwise, expand.
|
|
||||||
if (nodePath.length === navPath.length) {
|
|
||||||
self.isSelectedFlag = true;
|
|
||||||
} else { // node path is shorter: Expand!
|
|
||||||
if ($scope.toggle) {
|
|
||||||
$scope.toggle.setState(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.trackExpansion();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Callback for the selection updates; track the currently
|
|
||||||
// navigated object and update display parameters as needed.
|
|
||||||
function setSelection(object) {
|
|
||||||
selectedObject = object;
|
|
||||||
checkSelection();
|
|
||||||
}
|
|
||||||
|
|
||||||
this.isSelectedFlag = false;
|
|
||||||
this.hasBeenExpandedFlag = false;
|
|
||||||
this.$timeout = $timeout;
|
|
||||||
this.$scope = $scope;
|
|
||||||
|
|
||||||
// Listen for changes which will effect display parameters
|
|
||||||
$scope.$watch("ngModel.selectedObject", setSelection);
|
|
||||||
$scope.$watch("domainObject", checkSelection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Select the domain object represented by this node in the tree.
|
|
||||||
* This will both update the `selectedObject` property in
|
|
||||||
* the object passed in via `ng-model`, and will fire any `callback`
|
|
||||||
* passed in via `parameters`.
|
|
||||||
*/
|
|
||||||
TreeNodeController.prototype.select = function () {
|
|
||||||
if (this.$scope.ngModel) {
|
|
||||||
this.$scope.ngModel.selectedObject =
|
|
||||||
this.$scope.domainObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((this.$scope.parameters || {}).callback) {
|
|
||||||
this.$scope.parameters.callback(this.$scope.domainObject);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method should be called when a node is expanded
|
|
||||||
* to record that this has occurred, to support one-time
|
|
||||||
* lazy loading of the node's subtree.
|
|
||||||
*/
|
|
||||||
TreeNodeController.prototype.trackExpansion = function () {
|
|
||||||
var self = this;
|
|
||||||
if (!self.hasBeenExpanded()) {
|
|
||||||
// Run on a timeout; if a lot of expansion needs to
|
|
||||||
// occur (e.g. if the selection is several nodes deep) we
|
|
||||||
// want this to be spread across multiple digest cycles.
|
|
||||||
self.$timeout(function () {
|
|
||||||
self.hasBeenExpandedFlag = true;
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if this not has ever been expanded.
|
|
||||||
* @returns true if it has been expanded
|
|
||||||
*/
|
|
||||||
TreeNodeController.prototype.hasBeenExpanded = function () {
|
|
||||||
return this.hasBeenExpandedFlag;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check whether or not the domain object represented by
|
|
||||||
* this tree node should be highlighted.
|
|
||||||
* An object will be highlighted if it matches
|
|
||||||
* ngModel.selectedObject
|
|
||||||
* @returns true if this should be highlighted
|
|
||||||
*/
|
|
||||||
TreeNodeController.prototype.isSelected = function () {
|
|
||||||
return this.isSelectedFlag;
|
|
||||||
};
|
|
||||||
|
|
||||||
return TreeNodeController;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Verify that id paths are equivalent, staring at
|
||||||
|
// index, ending at the end of the node path.
|
||||||
|
function checkPath(nodePath, navPath, index) {
|
||||||
|
index = index || 0;
|
||||||
|
|
||||||
|
// The paths overlap if we have made it past the
|
||||||
|
// end of the node's path; otherwise, check the
|
||||||
|
// id at the current index for equality and perform
|
||||||
|
// a recursive step for subsequent ids in the paths,
|
||||||
|
// until we exceed path length or hit a mismatch.
|
||||||
|
return (index >= nodePath.length)
|
||||||
|
|| ((navPath[index] === nodePath[index])
|
||||||
|
&& checkPath(nodePath, navPath, index + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Consider the currently-navigated object and update
|
||||||
|
// parameters which support display.
|
||||||
|
function checkSelection() {
|
||||||
|
var nodeObject = $scope.domainObject,
|
||||||
|
navObject = selectedObject,
|
||||||
|
nodeContext = nodeObject
|
||||||
|
&& nodeObject.getCapability('context'),
|
||||||
|
navContext = navObject
|
||||||
|
&& navObject.getCapability('context'),
|
||||||
|
nodePath,
|
||||||
|
navPath;
|
||||||
|
|
||||||
|
// Deselect; we will reselect below, iff we are
|
||||||
|
// exactly at the end of the path.
|
||||||
|
self.isSelectedFlag = false;
|
||||||
|
|
||||||
|
// Expand if necessary (if the navigated object will
|
||||||
|
// be in this node's subtree)
|
||||||
|
if (nodeContext && navContext) {
|
||||||
|
// Get the paths as arrays of identifiers
|
||||||
|
nodePath = nodeContext.getPath().map(getId);
|
||||||
|
navPath = navContext.getPath().map(getId);
|
||||||
|
|
||||||
|
// Check to see if the node's path lies entirely
|
||||||
|
// within the navigation path; otherwise, navigation
|
||||||
|
// has happened in some other subtree.
|
||||||
|
if (navPath.length >= nodePath.length
|
||||||
|
&& checkPath(nodePath, navPath)) {
|
||||||
|
|
||||||
|
// nodePath is along the navPath; if it's
|
||||||
|
// at the end of the path, highlight;
|
||||||
|
// otherwise, expand.
|
||||||
|
if (nodePath.length === navPath.length) {
|
||||||
|
self.isSelectedFlag = true;
|
||||||
|
} else { // node path is shorter: Expand!
|
||||||
|
if ($scope.toggle) {
|
||||||
|
$scope.toggle.setState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.trackExpansion();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Callback for the selection updates; track the currently
|
||||||
|
// navigated object and update display parameters as needed.
|
||||||
|
function setSelection(object) {
|
||||||
|
selectedObject = object;
|
||||||
|
checkSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.isSelectedFlag = false;
|
||||||
|
this.hasBeenExpandedFlag = false;
|
||||||
|
this.$timeout = $timeout;
|
||||||
|
this.$scope = $scope;
|
||||||
|
|
||||||
|
// Listen for changes which will effect display parameters
|
||||||
|
$scope.$watch("ngModel.selectedObject", setSelection);
|
||||||
|
$scope.$watch("domainObject", checkSelection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the domain object represented by this node in the tree.
|
||||||
|
* This will both update the `selectedObject` property in
|
||||||
|
* the object passed in via `ng-model`, and will fire any `callback`
|
||||||
|
* passed in via `parameters`.
|
||||||
|
*/
|
||||||
|
TreeNodeController.prototype.select = function () {
|
||||||
|
if (this.$scope.ngModel) {
|
||||||
|
this.$scope.ngModel.selectedObject =
|
||||||
|
this.$scope.domainObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((this.$scope.parameters || {}).callback) {
|
||||||
|
this.$scope.parameters.callback(this.$scope.domainObject);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should be called when a node is expanded
|
||||||
|
* to record that this has occurred, to support one-time
|
||||||
|
* lazy loading of the node's subtree.
|
||||||
|
*/
|
||||||
|
TreeNodeController.prototype.trackExpansion = function () {
|
||||||
|
var self = this;
|
||||||
|
if (!self.hasBeenExpanded()) {
|
||||||
|
// Run on a timeout; if a lot of expansion needs to
|
||||||
|
// occur (e.g. if the selection is several nodes deep) we
|
||||||
|
// want this to be spread across multiple digest cycles.
|
||||||
|
self.$timeout(function () {
|
||||||
|
self.hasBeenExpandedFlag = true;
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this not has ever been expanded.
|
||||||
|
* @returns true if it has been expanded
|
||||||
|
*/
|
||||||
|
TreeNodeController.prototype.hasBeenExpanded = function () {
|
||||||
|
return this.hasBeenExpandedFlag;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check whether or not the domain object represented by
|
||||||
|
* this tree node should be highlighted.
|
||||||
|
* An object will be highlighted if it matches
|
||||||
|
* ngModel.selectedObject
|
||||||
|
* @returns true if this should be highlighted
|
||||||
|
*/
|
||||||
|
TreeNodeController.prototype.isSelected = function () {
|
||||||
|
return this.isSelectedFlag;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TreeNodeController;
|
@ -23,51 +23,63 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining ViewSwitcherController. Created by vwoeltje on 11/7/14.
|
* Module defining ViewSwitcherController. Created by vwoeltje on 11/7/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller for the view switcher; populates and maintains a list
|
* Module defining ViewSwitcherController. Created by vwoeltje on 11/7/14.
|
||||||
* of applicable views for a represented domain object.
|
*/
|
||||||
* @memberof platform/commonUI/general
|
function ViewSwitcherController($scope, $timeout) {
|
||||||
* @constructor
|
// If the view capability gets refreshed, try to
|
||||||
*/
|
// keep the same option chosen.
|
||||||
function ViewSwitcherController($scope, $timeout) {
|
function findMatchingOption(options, selected) {
|
||||||
// If the view capability gets refreshed, try to
|
var i;
|
||||||
// keep the same option chosen.
|
|
||||||
function findMatchingOption(options, selected) {
|
|
||||||
var i;
|
|
||||||
|
|
||||||
if (selected) {
|
if (selected) {
|
||||||
for (i = 0; i < options.length; i += 1) {
|
for (i = 0; i < options.length; i += 1) {
|
||||||
if (options[i].key === selected.key) {
|
if (options[i].key === selected.key) {
|
||||||
return options[i];
|
return options[i];
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return options[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get list of views, read from capability
|
|
||||||
function updateOptions(views) {
|
|
||||||
if (Array.isArray(views)) {
|
|
||||||
$timeout(function () {
|
|
||||||
$scope.ngModel.selected = findMatchingOption(
|
|
||||||
views,
|
|
||||||
($scope.ngModel || {}).selected
|
|
||||||
);
|
|
||||||
}, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update view options when the in-scope results of using the
|
|
||||||
// view capability change.
|
|
||||||
$scope.$watch("view", updateOptions);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ViewSwitcherController;
|
return options[0];
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
|
// Get list of views, read from capability
|
||||||
|
function updateOptions(views) {
|
||||||
|
if (Array.isArray(views)) {
|
||||||
|
$timeout(function () {
|
||||||
|
$scope.ngModel.selected = findMatchingOption(
|
||||||
|
views,
|
||||||
|
($scope.ngModel || {}).selected
|
||||||
|
);
|
||||||
|
}, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update view options when the in-scope results of using the
|
||||||
|
// view capability change.
|
||||||
|
$scope.$watch("view", updateOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default ViewSwitcherController;
|
@ -20,58 +20,66 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
function MCTClickElsewhere($document) {
|
||||||
* The `mct-click-elsewhere` directive will evaluate its
|
|
||||||
* associated expression whenever a `mousedown` occurs anywhere
|
|
||||||
* outside of the element that has the `mct-click-elsewhere`
|
|
||||||
* directive attached. This is useful for dismissing popups
|
|
||||||
* and the like.
|
|
||||||
*/
|
|
||||||
function MCTClickElsewhere($document) {
|
|
||||||
|
|
||||||
// Link; install event handlers.
|
// Link; install event handlers.
|
||||||
function link(scope, element, attrs) {
|
function link(scope, element, attrs) {
|
||||||
// Keep a reference to the body, to attach/detach
|
// Keep a reference to the body, to attach/detach
|
||||||
// mouse event handlers; mousedown and mouseup cannot
|
// mouse event handlers; mousedown and mouseup cannot
|
||||||
// only be attached to the element being linked, as the
|
// only be attached to the element being linked, as the
|
||||||
// mouse may leave this element during the drag.
|
// mouse may leave this element during the drag.
|
||||||
var body = $document.find('body');
|
var body = $document.find('body');
|
||||||
|
|
||||||
function clickBody(event) {
|
function clickBody(event) {
|
||||||
var x = event.clientX,
|
var x = event.clientX,
|
||||||
y = event.clientY,
|
y = event.clientY,
|
||||||
rect = element[0].getBoundingClientRect(),
|
rect = element[0].getBoundingClientRect(),
|
||||||
xMin = rect.left,
|
xMin = rect.left,
|
||||||
xMax = xMin + rect.width,
|
xMax = xMin + rect.width,
|
||||||
yMin = rect.top,
|
yMin = rect.top,
|
||||||
yMax = yMin + rect.height;
|
yMax = yMin + rect.height;
|
||||||
|
|
||||||
if (x < xMin || x > xMax || y < yMin || y > yMax) {
|
if (x < xMin || x > xMax || y < yMin || y > yMax) {
|
||||||
scope.$apply(function () {
|
scope.$apply(function () {
|
||||||
scope.$eval(attrs.mctClickElsewhere);
|
scope.$eval(attrs.mctClickElsewhere);
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
body.on("mousedown", clickBody);
|
|
||||||
scope.$on("$destroy", function () {
|
|
||||||
body.off("mousedown", clickBody);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
|
||||||
// mct-drag only makes sense as an attribute
|
|
||||||
restrict: "A",
|
|
||||||
// Link function, to install event handlers
|
|
||||||
link: link
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return MCTClickElsewhere;
|
body.on("mousedown", clickBody);
|
||||||
|
scope.$on("$destroy", function () {
|
||||||
|
body.off("mousedown", clickBody);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
|
return {
|
||||||
|
// mct-drag only makes sense as an attribute
|
||||||
|
restrict: "A",
|
||||||
|
// Link function, to install event handlers
|
||||||
|
link: link
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MCTClickElsewhere;
|
@ -23,69 +23,75 @@
|
|||||||
/**
|
/**
|
||||||
* Module defining MCTContainer. Created by vwoeltje on 11/17/14.
|
* Module defining MCTContainer. Created by vwoeltje on 11/17/14.
|
||||||
*/
|
*/
|
||||||
define(
|
/*****************************************************************************
|
||||||
[],
|
* Open MCT, Copyright (c) 2014-2021, United States Government
|
||||||
function () {
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT 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 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The mct-container is similar to the mct-include directive
|
* Module defining MCTContainer. Created by vwoeltje on 11/17/14.
|
||||||
* insofar as it allows templates to be referenced by
|
*/
|
||||||
* symbolic keys instead of by URL. Unlike mct-include, it
|
function MCTContainer(containers) {
|
||||||
* supports transclusion.
|
var containerMap = {};
|
||||||
*
|
|
||||||
* Unlike mct-include, mct-container accepts a key as a
|
|
||||||
* plain string attribute, instead of as an Angular
|
|
||||||
* expression.
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/general
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function MCTContainer(containers) {
|
|
||||||
var containerMap = {};
|
|
||||||
|
|
||||||
// Initialize container map from extensions
|
// Initialize container map from extensions
|
||||||
containers.forEach(function (container) {
|
containers.forEach(function (container) {
|
||||||
containerMap[container.key] = container;
|
containerMap[container.key] = container;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
||||||
// Allow only at the element level
|
// Allow only at the element level
|
||||||
restrict: 'E',
|
restrict: 'E',
|
||||||
|
|
||||||
// Support transclusion
|
// Support transclusion
|
||||||
transclude: true,
|
transclude: true,
|
||||||
|
|
||||||
// Create a new (non-isolate) scope
|
// Create a new (non-isolate) scope
|
||||||
scope: true,
|
scope: true,
|
||||||
|
|
||||||
// Populate initial scope based on attributes requested
|
// Populate initial scope based on attributes requested
|
||||||
// by the container definition
|
// by the container definition
|
||||||
link: function (scope, element, attrs) {
|
link: function (scope, element, attrs) {
|
||||||
var key = attrs.key,
|
var key = attrs.key,
|
||||||
container = containerMap[key],
|
container = containerMap[key],
|
||||||
alias = "container",
|
alias = "container",
|
||||||
copiedAttributes = {};
|
copiedAttributes = {};
|
||||||
|
|
||||||
if (container) {
|
if (container) {
|
||||||
alias = container.alias || alias;
|
alias = container.alias || alias;
|
||||||
(container.attributes || []).forEach(function (attr) {
|
(container.attributes || []).forEach(function (attr) {
|
||||||
copiedAttributes[attr] = attrs[attr];
|
copiedAttributes[attr] = attrs[attr];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
scope[alias] = copiedAttributes;
|
scope[alias] = copiedAttributes;
|
||||||
},
|
},
|
||||||
|
|
||||||
template: function (element, attrs) {
|
template: function (element, attrs) {
|
||||||
var key = attrs.key,
|
var key = attrs.key,
|
||||||
container = containerMap[key];
|
container = containerMap[key];
|
||||||
|
|
||||||
return container ? container.template : "";
|
return container ? container.template : "";
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return MCTContainer;
|
export default MCTContainer;
|
||||||
}
|
|
||||||
);
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user