Compare commits
1 Commits
summary-wi
...
slideshow
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d75058d5bd |
15
API.md
15
API.md
@@ -879,21 +879,6 @@ openmct.install(openmct.plugins.CouchDB('http://localhost:9200'))
|
||||
* `openmct.plugins.Espresso` and `openmct.plugins.Snow` are two different
|
||||
themes (dark and light) available for Open MCT. Note that at least one
|
||||
of these themes must be installed for Open MCT to appear correctly.
|
||||
* `openmct.plugins.URLIndicatorPlugin` adds an indicator which shows the
|
||||
availability of a URL with the following options:
|
||||
- `url` : URL to indicate the status of
|
||||
- `cssClass`: Icon to show in the status bar, defaults to `icon-database`, [list of all icons](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home?view=items)
|
||||
- `interval`: Interval between checking the connection, defaults to `10000`
|
||||
- `label` Name showing up as text in the status bar, defaults to url
|
||||
```javascript
|
||||
openmct.install(openmct.plugins.URLIndicatorPlugin({
|
||||
url: 'http://google.com',
|
||||
cssClass: 'check',
|
||||
interval: 10000,
|
||||
label: 'Google'
|
||||
})
|
||||
);
|
||||
```
|
||||
* `openmct.plugins.LocalStorage` provides persistence of user-created
|
||||
objects in browser-local storage. This is particularly useful in
|
||||
development environments.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"screenfull": "^3.0.0",
|
||||
"node-uuid": "^1.4.7",
|
||||
"comma-separated-values": "^3.6.4",
|
||||
"file-saver": "^1.3.3",
|
||||
"FileSaver.js": "^0.0.2",
|
||||
"zepto": "^1.1.6",
|
||||
"eventemitter3": "^1.2.0",
|
||||
"lodash": "3.10.1",
|
||||
|
||||
@@ -4,6 +4,12 @@ deployment:
|
||||
commands:
|
||||
- npm install canvas nomnoml
|
||||
- ./build-docs.sh
|
||||
- git fetch --unshallow
|
||||
- git push git@heroku.com:openmctweb-demo.git $CIRCLE_SHA1:refs/heads/master
|
||||
openmct-demo:
|
||||
branch: live_demo
|
||||
heroku:
|
||||
appname: openmct-demo
|
||||
openmctweb-staging-deux:
|
||||
branch: mobile
|
||||
heroku:
|
||||
|
||||
@@ -59,7 +59,7 @@ define([
|
||||
if (domainObject.telemetry && domainObject.telemetry.hasOwnProperty(prop)) {
|
||||
workerRequest[prop] = domainObject.telemetry[prop];
|
||||
}
|
||||
if (request && request.hasOwnProperty(prop)) {
|
||||
if (request.hasOwnProperty(prop)) {
|
||||
workerRequest[prop] = request[prop];
|
||||
}
|
||||
if (!workerRequest[prop]) {
|
||||
|
||||
@@ -44,7 +44,9 @@ define([
|
||||
message = message.data;
|
||||
var callback = this.callbacks[message.id];
|
||||
if (callback) {
|
||||
callback(message);
|
||||
if (callback(message)) {
|
||||
delete this.callbacks[message.id];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,7 +72,6 @@ define([
|
||||
deferred.resolve = resolve;
|
||||
deferred.reject = reject;
|
||||
});
|
||||
var messageId;
|
||||
|
||||
function callback(message) {
|
||||
if (message.error) {
|
||||
@@ -78,27 +79,33 @@ define([
|
||||
} else {
|
||||
deferred.resolve(message.data);
|
||||
}
|
||||
delete this.callbacks[messageId];
|
||||
return true;
|
||||
}
|
||||
|
||||
messageId = this.dispatch('request', request, callback.bind(this));
|
||||
this.dispatch('request', request, callback);
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
WorkerInterface.prototype.subscribe = function (request, cb) {
|
||||
function callback(message) {
|
||||
var isCancelled = false;
|
||||
|
||||
var callback = function (message) {
|
||||
if (isCancelled) {
|
||||
return true;
|
||||
}
|
||||
cb(message.data);
|
||||
};
|
||||
|
||||
var messageId = this.dispatch('subscribe', request, callback);
|
||||
var messageId = this.dispatch('subscribe', request, callback)
|
||||
|
||||
return function () {
|
||||
isCancelled = true;
|
||||
this.dispatch('unsubscribe', {
|
||||
id: messageId
|
||||
});
|
||||
delete this.callbacks[messageId];
|
||||
}.bind(this);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -127,8 +127,7 @@
|
||||
{ 'meaning': 'Timer object', 'cssClass': 'icon-timer', 'cssContent': 'e1127', 'htmlEntity': '&#xe1127' },
|
||||
{ 'meaning': 'Data Topic', 'cssClass': 'icon-topic', 'cssContent': 'e1128', 'htmlEntity': '&#xe1128' },
|
||||
{ 'meaning': 'Fixed Position object', 'cssClass': 'icon-box-with-dashed-lines', 'cssContent': 'e1129', 'htmlEntity': '&#xe1129' },
|
||||
{ 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' },
|
||||
{ 'meaning': 'Notebook object', 'cssClass': 'icon-notebook', 'cssContent': 'e1131', 'htmlEntity': '&#xe1131' }
|
||||
{ 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' }
|
||||
];
|
||||
"></div>
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@
|
||||
<h2>Palettes</h2>
|
||||
<div class="cols cols1-1">
|
||||
<div class="col">
|
||||
<p>Use a palette to provide color choices. Similar to context menus and dropdowns, palettes should be dismissed when a choice is made within them, or if the user clicks outside one. Selected palette choices should utilize the <code>selected</code> CSS class to visualize indicate that state.</p>
|
||||
<p>Use a palette to provide color choices. Similar to context menus and dropdowns, palettes should be dismissed when a choice is made within them, or if the user clicks outside one.</p>
|
||||
<p>Note that while this example uses static markup for illustrative purposes, don't do this - use a front-end framework with repeaters to build the color choices.</p>
|
||||
</div>
|
||||
<mct-example><div style="height: 220px" title="Ignore me, I'm just here to provide space for this example.">
|
||||
@@ -129,9 +129,9 @@
|
||||
<div class="s-button s-menu-button menu-element t-color-palette icon-paint-bucket" ng-controller="ClickAwayController as toggle">
|
||||
<span class="l-click-area" ng-click="toggle.toggle()"></span>
|
||||
<span class="color-swatch" style="background: rgb(255, 0, 0);"></span>
|
||||
<div class="menu l-palette l-color-palette" ng-show="toggle.isActive()">
|
||||
<div class="menu l-color-palette" ng-show="toggle.isActive()">
|
||||
<div class="l-palette-row l-option-row">
|
||||
<div class="l-palette-item s-palette-item no-selection"></div>
|
||||
<div class="l-palette-item s-palette-item " ng-click="ngModel[field] = 'transparent'"></div>
|
||||
<span class="l-palette-item-label">None</span>
|
||||
</div>
|
||||
<div class="l-palette-row">
|
||||
@@ -147,7 +147,7 @@
|
||||
<div class="l-palette-item s-palette-item" style="background: rgb(255, 255, 255);"></div>
|
||||
</div>
|
||||
<div class="l-palette-row">
|
||||
<div class="l-palette-item s-palette-item selected" style="background: rgb(255, 0, 0);"></div>
|
||||
<div class="l-palette-item s-palette-item" style="background: rgb(136, 32, 32);"></div>
|
||||
<div class="l-palette-item s-palette-item" style="background: rgb(224, 64, 64);"></div>
|
||||
<div class="l-palette-item s-palette-item" style="background: rgb(240, 160, 72);"></div>
|
||||
<div class="l-palette-item s-palette-item" style="background: rgb(255, 248, 96);"></div>
|
||||
|
||||
@@ -25,7 +25,8 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||
<title></title>
|
||||
<script src="bower_components/requirejs/require.js"> </script>
|
||||
<script src="bower_components/requirejs/require.js">
|
||||
</script>
|
||||
<script>
|
||||
var THIRTY_MINUTES = 30 * 60 * 1000;
|
||||
|
||||
@@ -49,7 +50,7 @@
|
||||
name: "Fixed",
|
||||
timeSystem: 'utc',
|
||||
bounds: {
|
||||
start: Date.now() - THIRTY_MINUTES,
|
||||
start: Date.now() - 30 * 60 * 1000,
|
||||
end: Date.now()
|
||||
}
|
||||
},
|
||||
@@ -64,7 +65,6 @@
|
||||
}
|
||||
]
|
||||
}));
|
||||
openmct.install(openmct.plugins.SummaryWidget());
|
||||
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
|
||||
openmct.time.timeSystem('utc');
|
||||
openmct.start();
|
||||
|
||||
@@ -33,7 +33,7 @@ requirejs.config({
|
||||
"moment": "bower_components/moment/moment",
|
||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||
"moment-timezone": "bower_components/moment-timezone/builds/moment-timezone-with-data",
|
||||
"saveAs": "bower_components/file-saver/FileSaver.min",
|
||||
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
||||
"screenfull": "bower_components/screenfull/dist/screenfull.min",
|
||||
"text": "bower_components/text/text",
|
||||
"uuid": "bower_components/node-uuid/uuid",
|
||||
@@ -66,9 +66,6 @@ requirejs.config({
|
||||
"moment-duration-format": {
|
||||
"deps": ["moment"]
|
||||
},
|
||||
"saveAs": {
|
||||
"exports": "saveAs"
|
||||
},
|
||||
"screenfull": {
|
||||
"exports": "screenfull"
|
||||
},
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
|
||||
<span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller">
|
||||
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
|
||||
<span ng-attr-contenteditable="{{ controller.editable ? true : undefined }}"
|
||||
<span contenteditable="true"
|
||||
class='title-label flex-elem holder flex-can-shrink s-input-inline'
|
||||
ng-click="controller.edit()"
|
||||
ng-blur="controller.updateName($event)"
|
||||
|
||||
@@ -32,8 +32,7 @@ define(
|
||||
*/
|
||||
function ObjectHeaderController($scope) {
|
||||
this.$scope = $scope;
|
||||
this.domainObject = $scope.domainObject;
|
||||
this.editable = this.allowEdit();
|
||||
$scope.editing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,49 +41,33 @@ define(
|
||||
* @param event the mouse event
|
||||
*/
|
||||
ObjectHeaderController.prototype.updateName = function (event) {
|
||||
if (!event || !event.currentTarget) {
|
||||
return;
|
||||
}
|
||||
if (event && (event.type === 'blur' || event.which === 13)) {
|
||||
var name = event.currentTarget.innerHTML;
|
||||
|
||||
if (event.type === 'blur') {
|
||||
this.updateModel(event);
|
||||
} else if (event.which === 13) {
|
||||
this.updateModel(event);
|
||||
event.currentTarget.blur();
|
||||
window.getSelection().removeAllRanges();
|
||||
if (name.length === 0) {
|
||||
name = "Unnamed " + this.$scope.domainObject.getCapability("type").typeDef.name;
|
||||
event.currentTarget.innerHTML = name;
|
||||
}
|
||||
|
||||
if (name !== this.$scope.domainObject.model.name) {
|
||||
this.$scope.domainObject.getCapability('mutation').mutate(function (model) {
|
||||
model.name = name;
|
||||
});
|
||||
}
|
||||
|
||||
this.$scope.editing = false;
|
||||
|
||||
if (event.which === 13) {
|
||||
event.currentTarget.blur();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates the model.
|
||||
*
|
||||
* @param event the mouse event
|
||||
* @param private
|
||||
* Marks the status of the field as editing.
|
||||
*/
|
||||
ObjectHeaderController.prototype.updateModel = function (event) {
|
||||
var name = event.currentTarget.textContent.replace(/\n/g, ' ');
|
||||
|
||||
if (name.length === 0) {
|
||||
name = "Unnamed " + this.domainObject.getCapability("type").typeDef.name;
|
||||
event.currentTarget.textContent = name;
|
||||
}
|
||||
|
||||
if (name !== this.domainObject.getModel().name) {
|
||||
this.domainObject.getCapability('mutation').mutate(function (model) {
|
||||
model.name = name;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the domain object is editable.
|
||||
*
|
||||
* @private
|
||||
* @return true if object is editable
|
||||
*/
|
||||
ObjectHeaderController.prototype.allowEdit = function () {
|
||||
var type = this.domainObject && this.domainObject.getCapability('type');
|
||||
return !!(type && type.hasFeature('creation'));
|
||||
ObjectHeaderController.prototype.edit = function () {
|
||||
this.$scope.editing = true;
|
||||
};
|
||||
|
||||
return ObjectHeaderController;
|
||||
|
||||
@@ -32,27 +32,22 @@ define(
|
||||
mockTypeCapability,
|
||||
mockEvent,
|
||||
mockCurrentTarget,
|
||||
model,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
|
||||
mockTypeCapability = jasmine.createSpyObj("type", ["typeDef", "hasFeature"]);
|
||||
mockTypeCapability.typeDef = { name: ""};
|
||||
mockTypeCapability.hasFeature.andCallFake(function (feature) {
|
||||
return feature === 'creation';
|
||||
});
|
||||
|
||||
mockTypeCapability = {
|
||||
typeDef: {
|
||||
name: ""
|
||||
}
|
||||
};
|
||||
mockCapabilities = {
|
||||
mutation: mockMutationCapability,
|
||||
type: mockTypeCapability
|
||||
};
|
||||
|
||||
model = {
|
||||
name: "Test name"
|
||||
};
|
||||
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "getModel"]);
|
||||
mockDomainObject.getModel.andReturn(model);
|
||||
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "model"]);
|
||||
mockDomainObject.model = {name: "Test name"};
|
||||
mockDomainObject.getCapability.andCallFake(function (key) {
|
||||
return mockCapabilities[key];
|
||||
});
|
||||
@@ -61,7 +56,7 @@ define(
|
||||
domainObject: mockDomainObject
|
||||
};
|
||||
|
||||
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "textContent"]);
|
||||
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "innerHTML"]);
|
||||
mockCurrentTarget.blur.andReturn(mockCurrentTarget);
|
||||
|
||||
mockEvent = {
|
||||
@@ -75,7 +70,7 @@ define(
|
||||
|
||||
it("updates the model with new name on blur", function () {
|
||||
mockEvent.type = "blur";
|
||||
mockCurrentTarget.textContent = "New name";
|
||||
mockCurrentTarget.innerHTML = "New name";
|
||||
controller.updateName(mockEvent);
|
||||
|
||||
expect(mockMutationCapability.mutate).toHaveBeenCalled();
|
||||
@@ -83,23 +78,23 @@ define(
|
||||
|
||||
it("updates the model with a default for blank names", function () {
|
||||
mockEvent.type = "blur";
|
||||
mockCurrentTarget.textContent = "";
|
||||
mockCurrentTarget.innerHTML = "";
|
||||
controller.updateName(mockEvent);
|
||||
|
||||
expect(mockCurrentTarget.textContent.length).not.toEqual(0);
|
||||
expect(mockCurrentTarget.innerHTML.length).not.toEqual(0);
|
||||
expect(mockMutationCapability.mutate).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("does not update the model if the same name", function () {
|
||||
mockEvent.type = "blur";
|
||||
mockCurrentTarget.textContent = mockDomainObject.getModel().name;
|
||||
mockCurrentTarget.innerHTML = mockDomainObject.model.name;
|
||||
controller.updateName(mockEvent);
|
||||
|
||||
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("updates the model on enter keypress event only", function () {
|
||||
mockCurrentTarget.textContent = "New name";
|
||||
mockCurrentTarget.innerHTML = "New name";
|
||||
controller.updateName(mockEvent);
|
||||
|
||||
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
|
||||
@@ -109,29 +104,17 @@ define(
|
||||
|
||||
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
|
||||
mockMutationCapability.mutate.mostRecentCall.args[0](model);
|
||||
mockMutationCapability.mutate.mostRecentCall.args[0](mockDomainObject.model);
|
||||
|
||||
expect(mockDomainObject.getModel().name).toBe("New name");
|
||||
expect(mockDomainObject.model.name).toBe("New name");
|
||||
});
|
||||
|
||||
it("blurs the field on enter key press", function () {
|
||||
mockCurrentTarget.textContent = "New name";
|
||||
mockEvent.which = 13;
|
||||
controller.updateName(mockEvent);
|
||||
|
||||
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("allows editting name when object is creatable", function () {
|
||||
expect(controller.allowEdit()).toBe(true);
|
||||
});
|
||||
|
||||
it("disallows editting name when object is non-creatable", function () {
|
||||
mockTypeCapability.hasFeature.andReturn(false);
|
||||
|
||||
expect(controller.allowEdit()).toBe(false);
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="abs top-bar">
|
||||
<div class="dialog-title">{{ngModel.title}}</div>
|
||||
<div class="title">{{ngModel.title}}</div>
|
||||
<div class="hint">All fields marked <span class="req icon-asterisk"></span> are required.</div>
|
||||
</div>
|
||||
<div class='abs editor'>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<div class="l-message"
|
||||
ng-class="'message-severity-' + ngModel.severity">
|
||||
<div class="w-message-contents">
|
||||
<div class="ui-symbol type-icon message-type"></div>
|
||||
<div class="message-contents">
|
||||
<div class="top-bar">
|
||||
<div class="title">{{ngModel.title}}</div>
|
||||
<div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div>
|
||||
</div>
|
||||
<div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div>
|
||||
<div class="message-body">
|
||||
<div class="message-action">
|
||||
{{ngModel.actionText}}
|
||||
@@ -24,6 +25,8 @@
|
||||
ng-click="ngModel.primaryOption.callback()">
|
||||
{{ngModel.primaryOption.label}}
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
<mct-container key="overlay">
|
||||
<div class="t-message-list">
|
||||
<div class="top-bar">
|
||||
<div class="dialog-title">{{ngModel.dialog.title}}</div>
|
||||
<mct-container key="overlay" class="t-message-list">
|
||||
<div class="message-contents">
|
||||
<div class="abs top-bar">
|
||||
<div class="title">{{ngModel.dialog.title}}</div>
|
||||
<div class="hint">Displaying {{ngModel.dialog.messages.length}} message<span ng-show="ngModel.dialog.messages.length > 1 ||
|
||||
ngModel.dialog.messages.length == 0">s</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-messages">
|
||||
<div class="abs message-body">
|
||||
<mct-include
|
||||
ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'"
|
||||
key="'message'" ng-model="msg.model"></mct-include>
|
||||
ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'"
|
||||
key="'message'" ng-model="msg.model"></mct-include>
|
||||
</div>
|
||||
<div class="bottom-bar">
|
||||
<div class="abs bottom-bar">
|
||||
<a ng-repeat="dialogAction in ngModel.dialog.actions"
|
||||
class="s-button major"
|
||||
ng-click="dialogAction.action()">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<mct-container key="overlay">
|
||||
<div class="abs top-bar">
|
||||
<div class="dialog-title">{{ngModel.dialog.title}}</div>
|
||||
<div class="title">{{ngModel.dialog.title}}</div>
|
||||
<div class="hint">{{ngModel.dialog.hint}}</div>
|
||||
</div>
|
||||
<div class='abs editor'>
|
||||
|
||||
@@ -101,15 +101,10 @@ define(
|
||||
*/
|
||||
EditorCapability.prototype.finish = function () {
|
||||
var domainObject = this.domainObject;
|
||||
|
||||
if (this.transactionService.isActive()) {
|
||||
return this.transactionService.cancel().then(function () {
|
||||
domainObject.getCapability("status").set("editing", false);
|
||||
return domainObject;
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve(domainObject);
|
||||
}
|
||||
return this.transactionService.cancel().then(function () {
|
||||
domainObject.getCapability("status").set("editing", false);
|
||||
return domainObject;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -62,7 +62,6 @@ define(
|
||||
);
|
||||
mockTransactionService.commit.andReturn(fastPromise());
|
||||
mockTransactionService.cancel.andReturn(fastPromise());
|
||||
mockTransactionService.isActive = jasmine.createSpy('isActive');
|
||||
|
||||
mockStatusCapability = jasmine.createSpyObj(
|
||||
"statusCapability",
|
||||
@@ -142,7 +141,6 @@ define(
|
||||
|
||||
describe("finish", function () {
|
||||
beforeEach(function () {
|
||||
mockTransactionService.isActive.andReturn(true);
|
||||
capability.edit();
|
||||
capability.finish();
|
||||
});
|
||||
@@ -154,23 +152,6 @@ define(
|
||||
});
|
||||
});
|
||||
|
||||
describe("finish", function () {
|
||||
beforeEach(function () {
|
||||
mockTransactionService.isActive.andReturn(false);
|
||||
capability.edit();
|
||||
});
|
||||
|
||||
it("does not cancel transaction when transaction is not active", function () {
|
||||
capability.finish();
|
||||
expect(mockTransactionService.cancel).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("returns a promise", function () {
|
||||
expect(capability.finish() instanceof Promise).toBe(true);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("dirty", function () {
|
||||
var model = {};
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"metadata": {
|
||||
"name": "openmct-symbols-16px",
|
||||
"lastOpened": 0,
|
||||
"created": 1506973656040
|
||||
"created": 1505151140023
|
||||
},
|
||||
"iconSets": [
|
||||
{
|
||||
@@ -899,14 +899,6 @@
|
||||
"prevSize": 24,
|
||||
"code": 921904,
|
||||
"tempChar": ""
|
||||
},
|
||||
{
|
||||
"order": 139,
|
||||
"id": 117,
|
||||
"name": "icon-notebook",
|
||||
"prevSize": 24,
|
||||
"code": 921905,
|
||||
"tempChar": ""
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
@@ -3532,29 +3524,6 @@
|
||||
{}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 117,
|
||||
"paths": [
|
||||
"M896 110.8c0-79.8-55.4-127.4-123-105.4l-773 250.6h896v-145.2z",
|
||||
"M896 320h-896v576c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-448c0-70.4-57.6-128-128-128zM832 832h-384v-320h384v320z"
|
||||
],
|
||||
"attrs": [
|
||||
{},
|
||||
{}
|
||||
],
|
||||
"isMulticolor": false,
|
||||
"isMulticolor2": false,
|
||||
"grid": 16,
|
||||
"tags": [
|
||||
"icon-notebook"
|
||||
],
|
||||
"colorPermutations": {
|
||||
"1161751207457516161751": [
|
||||
{},
|
||||
{}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"colorThemes": [
|
||||
|
||||
Binary file not shown.
@@ -118,5 +118,4 @@
|
||||
<glyph unicode="󡄨" glyph-name="icon-topic" d="M454.36 483.36l86.3 86.3c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c19.328-19.358 42.832-34.541 69.047-44.082l1.313 171.722-57.64 57.64c-34.407 34.33-81.9 55.558-134.35 55.558s-99.943-21.228-134.354-55.562l-86.296-86.297c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-28.674 28.654v-172.14c19.045-7.022 41.040-11.084 63.984-11.084 52.463 0 99.966 21.239 134.379 55.587zM505.64 412.64l-86.3-86.3c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-86.294 86.294c-2 2-4.2 4-6.36 6v-197.36c33.664-30.72 78.65-49.537 128.031-49.537 52.44 0 99.923 21.22 134.333 55.541l86.296 86.296c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c2-2 4.2-4 6.36-6v197.36c-33.664 30.72-78.65 49.537-128.031 49.537-52.44 0-99.923-21.22-134.333-55.541zM832 960h-128v-192h127.66l0.34-0.34v-639.32l-0.34-0.34h-127.66v-192h128c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM320 128h-127.66l-0.34 0.34v639.32l0.34 0.34h127.66v192h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192z" />
|
||||
<glyph unicode="󡄩" glyph-name="icon-box-with-dashed-lines" d="M0 576h128v-256h-128v256zM128 831.78l0.22 0.22h191.78v128h-192c-70.606-0.215-127.785-57.394-128-127.979v-192.021h128v191.78zM128 64.22v191.78h-128v-192c0.215-70.606 57.394-127.785 127.979-128h192.021v128h-191.78zM384 960h256v-128h-256v128zM896 64.22l-0.22-0.22h-191.78v-128h192c70.606 0.215 127.785 57.394 128 127.979v192.021h-128v-191.78zM896 960h-192v-128h191.78l0.22-0.22v-191.78h128v192c-0.215 70.606-57.394 127.785-127.979 128zM896 576h128v-256h-128v256zM384 64h256v-128h-256v128zM256 704h512v-512h-512v512z" />
|
||||
<glyph unicode="󡄰" glyph-name="icon-summary-widget" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM847.8 349.6l-82.6-143.2-189.6 131.6 19.2-230h-165.4l19.2 230-189.6-131.6-82.6 143.2 208.6 98.4-208.8 98.4 82.6 143.2 189.6-131.6-19.2 230h165.4l-19.2-230 189.6 131.6 82.6-143.2-208.6-98.4 208.8-98.4z" />
|
||||
<glyph unicode="󡄱" glyph-name="icon-notebook" d="M896 849.2c0 79.8-55.4 127.4-123 105.4l-773-250.6h896v145.2zM896 640h-896v-576c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v448c0 70.4-57.6 128-128 128zM832 128h-384v320h384v-320z" />
|
||||
</font></defs></svg>
|
||||
|
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Binary file not shown.
Binary file not shown.
@@ -137,11 +137,6 @@
|
||||
min-height: 0;
|
||||
&.holder:not(:last-child) { margin-bottom: $interiorMarginLg; }
|
||||
}
|
||||
&.l-flex-accordion .flex-accordion-holder {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
//overflow: hidden !important;
|
||||
}
|
||||
.flex-container { @include flex-direction(column); }
|
||||
}
|
||||
|
||||
|
||||
@@ -180,20 +180,6 @@ a.disabled {
|
||||
@include ellipsize();
|
||||
}
|
||||
|
||||
.no-selection {
|
||||
// aka selection = "None". Used in palettes and their menu buttons.
|
||||
$c: red; $s: 48%; $e: 52%;
|
||||
@include background-image(linear-gradient(-45deg,
|
||||
transparent $s - 5%,
|
||||
$c $s,
|
||||
$c $e,
|
||||
transparent $e + 5%
|
||||
));
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
|
||||
.scrolling,
|
||||
.scroll {
|
||||
overflow: auto;
|
||||
|
||||
@@ -146,7 +146,6 @@ $glyph-icon-timer: '\e1127';
|
||||
$glyph-icon-topic: '\e1128';
|
||||
$glyph-icon-box-with-dashed-lines: '\e1129';
|
||||
$glyph-icon-summary-widget: '\e1130';
|
||||
$glyph-icon-notebook: '\e1131';
|
||||
|
||||
/************************** 16 PX CLASSES */
|
||||
|
||||
@@ -261,7 +260,6 @@ $glyph-icon-notebook: '\e1131';
|
||||
.icon-topic { @include glyphBefore($glyph-icon-topic); }
|
||||
.icon-box-with-dashed-lines { @include glyphBefore($glyph-icon-box-with-dashed-lines); }
|
||||
.icon-summary-widget { @include glyphBefore($glyph-icon-summary-widget); }
|
||||
.icon-notebook { @include glyphBefore($glyph-icon-notebook); }
|
||||
|
||||
/************************** 12 PX CLASSES */
|
||||
.icon-crosshair-12px { @include glyphBefore($glyph-icon-crosshair,'symbolsfont-12px'); }
|
||||
|
||||
@@ -26,6 +26,5 @@
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
/********************************* CONTROLS */
|
||||
@import "controls/breadcrumb";
|
||||
@import "controls/buttons";
|
||||
@import "controls/palette";
|
||||
@import "controls/color-palette";
|
||||
@import "controls/controls";
|
||||
@import "controls/lists";
|
||||
@import "controls/menus";
|
||||
@@ -80,4 +80,3 @@
|
||||
@import "autoflow";
|
||||
@import "features/imagery";
|
||||
@import "features/time-display";
|
||||
@import "widgets";
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
content:'';
|
||||
font-family: symbolsfont;
|
||||
font-size: 0.8em;
|
||||
display: inline;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,306 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
/************************************************************* WIDGET OBJECT */
|
||||
.l-summary-widget {
|
||||
// Widget layout classes here
|
||||
@include ellipsize();
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
.widget-label:before {
|
||||
// Widget icon
|
||||
font-size: 0.9em;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
|
||||
.s-summary-widget {
|
||||
// Widget style classes here
|
||||
@include boxShdw($shdwBtns);
|
||||
border-radius: $basicCr;
|
||||
border-style: solid;
|
||||
border-width: 1px;
|
||||
box-sizing: border-box;
|
||||
cursor: default;
|
||||
font-size: 0.8rem;
|
||||
padding: $interiorMarginLg $interiorMarginLg * 2;
|
||||
&[href] {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.widget-edit-holder {
|
||||
// Hide edit area when in browse mode
|
||||
display: none;
|
||||
}
|
||||
|
||||
.widget-rule-header {
|
||||
@extend .l-flex-row;
|
||||
@include align-items(center);
|
||||
margin-bottom: $interiorMargin;
|
||||
> .flex-elem {
|
||||
&:not(:first-child) {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.widget-rules-wrapper,
|
||||
.widget-rule-content,
|
||||
.w-widget-test-data-content {
|
||||
@include trans-prop-nice($props: (height, min-height, opacity), $dur: 250ms);
|
||||
min-height: 0;
|
||||
height: 0;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.widget-rules-wrapper {
|
||||
flex: 1 1 auto !important;
|
||||
}
|
||||
|
||||
.widget-rule-content.expanded {
|
||||
overflow: visible !important;
|
||||
min-height: 50px;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
pointer-events: inherit;
|
||||
}
|
||||
|
||||
.w-widget-test-data-content {
|
||||
.l-enable {
|
||||
padding: $interiorMargin 0;
|
||||
}
|
||||
|
||||
.w-widget-test-data-items {
|
||||
max-height: 20vh;
|
||||
overflow-y: scroll !important;
|
||||
padding-right: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
.l-widget-thumb-wrapper,
|
||||
.l-compact-form label {
|
||||
$ruleLabelW: 40%;
|
||||
$ruleLabelMaxW: 150px;
|
||||
@include display(flex);
|
||||
max-width: $ruleLabelMaxW;
|
||||
width: $ruleLabelW;
|
||||
}
|
||||
|
||||
.t-message-widget-no-data {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/********************************************************** EDITING A WIDGET */
|
||||
.s-status-editing > mct-view > .w-summary-widget {
|
||||
// Classes for editor layout while editing a widget
|
||||
// This selector is ugly and brittle, but needed to prevent interface from showing when widget is in a layout
|
||||
// being edited.
|
||||
@include absPosDefault();
|
||||
@extend .l-flex-col;
|
||||
|
||||
> .l-summary-widget {
|
||||
// Main view of the summary widget
|
||||
// Give some airspace and center the widget in the area
|
||||
margin: 30px auto;
|
||||
}
|
||||
|
||||
.widget-edit-holder {
|
||||
display: flex; // Overrides `display: none` during Browse mode
|
||||
.flex-accordion-holder {
|
||||
// Needed because otherwise accordion elements "creep" when contents expand and contract
|
||||
display: block !important;
|
||||
}
|
||||
&.expanded-widget-test-data {
|
||||
.w-widget-test-data-content {
|
||||
min-height: 50px;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
pointer-events: inherit;
|
||||
}
|
||||
&:not(.expanded-widget-rules) {
|
||||
// Test data is expanded and rules are collapsed
|
||||
// Make text data take up all the vertical space
|
||||
.flex-accordion-holder { display: flex; }
|
||||
.widget-test-data {
|
||||
flex-grow: 999999;
|
||||
}
|
||||
.w-widget-test-data-items {
|
||||
max-height: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.expanded-widget-rules {
|
||||
.widget-rules-wrapper {
|
||||
min-height: 50px;
|
||||
height: auto;
|
||||
opacity: 1;
|
||||
pointer-events: inherit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.s-status-no-data {
|
||||
.widget-edit-holder {
|
||||
opacity: 0.3;
|
||||
pointer-events: none;
|
||||
}
|
||||
.t-message-widget-no-data {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.l-compact-form {
|
||||
// Overrides on .l-compact-form
|
||||
ul {
|
||||
&:last-child { margin: 0; }
|
||||
li {
|
||||
@include align-items(flex-start);
|
||||
@include flex-wrap(nowrap);
|
||||
line-height: 230%; // Provide enough space when controls wrap
|
||||
padding: 2px 0;
|
||||
&:not(.widget-rule-header) {
|
||||
&:not(.connects-to-previous) {
|
||||
border-top: 1px solid $colorFormLines;
|
||||
}
|
||||
}
|
||||
&.connects-to-previous {
|
||||
padding: $interiorMargin 0;
|
||||
}
|
||||
|
||||
> label {
|
||||
display: block; // Needed to align text to right
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.s-widget-test-data-item {
|
||||
// Single line of ul li label span, etc.
|
||||
ul {
|
||||
li {
|
||||
border: none !important;
|
||||
> label {
|
||||
display: inline-block;
|
||||
width: auto;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.widget-edit-holder {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
|
||||
.widget-rules-wrapper {
|
||||
// Wrapper area that holds n rules
|
||||
box-sizing: border-box;
|
||||
overflow-y: scroll;
|
||||
padding-right: $interiorMargin;
|
||||
}
|
||||
|
||||
.l-widget-rule,
|
||||
.l-widget-test-data-item {
|
||||
box-sizing: border-box;
|
||||
margin-bottom: $interiorMarginSm;
|
||||
padding: $interiorMargin $interiorMarginLg;
|
||||
}
|
||||
|
||||
.l-widget-thumb-wrapper {
|
||||
@extend .l-flex-row;
|
||||
@include align-items(center);
|
||||
> span { display: block; }
|
||||
.grippy-holder,
|
||||
.view-control {
|
||||
margin-right: $interiorMargin;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
|
||||
.widget-thumb {
|
||||
@include flex(1 1 auto);
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.rule-title {
|
||||
@include flex(0 1 auto);
|
||||
color: pullForward($colorBodyFg, 50%);
|
||||
}
|
||||
|
||||
.rule-description {
|
||||
@include flex(1 1 auto);
|
||||
@include ellipsize();
|
||||
color: pushBack($colorBodyFg, 20%);
|
||||
}
|
||||
|
||||
.s-widget-rule,
|
||||
.s-widget-test-data-item {
|
||||
background-color: rgba($colorBodyFg, 0.1);
|
||||
border-radius: $basicCr;
|
||||
}
|
||||
|
||||
.widget-thumb {
|
||||
@include ellipsize();
|
||||
@extend .s-summary-widget;
|
||||
@extend .l-summary-widget;
|
||||
padding: $interiorMarginSm $interiorMargin;
|
||||
}
|
||||
|
||||
// Hide and show elements in the rule-header on hover
|
||||
.l-widget-rule,
|
||||
.l-widget-test-data-item {
|
||||
.grippy,
|
||||
.l-rule-action-buttons-wrapper,
|
||||
.l-condition-action-buttons-wrapper,
|
||||
.l-widget-test-data-item-action-buttons-wrapper {
|
||||
@include trans-prop-nice($props: opacity, $dur: 500ms);
|
||||
opacity: 0;
|
||||
}
|
||||
&:hover {
|
||||
.grippy,
|
||||
.l-rule-action-buttons-wrapper,
|
||||
.l-widget-test-data-item-action-buttons-wrapper {
|
||||
@include trans-prop-nice($props: opacity, $dur: 0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.l-rule-action-buttons-wrapper {
|
||||
.t-delete {
|
||||
margin-left: 10px;
|
||||
}
|
||||
}
|
||||
.t-condition {
|
||||
&:hover {
|
||||
.l-condition-action-buttons-wrapper {
|
||||
@include trans-prop-nice($props: opacity, $dur: 0);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,11 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.l-palette {
|
||||
.l-color-palette {
|
||||
$d: 16px;
|
||||
$colorsPerRow: 10;
|
||||
$m: 1;
|
||||
$colorSelectedColor: #fff;
|
||||
|
||||
box-sizing: border-box;
|
||||
padding: $interiorMargin !important;
|
||||
@@ -32,41 +33,46 @@
|
||||
line-height: $d;
|
||||
width: ($d * $colorsPerRow) + ($m * $colorsPerRow);
|
||||
|
||||
&.l-option-row {
|
||||
margin-bottom: $interiorMargin;
|
||||
.s-palette-item {
|
||||
border-color: $colorPaletteFg;
|
||||
}
|
||||
}
|
||||
|
||||
.l-palette-item {
|
||||
box-sizing: border-box;
|
||||
@include txtShdwSubtle(0.8);
|
||||
@include trans-prop-nice-fade(0.25s);
|
||||
border: 1px solid transparent;
|
||||
color: $colorSelectedColor;
|
||||
display: block;
|
||||
float: left;
|
||||
height: $d; width: $d;
|
||||
line-height: $d * 0.9;
|
||||
margin: 0 ($m * 1px) ($m * 1px) 0;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
&:before {
|
||||
// Check mark for selected items
|
||||
font-size: 0.8em;
|
||||
}
|
||||
}
|
||||
|
||||
.s-palette-item {
|
||||
border: 1px solid transparent;
|
||||
color: $colorPaletteFg;
|
||||
text-shadow: $shdwPaletteFg;
|
||||
@include trans-prop-nice-fade(0.25s);
|
||||
&:hover {
|
||||
@include trans-prop-nice-fade(0);
|
||||
border-color: $colorPaletteSelected !important;
|
||||
border-color: $colorSelectedColor !important;
|
||||
}
|
||||
&.selected {
|
||||
border-color: $colorPaletteSelected;
|
||||
box-shadow: $shdwPaletteSelected; //Needed to see selection rect on light colored swatches
|
||||
}
|
||||
}
|
||||
|
||||
.l-palette-item-label {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
|
||||
&.l-option-row {
|
||||
margin-bottom: $interiorMargin;
|
||||
.s-palette-item {
|
||||
border-color: $colorBodyFg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -261,7 +261,7 @@ input[type="number"] {
|
||||
input[type="text"].lg { width: 100% !important; }
|
||||
.l-input-med input[type="text"],
|
||||
input[type="text"].med { width: 200px !important; }
|
||||
input[type="text"].sm, input[type="number"].sm { width: 50px !important; }
|
||||
input[type="text"].sm { width: 50px !important; }
|
||||
.l-numeric input[type="text"],
|
||||
input[type="text"].numeric { text-align: right; }
|
||||
|
||||
@@ -317,10 +317,14 @@ input[type="text"].s-input-inline,
|
||||
.select {
|
||||
@include btnSubtle($bg: $colorSelectBg);
|
||||
@extend .icon-arrow-down; // Context arrow
|
||||
@if $shdwBtns != none {
|
||||
margin: 0 0 2px 0; // Needed to avoid dropshadow from being clipped by parent containers
|
||||
}
|
||||
display: inline-block;
|
||||
padding: 0 $interiorMargin;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
line-height: $formInputH;
|
||||
select {
|
||||
@include appearance(none);
|
||||
box-sizing: border-box;
|
||||
@@ -336,13 +340,11 @@ input[type="text"].s-input-inline,
|
||||
}
|
||||
}
|
||||
&:before {
|
||||
@include transform(translateY(-50%));
|
||||
pointer-events: none;
|
||||
color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
|
||||
display: block;
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
right: $interiorMargin;
|
||||
top: 50%;
|
||||
right: $interiorMargin; top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,7 +396,8 @@ input[type="text"].s-input-inline,
|
||||
.l-elem-wrapper {
|
||||
mct-representation {
|
||||
// Holds the context-available item
|
||||
// Must have min-width to make flex work properly in Safari
|
||||
// Must have min-width to make flex work properly
|
||||
// in Safari
|
||||
min-width: 0.7em;
|
||||
}
|
||||
}
|
||||
@@ -560,6 +563,7 @@ input[type="text"].s-input-inline,
|
||||
height: $h;
|
||||
margin-top: 1 + floor($h/2) * -1;
|
||||
@include btnSubtle(pullForward($colorBtnBg, 10%));
|
||||
//border-radius: 50% !important;
|
||||
}
|
||||
|
||||
@mixin sliderKnobRound() {
|
||||
@@ -574,6 +578,7 @@ input[type="text"].s-input-inline,
|
||||
|
||||
input[type="range"] {
|
||||
// HTML5 range inputs
|
||||
|
||||
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
|
||||
background: transparent; /* Otherwise white in Chrome */
|
||||
&:focus {
|
||||
@@ -731,30 +736,6 @@ textarea {
|
||||
}
|
||||
}
|
||||
|
||||
.view-switcher,
|
||||
.t-btn-view-large {
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
}
|
||||
|
||||
.view-control {
|
||||
@extend .icon-arrow-right;
|
||||
cursor: pointer;
|
||||
font-size: 0.75em;
|
||||
&:before {
|
||||
position: absolute;
|
||||
@include trans-prop-nice(transform, 100ms);
|
||||
@include transform-origin(center);
|
||||
}
|
||||
&.expanded:before {
|
||||
@include transform(rotate(90deg));
|
||||
}
|
||||
}
|
||||
|
||||
.grippy {
|
||||
@extend .icon-grippy;
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
/******************************************************** BROWSER ELEMENTS */
|
||||
body.desktop {
|
||||
::-webkit-scrollbar {
|
||||
|
||||
@@ -29,27 +29,23 @@
|
||||
}
|
||||
|
||||
.icon {
|
||||
font-size: 16px;
|
||||
font-size: 16px; //120%;
|
||||
}
|
||||
|
||||
.title-label {
|
||||
margin-left: $interiorMarginSm;
|
||||
}
|
||||
|
||||
.icon-swatch,
|
||||
.color-swatch {
|
||||
// Used in color menu buttons in toolbar
|
||||
$d: 10px;
|
||||
display: inline-block;
|
||||
border: 1px solid rgba($colorBtnFg, 0.2);
|
||||
height: $d; width: $d;
|
||||
line-height: $d;
|
||||
height: $d;
|
||||
width: $d;
|
||||
vertical-align: middle;
|
||||
margin-left: $interiorMarginSm;
|
||||
margin-top: -2px;
|
||||
&:not(.no-selection) {
|
||||
border-color: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
&:after {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/******************************************************************* STATUS BLOCK ELEMS */
|
||||
|
||||
@mixin statusBannerColors($bg, $fg: $colorStatusFg) {
|
||||
$bgPb: 30%;
|
||||
$bgPbD: 10%;
|
||||
@@ -120,11 +120,7 @@
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
background: none !important;
|
||||
margin-right: $interiorMarginSm;
|
||||
&[class*='s-status']:before {
|
||||
font-size: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.count {
|
||||
@@ -140,7 +136,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************* MESSAGE BANNERS */
|
||||
/* Styles for messages and message banners */
|
||||
.message {
|
||||
&.block {
|
||||
border-radius: $basicCr;
|
||||
@@ -196,6 +192,7 @@
|
||||
padding: 0 $interiorMargin;
|
||||
}
|
||||
.close {
|
||||
//@include test(red, 0.7);
|
||||
cursor: pointer;
|
||||
font-size: 7px;
|
||||
width: 8px;
|
||||
@@ -239,147 +236,132 @@
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************************* MESSAGES */
|
||||
|
||||
/* Contexts:
|
||||
In .t-message-list
|
||||
In .overlay as a singleton
|
||||
Inline in the view area
|
||||
*/
|
||||
|
||||
// Archetypal message
|
||||
.l-message {
|
||||
$iconW: 32px;
|
||||
@include display(flex);
|
||||
@include flex-direction(row);
|
||||
@include align-items(stretch);
|
||||
padding: $interiorMarginLg;
|
||||
|
||||
&:before {
|
||||
// Icon
|
||||
@include flex(0 1 auto);
|
||||
@mixin messageBlock($iconW: 32px) {
|
||||
.type-icon.message-type {
|
||||
@include txtShdw($shdwStatusIc);
|
||||
@extend .icon-bell;
|
||||
color: $colorStatusDefault;
|
||||
font-size: $iconW;
|
||||
padding: 1px;
|
||||
width: $iconW + 2;
|
||||
margin-right: $interiorMarginLg;
|
||||
}
|
||||
|
||||
&.message-severity-info:before {
|
||||
.message-severity-info .type-icon.message-type {
|
||||
@extend .icon-info;
|
||||
color: $colorInfo;
|
||||
}
|
||||
|
||||
&.message-severity-alert:before {
|
||||
.message-severity-alert .type-icon.message-type {
|
||||
@extend .icon-bell;
|
||||
color: $colorWarningLo;
|
||||
}
|
||||
|
||||
&.message-severity-error:before {
|
||||
.message-severity-error .type-icon.message-type {
|
||||
@extend .icon-alert-rect;
|
||||
color: $colorWarningHi;
|
||||
}
|
||||
}
|
||||
/* Paths:
|
||||
t-dialog | t-dialog-sm > t-message-single | t-message-list > overlay > holder > contents > l-message >
|
||||
message-type > (icon)
|
||||
message-contents >
|
||||
top-bar >
|
||||
title
|
||||
hint
|
||||
editor >
|
||||
(if displaying list of messages)
|
||||
ul > li > l-message >
|
||||
... same as above
|
||||
bottom-bar
|
||||
*/
|
||||
|
||||
|
||||
.w-message-contents {
|
||||
@include flex(1 1 auto);
|
||||
.l-message {
|
||||
@include display(flex);
|
||||
@include flex-direction(column);
|
||||
|
||||
> div,
|
||||
> span {
|
||||
//@include test(red);
|
||||
margin-bottom: $interiorMargin;
|
||||
@include flex-direction(row);
|
||||
@include align-items(stretch);
|
||||
.type-icon.message-type {
|
||||
@include flex(0 1 auto);
|
||||
position: relative;
|
||||
}
|
||||
.message-contents {
|
||||
@include flex(1 1 auto);
|
||||
margin-left: $overlayMargin;
|
||||
position: relative;
|
||||
|
||||
.message-body {
|
||||
@include flex(1 1 100%);
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton in an overlay dialog
|
||||
.t-message-single .l-message,
|
||||
.t-message-single.l-message {
|
||||
$iconW: 80px;
|
||||
@include absPosDefault();
|
||||
padding: 0;
|
||||
&:before {
|
||||
font-size: $iconW;
|
||||
width: $iconW + 2;
|
||||
}
|
||||
.title {
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton inline in a view
|
||||
.t-message-inline .l-message,
|
||||
.t-message-inline.l-message {
|
||||
border-radius: $controlCr;
|
||||
&.message-severity-info { background-color: rgba($colorInfo, 0.3); }
|
||||
&.message-severity-alert { background-color: rgba($colorWarningLo, 0.3); }
|
||||
&.message-severity-error { background-color: rgba($colorWarningHi, 0.3); }
|
||||
|
||||
.w-message-contents.l-message-body-only {
|
||||
.top-bar,
|
||||
.message-body {
|
||||
margin-top: $interiorMargin;
|
||||
margin-bottom: $interiorMarginLg * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// In a list
|
||||
.t-message-list {
|
||||
@include absPosDefault();
|
||||
@include display(flex);
|
||||
@include flex-direction(column);
|
||||
|
||||
> div,
|
||||
> span {
|
||||
margin-bottom: $interiorMargin;
|
||||
// Message as singleton
|
||||
.t-message-single {
|
||||
@include messageBlock(80px);
|
||||
}
|
||||
|
||||
body.desktop .t-message-single {
|
||||
.l-message,
|
||||
.bottom-bar {
|
||||
@include absPosDefault();
|
||||
}
|
||||
|
||||
.w-messages {
|
||||
@include flex(1 1 100%);
|
||||
overflow-y: auto;
|
||||
padding-right: $interiorMargin;
|
||||
.bottom-bar {
|
||||
top: auto;
|
||||
height: $ovrFooterH;
|
||||
}
|
||||
// Each message
|
||||
.l-message {
|
||||
border-radius: $controlCr;
|
||||
background: rgba($colorOvrFg, 0.1);
|
||||
margin-bottom: $interiorMargin;
|
||||
.hint,
|
||||
.bottom-bar {
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@include phonePortrait {
|
||||
.t-message-single .l-message,
|
||||
.t-message-single.l-message {
|
||||
@include flex-direction(column);
|
||||
&:before {
|
||||
margin-right: 0;
|
||||
.t-message-single {
|
||||
.l-message {
|
||||
@include flex-direction(column);
|
||||
.message-contents { margin-left: 0; }
|
||||
}
|
||||
.type-icon.message-type {
|
||||
margin-bottom: $interiorMarginLg;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
text-align: center;
|
||||
.s-button {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: center !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Messages in list
|
||||
.t-message-list {
|
||||
@include messageBlock(32px);
|
||||
|
||||
.message-contents {
|
||||
.l-message {
|
||||
border-radius: $controlCr;
|
||||
background: rgba($colorOvrFg, 0.1);
|
||||
margin-bottom: $interiorMargin;
|
||||
padding: $interiorMarginLg;
|
||||
|
||||
.message-contents,
|
||||
.bottom-bar {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.message-contents {
|
||||
font-size: 0.9em;
|
||||
margin-left: $interiorMarginLg;
|
||||
.message-action { color: pushBack($colorOvrFg, 20%); }
|
||||
.bottom-bar { text-align: left; }
|
||||
}
|
||||
|
||||
.top-bar,
|
||||
.message-body {
|
||||
margin-bottom: $interiorMarginLg;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
body.desktop .t-message-list {
|
||||
.w-message-contents { padding-right: $interiorMargin; }
|
||||
.message-contents .l-message { margin-right: $interiorMarginLg; }
|
||||
}
|
||||
|
||||
// Alert elements in views
|
||||
|
||||
@@ -20,19 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.section-header {
|
||||
border-radius: $basicCr;
|
||||
background: $colorFormSectionHeader;
|
||||
color: lighten($colorBodyFg, 20%);
|
||||
font-size: inherit;
|
||||
margin: $interiorMargin 0;
|
||||
padding: $formTBPad $formLRPad;
|
||||
text-transform: uppercase;
|
||||
.view-control {
|
||||
display: inline-block;
|
||||
margin-right: $interiorMargin;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.form {
|
||||
@@ -53,6 +41,15 @@
|
||||
}
|
||||
}
|
||||
|
||||
.section-header {
|
||||
border-radius: $basicCr;
|
||||
background: $colorFormSectionHeader;
|
||||
$c: lighten($colorBodyFg, 20%);
|
||||
color: $c;
|
||||
font-size: 0.8em;
|
||||
padding: $formTBPad $formLRPad;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
$m: $interiorMargin;
|
||||
box-sizing: border-box;
|
||||
@@ -60,6 +57,9 @@
|
||||
margin-bottom: $interiorMarginLg * 2;
|
||||
padding: $formTBPad 0;
|
||||
position: relative;
|
||||
//&ng-form {
|
||||
// display: block;
|
||||
//}
|
||||
|
||||
&.first {
|
||||
border-top: none;
|
||||
@@ -171,106 +171,3 @@
|
||||
padding: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************************************** COMPACT FORM */
|
||||
// ul > li > label, control
|
||||
// Make a new UL for each form section
|
||||
// Allow control-first, controls-below
|
||||
// TO-DO: migrate work in branch ch-plot-styling that users .inspector-config to use classes below instead
|
||||
|
||||
.l-compact-form .tree ul li,
|
||||
.l-compact-form ul li {
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
|
||||
.l-compact-form {
|
||||
$labelW: 40%;
|
||||
$minW: $labelW;
|
||||
ul {
|
||||
margin-bottom: $interiorMarginLg;
|
||||
li {
|
||||
@include display(flex);
|
||||
@include flex-wrap(wrap);
|
||||
@include align-items(center);
|
||||
label,
|
||||
.control {
|
||||
@include display(flex);
|
||||
}
|
||||
label {
|
||||
line-height: inherit;
|
||||
width: $labelW;
|
||||
}
|
||||
.controls {
|
||||
@include flex-grow(1);
|
||||
margin-left: $interiorMargin;
|
||||
input[type="text"],
|
||||
input[type="search"],
|
||||
input[type="number"],
|
||||
.select {
|
||||
height: $btnStdH;
|
||||
line-height: $btnStdH;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.e-control {
|
||||
// Individual form controls
|
||||
&:not(:first-child) {
|
||||
margin-left: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.connects-to-previous {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
&.section-header {
|
||||
margin-top: $interiorMarginLg;
|
||||
border-top: 1px solid $colorFormLines;
|
||||
}
|
||||
|
||||
&.controls-first {
|
||||
.control {
|
||||
@include flex-grow(0);
|
||||
margin-right: $interiorMargin;
|
||||
min-width: 0;
|
||||
order: 1;
|
||||
width: auto;
|
||||
}
|
||||
label {
|
||||
@include flex-grow(1);
|
||||
order: 2;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
&.controls-under {
|
||||
display: block;
|
||||
.control, label {
|
||||
display: block;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
ul li {
|
||||
border-top: none !important;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.form-error {
|
||||
// Block element that visually flags an error and contains a message
|
||||
background-color: $colorFormFieldErrorBg;
|
||||
color: $colorFormFieldErrorFg;
|
||||
border-radius: $basicCr;
|
||||
display: block;
|
||||
padding: 1px 6px;
|
||||
&:before {
|
||||
content: $glyph-icon-alert-triangle;
|
||||
display: inline;
|
||||
font-family: symbolsfont;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,6 @@
|
||||
|
||||
// Dialog boxes, size constrained and centered in desktop/tablet
|
||||
&.l-dialog {
|
||||
font-size: 0.8rem;
|
||||
.s-button {
|
||||
&:not(.major) {
|
||||
@include btnSubtle($bg: $colorOvrBtnBg, $bgHov: pullForward($colorOvrBtnBg, 10%), $fg: $colorOvrBtnFg, $fgHov: $colorOvrBtnFg, $ic: $colorOvrBtnFg, $icHov: $colorOvrBtnFg);
|
||||
@@ -126,9 +125,9 @@
|
||||
@include containerSubtle($colorOvrBg, $colorOvrFg);
|
||||
}
|
||||
|
||||
.dialog-title {
|
||||
.title {
|
||||
@include ellipsize();
|
||||
font-size: 1.5em;
|
||||
font-size: 1.2em;
|
||||
line-height: 120%;
|
||||
margin-bottom: $interiorMargin;
|
||||
}
|
||||
|
||||
@@ -52,13 +52,21 @@ ul.tree {
|
||||
|
||||
.view-control {
|
||||
color: $colorItemTreeVC;
|
||||
font-size: 0.75em;
|
||||
margin-right: $interiorMargin;
|
||||
height: 100%;
|
||||
line-height: inherit;
|
||||
width: $treeVCW;
|
||||
&:before { display: none; }
|
||||
&.has-children {
|
||||
&:before { display: block; }
|
||||
&:before {
|
||||
position: absolute;
|
||||
@include trans-prop-nice(transform, 100ms);
|
||||
content: "\e904";
|
||||
@include transform-origin(center);
|
||||
}
|
||||
&.expanded:before {
|
||||
@include transform(rotate(90deg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,8 +44,7 @@
|
||||
|
||||
&.t-object-type-timer,
|
||||
&.t-object-type-clock,
|
||||
&.t-object-type-hyperlink,
|
||||
&.t-object-type-summary-widget {
|
||||
&.t-object-type-hyperlink {
|
||||
// Hide the right side buttons for objects where they don't make sense
|
||||
// Note that this will hide the view Switcher button if applied
|
||||
// to an object that has it.
|
||||
@@ -126,21 +125,14 @@
|
||||
pointer-events: none !important;
|
||||
}
|
||||
|
||||
/********************************************************** OBJECT TYPES */
|
||||
.t-object-type-hyperlink,
|
||||
.t-object-type-summary-widget {
|
||||
/********************************************************** OBJECT TYPES */
|
||||
.t-object-type-hyperlink {
|
||||
.object-holder {
|
||||
overflow: hidden;
|
||||
}
|
||||
.w-summary-widget,
|
||||
.l-summary-widget,
|
||||
.l-hyperlink.s-button {
|
||||
// Some object types expand to the full size of the object-holder.
|
||||
// When a hyperlink is a button in a frame, make it expand to fill out to the object-holder
|
||||
@extend .abs;
|
||||
}
|
||||
|
||||
.l-summary-widget,
|
||||
.l-hyperlink.s-button {
|
||||
.label {
|
||||
@include ellipsize();
|
||||
@include transform(translateY(-50%));
|
||||
|
||||
@@ -108,11 +108,8 @@ define(
|
||||
|
||||
getMetadata();
|
||||
});
|
||||
|
||||
var mutation = $scope.ngModel.selectedObject.getCapability('mutation');
|
||||
var unlisten = mutation.listen(getMetadata);
|
||||
$scope.$on('$destroy', unlisten);
|
||||
}
|
||||
|
||||
return ObjectInspectorController;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -39,18 +39,10 @@ define(
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
["$watch", "$on"]
|
||||
["$watch"]
|
||||
);
|
||||
mockScope.ngModel = {};
|
||||
mockScope.ngModel.selectedObject = {
|
||||
getCapability: function () {
|
||||
return {
|
||||
listen: function () {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
mockScope.ngModel.selectedObject = 'mock selected object';
|
||||
|
||||
mockObjectService = jasmine.createSpyObj(
|
||||
"objectService",
|
||||
|
||||
@@ -243,12 +243,6 @@ $colorCalCellSelectedBg: $colorItemTreeSelectedBg;
|
||||
$colorCalCellSelectedFg: $colorItemTreeSelectedFg;
|
||||
$colorCalCellInMonthBg: pushBack($colorMenuBg, 5%);
|
||||
|
||||
// Palettes
|
||||
$colorPaletteFg: pullForward($colorMenuBg, 30%);
|
||||
$colorPaletteSelected: #fff;
|
||||
$shdwPaletteFg: black 0 0 2px;
|
||||
$shdwPaletteSelected: inset 0 0 0 1px #000;
|
||||
|
||||
// About Screen
|
||||
$colorAboutLink: #84b3ff;
|
||||
|
||||
|
||||
@@ -243,12 +243,6 @@ $colorCalCellSelectedBg: $colorItemTreeSelectedBg;
|
||||
$colorCalCellSelectedFg: $colorItemTreeSelectedFg;
|
||||
$colorCalCellInMonthBg: pullForward($colorMenuBg, 5%);
|
||||
|
||||
// Palettes
|
||||
$colorPaletteFg: pullForward($colorMenuBg, 30%);
|
||||
$colorPaletteSelected: #333;
|
||||
$shdwPaletteFg: none;
|
||||
$shdwPaletteSelected: inset 0 0 0 1px #fff;
|
||||
|
||||
// About Screen
|
||||
$colorAboutLink: #84b3ff;
|
||||
|
||||
|
||||
@@ -23,13 +23,10 @@
|
||||
define([
|
||||
"moment-timezone",
|
||||
"./src/indicators/ClockIndicator",
|
||||
"./src/indicators/FollowIndicator",
|
||||
"./src/services/TickerService",
|
||||
"./src/services/TimerService",
|
||||
"./src/controllers/ClockController",
|
||||
"./src/controllers/TimerController",
|
||||
"./src/controllers/RefreshingController",
|
||||
"./src/actions/FollowTimerAction",
|
||||
"./src/actions/StartTimerAction",
|
||||
"./src/actions/RestartTimerAction",
|
||||
"./src/actions/StopTimerAction",
|
||||
@@ -40,13 +37,10 @@ define([
|
||||
], function (
|
||||
MomentTimezone,
|
||||
ClockIndicator,
|
||||
FollowIndicator,
|
||||
TickerService,
|
||||
TimerService,
|
||||
ClockController,
|
||||
TimerController,
|
||||
RefreshingController,
|
||||
FollowTimerAction,
|
||||
StartTimerAction,
|
||||
RestartTimerAction,
|
||||
StopTimerAction,
|
||||
@@ -86,11 +80,6 @@ define([
|
||||
"CLOCK_INDICATOR_FORMAT"
|
||||
],
|
||||
"priority": "preferred"
|
||||
},
|
||||
{
|
||||
"implementation": FollowIndicator,
|
||||
"depends": ["timerService"],
|
||||
"priority": "fallback"
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
@@ -101,11 +90,6 @@ define([
|
||||
"$timeout",
|
||||
"now"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "timerService",
|
||||
"implementation": TimerService,
|
||||
"depends": ["openmct"]
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
@@ -150,15 +134,6 @@ define([
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"key": "timer.follow",
|
||||
"implementation": FollowTimerAction,
|
||||
"depends": ["timerService"],
|
||||
"category": "contextual",
|
||||
"name": "Follow Timer",
|
||||
"cssClass": "icon-clock",
|
||||
"priority": "optional"
|
||||
},
|
||||
{
|
||||
"key": "timer.start",
|
||||
"implementation": StartTimerAction,
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Designates a specific timer for following. Timelines, for example,
|
||||
* use the actively followed timer to display a time-of-interest line
|
||||
* and interpret time conductor bounds in the Timeline's relative
|
||||
* time frame.
|
||||
*
|
||||
* @implements {Action}
|
||||
* @memberof platform/features/clock
|
||||
* @constructor
|
||||
* @param {ActionContext} context the context for this action
|
||||
*/
|
||||
function FollowTimerAction(timerService, context) {
|
||||
var domainObject =
|
||||
context.domainObject &&
|
||||
context.domainObject.useCapability('adapter');
|
||||
this.perform =
|
||||
timerService.setTimer.bind(timerService, domainObject);
|
||||
}
|
||||
|
||||
FollowTimerAction.appliesTo = function (context) {
|
||||
var model =
|
||||
(context.domainObject && context.domainObject.getModel()) ||
|
||||
{};
|
||||
|
||||
return model.type === 'timer';
|
||||
};
|
||||
|
||||
return FollowTimerAction;
|
||||
}
|
||||
);
|
||||
@@ -1,113 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(['EventEmitter'], function (EventEmitter) {
|
||||
|
||||
/**
|
||||
* Tracks the currently-followed Timer object. Used by
|
||||
* timelines et al to synchronize to a particular timer.
|
||||
*
|
||||
* The TimerService emits `change` events when the active timer
|
||||
* is changed.
|
||||
*/
|
||||
function TimerService(openmct) {
|
||||
EventEmitter.apply(this);
|
||||
this.time = openmct.time;
|
||||
this.objects = openmct.objects;
|
||||
}
|
||||
|
||||
TimerService.prototype = Object.create(EventEmitter.prototype);
|
||||
|
||||
/**
|
||||
* Set (or clear, if `timer` is undefined) the currently active timer.
|
||||
* @param {DomainObject} timer the new active timer
|
||||
* @emits change
|
||||
*/
|
||||
TimerService.prototype.setTimer = function (timer) {
|
||||
this.timer = timer;
|
||||
this.emit('change');
|
||||
|
||||
if (this.stopObserving) {
|
||||
this.stopObserving();
|
||||
delete this.stopObserving;
|
||||
}
|
||||
|
||||
if (timer) {
|
||||
this.stopObserving =
|
||||
this.objects.observe(timer, '*', this.setTimer.bind(this));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the currently active timer.
|
||||
* @return {DomainObject} the active timer
|
||||
* @emits change
|
||||
*/
|
||||
TimerService.prototype.getTimer = function () {
|
||||
return this.timer;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Check if there is a currently active timer.
|
||||
* @return {boolean} true if there is a timer
|
||||
*/
|
||||
TimerService.prototype.hasTimer = function () {
|
||||
return !!this.timer;
|
||||
};
|
||||
|
||||
/**
|
||||
* Convert the provided timestamp to milliseconds relative to
|
||||
* the active timer.
|
||||
* @return {number} milliseconds since timer start
|
||||
*/
|
||||
TimerService.prototype.convert = function (timestamp) {
|
||||
var clock = this.time.clock();
|
||||
var canConvert = this.hasTimer() &&
|
||||
!!clock &&
|
||||
this.timer.timerState !== 'stopped';
|
||||
|
||||
if (!canConvert) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var now = clock.currentValue();
|
||||
var delta = this.timer.timerState === 'paused' ?
|
||||
now - this.timer.pausedTime : 0;
|
||||
var epoch = this.timer.timestamp;
|
||||
|
||||
return timestamp - epoch - delta;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the value of the active clock, adjusted to be relative to the active
|
||||
* timer. If there is no clock or no active timer, this will return
|
||||
* `undefined`.
|
||||
* @return {number} milliseconds since the start of the active timer
|
||||
*/
|
||||
TimerService.prototype.now = function () {
|
||||
var clock = this.time.clock();
|
||||
return clock && this.convert(clock.currentValue());
|
||||
};
|
||||
|
||||
return TimerService;
|
||||
});
|
||||
@@ -1,87 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
"../../src/actions/FollowTimerAction"
|
||||
], function (FollowTimerAction) {
|
||||
var TIMER_SERVICE_METHODS =
|
||||
['setTimer', 'getTimer', 'clearTimer', 'on', 'off'];
|
||||
|
||||
describe("The Follow Timer action", function () {
|
||||
var testContext;
|
||||
var testModel;
|
||||
var testAdaptedObject;
|
||||
|
||||
beforeEach(function () {
|
||||
testModel = {};
|
||||
testContext = { domainObject: jasmine.createSpyObj('domainObject', [
|
||||
'getModel',
|
||||
'useCapability'
|
||||
]) };
|
||||
testAdaptedObject = { foo: 'bar' };
|
||||
testContext.domainObject.getModel.andReturn(testModel);
|
||||
testContext.domainObject.useCapability.andCallFake(function (c) {
|
||||
return c === 'adapter' && testAdaptedObject;
|
||||
});
|
||||
});
|
||||
|
||||
it("is applicable to timers", function () {
|
||||
testModel.type = "timer";
|
||||
expect(FollowTimerAction.appliesTo(testContext)).toBe(true);
|
||||
});
|
||||
|
||||
it("is inapplicable to non-timers", function () {
|
||||
testModel.type = "folder";
|
||||
expect(FollowTimerAction.appliesTo(testContext)).toBe(false);
|
||||
});
|
||||
|
||||
describe("when instantiated", function () {
|
||||
var mockTimerService;
|
||||
var action;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimerService = jasmine.createSpyObj(
|
||||
'timerService',
|
||||
TIMER_SERVICE_METHODS
|
||||
);
|
||||
action = new FollowTimerAction(mockTimerService, testContext);
|
||||
});
|
||||
|
||||
it("does not interact with the timer service", function () {
|
||||
TIMER_SERVICE_METHODS.forEach(function (method) {
|
||||
expect(mockTimerService[method]).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("and performed", function () {
|
||||
beforeEach(function () {
|
||||
action.perform();
|
||||
});
|
||||
|
||||
it("sets the active timer", function () {
|
||||
expect(mockTimerService.setTimer)
|
||||
.toHaveBeenCalledWith(testAdaptedObject);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,61 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(["../../src/indicators/FollowIndicator"], function (FollowIndicator) {
|
||||
var TIMER_SERVICE_METHODS =
|
||||
['setTimer', 'getTimer', 'clearTimer', 'on', 'off'];
|
||||
|
||||
describe("The timer-following indicator", function () {
|
||||
var mockTimerService;
|
||||
var indicator;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimerService =
|
||||
jasmine.createSpyObj('timerService', TIMER_SERVICE_METHODS);
|
||||
indicator = new FollowIndicator(mockTimerService);
|
||||
});
|
||||
|
||||
it("implements the Indicator interface", function () {
|
||||
expect(indicator.getGlyphClass()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getCssClass()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getText()).toEqual(jasmine.any(String));
|
||||
expect(indicator.getDescription()).toEqual(jasmine.any(String));
|
||||
});
|
||||
|
||||
describe("when a timer is set", function () {
|
||||
var testModel;
|
||||
var mockDomainObject;
|
||||
|
||||
beforeEach(function () {
|
||||
testModel = { name: "some timer!" };
|
||||
mockDomainObject = jasmine.createSpyObj('timer', ['getModel']);
|
||||
mockDomainObject.getModel.andReturn(testModel);
|
||||
mockTimerService.getTimer.andReturn(mockDomainObject);
|
||||
});
|
||||
|
||||
it("displays the timer's name", function () {
|
||||
expect(indicator.getText().indexOf(testModel.name))
|
||||
.not.toEqual(-1);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,77 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'../../src/services/TimerService'
|
||||
], function (TimerService) {
|
||||
describe("TimerService", function () {
|
||||
var callback;
|
||||
var mockmct;
|
||||
var timerService;
|
||||
|
||||
beforeEach(function () {
|
||||
callback = jasmine.createSpy('callback');
|
||||
mockmct = {
|
||||
time: { clock: jasmine.createSpy('clock') },
|
||||
objects: { observe: jasmine.createSpy('observe') }
|
||||
};
|
||||
timerService = new TimerService(mockmct);
|
||||
timerService.on('change', callback);
|
||||
});
|
||||
|
||||
it("initially emits no change events", function () {
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reports no current timer", function () {
|
||||
expect(timerService.getTimer()).toBeUndefined();
|
||||
});
|
||||
|
||||
describe("setTimer", function () {
|
||||
var testTimer;
|
||||
|
||||
beforeEach(function () {
|
||||
testTimer = { name: "I am some timer; you are nobody." };
|
||||
timerService.setTimer(testTimer);
|
||||
});
|
||||
|
||||
it("emits a change event", function () {
|
||||
expect(callback).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("reports the current timer", function () {
|
||||
expect(timerService.getTimer()).toBe(testTimer);
|
||||
});
|
||||
|
||||
it("observes changes to an object", function () {
|
||||
var newTimer = { name: "I am another timer." };
|
||||
expect(mockmct.objects.observe).toHaveBeenCalledWith(
|
||||
testTimer,
|
||||
'*',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
mockmct.objects.observe.mostRecentCall.args[2](newTimer);
|
||||
expect(timerService.getTimer()).toBe(newTimer);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -255,8 +255,6 @@ define(
|
||||
if (this.nextDatum) {
|
||||
this.updateValues(this.nextDatum);
|
||||
delete this.nextDatum;
|
||||
} else {
|
||||
this.updateValues(this.$scope.imageHistory[this.$scope.imageHistory.length - 1]);
|
||||
}
|
||||
this.autoScroll = true;
|
||||
}
|
||||
|
||||
@@ -183,17 +183,6 @@ define(
|
||||
expect(controller.getImageUrl()).toEqual(newUrl);
|
||||
});
|
||||
|
||||
it("forwards large image view to latest image in history on un-pause", function () {
|
||||
$scope.imageHistory = [
|
||||
{ utc: 1434600258122, url: 'some/url1', selected: false},
|
||||
{ utc: 1434600258123, url: 'some/url2', selected: false}
|
||||
];
|
||||
controller.paused(true);
|
||||
controller.paused(false);
|
||||
|
||||
expect(controller.getImageUrl()).toEqual(controller.getImageUrl($scope.imageHistory[1]));
|
||||
});
|
||||
|
||||
it("subscribes to telemetry", function () {
|
||||
expect(openmct.telemetry.subscribe).toHaveBeenCalledWith(
|
||||
newDomainObject,
|
||||
@@ -238,7 +227,7 @@ define(
|
||||
expect(controller.updateHistory(mockDatum)).toBe(false);
|
||||
});
|
||||
|
||||
describe("when user clicks on imagery thumbnail", function () {
|
||||
describe("user clicks on imagery thumbnail", function () {
|
||||
var mockDatum = { utc: 1434600258123, url: 'some/url', selected: false};
|
||||
|
||||
it("pauses and adds selected class to imagery thumbnail", function () {
|
||||
@@ -259,7 +248,6 @@ define(
|
||||
expect(controller.getTime()).toEqual(controller.timeFormat.format(mockDatum.utc));
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it("initially shows an empty string for date/time", function () {
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="frame frame-template t-frame-inner abs t-object-type-{{ domainObject.getModel().type }}">
|
||||
<div class="frame frame-template t-frame-inner abs t-object-type-{{ representation.selected.key }}">
|
||||
<div class="abs object-browse-bar l-flex-row">
|
||||
<div class="left flex-elem l-flex-row grows">
|
||||
<mct-representation
|
||||
|
||||
@@ -360,47 +360,22 @@ define(
|
||||
*/
|
||||
FixedController.prototype.updateView = function (telemetryObject, datum) {
|
||||
var metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
var telemetryKeyToDisplay = this.chooseTelemetryKeyToDisplay(metadata);
|
||||
var formattedTelemetryValue = this.getFormattedTelemetryValueForKey(telemetryKeyToDisplay, datum, metadata);
|
||||
var rangeMetadata = metadata.valuesForHints(['range'])[0];
|
||||
var rangeKey = rangeMetadata.source || rangeMetadata.key;
|
||||
var valueMetadata = metadata.value(rangeKey);
|
||||
var limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
|
||||
var alarm = limitEvaluator && limitEvaluator.evaluate(datum, telemetryKeyToDisplay);
|
||||
var formatter = this.openmct.telemetry.getValueFormatter(valueMetadata);
|
||||
var value = datum[valueMetadata.key];
|
||||
var alarm = limitEvaluator && limitEvaluator.evaluate(datum, rangeKey);
|
||||
|
||||
this.setDisplayedValue(
|
||||
telemetryObject,
|
||||
formattedTelemetryValue,
|
||||
formatter.format(value),
|
||||
alarm && alarm.cssClass
|
||||
);
|
||||
this.digest();
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.getFormattedTelemetryValueForKey = function (telemetryKeyToDisplay, datum, metadata) {
|
||||
var valueMetadata = metadata.value(telemetryKeyToDisplay);
|
||||
var formatter = this.openmct.telemetry.getValueFormatter(valueMetadata);
|
||||
|
||||
return formatter.format(datum[valueMetadata.key]);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
FixedController.prototype.chooseTelemetryKeyToDisplay = function (metadata) {
|
||||
// If there is a range value, show that preferentially
|
||||
var telemetryKeyToDisplay = metadata.valuesForHints(['range'])[0];
|
||||
|
||||
// If no range is defined, default to the highest priority non time-domain data.
|
||||
if (telemetryKeyToDisplay === undefined) {
|
||||
var valuesOrderedByPriority = metadata.values();
|
||||
telemetryKeyToDisplay = valuesOrderedByPriority.filter(function (valueMetadata) {
|
||||
return !(valueMetadata.hints.domain);
|
||||
})[0];
|
||||
}
|
||||
|
||||
return telemetryKeyToDisplay.source;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request the last historical data point for the given domain objects
|
||||
* @param {object[]} objects
|
||||
@@ -413,9 +388,7 @@ define(
|
||||
objects.forEach(function (object) {
|
||||
self.openmct.telemetry.request(object, {start: bounds.start, end: bounds.end, size: 1})
|
||||
.then(function (data) {
|
||||
if (data.length > 0) {
|
||||
self.updateView(object, data[data.length - 1]);
|
||||
}
|
||||
self.updateView(object, data[data.length - 1]);
|
||||
});
|
||||
});
|
||||
return objects;
|
||||
|
||||
@@ -26,12 +26,8 @@
|
||||
* @namespace platform/features/layout
|
||||
*/
|
||||
define(
|
||||
[
|
||||
'./LayoutDrag'
|
||||
],
|
||||
function (
|
||||
LayoutDrag
|
||||
) {
|
||||
['./LayoutDrag'],
|
||||
function (LayoutDrag) {
|
||||
|
||||
var DEFAULT_DIMENSIONS = [12, 8],
|
||||
DEFAULT_GRID_SIZE = [32, 32],
|
||||
@@ -127,8 +123,6 @@ define(
|
||||
if (self.droppedIdToSelectAfterRefresh) {
|
||||
self.select(null, self.droppedIdToSelectAfterRefresh);
|
||||
delete self.droppedIdToSelectAfterRefresh;
|
||||
} else if (composition.indexOf(self.selectedId) === -1) {
|
||||
self.clearSelection();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -178,6 +178,7 @@ define(
|
||||
Promise.resolve(mockChildren)
|
||||
);
|
||||
|
||||
|
||||
mockScope.model = testModel;
|
||||
mockScope.configuration = testConfiguration;
|
||||
mockScope.selection = jasmine.createSpyObj(
|
||||
@@ -193,8 +194,7 @@ define(
|
||||
|
||||
mockMetadata = jasmine.createSpyObj('mockMetadata', [
|
||||
'valuesForHints',
|
||||
'value',
|
||||
'values'
|
||||
'value'
|
||||
]);
|
||||
mockMetadata.value.andReturn({
|
||||
key: 'value'
|
||||
@@ -653,39 +653,6 @@ define(
|
||||
});
|
||||
});
|
||||
|
||||
it("selects an range value to display, if available", function () {
|
||||
mockMetadata.valuesForHints.andReturn([
|
||||
{
|
||||
key: 'range',
|
||||
source: 'range'
|
||||
}
|
||||
]);
|
||||
var key = controller.chooseTelemetryKeyToDisplay(mockMetadata);
|
||||
expect(key).toEqual('range');
|
||||
});
|
||||
|
||||
it("selects the first non-domain value to display, if no range available", function () {
|
||||
mockMetadata.valuesForHints.andReturn([]);
|
||||
mockMetadata.values.andReturn([
|
||||
{
|
||||
key: 'domain',
|
||||
source: 'domain',
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: 'image',
|
||||
source: 'image',
|
||||
hints: {
|
||||
image: 1
|
||||
}
|
||||
}
|
||||
]);
|
||||
var key = controller.chooseTelemetryKeyToDisplay(mockMetadata);
|
||||
expect(key).toEqual('image');
|
||||
});
|
||||
|
||||
it("reflects limit status", function () {
|
||||
mockLimitEvaluator.evaluate.andReturn({cssClass: "alarm-a"});
|
||||
controller.updateView(mockTelemetryObject, [{
|
||||
|
||||
@@ -424,17 +424,6 @@ define(
|
||||
expect(selectedObj.showFrame).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("deselects the object that is no longer in the composition", function () {
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
var childObj = mockCompositionObjects[0];
|
||||
controller.select(mockEvent, childObj.getId());
|
||||
|
||||
var composition = ["b", "c"];
|
||||
mockScope.$watchCollection.mostRecentCall.args[1](composition);
|
||||
|
||||
expect(controller.selected(childObj)).toBe(false);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
{
|
||||
"key": "ListViewController",
|
||||
"implementation": ListViewController,
|
||||
"depends": ["$scope", "formatService"]
|
||||
"depends": ["$scope"]
|
||||
}
|
||||
],
|
||||
"directives": [
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define(function () {
|
||||
function ListViewController($scope, formatService) {
|
||||
function ListViewController($scope) {
|
||||
this.$scope = $scope;
|
||||
$scope.orderByField = 'title';
|
||||
$scope.reverseSort = false;
|
||||
@@ -30,8 +30,6 @@ define(function () {
|
||||
var unlisten = $scope.domainObject.getCapability('mutation')
|
||||
.listen(this.updateView.bind(this));
|
||||
|
||||
this.utc = formatService.getFormat('utc');
|
||||
|
||||
$scope.$on('$destroy', function () {
|
||||
unlisten();
|
||||
});
|
||||
@@ -52,13 +50,17 @@ define(function () {
|
||||
icon: child.getCapability('type').getCssClass(),
|
||||
title: child.getModel().name,
|
||||
type: child.getCapability('type').getName(),
|
||||
persisted: this.utc.format(child.getModel().persisted),
|
||||
modified: this.utc.format(child.getModel().modified),
|
||||
persisted: new Date(
|
||||
child.getModel().persisted
|
||||
).toUTCString(),
|
||||
modified: new Date(
|
||||
child.getModel().modified
|
||||
).toUTCString(),
|
||||
asDomainObject: child,
|
||||
location: child.getCapability('location'),
|
||||
action: child.getCapability('action')
|
||||
};
|
||||
}, this);
|
||||
});
|
||||
};
|
||||
|
||||
return ListViewController;
|
||||
|
||||
@@ -31,9 +31,7 @@ define(
|
||||
controller,
|
||||
childModel,
|
||||
typeCapability,
|
||||
mutationCapability,
|
||||
formatService;
|
||||
|
||||
mutationCapability;
|
||||
beforeEach(function () {
|
||||
unlistenFunc = jasmine.createSpy("unlisten");
|
||||
|
||||
@@ -43,18 +41,6 @@ define(
|
||||
);
|
||||
mutationCapability.listen.andReturn(unlistenFunc);
|
||||
|
||||
formatService = jasmine.createSpyObj(
|
||||
"formatService",
|
||||
["getFormat"]
|
||||
);
|
||||
formatService.getFormat.andReturn(jasmine.createSpyObj(
|
||||
'utc',
|
||||
["format"]
|
||||
));
|
||||
formatService.getFormat().format.andCallFake(function (v) {
|
||||
return "formatted " + v;
|
||||
});
|
||||
|
||||
typeCapability = jasmine.createSpyObj(
|
||||
"typeCapability",
|
||||
["getCssClass", "getName"]
|
||||
@@ -108,27 +94,20 @@ define(
|
||||
);
|
||||
scope.domainObject = domainObject;
|
||||
|
||||
controller = new ListViewController(scope, formatService);
|
||||
controller = new ListViewController(scope);
|
||||
|
||||
waitsFor(function () {
|
||||
return scope.children;
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the UTC time format", function () {
|
||||
expect(formatService.getFormat).toHaveBeenCalledWith('utc');
|
||||
});
|
||||
|
||||
it("updates the view", function () {
|
||||
expect(scope.children[0]).toEqual(
|
||||
{
|
||||
icon: "icon-folder",
|
||||
title: "Battery Charge Status",
|
||||
type: "Folder",
|
||||
persisted: formatService.getFormat('utc')
|
||||
.format(childModel.persisted),
|
||||
modified: formatService.getFormat('utc')
|
||||
.format(childModel.modified),
|
||||
persisted: "Wed, 07 Jun 2017 20:34:57 GMT",
|
||||
modified: "Wed, 07 Jun 2017 20:34:57 GMT",
|
||||
asDomainObject: childObject,
|
||||
location: ''
|
||||
}
|
||||
|
||||
@@ -170,9 +170,6 @@ define(
|
||||
* @param rows
|
||||
*/
|
||||
TelemetryTableController.prototype.addRowsToTable = function (rows) {
|
||||
rows.forEach(function (row) {
|
||||
this.$scope.rows.push(row);
|
||||
}, this);
|
||||
this.$scope.$broadcast('add:rows', rows);
|
||||
};
|
||||
|
||||
|
||||
@@ -436,28 +436,5 @@ define(
|
||||
expect(mockScope.$broadcast).toHaveBeenCalledWith("remove:rows", discardedRows);
|
||||
});
|
||||
|
||||
describe('when telemetry is added', function () {
|
||||
var testRows;
|
||||
var expectedRows;
|
||||
|
||||
beforeEach(function () {
|
||||
testRows = [{ a: 0 }, { a: 1 }, { a: 2 }];
|
||||
mockScope.rows = [{ a: -1 }];
|
||||
expectedRows = mockScope.rows.concat(testRows);
|
||||
|
||||
spyOn(controller.telemetry, "on").andCallThrough();
|
||||
controller.registerChangeListeners();
|
||||
|
||||
controller.telemetry.on.calls.forEach(function (call) {
|
||||
if (call.args[0] === 'added') {
|
||||
call.args[1](testRows);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it("adds it to rows in scope", function () {
|
||||
expect(mockScope.rows).toEqual(expectedRows);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -29,7 +29,6 @@ define([
|
||||
"./src/controllers/TimelineTickController",
|
||||
"./src/controllers/TimelineTableController",
|
||||
"./src/controllers/TimelineGanttController",
|
||||
"./src/controllers/TimelineTOIController",
|
||||
"./src/controllers/ActivityModeValuesController",
|
||||
"./src/capabilities/ActivityTimespanCapability",
|
||||
"./src/capabilities/TimelineTimespanCapability",
|
||||
@@ -38,7 +37,6 @@ define([
|
||||
"./src/capabilities/CostCapability",
|
||||
"./src/directives/MCTSwimlaneDrop",
|
||||
"./src/directives/MCTSwimlaneDrag",
|
||||
"./src/directives/MCTResourceGraphDrop",
|
||||
"./src/services/ObjectLoader",
|
||||
"./src/chart/MCTTimelineChart",
|
||||
"text!./res/templates/values.html",
|
||||
@@ -61,7 +59,6 @@ define([
|
||||
TimelineTickController,
|
||||
TimelineTableController,
|
||||
TimelineGanttController,
|
||||
TimelineTOIController,
|
||||
ActivityModeValuesController,
|
||||
ActivityTimespanCapability,
|
||||
TimelineTimespanCapability,
|
||||
@@ -70,7 +67,6 @@ define([
|
||||
CostCapability,
|
||||
MCTSwimlaneDrop,
|
||||
MCTSwimlaneDrag,
|
||||
MCTResourceGraphDrop,
|
||||
ObjectLoader,
|
||||
MCTTimelineChart,
|
||||
valuesTemplate,
|
||||
@@ -506,15 +502,6 @@ define([
|
||||
"TIMELINE_MAXIMUM_OFFSCREEN"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "TimelineTOIController",
|
||||
"implementation": TimelineTOIController,
|
||||
"depends": [
|
||||
"openmct",
|
||||
"timerService",
|
||||
"$scope"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "ActivityModeValuesController",
|
||||
"implementation": ActivityModeValuesController,
|
||||
@@ -579,13 +566,6 @@ define([
|
||||
"$interval",
|
||||
"$log"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "mctResourceGraphDrop",
|
||||
"implementation": MCTResourceGraphDrop,
|
||||
"depends": [
|
||||
"dndService"
|
||||
]
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
|
||||
@@ -29,44 +29,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Follow Line
|
||||
.l-follow-line {
|
||||
// TODO: move before and after into l-timeline-gantt so those only render in that pane
|
||||
pointer-events: none;
|
||||
position: absolute;
|
||||
top: 0; bottom: 0;
|
||||
width: 1px;
|
||||
z-index: 9; // Just below .l-hover-btns-holder
|
||||
}
|
||||
}
|
||||
|
||||
.l-timeline-gantt {
|
||||
.l-follow-line {
|
||||
$d: 0.8rem;
|
||||
top: $interiorMargin;
|
||||
&:before,
|
||||
&:after {
|
||||
content: '';
|
||||
display: block;
|
||||
height: $d;
|
||||
width: $d;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@include transform(translateX(-50%));
|
||||
}
|
||||
&:before {
|
||||
// Icon blocker
|
||||
width: 2 * $d;
|
||||
}
|
||||
&:after {
|
||||
// Icon
|
||||
font-size: $d;
|
||||
line-height: $d;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.s-timeline-gantt {
|
||||
@@ -146,9 +108,10 @@
|
||||
}
|
||||
.s-hover-btns-holder {
|
||||
$bg: $timelineHeaderColorBg;
|
||||
$bga: 1;
|
||||
$l: 5%;
|
||||
@include user-select(none);
|
||||
@include background-image(linear-gradient(-90deg, rgba($bg, 1), rgba($bg, 1) 70%, rgba($bg, 0) 100%));
|
||||
@include background-image(linear-gradient(-90deg, rgba($bg, $bga), rgba($bg, $bga) 70%, rgba($bg, 0) 100%));
|
||||
.s-button {
|
||||
height: 16px;
|
||||
line-height: 16px;
|
||||
@@ -166,27 +129,4 @@
|
||||
color: $timelineResourceGraphFg;
|
||||
}
|
||||
}
|
||||
|
||||
.s-follow-line {
|
||||
background: rgba($timeControllerToiLineColor, 0.5);
|
||||
}
|
||||
|
||||
.s-timeline-gantt {
|
||||
.s-follow-line {
|
||||
&:after {
|
||||
// Icon
|
||||
color: $timeControllerToiLineColor;
|
||||
content: $glyph-icon-timer;
|
||||
font-family: symbolsfont;
|
||||
text-shadow: $shdwItemText;
|
||||
}
|
||||
&:before {
|
||||
// Blocker
|
||||
$bg: $timelineHeaderColorBg;
|
||||
$l: 30%;
|
||||
@include background-image(linear-gradient(90deg, rgba($bg, 0), rgba($bg, 1) $l, rgba($bg, 1) 100% - $l, rgba($bg, 0)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,10 +38,6 @@
|
||||
.l-timeline-pane {
|
||||
@include absPosDefault();
|
||||
|
||||
&.drop-over {
|
||||
background-color: lighten($colorEditAreaBg, 5%);
|
||||
}
|
||||
|
||||
.l-width-control {
|
||||
position: relative;
|
||||
}
|
||||
@@ -79,10 +75,6 @@
|
||||
}
|
||||
}
|
||||
&.l-timeline-gantt {
|
||||
.abs.l-timeline-gantt-header-w {
|
||||
overflow: hidden;
|
||||
height: $timelineTopPaneHeaderH;
|
||||
}
|
||||
.l-swimlanes-holder {
|
||||
@include scrollV(scroll);
|
||||
bottom: $scrollbarTrackSize;
|
||||
|
||||
@@ -24,7 +24,6 @@ $output-bourbon-deprecation-warnings: false;
|
||||
|
||||
@import "../../../../commonUI/general/res/sass/constants";
|
||||
@import "../../../../commonUI/general/res/sass/mixins";
|
||||
@import "../../../../commonUI/general/res/sass/glyphs";
|
||||
@import "../../../../commonUI/themes/espresso/res/sass/constants";
|
||||
@import "../../../../commonUI/themes/espresso/res/sass/mixins";
|
||||
@import "constants";
|
||||
|
||||
@@ -24,7 +24,6 @@ $output-bourbon-deprecation-warnings: false;
|
||||
|
||||
@import "../../../../commonUI/general/res/sass/constants";
|
||||
@import "../../../../commonUI/general/res/sass/mixins";
|
||||
@import "../../../../commonUI/general/res/sass/glyphs";
|
||||
@import "../../../../commonUI/themes/snow/res/sass/constants";
|
||||
@import "../../../../commonUI/themes/snow/res/sass/mixins";
|
||||
@import "constants";
|
||||
|
||||
@@ -24,7 +24,6 @@ $output-bourbon-deprecation-warnings: false;
|
||||
|
||||
@import "../../../../commonUI/general/res/sass/constants";
|
||||
@import "../../../../commonUI/general/res/sass/mixins";
|
||||
@import "../../../../commonUI/general/res/sass/glyphs";
|
||||
@import "../../../../commonUI/themes/espresso/res/sass/constants";
|
||||
@import "../../../../commonUI/themes/espresso/res/sass/mixins";
|
||||
@import "constants";
|
||||
|
||||
@@ -77,8 +77,7 @@
|
||||
<mct-splitter></mct-splitter>
|
||||
|
||||
<!-- BOTTOM PANE RESOURCE LEGEND -->
|
||||
<div mct-resource-graph-drop
|
||||
class="split-pane-component abs l-timeline-pane t-pane-h l-pane-btm s-timeline-resource-legend l-timeline-resource-legend">
|
||||
<div class="split-pane-component abs l-timeline-pane t-pane-h l-pane-btm s-timeline-resource-legend l-timeline-resource-legend">
|
||||
<div class="l-title s-title">{{ngModel.title}}Resource Graph Legend</div>
|
||||
<div class="l-legend-items legend">
|
||||
<mct-include key="'timeline-legend-item'"
|
||||
@@ -97,124 +96,109 @@
|
||||
|
||||
<!-- RIGHT PANE: GANTT AND RESOURCE PLOTS -->
|
||||
<span ng-controller="TimelineZoomController as zoomController" class="abs">
|
||||
|
||||
<span class="toi-control-holder temp" ng-controller="TimelineTOIController as toiController">
|
||||
<mct-split-pane anchor="bottom"
|
||||
<mct-split-pane anchor="bottom"
|
||||
position="pane.y"
|
||||
class="abs split-pane-component l-timeline-pane l-pane-r t-pane-v">
|
||||
|
||||
<!-- TOP PANE GANTT BARS -->
|
||||
<div class="split-pane-component l-timeline-pane t-pane-h l-pane-top t-timeline-gantt l-timeline-gantt s-timeline-gantt">
|
||||
<div class="l-hover-btns-holder s-hover-btns-holder">
|
||||
<a class="s-button icon-timer"
|
||||
ng-click="scroll.follow = true"
|
||||
ng-show="!toiController.isFollowing() && toiController.isActive()"
|
||||
title="Follow time bounds">
|
||||
</a>
|
||||
<!-- TOP PANE GANTT BARS -->
|
||||
<div class="split-pane-component l-timeline-pane t-pane-h l-pane-top t-timeline-gantt l-timeline-gantt s-timeline-gantt">
|
||||
<div class="l-hover-btns-holder s-hover-btns-holder">
|
||||
<a class="s-button icon-arrows-out"
|
||||
ng-click="zoomController.fit()"
|
||||
ng-show="true"
|
||||
title="Zoom to fit">
|
||||
</a>
|
||||
|
||||
<a class="s-button icon-arrows-out"
|
||||
ng-click="scroll.follow = false; zoomController.fit()"
|
||||
ng-show="true"
|
||||
title="Zoom to fit">
|
||||
</a>
|
||||
<a class="s-button icon-magnify-in"
|
||||
ng-click="zoomController.zoom(-1)"
|
||||
ng-show="true"
|
||||
title="Zoom in">
|
||||
</a>
|
||||
|
||||
<a class="s-button icon-magnify-in"
|
||||
ng-click="scroll.follow = false; zoomController.zoom(-1)"
|
||||
ng-show="true"
|
||||
title="Zoom in">
|
||||
</a>
|
||||
<a class="s-button icon-magnify-out"
|
||||
ng-click="zoomController.zoom(1)"
|
||||
ng-show="true"
|
||||
title="Zoom out">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<a class="s-button icon-magnify-out"
|
||||
ng-click="scroll.follow = false; zoomController.zoom(1)"
|
||||
ng-show="true"
|
||||
title="Zoom out">
|
||||
</a>
|
||||
</div>
|
||||
<div style="overflow: hidden; position: absolute; left: 0; top: 0; right: 0; height: 30px;" mct-scroll-x="scroll.x">
|
||||
<mct-include key="'timeline-ticks'"
|
||||
parameters="{
|
||||
fullWidth: zoomController.width(timelineController.end()),
|
||||
start: scroll.x,
|
||||
width: scroll.width,
|
||||
step: zoomController.toPixels(zoomController.zoom()),
|
||||
toMillis: zoomController.toMillis
|
||||
}">
|
||||
</mct-include>
|
||||
</div>
|
||||
|
||||
<div style="overflow: hidden; position: absolute; left: 0; top: 0; right: 0; height: 30px;" mct-scroll-x="scroll.x">
|
||||
<mct-include key="'timeline-ticks'"
|
||||
parameters="{
|
||||
fullWidth: zoomController.width(timelineController.end()),
|
||||
start: scroll.x,
|
||||
width: scroll.width,
|
||||
step: zoomController.toPixels(zoomController.zoom()),
|
||||
toMillis: zoomController.toMillis
|
||||
}">
|
||||
</mct-include>
|
||||
</div>
|
||||
<div ng-if="toiController.isActive()" class="l-follow-line s-follow-line"
|
||||
ng-style="{ left: toiController.x() - scroll.x + 'px' }"></div>
|
||||
<div class="t-swimlanes-holder l-swimlanes-holder"
|
||||
mct-scroll-x="scroll.x"
|
||||
mct-scroll-y="scroll.y">
|
||||
<div class="l-width-control"
|
||||
ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
|
||||
<div class="t-swimlane s-swimlane l-swimlane"
|
||||
ng-repeat="swimlane in timelineController.swimlanes()"
|
||||
ng-class="{
|
||||
exceeded: swimlane.exceeded(),
|
||||
selected: selection.selected(swimlane),
|
||||
'drop-into': swimlane.highlight(),
|
||||
'drop-after': swimlane.highlightBottom()
|
||||
}"
|
||||
ng-click="selection.select(swimlane)"
|
||||
mct-swimlane-drop="swimlane">
|
||||
|
||||
<div class="t-swimlanes-holder l-swimlanes-holder"
|
||||
mct-scroll-x="scroll.x"
|
||||
mct-scroll-y="scroll.y">
|
||||
<div class="l-width-control"
|
||||
ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
|
||||
<div class="t-swimlane s-swimlane l-swimlane"
|
||||
ng-repeat="swimlane in timelineController.swimlanes()"
|
||||
ng-class="{
|
||||
exceeded: swimlane.exceeded(),
|
||||
selected: selection.selected(swimlane),
|
||||
'drop-into': swimlane.highlight(),
|
||||
'drop-after': swimlane.highlightBottom()
|
||||
}"
|
||||
ng-click="selection.select(swimlane)"
|
||||
mct-swimlane-drop="swimlane">
|
||||
<mct-representation key="'gantt'"
|
||||
mct-object="swimlane.domainObject"
|
||||
parameters="{
|
||||
scroll: scroll,
|
||||
toPixels: zoomController.toPixels
|
||||
}">
|
||||
</mct-representation>
|
||||
|
||||
<mct-representation key="'gantt'"
|
||||
mct-object="swimlane.domainObject"
|
||||
parameters="{
|
||||
scroll: scroll,
|
||||
toPixels: zoomController.toPixels
|
||||
}">
|
||||
</mct-representation>
|
||||
|
||||
<span ng-if="selection.selected(swimlane)">
|
||||
<span ng-repeat="handle in timelineController.handles()"
|
||||
ng-style="handle.style(zoomController)"
|
||||
style="position: absolute; top: 0px; bottom: 0px;"
|
||||
class="handle"
|
||||
ng-class="{ start: $index === 0, mid: $index === 1, end: $index > 1 }"
|
||||
mct-drag-down="handle.begin()"
|
||||
mct-drag="handle.drag(delta[0], zoomController); timelineController.refresh()"
|
||||
mct-drag-up="handle.finish()">
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<span ng-if="selection.selected(swimlane)">
|
||||
<span ng-repeat="handle in timelineController.handles()"
|
||||
ng-style="handle.style(zoomController)"
|
||||
style="position: absolute; top: 0px; bottom: 0px;"
|
||||
class="handle"
|
||||
ng-class="{ start: $index === 0, mid: $index === 1, end: $index > 1 }"
|
||||
mct-drag-down="handle.begin()"
|
||||
mct-drag="handle.drag(delta[0], zoomController); timelineController.refresh()"
|
||||
mct-drag-up="handle.finish()">
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- HORZ SPLITTER -->
|
||||
<mct-splitter></mct-splitter>
|
||||
<!-- HORZ SPLITTER -->
|
||||
<mct-splitter></mct-splitter>
|
||||
|
||||
<!-- BOTTOM PANE RESOURCE GRAPHS AND RIGHT PANE HORIZONTAL SCROLL CONTROL -->
|
||||
<div class="split-pane-component l-timeline-resource-graph l-timeline-pane t-pane-h l-pane-btm">
|
||||
<div class="l-graphs-holder"
|
||||
mct-resize="scroll.width = bounds.width">
|
||||
<div class="t-graphs l-graphs">
|
||||
<mct-include key="'timeline-resource-graphs'"
|
||||
parameters="{
|
||||
origin: zoomController.toMillis(scroll.x),
|
||||
duration: zoomController.toMillis(scroll.width),
|
||||
graphs: timelineController.graphs()
|
||||
}">
|
||||
</mct-include>
|
||||
</div>
|
||||
<div ng-if="toiController.isActive()" class="l-follow-line s-follow-line"
|
||||
ng-style="{ left: toiController.x() - scroll.x + 'px' }"></div>
|
||||
</div>
|
||||
<div mct-scroll-x="scroll.x"
|
||||
class="t-pane-r-scroll-h-control l-scroll-control s-scroll-control">
|
||||
<div class="l-width-control"
|
||||
ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
|
||||
</div>
|
||||
</div>
|
||||
<!-- BOTTOM PANE RESOURCE GRAPHS AND RIGHT PANE HORIZONTAL SCROLL CONTROL -->
|
||||
<div class="split-pane-component l-timeline-resource-graph l-timeline-pane t-pane-h l-pane-btm">
|
||||
<div class="l-graphs-holder"
|
||||
mct-resize="scroll.width = bounds.width">
|
||||
<div class="t-graphs l-graphs">
|
||||
<mct-include key="'timeline-resource-graphs'"
|
||||
parameters="{
|
||||
origin: zoomController.toMillis(scroll.x),
|
||||
duration: zoomController.toMillis(scroll.width),
|
||||
graphs: timelineController.graphs()
|
||||
}">
|
||||
</mct-include>
|
||||
</div>
|
||||
</mct-split-pane>
|
||||
</span>
|
||||
|
||||
|
||||
</div>
|
||||
<div mct-scroll-x="scroll.x"
|
||||
class="t-pane-r-scroll-h-control l-scroll-control s-scroll-control">
|
||||
<div class="l-width-control"
|
||||
ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</mct-split-pane>
|
||||
</span>
|
||||
</mct-split-pane>
|
||||
</div>
|
||||
|
||||
@@ -1,111 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([], function () {
|
||||
|
||||
/**
|
||||
* Tracks time-of-interest in timelines, updating both scroll state
|
||||
* (when appropriate) and positioning of the displayed line.
|
||||
*/
|
||||
function TimelineTOIController(openmct, timerService, $scope) {
|
||||
this.openmct = openmct;
|
||||
this.timerService = timerService;
|
||||
this.$scope = $scope;
|
||||
|
||||
this.change = this.change.bind(this);
|
||||
this.bounds = this.bounds.bind(this);
|
||||
this.destroy = this.destroy.bind(this);
|
||||
|
||||
this.timerService.on('change', this.change);
|
||||
this.openmct.time.on('bounds', this.bounds);
|
||||
|
||||
this.$scope.$on('$destroy', this.destroy);
|
||||
|
||||
this.$scope.scroll.follow = this.timerService.hasTimer();
|
||||
if (this.$scope.zoomController) {
|
||||
this.bounds(this.openmct.time.bounds());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle a `change` event from the timer service; track the
|
||||
* new timer.
|
||||
*/
|
||||
TimelineTOIController.prototype.change = function () {
|
||||
this.$scope.scroll.follow =
|
||||
this.$scope.scroll.follow || this.timerService.hasTimer();
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a `bounds` event from the time API; scroll the timeline
|
||||
* to match the current bounds, if currently in follow mode.
|
||||
*/
|
||||
TimelineTOIController.prototype.bounds = function (bounds) {
|
||||
if (this.isFollowing()) {
|
||||
var start = this.timerService.convert(bounds.start);
|
||||
var end = this.timerService.convert(bounds.end);
|
||||
this.duration = bounds.end - bounds.start;
|
||||
this.$scope.zoomController.bounds(start, end);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a `$destroy` event from scope; detach all observers.
|
||||
*/
|
||||
TimelineTOIController.prototype.destroy = function () {
|
||||
this.timerService.off('change', this.change);
|
||||
this.openmct.time.off('bounds', this.bounds);
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the x position of the time-of-interest line,
|
||||
* in pixels from the left edge of the timeline area.
|
||||
*/
|
||||
TimelineTOIController.prototype.x = function () {
|
||||
var now = this.timerService.now();
|
||||
|
||||
if (now === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return this.$scope.zoomController.toPixels(this.timerService.now());
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if there is an active time-of-interest to be shown.
|
||||
* @return {boolean} true when active
|
||||
*/
|
||||
TimelineTOIController.prototype.isActive = function () {
|
||||
return this.x() !== undefined;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if the timeline should be following time conductor bounds.
|
||||
* @return {boolean} true when following
|
||||
*/
|
||||
TimelineTOIController.prototype.isFollowing = function () {
|
||||
return !!this.$scope.scroll.follow && this.timerService.now() !== undefined;
|
||||
};
|
||||
|
||||
return TimelineTOIController;
|
||||
});
|
||||
@@ -32,8 +32,7 @@ define(
|
||||
// Prefer to start with the middle index
|
||||
var zoomLevels = ZOOM_CONFIGURATION.levels || [1000],
|
||||
zoomIndex = Math.floor(zoomLevels.length / 2),
|
||||
tickWidth = ZOOM_CONFIGURATION.width || 200,
|
||||
lastWidth = Number.MAX_VALUE; // Don't constrain prematurely
|
||||
tickWidth = ZOOM_CONFIGURATION.width || 200;
|
||||
|
||||
function toMillis(pixels) {
|
||||
return (pixels / tickWidth) * zoomLevels[zoomIndex];
|
||||
@@ -56,29 +55,19 @@ define(
|
||||
|
||||
function setScroll(x) {
|
||||
$window.requestAnimationFrame(function () {
|
||||
$scope.scroll.x = Math.min(
|
||||
Math.max(x, 0),
|
||||
lastWidth - $scope.scroll.width
|
||||
);
|
||||
$scope.scroll.x = x;
|
||||
$scope.$apply();
|
||||
});
|
||||
}
|
||||
|
||||
function initializeZoomFromStartEnd(start, end) {
|
||||
var duration = end - start;
|
||||
function initializeZoomFromTimespan(timespan) {
|
||||
var timelineDuration = timespan.getDuration();
|
||||
zoomIndex = 0;
|
||||
while (toMillis($scope.scroll.width) < duration &&
|
||||
while (toMillis($scope.scroll.width) < timelineDuration &&
|
||||
zoomIndex < zoomLevels.length - 1) {
|
||||
zoomIndex += 1;
|
||||
}
|
||||
setScroll(toPixels(start));
|
||||
}
|
||||
|
||||
function initializeZoomFromTimespan(timespan) {
|
||||
return initializeZoomFromStartEnd(
|
||||
timespan.getStart(),
|
||||
timespan.getEnd()
|
||||
);
|
||||
setScroll(toPixels(timespan.getStart()));
|
||||
}
|
||||
|
||||
function initializeZoom() {
|
||||
@@ -112,13 +101,6 @@ define(
|
||||
}
|
||||
return zoomLevels[zoomIndex];
|
||||
},
|
||||
/**
|
||||
* Adjust the current zoom bounds to fit both the
|
||||
* start and the end time provided.
|
||||
* @param {number} start the starting timestamp
|
||||
* @param {number} end the ending timestamp
|
||||
*/
|
||||
bounds: initializeZoomFromStartEnd,
|
||||
/**
|
||||
* Set the zoom level to fit the bounds of the timeline
|
||||
* being viewed.
|
||||
@@ -137,14 +119,14 @@ define(
|
||||
*/
|
||||
toMillis: toMillis,
|
||||
/**
|
||||
* Set the maximum timestamp value to be displayed, and get
|
||||
* the pixel width necessary to display this value.
|
||||
* Get the pixel width necessary to fit the specified
|
||||
* timestamp, expressed as an offset in milliseconds from
|
||||
* the start of the timeline.
|
||||
* @param {number} timestamp the time to display
|
||||
*/
|
||||
width: function (timestamp) {
|
||||
var pixels = Math.ceil(toPixels(timestamp * (1 + PADDING)));
|
||||
lastWidth = Math.max($scope.scroll.width, pixels);
|
||||
return lastWidth;
|
||||
return Math.max($scope.scroll.width, pixels);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['./SwimlaneDragConstants'],
|
||||
function (SwimlaneDragConstants) {
|
||||
|
||||
/**
|
||||
* Defines the `mct-resource-graph-drop` directive. When a drop occurs
|
||||
* on an element with this attribute, the swimlane targeted by the drop
|
||||
* will receive the dropped domain object (at which point it can handle
|
||||
* the drop, typically by toggling the swimlane graph.)
|
||||
* @param {DndService} dndService drag-and-drop service
|
||||
*/
|
||||
function MCTResourceGraphDrop(dndService) {
|
||||
|
||||
function link(scope, element, attrs) {
|
||||
// Handle dragover
|
||||
element.on('dragover', function (e) {
|
||||
var swimlane = dndService.getData(
|
||||
SwimlaneDragConstants.TIMELINE_SWIMLANE_DRAG_TYPE
|
||||
);
|
||||
|
||||
if (typeof swimlane !== "undefined" && !swimlane.graph()) {
|
||||
element.addClass('drop-over');
|
||||
scope.$apply();
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
// Handle drops
|
||||
element.on('drop', function (e) {
|
||||
var swimlane = dndService.getData(
|
||||
SwimlaneDragConstants.TIMELINE_SWIMLANE_DRAG_TYPE
|
||||
);
|
||||
|
||||
element.removeClass('drop-over');
|
||||
|
||||
// Only toggle if the graph isn't already set
|
||||
if (typeof swimlane !== "undefined" && !swimlane.graph()) {
|
||||
swimlane.toggleGraph();
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
// Clear highlights when drag leaves this swimlane
|
||||
element.on('dragleave', function (e) {
|
||||
element.removeClass('drop-over');
|
||||
scope.$apply();
|
||||
e.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
// Applies to attributes
|
||||
restrict: "A",
|
||||
// Link using above function
|
||||
link: link
|
||||
};
|
||||
}
|
||||
|
||||
return MCTResourceGraphDrop;
|
||||
}
|
||||
);
|
||||
@@ -1,138 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
"../../src/controllers/TimelineTOIController",
|
||||
"EventEmitter"
|
||||
], function (TimelineTOIController, EventEmitter) {
|
||||
describe("The timeline TOI controller", function () {
|
||||
var mockmct;
|
||||
var mockTimerService;
|
||||
var mockScope;
|
||||
var controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockmct = { time: new EventEmitter() };
|
||||
mockmct.time.bounds = jasmine.createSpy('bounds');
|
||||
mockTimerService = new EventEmitter();
|
||||
mockTimerService.getTimer = jasmine.createSpy('getTimer');
|
||||
mockTimerService.hasTimer = jasmine.createSpy('hasTimer');
|
||||
mockTimerService.now = jasmine.createSpy('now');
|
||||
mockTimerService.convert = jasmine.createSpy('convert');
|
||||
mockScope = new EventEmitter();
|
||||
mockScope.$on = mockScope.on.bind(mockScope);
|
||||
mockScope.zoomController = jasmine.createSpyObj('zoom', [
|
||||
'bounds',
|
||||
'toPixels'
|
||||
]);
|
||||
mockScope.scroll = { x: 10, width: 1000 };
|
||||
|
||||
spyOn(mockmct.time, "on").andCallThrough();
|
||||
spyOn(mockmct.time, "off").andCallThrough();
|
||||
spyOn(mockTimerService, "on").andCallThrough();
|
||||
spyOn(mockTimerService, "off").andCallThrough();
|
||||
|
||||
controller = new TimelineTOIController(
|
||||
mockmct,
|
||||
mockTimerService,
|
||||
mockScope
|
||||
);
|
||||
});
|
||||
|
||||
it("reports an undefined x position initially", function () {
|
||||
expect(controller.x()).toBeUndefined();
|
||||
});
|
||||
|
||||
it("listens for bounds changes", function () {
|
||||
expect(mockmct.time.on)
|
||||
.toHaveBeenCalledWith('bounds', controller.bounds);
|
||||
});
|
||||
|
||||
it("listens for timer changes", function () {
|
||||
expect(mockTimerService.on)
|
||||
.toHaveBeenCalledWith('change', controller.change);
|
||||
});
|
||||
|
||||
it("is not active", function () {
|
||||
expect(controller.isActive()).toBe(false);
|
||||
});
|
||||
|
||||
describe("on $destroy from scope", function () {
|
||||
beforeEach(function () {
|
||||
mockScope.emit("$destroy");
|
||||
});
|
||||
|
||||
it("unregisters listeners", function () {
|
||||
expect(mockmct.time.off)
|
||||
.toHaveBeenCalledWith('bounds', controller.bounds);
|
||||
expect(mockTimerService.off)
|
||||
.toHaveBeenCalledWith('change', controller.change);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when a timer and timestamp present", function () {
|
||||
var mockTimer;
|
||||
var testNow;
|
||||
|
||||
beforeEach(function () {
|
||||
testNow = 333221;
|
||||
mockScope.zoomController.toPixels
|
||||
.andCallFake(function (millis) {
|
||||
return millis * 2;
|
||||
});
|
||||
mockTimerService.emit('change', mockTimer);
|
||||
mockTimerService.now.andReturn(testNow);
|
||||
});
|
||||
|
||||
it("reports an x value from the zoomController", function () {
|
||||
var now = mockTimerService.now();
|
||||
var expected = mockScope.zoomController.toPixels(now);
|
||||
expect(controller.x()).toEqual(expected);
|
||||
});
|
||||
});
|
||||
|
||||
describe("when follow mode is disabled", function () {
|
||||
beforeEach(function () {
|
||||
mockScope.scroll.follow = false;
|
||||
});
|
||||
|
||||
it("ignores bounds events", function () {
|
||||
mockmct.time.emit('bounds', { start: 0, end: 1000 });
|
||||
expect(mockScope.zoomController.bounds)
|
||||
.not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("when follow mode is enabled", function () {
|
||||
beforeEach(function () {
|
||||
mockScope.scroll.follow = true;
|
||||
mockTimerService.now.andReturn(500);
|
||||
});
|
||||
|
||||
it("zooms on bounds events", function () {
|
||||
mockmct.time.emit('bounds', { start: 0, end: 1000 });
|
||||
expect(mockScope.zoomController.bounds)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,159 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['../../src/directives/MCTResourceGraphDrop', '../../src/directives/SwimlaneDragConstants'],
|
||||
function (MCTResourceGraphDrop, SwimlaneDragConstants) {
|
||||
|
||||
describe("The mct-resource-graph-drop directive", function () {
|
||||
var mockDndService,
|
||||
mockScope,
|
||||
mockElement,
|
||||
testAttrs,
|
||||
mockSwimlane,
|
||||
testEvent,
|
||||
handlers,
|
||||
directive;
|
||||
|
||||
beforeEach(function () {
|
||||
handlers = {};
|
||||
|
||||
mockDndService = jasmine.createSpyObj(
|
||||
'dndService',
|
||||
['setData', 'getData', 'removeData']
|
||||
);
|
||||
mockScope = jasmine.createSpyObj('$scope', ['$eval', '$apply']);
|
||||
mockElement = jasmine.createSpyObj('element', ['on', 'addClass', 'removeClass']);
|
||||
testAttrs = { mctSwimlaneDrop: "mockSwimlane" };
|
||||
mockSwimlane = jasmine.createSpyObj(
|
||||
"swimlane",
|
||||
['graph', 'toggleGraph']
|
||||
);
|
||||
|
||||
testEvent = {
|
||||
dataTransfer: { getData: jasmine.createSpy() },
|
||||
preventDefault: jasmine.createSpy(),
|
||||
stopPropagation: jasmine.createSpy()
|
||||
};
|
||||
|
||||
testEvent.dataTransfer.getData.andReturn('abc');
|
||||
mockDndService.getData.andCallFake(function (key) {
|
||||
return key === SwimlaneDragConstants.TIMELINE_SWIMLANE_DRAG_TYPE ?
|
||||
mockSwimlane : undefined;
|
||||
});
|
||||
|
||||
mockSwimlane.graph.andReturn(false);
|
||||
|
||||
directive = new MCTResourceGraphDrop(mockDndService);
|
||||
directive.link(mockScope, mockElement, testAttrs);
|
||||
|
||||
mockElement.on.calls.forEach(function (call) {
|
||||
handlers[call.args[0]] = call.args[1];
|
||||
});
|
||||
});
|
||||
|
||||
it("is available as an attribute", function () {
|
||||
expect(directive.restrict).toEqual("A");
|
||||
});
|
||||
|
||||
[false, true].forEach(function (graphing) {
|
||||
describe("when swimlane graph is " + (graphing ? "" : "not ") + "enabled", function () {
|
||||
beforeEach(function () {
|
||||
mockSwimlane.graph.andReturn(graphing);
|
||||
});
|
||||
|
||||
|
||||
describe("on dragover", function () {
|
||||
var prefix = !graphing ? "does" : "does not";
|
||||
|
||||
beforeEach(function () {
|
||||
handlers.dragover(testEvent);
|
||||
});
|
||||
|
||||
it(prefix + " add a drop-over class", function () {
|
||||
var expectAddClass = expect(mockElement.addClass);
|
||||
(!graphing ? expectAddClass : expectAddClass.not)
|
||||
.toHaveBeenCalledWith('drop-over');
|
||||
});
|
||||
|
||||
it(prefix + " call $apply on scope", function () {
|
||||
var expectApply = expect(mockScope.$apply);
|
||||
(!graphing ? expectApply : expectApply.not)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(prefix + " prevent default", function () {
|
||||
var expectPreventDefault = expect(testEvent.preventDefault);
|
||||
(!graphing ? expectPreventDefault : expectPreventDefault.not)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("on drop", function () {
|
||||
var prefix = !graphing ? "does" : "does not";
|
||||
|
||||
beforeEach(function () {
|
||||
handlers.drop(testEvent);
|
||||
});
|
||||
|
||||
it("removes any drop-over class", function () {
|
||||
expect(mockElement.removeClass)
|
||||
.toHaveBeenCalledWith('drop-over');
|
||||
});
|
||||
|
||||
it(prefix + " toggle the swimlane's resource graph", function () {
|
||||
var expectToggle = expect(mockSwimlane.toggleGraph);
|
||||
(!graphing ? expectToggle : expectToggle.not)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it(prefix + " prevent default", function () {
|
||||
var expectPreventDefault = expect(testEvent.preventDefault);
|
||||
(!graphing ? expectPreventDefault : expectPreventDefault.not)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("on dragleave", function () {
|
||||
beforeEach(function () {
|
||||
handlers.dragleave(testEvent);
|
||||
});
|
||||
|
||||
it("removes any drop-over class", function () {
|
||||
expect(mockElement.removeClass)
|
||||
.toHaveBeenCalledWith('drop-over');
|
||||
});
|
||||
|
||||
it("calls $apply on scope", function () {
|
||||
expect(mockScope.$apply).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("calls preventDefault on events", function () {
|
||||
expect(testEvent.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -24,22 +24,21 @@
|
||||
|
||||
<span class="l-click-area" ng-click="toggle.toggle()"></span>
|
||||
<span class="color-swatch"
|
||||
ng-class="{'no-selection':ngModel[field] === 'transparent'}"
|
||||
ng-style="{
|
||||
'background-color': ngModel[field]
|
||||
background: ngModel[field]
|
||||
}">
|
||||
</span>
|
||||
<span class="title-label" ng-if="structure.text">
|
||||
{{structure.text}}
|
||||
</span>
|
||||
|
||||
<div class="menu l-palette l-color-palette"
|
||||
<div class="menu l-color-palette"
|
||||
ng-controller="ColorController as colors"
|
||||
ng-show="toggle.isActive()">
|
||||
<div
|
||||
class="l-palette-row l-option-row"
|
||||
ng-if="!structure.mandatory">
|
||||
<div class="l-palette-item s-palette-item no-selection {{ngModel[field] === 'transparent' ? 'selected' : '' }}"
|
||||
<div class="l-palette-item s-palette-item {{ngModel[field] === 'transparent' ? 'icon-check' : '' }}"
|
||||
ng-click="ngModel[field] = 'transparent'">
|
||||
</div>
|
||||
<span class="l-palette-item-label">None</span>
|
||||
@@ -47,7 +46,7 @@
|
||||
<div
|
||||
class="l-palette-row"
|
||||
ng-repeat="group in colors.groups()">
|
||||
<div class="l-palette-item s-palette-item {{ngModel[field] === color ? 'selected' : '' }}"
|
||||
<div class="l-palette-item s-palette-item {{ngModel[field] === color ? 'icon-check' : '' }}"
|
||||
ng-repeat="color in group"
|
||||
ng-style="{ background: color }"
|
||||
ng-click="ngModel[field] = color">
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
ng-required="ngRequired || compositeCtrl.isNonEmpty(ngModel[field])"
|
||||
ng-pattern="ngPattern"
|
||||
options="item.options"
|
||||
structure="item"
|
||||
structure="row"
|
||||
field="$index">
|
||||
</mct-control>
|
||||
<span class="composite-control-label">
|
||||
|
||||
16
src/MCT.js
16
src/MCT.js
@@ -106,9 +106,9 @@ define([
|
||||
*
|
||||
* @type {module:openmct.ViewRegistry}
|
||||
* @memberof module:openmct.MCT#
|
||||
* @name objectViews
|
||||
* @name mainViews
|
||||
*/
|
||||
this.objectViews = new ViewRegistry();
|
||||
this.mainViews = new ViewRegistry();
|
||||
|
||||
/**
|
||||
* Registry for views which should appear in the Inspector area.
|
||||
@@ -255,18 +255,6 @@ define([
|
||||
this.legacyExtension('types', legacyDefinition);
|
||||
}.bind(this));
|
||||
|
||||
this.objectViews.getAllProviders().forEach(function (p) {
|
||||
this.legacyExtension('views', {
|
||||
key: p.key,
|
||||
provider: p,
|
||||
name: p.name,
|
||||
cssClass: p.cssClass,
|
||||
description: p.description,
|
||||
editable: p.editable,
|
||||
template: '<mct-view mct-provider-key="' + p.key + '"/>'
|
||||
});
|
||||
}, this);
|
||||
|
||||
legacyRegistry.register('adapter', this.legacyBundle);
|
||||
legacyRegistry.enable('adapter');
|
||||
/**
|
||||
|
||||
@@ -24,6 +24,7 @@ define([
|
||||
'legacyRegistry',
|
||||
'./actions/ActionDialogDecorator',
|
||||
'./capabilities/AdapterCapability',
|
||||
'./controllers/AdaptedViewController',
|
||||
'./directives/MCTView',
|
||||
'./services/Instantiate',
|
||||
'./services/MissingModelCompatibilityDecorator',
|
||||
@@ -31,11 +32,13 @@ define([
|
||||
'./policies/AdapterCompositionPolicy',
|
||||
'./policies/AdaptedViewPolicy',
|
||||
'./runs/AlternateCompositionInitializer',
|
||||
'./runs/TimeSettingsURLHandler'
|
||||
'./runs/TimeSettingsURLHandler',
|
||||
'text!./templates/adapted-view-template.html'
|
||||
], function (
|
||||
legacyRegistry,
|
||||
ActionDialogDecorator,
|
||||
AdapterCapability,
|
||||
AdaptedViewController,
|
||||
MCTView,
|
||||
Instantiate,
|
||||
MissingModelCompatibilityDecorator,
|
||||
@@ -43,15 +46,15 @@ define([
|
||||
AdapterCompositionPolicy,
|
||||
AdaptedViewPolicy,
|
||||
AlternateCompositionInitializer,
|
||||
TimeSettingsURLHandler
|
||||
TimeSettingsURLHandler,
|
||||
adaptedViewTemplate
|
||||
) {
|
||||
legacyRegistry.register('src/adapter', {
|
||||
"extensions": {
|
||||
"directives": [
|
||||
{
|
||||
key: "mctView",
|
||||
implementation: MCTView,
|
||||
depends: ["openmct"]
|
||||
implementation: MCTView
|
||||
}
|
||||
],
|
||||
capabilities: [
|
||||
@@ -60,6 +63,16 @@ define([
|
||||
implementation: AdapterCapability
|
||||
}
|
||||
],
|
||||
controllers: [
|
||||
{
|
||||
key: "AdaptedViewController",
|
||||
implementation: AdaptedViewController,
|
||||
depends: [
|
||||
'$scope',
|
||||
'openmct'
|
||||
]
|
||||
}
|
||||
],
|
||||
services: [
|
||||
{
|
||||
key: "instantiate",
|
||||
@@ -122,6 +135,12 @@ define([
|
||||
depends: ["openmct", "$location", "$rootScope"]
|
||||
}
|
||||
],
|
||||
views: [
|
||||
{
|
||||
key: "adapted-view",
|
||||
template: adaptedViewTemplate
|
||||
}
|
||||
],
|
||||
licenses: [
|
||||
{
|
||||
"name": "almond",
|
||||
|
||||
@@ -22,12 +22,10 @@
|
||||
|
||||
define([
|
||||
'./synchronizeMutationCapability',
|
||||
'./AlternateCompositionCapability',
|
||||
'./patchViewCapability'
|
||||
'./AlternateCompositionCapability'
|
||||
], function (
|
||||
synchronizeMutationCapability,
|
||||
AlternateCompositionCapability,
|
||||
patchViewCapability
|
||||
AlternateCompositionCapability
|
||||
) {
|
||||
|
||||
/**
|
||||
@@ -48,9 +46,6 @@ define([
|
||||
capabilities.mutation =
|
||||
synchronizeMutationCapability(capabilities.mutation);
|
||||
}
|
||||
if (capabilities.view) {
|
||||
capabilities.view = patchViewCapability(capabilities.view);
|
||||
}
|
||||
if (AlternateCompositionCapability.appliesTo(model, id)) {
|
||||
capabilities.composition = function (domainObject) {
|
||||
return new AlternateCompositionCapability(this.$injector, domainObject);
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'lodash'
|
||||
], function (
|
||||
_
|
||||
) {
|
||||
|
||||
function patchViewCapability(viewConstructor) {
|
||||
return function makeCapability(domainObject) {
|
||||
var capability = viewConstructor(domainObject);
|
||||
var oldInvoke = capability.invoke.bind(capability);
|
||||
|
||||
capability.invoke = function () {
|
||||
var availableViews = oldInvoke();
|
||||
var newDomainObject = capability
|
||||
.domainObject
|
||||
.useCapability('adapter');
|
||||
|
||||
return _(availableViews).map(function (v, i) {
|
||||
var vd = {
|
||||
view: v,
|
||||
priority: i + 100 // arbitrary to allow new views to
|
||||
// be defaults by returning priority less than 100.
|
||||
};
|
||||
if (v.provider && v.provider.priority) {
|
||||
vd.priority = v.provider.priority(newDomainObject);
|
||||
}
|
||||
return vd;
|
||||
})
|
||||
.sortBy('priority')
|
||||
.map('view')
|
||||
.value();
|
||||
};
|
||||
return capability;
|
||||
};
|
||||
}
|
||||
|
||||
return patchViewCapability;
|
||||
});
|
||||
@@ -20,25 +20,21 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
function SummaryWidgetsCompositionPolicy(openmct) {
|
||||
this.openmct = openmct;
|
||||
}
|
||||
|
||||
SummaryWidgetsCompositionPolicy.prototype.allow = function (parent, child) {
|
||||
var parentType = parent.getCapability('type');
|
||||
var newStyleChild = child.useCapability('adapter');
|
||||
|
||||
if (parentType.instanceOf('summary-widget') && !this.openmct.telemetry.canProvideTelemetry(newStyleChild)) {
|
||||
return false;
|
||||
define([], function () {
|
||||
function AdaptedViewController($scope, openmct) {
|
||||
function refresh(legacyObject) {
|
||||
if (!legacyObject) {
|
||||
$scope.view = undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
var domainObject = legacyObject.useCapability('adapter');
|
||||
var providers = openmct.mainViews.get(domainObject);
|
||||
$scope.view = providers[0] && providers[0].view(domainObject);
|
||||
}
|
||||
|
||||
return SummaryWidgetsCompositionPolicy;
|
||||
$scope.$watch('domainObject', refresh);
|
||||
}
|
||||
);
|
||||
|
||||
return AdaptedViewController;
|
||||
});
|
||||
@@ -21,23 +21,18 @@
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'angular',
|
||||
'./Region'
|
||||
], function (
|
||||
angular,
|
||||
Region
|
||||
) {
|
||||
function MCTView(openmct) {
|
||||
function MCTView() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
restrict: 'A',
|
||||
link: function (scope, element, attrs) {
|
||||
var provider = openmct.objectViews.getByProviderKey(attrs.mctProviderKey);
|
||||
var view = new provider.view(scope.domainObject.useCapability('adapter'));
|
||||
var domElement = element[0];
|
||||
|
||||
view.show(domElement);
|
||||
|
||||
if (view.destroy) {
|
||||
scope.$on('$destroy', function () {
|
||||
view.destroy(domElement);
|
||||
});
|
||||
}
|
||||
var region = new Region(element[0]);
|
||||
scope.$watch(attrs.mctView, region.show.bind(region));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2009-2016, United States Government
|
||||
* Open MCT, Copyright (c) 2014-2017, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
@@ -20,38 +20,26 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
['moment'],
|
||||
function (moment) {
|
||||
var NO_TIMER = "No timer being followed";
|
||||
|
||||
/**
|
||||
* Indicator that displays the active timer, as well as its
|
||||
* current state.
|
||||
* @implements {Indicator}
|
||||
* @memberof platform/features/clock
|
||||
*/
|
||||
function FollowIndicator(timerService) {
|
||||
this.timerService = timerService;
|
||||
}
|
||||
|
||||
FollowIndicator.prototype.getGlyphClass = function () {
|
||||
return "";
|
||||
};
|
||||
|
||||
FollowIndicator.prototype.getCssClass = function () {
|
||||
return (this.timerService.getTimer()) ? "icon-timer s-status-ok" : "icon-timer";
|
||||
};
|
||||
|
||||
FollowIndicator.prototype.getText = function () {
|
||||
var timer = this.timerService.getTimer();
|
||||
return (timer) ? 'Following timer ' + timer.getModel().name : NO_TIMER;
|
||||
};
|
||||
|
||||
FollowIndicator.prototype.getDescription = function () {
|
||||
return "";
|
||||
};
|
||||
|
||||
return FollowIndicator;
|
||||
define([], function () {
|
||||
function Region(element) {
|
||||
this.activeView = undefined;
|
||||
this.element = element;
|
||||
}
|
||||
);
|
||||
|
||||
Region.prototype.clear = function () {
|
||||
if (this.activeView) {
|
||||
this.activeView.destroy();
|
||||
this.activeView = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
Region.prototype.show = function (view) {
|
||||
this.clear();
|
||||
this.activeView = view;
|
||||
if (this.activeView) {
|
||||
this.activeView.show(this.element);
|
||||
}
|
||||
};
|
||||
|
||||
return Region;
|
||||
});
|
||||
@@ -29,9 +29,9 @@ define([], function () {
|
||||
view,
|
||||
legacyObject
|
||||
) {
|
||||
if (view.hasOwnProperty('provider')) {
|
||||
if (view.key === 'adapted-view') {
|
||||
var domainObject = legacyObject.useCapability('adapter');
|
||||
return view.provider.canView(domainObject);
|
||||
return this.openmct.mainViews.get(domainObject).length > 0;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
@@ -48,7 +48,6 @@ define([
|
||||
this.unlisteners.forEach(function (unlisten) {
|
||||
unlisten();
|
||||
});
|
||||
this.unlisteners = [];
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,18 +50,11 @@ define([
|
||||
this.rootProvider = new RootObjectProvider(this.rootRegistry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set fallback provider, this is an internal API for legacy reasons.
|
||||
* @private
|
||||
*/
|
||||
ObjectAPI.prototype.supersecretSetFallbackProvider = function (p) {
|
||||
this.fallbackProvider = p;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve the provider for a given identifier.
|
||||
* @private
|
||||
*/
|
||||
// Retrieve the provider for a given key.
|
||||
ObjectAPI.prototype.getProvider = function (identifier) {
|
||||
if (identifier.key === 'ROOT') {
|
||||
return this.rootProvider;
|
||||
@@ -142,28 +135,27 @@ define([
|
||||
* @returns {Promise} a promise which will resolve when the domain object
|
||||
* has been saved, or be rejected if it cannot be saved
|
||||
*/
|
||||
ObjectAPI.prototype.get = function (identifier) {
|
||||
identifier = utils.parseKeyString(identifier);
|
||||
var provider = this.getProvider(identifier);
|
||||
|
||||
if (!provider) {
|
||||
throw new Error('No Provider Matched');
|
||||
}
|
||||
[
|
||||
'save',
|
||||
'delete',
|
||||
'get'
|
||||
].forEach(function (method) {
|
||||
ObjectAPI.prototype[method] = function () {
|
||||
var identifier = arguments[0],
|
||||
provider = this.getProvider(identifier);
|
||||
|
||||
if (!provider.get) {
|
||||
throw new Error('Provider does not support get!');
|
||||
}
|
||||
if (!provider) {
|
||||
throw new Error('No Provider Matched');
|
||||
}
|
||||
|
||||
return provider.get(identifier);
|
||||
};
|
||||
if (!provider[method]) {
|
||||
throw new Error('Provider does not support [' + method + '].');
|
||||
}
|
||||
|
||||
ObjectAPI.prototype.delete = function () {
|
||||
throw new Error('Delete not implemented');
|
||||
};
|
||||
|
||||
ObjectAPI.prototype.save = function () {
|
||||
throw new Error('Save not implemented');
|
||||
};
|
||||
return provider[method].apply(provider, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
/**
|
||||
* Add a root-level object.
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<a class="close icon-x-in-circle"></a>
|
||||
<div class="abs inner-holder contents">
|
||||
<div class="abs top-bar">
|
||||
<div class="dialog-title"></div>
|
||||
<div class="title"></div>
|
||||
<div class="hint"></div>
|
||||
</div>
|
||||
<div class='abs editor'>
|
||||
|
||||
@@ -1,97 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
// Set of connection states; changing among these states will be
|
||||
// reflected in the indicator's appearance.
|
||||
// CONNECTED: Everything nominal, expect to be able to read/write.
|
||||
// DISCONNECTED: HTTP failed; maybe misconfigured, disconnected.
|
||||
// PENDING: Still trying to connect, and haven't failed yet.
|
||||
var CONNECTED = {
|
||||
glyphClass: "ok"
|
||||
},
|
||||
PENDING = {
|
||||
glyphClass: 'caution'
|
||||
},
|
||||
DISCONNECTED = {
|
||||
glyphClass: "err"
|
||||
};
|
||||
function URLIndicator($http, $interval) {
|
||||
var self = this;
|
||||
this.cssClass = this.options.cssClass ? this.options.cssClass : "icon-database";
|
||||
this.URLpath = this.options.url;
|
||||
this.label = this.options.label ? this.options.label : this.options.url;
|
||||
this.interval = this.options.interval || 10000;
|
||||
this.state = PENDING;
|
||||
|
||||
function handleError(e) {
|
||||
self.state = DISCONNECTED;
|
||||
}
|
||||
function handleResponse() {
|
||||
self.state = CONNECTED;
|
||||
}
|
||||
function updateIndicator() {
|
||||
$http.get(self.URLpath).then(handleResponse, handleError);
|
||||
}
|
||||
updateIndicator();
|
||||
$interval(updateIndicator, self.interval, 0, false);
|
||||
}
|
||||
|
||||
URLIndicator.prototype.getCssClass = function () {
|
||||
return this.cssClass;
|
||||
};
|
||||
URLIndicator.prototype.getGlyphClass = function () {
|
||||
return this.state.glyphClass;
|
||||
};
|
||||
URLIndicator.prototype.getText = function () {
|
||||
switch (this.state) {
|
||||
case CONNECTED: {
|
||||
return this.label + " is connected";
|
||||
}
|
||||
case PENDING: {
|
||||
return "Checking status of " + this.label + " please stand by...";
|
||||
}
|
||||
case DISCONNECTED: {
|
||||
return this.label + " is offline";
|
||||
}
|
||||
}
|
||||
};
|
||||
URLIndicator.prototype.getDescription = function () {
|
||||
switch (this.state) {
|
||||
case CONNECTED: {
|
||||
return this.label + " is online, checking status every " +
|
||||
this.interval + " milliseconds.";
|
||||
}
|
||||
case PENDING: {
|
||||
return "Checking status of " + this.label + " please stand by...";
|
||||
}
|
||||
case DISCONNECTED: {
|
||||
return this.label + " is offline, checking status every " +
|
||||
this.interval + " milliseconds";
|
||||
}
|
||||
}
|
||||
};
|
||||
return URLIndicator;
|
||||
});
|
||||
@@ -1,20 +0,0 @@
|
||||
define(
|
||||
[
|
||||
'./URLIndicator'
|
||||
],
|
||||
function URLIndicatorPlugin(URLIndicator) {
|
||||
return function (opts) {
|
||||
// Wrap the plugin in a function so we can apply the arguments.
|
||||
function URLIndicatorWrapper() {
|
||||
this.options = opts;
|
||||
URLIndicator.apply(this, arguments);
|
||||
}
|
||||
URLIndicatorWrapper.prototype = Object.create(URLIndicator.prototype);
|
||||
return function install(openmct) {
|
||||
openmct.legacyExtension('indicators', {
|
||||
"implementation": URLIndicatorWrapper,
|
||||
"depends": ["$http", "$interval"]
|
||||
});
|
||||
};
|
||||
};
|
||||
});
|
||||
@@ -1,158 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2016, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define(
|
||||
["./URLIndicator"],
|
||||
function (URLIndicator) {
|
||||
|
||||
describe("The URLIndicator", function () {
|
||||
var mockHttp,
|
||||
mockInterval,
|
||||
mockPromise,
|
||||
opts,
|
||||
Indicator,
|
||||
indicatorWrapper;
|
||||
|
||||
beforeEach(function () {
|
||||
mockHttp = jasmine.createSpyObj("$http", ["get"]);
|
||||
mockInterval = jasmine.createSpy("$interval");
|
||||
mockPromise = jasmine.createSpyObj("promise", ["then"]);
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
interval: 1337 //some number
|
||||
};
|
||||
mockHttp.get.andReturn(mockPromise);
|
||||
Indicator = function () {
|
||||
this.options = opts;
|
||||
URLIndicator.call(this, mockHttp, mockInterval);
|
||||
};
|
||||
Indicator.prototype = Object.create(URLIndicator.prototype);
|
||||
indicatorWrapper = new Indicator();
|
||||
});
|
||||
it("polls for changes", function () {
|
||||
expect(mockInterval).toHaveBeenCalledWith(
|
||||
jasmine.any(Function),
|
||||
opts.interval,
|
||||
0,
|
||||
false
|
||||
);
|
||||
});
|
||||
|
||||
it("has a database cssClass as default", function () {
|
||||
expect(indicatorWrapper.getCssClass()).toEqual("icon-database");
|
||||
});
|
||||
|
||||
it("consults the url with the path supplied", function () {
|
||||
expect(mockHttp.get).toHaveBeenCalledWith(opts.url);
|
||||
});
|
||||
|
||||
it("changes when the database connection is nominal", function () {
|
||||
var initialText = indicatorWrapper.getText(),
|
||||
initialDescrption = indicatorWrapper.getDescription(),
|
||||
initialGlyphClass = indicatorWrapper.getGlyphClass();
|
||||
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
||||
|
||||
// Verify that these values changed;
|
||||
// don't test for specific text.
|
||||
expect(indicatorWrapper.getText()).not.toEqual(initialText);
|
||||
expect(indicatorWrapper.getGlyphClass()).not.toEqual(initialGlyphClass);
|
||||
expect(indicatorWrapper.getDescription()).not.toEqual(initialDescrption);
|
||||
|
||||
// Do check for specific class
|
||||
expect(indicatorWrapper.getGlyphClass()).toEqual("ok");
|
||||
});
|
||||
|
||||
it("changes when the server cannot be reached", function () {
|
||||
var initialText = indicatorWrapper.getText(),
|
||||
initialDescrption = indicatorWrapper.getDescription(),
|
||||
initialGlyphClass = indicatorWrapper.getGlyphClass();
|
||||
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
||||
|
||||
// Verify that these values changed;
|
||||
// don't test for specific text.
|
||||
expect(indicatorWrapper.getText()).not.toEqual(initialText);
|
||||
expect(indicatorWrapper.getGlyphClass()).not.toEqual(initialGlyphClass);
|
||||
expect(indicatorWrapper.getDescription()).not.toEqual(initialDescrption);
|
||||
|
||||
// Do check for specific class
|
||||
expect(indicatorWrapper.getGlyphClass()).toEqual("err");
|
||||
});
|
||||
it("has a customized cssClass if supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
cssClass: "cssClass-checked",
|
||||
interval: 10000
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(indicatorWrapper.getCssClass()).toEqual("cssClass-checked");
|
||||
});
|
||||
it("has a customized interval if supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
interval: 1814
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(mockInterval).toHaveBeenCalledWith(
|
||||
jasmine.any(Function),
|
||||
1814,
|
||||
0,
|
||||
false
|
||||
);
|
||||
});
|
||||
it("has a custom label if supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080",
|
||||
label: "Localhost"
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(indicatorWrapper.getText()).toEqual("Checking status of Localhost please stand by...");
|
||||
});
|
||||
it("has a default label if not supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080"
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(indicatorWrapper.getText()).toEqual(
|
||||
"Checking status of http://localhost:8080 please stand by..."
|
||||
);
|
||||
});
|
||||
it("has a default interval if not supplied in initialization", function () {
|
||||
opts = {
|
||||
url: "http://localhost:8080"
|
||||
};
|
||||
indicatorWrapper = new Indicator();
|
||||
expect(mockInterval).toHaveBeenCalledWith(
|
||||
jasmine.any(Function),
|
||||
10000,
|
||||
0,
|
||||
false
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
@@ -28,8 +28,7 @@ define([
|
||||
'./timeConductor/plugin',
|
||||
'../../example/imagery/plugin',
|
||||
'../../platform/import-export/bundle',
|
||||
'./summaryWidget/plugin',
|
||||
'./URLIndicatorPlugin/URLIndicatorPlugin'
|
||||
'./slideshow/plugin'
|
||||
], function (
|
||||
_,
|
||||
UTCTimeSystem,
|
||||
@@ -38,8 +37,7 @@ define([
|
||||
TimeConductorPlugin,
|
||||
ExampleImagery,
|
||||
ImportExport,
|
||||
SummaryWidget,
|
||||
URLIndicatorPlugin
|
||||
Slideshow
|
||||
) {
|
||||
var bundleMap = {
|
||||
CouchDB: 'platform/persistence/couch',
|
||||
@@ -62,6 +60,8 @@ define([
|
||||
|
||||
plugins.ImportExport = ImportExport;
|
||||
|
||||
plugins.Slideshow = Slideshow;
|
||||
|
||||
/**
|
||||
* A tabular view showing the latest values of multiple telemetry points at
|
||||
* once. Formatted so that labels and values are aligned.
|
||||
@@ -125,8 +125,5 @@ define([
|
||||
|
||||
plugins.ExampleImagery = ExampleImagery;
|
||||
|
||||
plugins.SummaryWidget = SummaryWidget;
|
||||
plugins.URLIndicatorPlugin = URLIndicatorPlugin;
|
||||
|
||||
return plugins;
|
||||
});
|
||||
|
||||
93
src/plugins/slideshow/plugin.js
Normal file
93
src/plugins/slideshow/plugin.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2017, 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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([], function () {
|
||||
var SLIDESHOW_TEMPLATE =
|
||||
'<span ng-controller="SlideshowController as slideshow">' +
|
||||
'<mct-representation key="slideshow.key()" mct-object="slideshow.object()">' +
|
||||
'</mct-representation></span>';
|
||||
|
||||
function SlideshowController($scope, $interval) {
|
||||
this.composition = [];
|
||||
this.counter = 0;
|
||||
|
||||
$scope.$watch('domainObject', this.update.bind(this));
|
||||
|
||||
var interval = $interval(function () {
|
||||
this.counter += 1;
|
||||
}.bind(this), 4000);
|
||||
//$scope.$on("$destroy", interval.cancel.bind(interval));
|
||||
}
|
||||
|
||||
SlideshowController.prototype.update = function (domainObject) {
|
||||
var composition = domainObject.useCapability("composition");
|
||||
|
||||
if (!composition) {
|
||||
this.composition = [];
|
||||
return;
|
||||
}
|
||||
|
||||
composition.then(function (composition) {
|
||||
this.composition = composition;
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
SlideshowController.prototype.object = function () {
|
||||
return Array.isArray(this.composition) && this.composition.length ?
|
||||
this.composition[this.counter % this.composition.length] :
|
||||
undefined;
|
||||
};
|
||||
|
||||
SlideshowController.prototype.key = function () {
|
||||
var object = this.object();
|
||||
var view = object && object.useCapability('view')[0];
|
||||
return view && view.key;
|
||||
};
|
||||
|
||||
return function slideshow(options) {
|
||||
return function install(openmct) {
|
||||
openmct.types.addType('slideshow', {
|
||||
name: "Slideshow",
|
||||
description: "A slideshow display of other objects",
|
||||
cssClass: 'icon-object',
|
||||
initialize: function (slideshow) {
|
||||
slideshow.composition = [];
|
||||
},
|
||||
creatable: true
|
||||
});
|
||||
|
||||
openmct.legacyExtension("controllers", {
|
||||
key: "SlideshowController",
|
||||
implementation: SlideshowController,
|
||||
depends: [ "$scope", "$interval" ]
|
||||
});
|
||||
|
||||
openmct.legacyExtension("views", {
|
||||
key: "slideshow",
|
||||
type: "slideshow",
|
||||
editable: true,
|
||||
gestures: [ "drop" ],
|
||||
template: SLIDESHOW_TEMPLATE
|
||||
});
|
||||
};
|
||||
};
|
||||
});
|
||||
@@ -1,67 +0,0 @@
|
||||
define(['./src/SummaryWidget', './SummaryWidgetsCompositionPolicy'], function (SummaryWidget, SummaryWidgetsCompositionPolicy) {
|
||||
|
||||
function plugin() {
|
||||
|
||||
var widgetType = {
|
||||
name: 'Summary Widget',
|
||||
description: 'A compact status update for collections of telemetry-producing items',
|
||||
creatable: true,
|
||||
cssClass: 'icon-summary-widget',
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
domainObject.configuration = {};
|
||||
domainObject.openNewTab = 'thisTab';
|
||||
},
|
||||
form: [
|
||||
{
|
||||
"key": "url",
|
||||
"name": "URL",
|
||||
"control": "textfield",
|
||||
"pattern": "^(ftp|https?)\\:\\/\\/",
|
||||
"required": false,
|
||||
"cssClass": "l-input-lg"
|
||||
},
|
||||
{
|
||||
"key": "openNewTab",
|
||||
"name": "Tab to Open Hyperlink",
|
||||
"control": "select",
|
||||
"options": [
|
||||
{
|
||||
"value": "thisTab",
|
||||
"name": "Open in this tab"
|
||||
},
|
||||
{
|
||||
"value": "newTab",
|
||||
"name": "Open in a new tab"
|
||||
}
|
||||
],
|
||||
"cssClass": "l-inline"
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
function initViewProvider(openmct) {
|
||||
return {
|
||||
name: 'Widget View',
|
||||
view: function (domainObject) {
|
||||
return new SummaryWidget(domainObject, openmct);
|
||||
},
|
||||
canView: function (domainObject) {
|
||||
return (domainObject.type === 'summary-widget');
|
||||
},
|
||||
editable: true,
|
||||
key: 'summaryWidgets'
|
||||
};
|
||||
}
|
||||
|
||||
return function install(openmct) {
|
||||
openmct.types.addType('summary-widget', widgetType);
|
||||
openmct.objectViews.addProvider(initViewProvider(openmct));
|
||||
openmct.legacyExtension('policies', {category: 'composition',
|
||||
implementation: SummaryWidgetsCompositionPolicy, depends: ['openmct']
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return plugin;
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
<li class="t-condition">
|
||||
<label class="t-condition-context">when</label>
|
||||
<span class="controls">
|
||||
<span class="t-configuration"> </span>
|
||||
<span class="t-value-inputs"> </span>
|
||||
</span>
|
||||
<span class="flex-elem l-condition-action-buttons-wrapper">
|
||||
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this condition"></a>
|
||||
<a class="s-icon-button icon-trash t-delete" title="Delete this condition"></a>
|
||||
</span>
|
||||
</li>
|
||||
@@ -1,10 +0,0 @@
|
||||
<a class="e-control s-button s-menu-button menu-element">
|
||||
<span class="l-click-area"></span>
|
||||
<span class="t-swatch"></span>
|
||||
<div class="menu l-palette">
|
||||
<div class="l-palette-row l-option-row">
|
||||
<div class="l-palette-item s-palette-item no-selection"></div>
|
||||
<span class="l-palette-item-label">None</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@@ -1,4 +0,0 @@
|
||||
<div class="e-control select">
|
||||
<select>
|
||||
</select>
|
||||
</div>
|
||||
@@ -1,3 +0,0 @@
|
||||
<div class="holder widget-rules-wrapper">
|
||||
<div class="t-drag-rule-image l-widget-rule s-widget-rule"></div>
|
||||
</div>
|
||||
@@ -1,69 +0,0 @@
|
||||
<div>
|
||||
<div class="l-widget-rule s-widget-rule l-compact-form">
|
||||
<div class="widget-rule-header">
|
||||
<span class="flex-elem l-widget-thumb-wrapper">
|
||||
<span class="grippy-holder">
|
||||
<span class="t-grippy grippy"></span>
|
||||
</span>
|
||||
<span class="view-control expanded"></span>
|
||||
<span class="t-widget-thumb widget-thumb">
|
||||
<span class="widget-label">DEF</span>
|
||||
</span>
|
||||
</span>
|
||||
<span class="flex-elem rule-title">Default Title</span>
|
||||
<span class="flex-elem rule-description grows">Rule description goes here</span>
|
||||
<span class="flex-elem l-rule-action-buttons-wrapper">
|
||||
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this rule"></a>
|
||||
<a class="s-icon-button icon-trash t-delete" title="Delete this rule"></a>
|
||||
</span>
|
||||
</div>
|
||||
<div class="widget-rule-content expanded">
|
||||
<ul>
|
||||
<li>
|
||||
<label>Rule Name:</label>
|
||||
<span class="controls">
|
||||
<input class="t-rule-name-input" type="text" />
|
||||
</span>
|
||||
</li>
|
||||
<li class="connects-to-previous">
|
||||
<label>Label:</label>
|
||||
<span class="controls t-label-input">
|
||||
<input class="e-control t-rule-label-input" type="text" />
|
||||
</span>
|
||||
</li>
|
||||
<li class="connects-to-previous">
|
||||
<label>Message:</label>
|
||||
<span class="controls">
|
||||
<input type="text" class="lg s t-rule-message-input"
|
||||
placeholder="Will appear as tooltip when hovering on the widget"/>
|
||||
</span>
|
||||
</li>
|
||||
<li class="connects-to-previous">
|
||||
<label>Style:</label>
|
||||
<span class="controls t-style-input">
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="t-widget-rule-config">
|
||||
<li>
|
||||
<label>Trigger when</label>
|
||||
<span class="controls">
|
||||
<div class="e-control select">
|
||||
<select class="t-trigger">
|
||||
<option value="any">any condition is met</option>
|
||||
<option value="all">all conditions are met</option>
|
||||
</select>
|
||||
</div>
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<label></label>
|
||||
<span class="controls">
|
||||
<a class="e-control s-button labeled add-condition icon-plus">Add Condition</a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="t-drag-indicator l-widget-rule s-widget-rule" style="opacity:0;" hidden></div>
|
||||
</div>
|
||||
@@ -1,16 +0,0 @@
|
||||
<div class="t-test-data-item l-compact-form l-widget-test-data-item s-widget-test-data-item">
|
||||
<ul>
|
||||
<li>
|
||||
<label>Set </label>
|
||||
<span class="controls">
|
||||
<span class="t-configuration"></span>
|
||||
<span class="equal-to hidden"> equal to </span>
|
||||
<span class="t-value-inputs"></span>
|
||||
</span>
|
||||
<span class="flex-elem l-widget-test-data-item-action-buttons-wrapper">
|
||||
<a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this test value"></a>
|
||||
<a class="s-icon-button icon-trash t-delete" title="Delete this test value"></a>
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -1,15 +0,0 @@
|
||||
<div class="flex-accordion-holder">
|
||||
<div class="flex-accordion-holder t-widget-test-data-content w-widget-test-data-content">
|
||||
<div class="l-enable">
|
||||
<label class="checkbox custom">Apply Test Values
|
||||
<input type="checkbox" class="t-test-data-checkbox">
|
||||
<em></em>
|
||||
</label>
|
||||
</div>
|
||||
<div class="t-test-data-config w-widget-test-data-items">
|
||||
<div class="holder add-rule-button-wrapper align-right">
|
||||
<a id="addRule" class="e-control s-button major labeled add-test-condition icon-plus">Add Test Value</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,23 +0,0 @@
|
||||
<div class="w-summary-widget s-status-no-data">
|
||||
<a id="widget" class="t-summary-widget l-summary-widget s-summary-widget labeled">
|
||||
<span id="widgetLabel" class="label widget-label">Default Static Name</span>
|
||||
</a>
|
||||
<div class="holder flex-elem t-message-inline l-message message-severity-alert t-message-widget-no-data">
|
||||
<div class="w-message-contents l-message-body-only">
|
||||
<div class="message-body">
|
||||
You must add at least one telemetry object to edit this widget.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="holder l-flex-col l-flex-accordion flex-elem grows widget-edit-holder expanded-widget-test-data expanded-widget-rules">
|
||||
<div class="section-header"><span class="view-control t-view-control-test-data expanded"></span>Test Data Values</div>
|
||||
<div class="widget-test-data flex-accordion-holder"></div>
|
||||
<div class="section-header"><span class="view-control t-view-control-rules expanded"></span>Rules</div>
|
||||
<div class="holder widget-rules-wrapper flex-elem expanded">
|
||||
<div id="ruleArea" class="widget-rules"></div>
|
||||
<div class="holder add-rule-button-wrapper align-right">
|
||||
<a id="addRule" class="s-button major labeled add-rule-button icon-plus">Add Rule</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,200 +0,0 @@
|
||||
define([
|
||||
'text!../res/conditionTemplate.html',
|
||||
'./input/ObjectSelect',
|
||||
'./input/KeySelect',
|
||||
'./input/OperationSelect',
|
||||
'./eventHelpers',
|
||||
'EventEmitter',
|
||||
'zepto'
|
||||
], function (
|
||||
conditionTemplate,
|
||||
ObjectSelect,
|
||||
KeySelect,
|
||||
OperationSelect,
|
||||
eventHelpers,
|
||||
EventEmitter,
|
||||
$
|
||||
) {
|
||||
/**
|
||||
* Represents an individual condition for a summary widget rule. Manages the
|
||||
* associated inputs and view.
|
||||
* @param {Object} conditionConfig The configurration for this condition, consisting
|
||||
* of object, key, operation, and values fields
|
||||
* @param {number} index the index of this Condition object in it's parent Rule's data model,
|
||||
* to be injected into callbacks for removes
|
||||
* @param {ConditionManager} conditionManager A ConditionManager instance for populating
|
||||
* selects with configuration data
|
||||
*/
|
||||
function Condition(conditionConfig, index, conditionManager) {
|
||||
eventHelpers.extend(this);
|
||||
this.config = conditionConfig;
|
||||
this.index = index;
|
||||
this.conditionManager = conditionManager;
|
||||
|
||||
this.domElement = $(conditionTemplate);
|
||||
this.eventEmitter = new EventEmitter();
|
||||
this.supportedCallbacks = ['remove', 'duplicate', 'change'];
|
||||
|
||||
this.deleteButton = $('.t-delete', this.domElement);
|
||||
this.duplicateButton = $('.t-duplicate', this.domElement);
|
||||
|
||||
this.selects = {};
|
||||
this.valueInputs = [];
|
||||
|
||||
this.remove = this.remove.bind(this);
|
||||
this.duplicate = this.duplicate.bind(this);
|
||||
|
||||
var self = this;
|
||||
|
||||
/**
|
||||
* Event handler for a change in one of this conditions' custom selects
|
||||
* @param {string} value The new value of this selects
|
||||
* @param {string} property The property of this condition to modify
|
||||
* @private
|
||||
*/
|
||||
function onSelectChange(value, property) {
|
||||
if (property === 'operation') {
|
||||
self.generateValueInputs(value);
|
||||
}
|
||||
self.eventEmitter.emit('change', {
|
||||
value: value,
|
||||
property: property,
|
||||
index: self.index
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Event handler for this conditions value inputs
|
||||
* @param {Event} event The oninput event that triggered this callback
|
||||
* @private
|
||||
*/
|
||||
function onValueInput(event) {
|
||||
var elem = event.target,
|
||||
value = (isNaN(elem.valueAsNumber) ? elem.value : elem.valueAsNumber),
|
||||
inputIndex = self.valueInputs.indexOf(elem);
|
||||
|
||||
if (elem.tagName.toUpperCase() === 'INPUT') {
|
||||
self.eventEmitter.emit('change', {
|
||||
value: value,
|
||||
property: 'values[' + inputIndex + ']',
|
||||
index: self.index
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
this.listenTo(this.deleteButton, 'click', this.remove, this);
|
||||
this.listenTo(this.duplicateButton, 'click', this.duplicate, this);
|
||||
|
||||
this.selects.object = new ObjectSelect(this.config, this.conditionManager, [
|
||||
['any', 'any telemetry'],
|
||||
['all', 'all telemetry']
|
||||
]);
|
||||
this.selects.key = new KeySelect(this.config, this.selects.object, this.conditionManager);
|
||||
this.selects.operation = new OperationSelect(
|
||||
this.config,
|
||||
this.selects.key,
|
||||
this.conditionManager,
|
||||
function (value) {
|
||||
onSelectChange(value, 'operation');
|
||||
});
|
||||
|
||||
this.selects.object.on('change', function (value) {
|
||||
onSelectChange(value, 'object');
|
||||
});
|
||||
this.selects.key.on('change', function (value) {
|
||||
onSelectChange(value, 'key');
|
||||
});
|
||||
|
||||
Object.values(this.selects).forEach(function (select) {
|
||||
$('.t-configuration', self.domElement).append(select.getDOM());
|
||||
});
|
||||
|
||||
this.listenTo($(this.domElement), 'input', onValueInput);
|
||||
}
|
||||
|
||||
Condition.prototype.getDOM = function (container) {
|
||||
return this.domElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* Register a callback with this condition: supported callbacks are remove, change,
|
||||
* duplicate
|
||||
* @param {string} event The key for the event to listen to
|
||||
* @param {function} callback The function that this rule will envoke on this event
|
||||
* @param {Object} context A reference to a scope to use as the context for
|
||||
* context for the callback function
|
||||
*/
|
||||
Condition.prototype.on = function (event, callback, context) {
|
||||
if (this.supportedCallbacks.includes(event)) {
|
||||
this.eventEmitter.on(event, callback, context || this);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the appropriate inputs when this is the only condition
|
||||
*/
|
||||
Condition.prototype.hideButtons = function () {
|
||||
this.deleteButton.hide();
|
||||
};
|
||||
|
||||
/**
|
||||
* Remove this condition from the configuration. Invokes any registered
|
||||
* remove callbacks
|
||||
*/
|
||||
Condition.prototype.remove = function () {
|
||||
this.eventEmitter.emit('remove', this.index);
|
||||
this.destroy();
|
||||
};
|
||||
|
||||
Condition.prototype.destroy = function () {
|
||||
this.stopListening();
|
||||
Object.values(this.selects).forEach(function (select) {
|
||||
select.destroy();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Make a deep clone of this condition's configuration and invoke any duplicate
|
||||
* callbacks with the cloned configuration and this rule's index
|
||||
*/
|
||||
Condition.prototype.duplicate = function () {
|
||||
var sourceCondition = JSON.parse(JSON.stringify(this.config));
|
||||
this.eventEmitter.emit('duplicate', {
|
||||
sourceCondition: sourceCondition,
|
||||
index: this.index
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* When an operation is selected, create the appropriate value inputs
|
||||
* and add them to the view
|
||||
* @param {string} operation The key of currently selected operation
|
||||
*/
|
||||
Condition.prototype.generateValueInputs = function (operation) {
|
||||
var evaluator = this.conditionManager.getEvaluator(),
|
||||
inputArea = $('.t-value-inputs', this.domElement),
|
||||
inputCount,
|
||||
inputType,
|
||||
newInput,
|
||||
index = 0;
|
||||
|
||||
inputArea.html('');
|
||||
this.valueInputs = [];
|
||||
|
||||
if (evaluator.getInputCount(operation)) {
|
||||
inputCount = evaluator.getInputCount(operation);
|
||||
inputType = evaluator.getInputType(operation);
|
||||
while (index < inputCount) {
|
||||
if (!this.config.values[index]) {
|
||||
this.config.values[index] = (inputType === 'number' ? 0 : '');
|
||||
}
|
||||
newInput = $('<input class="sm" type = "' + inputType + '" value = "' + this.config.values[index] + '"> </input>');
|
||||
this.valueInputs.push(newInput.get(0));
|
||||
inputArea.append(newInput);
|
||||
index += 1;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Condition;
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user