mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 05:07:52 +00:00
Merge branch 'open933' into open1182
This commit is contained in:
commit
b384e84872
@ -21,7 +21,6 @@
|
||||
"zepto": "^1.1.6",
|
||||
"eventemitter3": "^1.2.0",
|
||||
"d3": "~4.1.0",
|
||||
"html2canvas": "^0.4.1",
|
||||
"jspdf": "^1.2.61"
|
||||
"html2canvas": "^0.4.1"
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ WEBSITE_DIRECTORY="website"
|
||||
BUILD_SHA=`git rev-parse HEAD`
|
||||
|
||||
# A remote will be created for the git repository we are pushing to.
|
||||
# Don't worry, as this entire directory will get trashed inbetween builds.
|
||||
# Don't worry, as this entire directory will get trashed in between builds.
|
||||
REMOTE_NAME="documentation"
|
||||
WEBSITE_BRANCH="master"
|
||||
|
||||
|
@ -616,7 +616,7 @@ follows:
|
||||
part of an action's extension definition.
|
||||
* `CreateActionProvider` provides the various Create actions which
|
||||
populate the Create menu. These are driven by the available types,
|
||||
so do not map easily ot extension category `actions`; instead, these
|
||||
so do not map easily to extension category `actions`; instead, these
|
||||
are generated after looking up which actions are available from the
|
||||
[`TypeService`](#type-service).
|
||||
* `ActionAggregator` merges together actions from multiple providers.
|
||||
|
@ -98,7 +98,7 @@ Worked on bug fixes in the platform and a plugin for search.
|
||||
It is hard to figure out what the difference between the various ways of
|
||||
dealing with telemetry are. e.g., what is the difference between just
|
||||
"Telemetry" and the "Telemetry Service"? There are many
|
||||
"Telemetry Thing"s which seem related, but in an unclear way.
|
||||
"Telemetry Things" which seem related, but in an unclear way.
|
||||
|
||||
### Developer Intern 2
|
||||
|
||||
@ -456,7 +456,7 @@ Instead, propose that:
|
||||
For parity with actions, a `View` would be a constructor which
|
||||
takes an `ActionContext` as a parameter (with similarly-defined
|
||||
properties) and exposes a method to retrieve the HTML elements
|
||||
associateed with it.
|
||||
associated with it.
|
||||
|
||||
The platform would then additionally expose an `AngularView`
|
||||
implementation to improve compatibility with existing
|
||||
|
@ -99,7 +99,7 @@ To reduce interface depth, we can replace our own provider and registry patterns
|
||||
|
||||
## More angular: for all services
|
||||
|
||||
Increasing our commitment to angular would mean using more of the angular factorys, services, etc, and less of our home grown tools. We'd implement our services and extension points as angular providers, and make them configurable via app.config.
|
||||
Increasing our commitment to angular would mean using more of the angular factories, services, etc, and less of our home grown tools. We'd implement our services and extension points as angular providers, and make them configurable via app.config.
|
||||
|
||||
As an example, registering a specific type of model provider in angular would look like:
|
||||
|
||||
|
@ -3238,7 +3238,7 @@ define(
|
||||
__tutorials/telemetry/src/ExampleTelemetryServerAdapter.js__
|
||||
|
||||
Here, we have added `subscribe` and `unsubscribe` methods which issue the
|
||||
corresponding requests to the server. Seperately, we introduce the ability to
|
||||
corresponding requests to the server. Separately, we introduce the ability to
|
||||
listen for `data` messages as they come in: These will contain the data associated
|
||||
with these subscriptions.
|
||||
|
||||
|
@ -10,7 +10,7 @@
|
||||
"LMP: 47 degrees.",
|
||||
"CC: Eagle, looking great. You're GO.",
|
||||
"CC: Roger. 1202. We copy it.",
|
||||
"O1: LMP 35 degrees. 35 degrees. 750. Coming aown to 23.fl",
|
||||
"O1: LMP 35 degrees. 35 degrees. 750. Coming down to 23.fl",
|
||||
"LMP: 700 feet, 21 down, 33 degrees.",
|
||||
"LMP: 600 feet, down at 19.",
|
||||
"LMP: 540 feet, down at - 30. Down at 15.",
|
||||
|
4
main.js
4
main.js
@ -30,7 +30,6 @@ requirejs.config({
|
||||
"EventEmitter": "bower_components/eventemitter3/index",
|
||||
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
||||
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
||||
"jsPDF": "bower_components/jspdf/dist/jspdf.min",
|
||||
"moment": "bower_components/moment/moment",
|
||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
||||
@ -50,9 +49,6 @@ requirejs.config({
|
||||
"html2canvas": {
|
||||
"exports": "html2canvas"
|
||||
},
|
||||
"jsPDF": {
|
||||
"exports": "jsPDF"
|
||||
},
|
||||
"EventEmitter": {
|
||||
"exports": "EventEmitter"
|
||||
},
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openmct",
|
||||
"version": "0.11.3-SNAPSHOT",
|
||||
"version": "0.12.0-SNAPSHOT",
|
||||
"description": "The Open MCT core platform",
|
||||
"dependencies": {
|
||||
"express": "^4.13.1",
|
||||
|
@ -48,20 +48,35 @@ define(
|
||||
*/
|
||||
NavigateAction.prototype.perform = function () {
|
||||
var self = this,
|
||||
navigationAllowed = true;
|
||||
navigateTo = this.domainObject,
|
||||
currentObject = self.navigationService.getNavigation();
|
||||
|
||||
function allow() {
|
||||
self.policyService.allow("navigation", self.navigationService.getNavigation(), self.domainObject, function (message) {
|
||||
var navigationAllowed = true;
|
||||
self.policyService.allow("navigation", currentObject, navigateTo, function (message) {
|
||||
navigationAllowed = self.$window.confirm(message + "\r\n\r\n" +
|
||||
" Are you sure you want to continue?");
|
||||
});
|
||||
return navigationAllowed;
|
||||
}
|
||||
|
||||
// Set navigation, and wrap like a promise
|
||||
return this.$q.when(
|
||||
allow() && this.navigationService.setNavigation(this.domainObject)
|
||||
);
|
||||
function cancelIfEditing() {
|
||||
var editing = currentObject.hasCapability('editor') &&
|
||||
currentObject.getCapability('editor').isEditContextRoot();
|
||||
|
||||
return self.$q.when(editing && currentObject.getCapability("editor").finish());
|
||||
}
|
||||
|
||||
function navigate() {
|
||||
return self.navigationService.setNavigation(navigateTo);
|
||||
}
|
||||
|
||||
if (allow()) {
|
||||
return cancelIfEditing().then(navigate);
|
||||
} else {
|
||||
return this.$q.when(false);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -32,7 +32,9 @@ define(
|
||||
mockQ,
|
||||
mockDomainObject,
|
||||
mockPolicyService,
|
||||
mockNavigatedObject,
|
||||
mockWindow,
|
||||
capabilities,
|
||||
action;
|
||||
|
||||
function mockPromise(value) {
|
||||
@ -44,6 +46,29 @@ define(
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
capabilities = {};
|
||||
|
||||
mockQ = { when: mockPromise };
|
||||
mockNavigatedObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[
|
||||
"getId",
|
||||
"getModel",
|
||||
"hasCapability",
|
||||
"getCapability"
|
||||
]
|
||||
);
|
||||
|
||||
capabilities.editor = jasmine.createSpyObj("editorCapability", [
|
||||
"isEditContextRoot",
|
||||
"finish"
|
||||
]);
|
||||
|
||||
mockNavigatedObject.getCapability.andCallFake(function (capability) {
|
||||
return capabilities[capability];
|
||||
});
|
||||
mockNavigatedObject.hasCapability.andReturn(false);
|
||||
|
||||
mockNavigationService = jasmine.createSpyObj(
|
||||
"navigationService",
|
||||
[
|
||||
@ -51,11 +76,14 @@ define(
|
||||
"getNavigation"
|
||||
]
|
||||
);
|
||||
mockNavigationService.getNavigation.andReturn({});
|
||||
mockQ = { when: mockPromise };
|
||||
mockNavigationService.getNavigation.andReturn(mockNavigatedObject);
|
||||
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
["getId", "getModel", "getCapability"]
|
||||
[
|
||||
"getId",
|
||||
"getModel"
|
||||
]
|
||||
);
|
||||
|
||||
mockPolicyService = jasmine.createSpyObj("policyService",
|
||||
@ -112,6 +140,21 @@ define(
|
||||
});
|
||||
});
|
||||
|
||||
describe("in edit mode", function () {
|
||||
beforeEach(function () {
|
||||
mockNavigatedObject.hasCapability.andCallFake(function (capability) {
|
||||
return capability === "editor";
|
||||
});
|
||||
capabilities.editor.isEditContextRoot.andReturn(true);
|
||||
});
|
||||
|
||||
it("finishes editing if in edit mode", function () {
|
||||
action.perform();
|
||||
expect(capabilities.editor.finish)
|
||||
.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("is only applicable when a domain object is in context", function () {
|
||||
expect(NavigateAction.appliesTo({})).toBeFalsy();
|
||||
expect(NavigateAction.appliesTo({
|
||||
|
@ -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="abs overlay">
|
||||
<div class="abs overlay" ng-class="{'delayEntry100ms' : ngModel.delay}">
|
||||
<div class="abs blocker"></div>
|
||||
<div class="abs holder">
|
||||
<a ng-click="ngModel.cancel()"
|
||||
|
@ -187,7 +187,7 @@ define(
|
||||
|
||||
/**
|
||||
* A description of the model options that may be passed to the
|
||||
* showBlockingMessage method. Note that the DialogModel desribed
|
||||
* showBlockingMessage method. Note that the DialogModel described
|
||||
* here is shared with the Notifications framework.
|
||||
* @see NotificationService
|
||||
*
|
||||
@ -200,6 +200,9 @@ define(
|
||||
* shown above a progress bar to indicate what's happening.
|
||||
* @property {number} progress a percentage value (1-100)
|
||||
* indicating the completion of the blocking task
|
||||
* @property {boolean} delay adds a brief delay before loading
|
||||
* the dialog. Useful for removing the dialog flicker when the
|
||||
* conditions for displaying the dialog change rapidly.
|
||||
* @property {string} progressText the message to show below a
|
||||
* progress bar to indicate progress. For example, this might be
|
||||
* used to indicate time remaining, or items still to process.
|
||||
|
@ -31,6 +31,7 @@ define([
|
||||
"./src/actions/PropertiesAction",
|
||||
"./src/actions/RemoveAction",
|
||||
"./src/actions/SaveAction",
|
||||
"./src/actions/SaveAndStopEditingAction",
|
||||
"./src/actions/SaveAsAction",
|
||||
"./src/actions/CancelAction",
|
||||
"./src/policies/EditActionPolicy",
|
||||
@ -70,6 +71,7 @@ define([
|
||||
PropertiesAction,
|
||||
RemoveAction,
|
||||
SaveAction,
|
||||
SaveAndStopEditingAction,
|
||||
SaveAsAction,
|
||||
CancelAction,
|
||||
EditActionPolicy,
|
||||
@ -203,20 +205,30 @@ define([
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "save",
|
||||
"category": "conclude-editing",
|
||||
"implementation": SaveAction,
|
||||
"name": "Save",
|
||||
"key": "save-and-stop-editing",
|
||||
"category": "save",
|
||||
"implementation": SaveAndStopEditingAction,
|
||||
"name": "Save and Finish Editing",
|
||||
"cssclass": "icon-save labeled",
|
||||
"description": "Save changes made to these objects.",
|
||||
"depends": [
|
||||
"dialogService"
|
||||
],
|
||||
"priority": "mandatory"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "save",
|
||||
"category": "conclude-editing",
|
||||
"category": "save",
|
||||
"implementation": SaveAction,
|
||||
"name": "Save and Continue Editing",
|
||||
"cssclass": "icon-save labeled",
|
||||
"description": "Save changes made to these objects.",
|
||||
"depends": [
|
||||
"dialogService"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "save-as",
|
||||
"category": "save",
|
||||
"implementation": SaveAsAction,
|
||||
"name": "Save As...",
|
||||
"cssclass": "icon-save labeled",
|
||||
@ -225,7 +237,6 @@ define([
|
||||
"$injector",
|
||||
"policyService",
|
||||
"dialogService",
|
||||
"creationService",
|
||||
"copyService"
|
||||
],
|
||||
"priority": "mandatory"
|
||||
@ -234,7 +245,9 @@ define([
|
||||
"key": "cancel",
|
||||
"category": "conclude-editing",
|
||||
"implementation": CancelAction,
|
||||
"name": "Cancel",
|
||||
// Because we use the name as label for edit buttons and mct-control buttons need
|
||||
// the label to be set to undefined in order to not apply the labeled CSS rule.
|
||||
"name": undefined,
|
||||
"cssclass": "icon-x no-label",
|
||||
"description": "Discard changes made to these objects.",
|
||||
"depends": []
|
||||
|
@ -20,12 +20,34 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span ng-controller="EditActionController">
|
||||
<span ng-repeat="currentAction in editActions">
|
||||
<a class='s-button {{currentAction.getMetadata().cssclass}}'
|
||||
title='{{currentAction.getMetadata().name}}'
|
||||
ng-click="currentAction.perform()"
|
||||
ng-class="{ major: $index === 0 }">
|
||||
<span class="title-label">{{currentAction.getMetadata().name}}</span>
|
||||
</a>
|
||||
<!-- If there's a single save action show a button, otherwise show a dropdown with all save actions. -->
|
||||
<span ng-if="saveActions.length === 1">
|
||||
<mct-control key="'button'"
|
||||
structure="{
|
||||
text: saveActions[0].getMetadata().name,
|
||||
click: actionPerformer(saveActions[0]),
|
||||
cssclass: 'major ' + saveActions[0].getMetadata().cssclass
|
||||
}">
|
||||
</mct-control>
|
||||
</span>
|
||||
|
||||
<span ng-if="saveActions.length > 1">
|
||||
<mct-control key="'menu-button'"
|
||||
structure="{
|
||||
options: saveActionsAsMenuOptions,
|
||||
click: saveActionMenuClickHandler,
|
||||
cssclass: 'btn-bar right icon-save no-label major'
|
||||
}">
|
||||
</mct-control>
|
||||
</span>
|
||||
|
||||
<span ng-repeat="currentAction in otherEditActions">
|
||||
<mct-control key="'button'"
|
||||
structure="{
|
||||
text: currentAction.getMetadata().name,
|
||||
click: actionPerformer(currentAction),
|
||||
cssclass: currentAction.getMetadata().cssclass
|
||||
}">
|
||||
</mct-control>
|
||||
</span>
|
||||
</span>
|
@ -62,7 +62,7 @@ define(
|
||||
}
|
||||
|
||||
function cancel(allowed) {
|
||||
return allowed && domainObject.getCapability("editor").cancel();
|
||||
return allowed && domainObject.getCapability("editor").finish();
|
||||
}
|
||||
|
||||
//Do navigation first in order to trigger unsaved changes dialog
|
||||
|
@ -69,18 +69,13 @@ define(
|
||||
* Enter edit mode.
|
||||
*/
|
||||
EditAction.prototype.perform = function () {
|
||||
var self = this;
|
||||
function cancelEditing() {
|
||||
self.domainObject.getCapability('editor').cancel();
|
||||
self.navigationService.removeListener(cancelEditing);
|
||||
}
|
||||
|
||||
//If this is not the currently navigated object, then navigate
|
||||
// to it.
|
||||
if (this.navigationService.getNavigation() !== this.domainObject) {
|
||||
this.navigationService.setNavigation(this.domainObject);
|
||||
}
|
||||
|
||||
this.navigationService.addListener(cancelEditing);
|
||||
this.domainObject.useCapability("editor");
|
||||
};
|
||||
|
||||
|
@ -25,9 +25,8 @@ define(
|
||||
function (SaveInProgressDialog) {
|
||||
|
||||
/**
|
||||
* The "Save" action; the action triggered by clicking Save from
|
||||
* Edit Mode. Exits the editing user interface and invokes object
|
||||
* capabilities to persist the changes that have been made.
|
||||
* The "Save" action; it invokes object capabilities to persist
|
||||
* the changes that have been made.
|
||||
* @constructor
|
||||
* @implements {Action}
|
||||
* @memberof platform/commonUI/edit
|
||||
@ -41,7 +40,7 @@ define(
|
||||
}
|
||||
|
||||
/**
|
||||
* Save changes and conclude editing.
|
||||
* Save changes.
|
||||
*
|
||||
* @returns {Promise} a promise that will be fulfilled when
|
||||
* cancellation has completed
|
||||
@ -51,40 +50,22 @@ define(
|
||||
var domainObject = this.domainObject,
|
||||
dialog = new SaveInProgressDialog(this.dialogService);
|
||||
|
||||
function resolveWith(object) {
|
||||
return function () {
|
||||
return object;
|
||||
};
|
||||
}
|
||||
|
||||
// Invoke any save behavior introduced by the editor capability;
|
||||
// this is introduced by EditableDomainObject which is
|
||||
// used to insulate underlying objects from changes made
|
||||
// during editing.
|
||||
function doSave() {
|
||||
return domainObject.getCapability("editor").save()
|
||||
.then(resolveWith(domainObject));
|
||||
return domainObject.getCapability("editor").save();
|
||||
}
|
||||
|
||||
// Discard the current root view (which will be the editing
|
||||
// UI, which will have been pushed atop the Browse UI.)
|
||||
function returnToBrowse(object) {
|
||||
if (object) {
|
||||
object.getCapability("action").perform("navigate");
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
function hideBlockingDialog(object) {
|
||||
function hideBlockingDialog() {
|
||||
dialog.hide();
|
||||
return object;
|
||||
}
|
||||
|
||||
dialog.show();
|
||||
|
||||
return doSave()
|
||||
.then(hideBlockingDialog)
|
||||
.then(returnToBrowse)
|
||||
.catch(hideBlockingDialog);
|
||||
};
|
||||
|
||||
|
@ -0,0 +1,73 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
["./SaveAction"],
|
||||
function (SaveAction) {
|
||||
|
||||
/**
|
||||
* The "Save and Stop Editing" action performs a [Save action]{@link SaveAction}
|
||||
* on the object under edit followed by exiting the edit user interface.
|
||||
* @constructor
|
||||
* @implements {Action}
|
||||
* @memberof platform/commonUI/edit
|
||||
*/
|
||||
function SaveAndStopEditingAction(
|
||||
dialogService,
|
||||
context
|
||||
) {
|
||||
this.context = context;
|
||||
this.domainObject = (context || {}).domainObject;
|
||||
this.dialogService = dialogService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger a save operation and exit edit mode.
|
||||
*
|
||||
* @returns {Promise} a promise that will be fulfilled when
|
||||
* cancellation has completed
|
||||
* @memberof platform/commonUI/edit.SaveAndStopEditingAction#
|
||||
*/
|
||||
SaveAndStopEditingAction.prototype.perform = function () {
|
||||
var domainObject = this.domainObject,
|
||||
saveAction = new SaveAction(this.dialogService, this.context);
|
||||
|
||||
function closeEditor() {
|
||||
return domainObject.getCapability("editor").finish();
|
||||
}
|
||||
|
||||
return saveAction.perform()
|
||||
.then(closeEditor)
|
||||
.catch(closeEditor);
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if this action is applicable in a given context.
|
||||
* This will ensure that a domain object is present in the context,
|
||||
* and that this domain object is in Edit mode.
|
||||
* @returns true if applicable
|
||||
*/
|
||||
SaveAndStopEditingAction.appliesTo = SaveAction.appliesTo;
|
||||
|
||||
return SaveAndStopEditingAction;
|
||||
}
|
||||
);
|
@ -42,7 +42,6 @@ define([
|
||||
$injector,
|
||||
policyService,
|
||||
dialogService,
|
||||
creationService,
|
||||
copyService,
|
||||
context
|
||||
) {
|
||||
@ -52,7 +51,6 @@ define([
|
||||
};
|
||||
this.policyService = policyService;
|
||||
this.dialogService = dialogService;
|
||||
this.creationService = creationService;
|
||||
this.copyService = copyService;
|
||||
}
|
||||
|
||||
@ -166,11 +164,16 @@ define([
|
||||
.then(resolveWith(object));
|
||||
}
|
||||
|
||||
function commitEditingAfterClone(clonedObject) {
|
||||
function saveAfterClone(clonedObject) {
|
||||
return domainObject.getCapability("editor").save()
|
||||
.then(resolveWith(clonedObject));
|
||||
}
|
||||
|
||||
function finishEditing(clonedObject) {
|
||||
return domainObject.getCapability("editor").finish()
|
||||
.then(resolveWith(clonedObject));
|
||||
}
|
||||
|
||||
function onFailure() {
|
||||
hideBlockingDialog();
|
||||
return false;
|
||||
@ -182,7 +185,8 @@ define([
|
||||
.then(getParent)
|
||||
.then(cloneIntoParent)
|
||||
.then(undirtyOriginals)
|
||||
.then(commitEditingAfterClone)
|
||||
.then(saveAfterClone)
|
||||
.then(finishEditing)
|
||||
.then(hideBlockingDialog)
|
||||
.catch(onFailure);
|
||||
};
|
||||
|
@ -9,7 +9,8 @@ define([], function () {
|
||||
title: "Saving...",
|
||||
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
|
||||
unknownProgress: true,
|
||||
severity: "info"
|
||||
severity: "info",
|
||||
delay: true
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -28,8 +28,8 @@ define(
|
||||
* A capability that implements an editing 'session' for a domain
|
||||
* object. An editing session is initiated via a call to .edit().
|
||||
* Once initiated, any persist operations will be queued pending a
|
||||
* subsequent call to [.save()](@link #save) or [.cancel()](@link
|
||||
* #cancel).
|
||||
* subsequent call to [.save()](@link #save) or [.finish()](@link
|
||||
* #finish).
|
||||
* @param transactionService
|
||||
* @param domainObject
|
||||
* @constructor
|
||||
@ -45,7 +45,7 @@ define(
|
||||
/**
|
||||
* Initiate an editing session. This will start a transaction during
|
||||
* which any persist operations will be deferred until either save()
|
||||
* or cancel() are called.
|
||||
* or finish() are called.
|
||||
*/
|
||||
EditorCapability.prototype.edit = function () {
|
||||
this.transactionService.startTransaction();
|
||||
@ -81,25 +81,25 @@ define(
|
||||
};
|
||||
|
||||
/**
|
||||
* Save any changes from this editing session. This will flush all
|
||||
* pending persists and end the current transaction
|
||||
* Save any unsaved changes from this editing session. This will
|
||||
* end the current transaction and continue with a new one.
|
||||
* @returns {*}
|
||||
*/
|
||||
EditorCapability.prototype.save = function () {
|
||||
var domainObject = this.domainObject;
|
||||
return this.transactionService.commit().then(function () {
|
||||
domainObject.getCapability('status').set('editing', false);
|
||||
var transactionService = this.transactionService;
|
||||
return transactionService.commit().then(function () {
|
||||
transactionService.startTransaction();
|
||||
});
|
||||
};
|
||||
|
||||
EditorCapability.prototype.invoke = EditorCapability.prototype.edit;
|
||||
|
||||
/**
|
||||
* Cancel the current editing session. This will discard any pending
|
||||
* Finish the current editing session. This will discard any pending
|
||||
* persist operations
|
||||
* @returns {*}
|
||||
*/
|
||||
EditorCapability.prototype.cancel = function () {
|
||||
EditorCapability.prototype.finish = function () {
|
||||
var domainObject = this.domainObject;
|
||||
return this.transactionService.cancel().then(function () {
|
||||
domainObject.getCapability("status").set("editing", false);
|
||||
|
@ -27,7 +27,8 @@ define(
|
||||
[],
|
||||
function () {
|
||||
|
||||
var ACTION_CONTEXT = { category: 'conclude-editing' };
|
||||
var SAVE_ACTION_CONTEXT = { category: 'save' };
|
||||
var OTHERS_ACTION_CONTEXT = { category: 'conclude-editing' };
|
||||
|
||||
/**
|
||||
* Controller which supplies action instances for Save/Cancel.
|
||||
@ -35,12 +36,37 @@ define(
|
||||
* @constructor
|
||||
*/
|
||||
function EditActionController($scope) {
|
||||
// Maintain all "conclude-editing" actions in the present
|
||||
// context.
|
||||
|
||||
function actionToMenuOption(action) {
|
||||
return {
|
||||
key: action,
|
||||
name: action.getMetadata().name,
|
||||
cssclass: action.getMetadata().cssclass
|
||||
};
|
||||
}
|
||||
|
||||
// Maintain all "conclude-editing" and "save" actions in the
|
||||
// present context.
|
||||
function updateActions() {
|
||||
$scope.editActions = $scope.action ?
|
||||
$scope.action.getActions(ACTION_CONTEXT) :
|
||||
$scope.saveActions = $scope.action ?
|
||||
$scope.action.getActions(SAVE_ACTION_CONTEXT) :
|
||||
[];
|
||||
|
||||
$scope.saveActionsAsMenuOptions = $scope.saveActions.map(actionToMenuOption);
|
||||
|
||||
$scope.saveActionMenuClickHandler = function (clickedAction) {
|
||||
clickedAction.perform();
|
||||
};
|
||||
|
||||
$scope.otherEditActions = $scope.action ?
|
||||
$scope.action.getActions(OTHERS_ACTION_CONTEXT) :
|
||||
[];
|
||||
|
||||
// Required because Angular does not allow 'bind'
|
||||
// in expressions.
|
||||
$scope.actionPerformer = function (action) {
|
||||
return action.perform.bind(action);
|
||||
};
|
||||
}
|
||||
|
||||
// Update set of actions whenever the action capability
|
||||
|
@ -67,12 +67,17 @@ define(
|
||||
editAction,
|
||||
editorCapability;
|
||||
|
||||
function closeEditor() {
|
||||
return editorCapability.finish();
|
||||
}
|
||||
|
||||
function onSave() {
|
||||
return editorCapability.save();
|
||||
return editorCapability.save()
|
||||
.then(closeEditor);
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
return editorCapability.cancel();
|
||||
return closeEditor();
|
||||
}
|
||||
|
||||
newModel.type = this.type.getKey();
|
||||
@ -85,9 +90,9 @@ define(
|
||||
if (editAction) {
|
||||
return editAction.perform();
|
||||
} else if (editorCapability) {
|
||||
//otherwise, use the save action
|
||||
//otherwise, use the save as action
|
||||
editorCapability.edit();
|
||||
return newObject.getCapability("action").perform("save").then(onSave, onCancel);
|
||||
return newObject.getCapability("action").perform("save-as").then(onSave, onCancel);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -138,7 +138,7 @@ define(
|
||||
try {
|
||||
results.push(onCancel());
|
||||
} catch (error) {
|
||||
this.$log.error("Error committing transaction.");
|
||||
this.$log.error("Error cancelling transaction.");
|
||||
}
|
||||
}
|
||||
return this.$q.all(results).then(function () {
|
||||
|
@ -63,7 +63,7 @@ define(
|
||||
|
||||
capabilities.editor = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "cancel", "isEditContextRoot"]
|
||||
["save", "finish", "isEditContextRoot"]
|
||||
);
|
||||
capabilities.action = jasmine.createSpyObj(
|
||||
"actionCapability",
|
||||
@ -105,7 +105,7 @@ define(
|
||||
return !!capabilities[name];
|
||||
});
|
||||
|
||||
capabilities.editor.cancel.andReturn(mockPromise(true));
|
||||
capabilities.editor.finish.andReturn(mockPromise(true));
|
||||
|
||||
action = new CancelAction(actionContext);
|
||||
|
||||
@ -130,8 +130,8 @@ define(
|
||||
capabilities.action.perform.andReturn(mockPromise(true));
|
||||
action.perform();
|
||||
|
||||
// Should have called cancel
|
||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
||||
// Should have called finish
|
||||
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||
|
||||
// Definitely shouldn't call save!
|
||||
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
||||
|
@ -58,7 +58,7 @@ define(
|
||||
);
|
||||
mockEditor = jasmine.createSpyObj(
|
||||
"editorCapability",
|
||||
["edit", "isEditContextRoot", "cancel"]
|
||||
["edit", "isEditContextRoot"]
|
||||
);
|
||||
|
||||
capabilities = {
|
||||
@ -98,13 +98,6 @@ define(
|
||||
expect(EditAction.appliesTo(actionContext)).toBe(false);
|
||||
});
|
||||
|
||||
it ("cancels editing when user navigates away", function () {
|
||||
action.perform();
|
||||
expect(mockNavigationService.addListener).toHaveBeenCalled();
|
||||
mockNavigationService.addListener.mostRecentCall.args[0]();
|
||||
expect(mockEditor.cancel).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it ("invokes the Edit capability on the object", function () {
|
||||
action.perform();
|
||||
expect(mockDomainObject.useCapability).toHaveBeenCalledWith("editor");
|
||||
|
@ -56,7 +56,7 @@ define(
|
||||
);
|
||||
mockEditorCapability = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "cancel", "isEditContextRoot"]
|
||||
["save", "isEditContextRoot"]
|
||||
);
|
||||
mockActionCapability = jasmine.createSpyObj(
|
||||
"actionCapability",
|
||||
@ -105,12 +105,6 @@ define(
|
||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("navigates to the object after saving",
|
||||
function () {
|
||||
action.perform();
|
||||
expect(mockActionCapability.perform).toHaveBeenCalledWith("navigate");
|
||||
});
|
||||
|
||||
describe("a blocking dialog", function () {
|
||||
var mockDialogHandle;
|
||||
|
||||
|
@ -0,0 +1,123 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
["../../src/actions/SaveAndStopEditingAction"],
|
||||
function (SaveAndStopEditingAction) {
|
||||
|
||||
describe("The Save and Stop Editing action", function () {
|
||||
|
||||
// Some mocks appear unused because the
|
||||
// underlying SaveAction that this action
|
||||
// depends on is not mocked, so we mock some
|
||||
// of SaveAction's own dependencies to make
|
||||
// it run.
|
||||
var mockDomainObject,
|
||||
mockEditorCapability,
|
||||
actionContext,
|
||||
dialogService,
|
||||
mockActionCapability,
|
||||
capabilities = {},
|
||||
action;
|
||||
|
||||
function mockPromise(value) {
|
||||
return {
|
||||
then: function (callback) {
|
||||
return mockPromise(callback(value));
|
||||
},
|
||||
catch: function (callback) {
|
||||
return mockPromise(callback(value));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[
|
||||
"getCapability",
|
||||
"hasCapability",
|
||||
"getModel",
|
||||
"getOriginalObject"
|
||||
]
|
||||
);
|
||||
mockEditorCapability = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "finish", "isEditContextRoot"]
|
||||
);
|
||||
mockActionCapability = jasmine.createSpyObj(
|
||||
"actionCapability",
|
||||
["perform"]
|
||||
);
|
||||
capabilities.editor = mockEditorCapability;
|
||||
capabilities.action = mockActionCapability;
|
||||
|
||||
actionContext = {
|
||||
domainObject: mockDomainObject
|
||||
};
|
||||
dialogService = jasmine.createSpyObj(
|
||||
"dialogService",
|
||||
["showBlockingMessage"]
|
||||
);
|
||||
|
||||
mockDomainObject.hasCapability.andReturn(true);
|
||||
mockDomainObject.getCapability.andCallFake(function (capability) {
|
||||
return capabilities[capability];
|
||||
});
|
||||
mockDomainObject.getModel.andReturn({ persisted: 0 });
|
||||
mockEditorCapability.save.andReturn(mockPromise(true));
|
||||
mockEditorCapability.isEditContextRoot.andReturn(true);
|
||||
|
||||
action = new SaveAndStopEditingAction(dialogService, actionContext);
|
||||
});
|
||||
|
||||
|
||||
it("only applies to domain object with an editor capability", function () {
|
||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(true);
|
||||
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
||||
|
||||
mockDomainObject.hasCapability.andReturn(false);
|
||||
mockDomainObject.getCapability.andReturn(undefined);
|
||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
||||
});
|
||||
|
||||
it("only applies to domain object that has already been persisted", function () {
|
||||
mockDomainObject.getModel.andReturn({ persisted: undefined });
|
||||
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
|
||||
});
|
||||
|
||||
it("does not close the editor before completing the save", function () {
|
||||
mockEditorCapability.save.andReturn(new Promise(function () {
|
||||
}));
|
||||
action.perform();
|
||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("closes the editor after saving", function () {
|
||||
action.perform();
|
||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||
expect(mockEditorCapability.finish).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -19,7 +19,7 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global describe,it,expect,beforeEach,jasmine*/
|
||||
/*global describe,it,expect,beforeEach,jasmine,runs,waitsFor,spyOn*/
|
||||
|
||||
define(
|
||||
["../../src/actions/SaveAsAction"],
|
||||
@ -33,7 +33,6 @@ define(
|
||||
mockDialogService,
|
||||
mockCopyService,
|
||||
mockParent,
|
||||
mockUrlService,
|
||||
actionContext,
|
||||
capabilities = {},
|
||||
action;
|
||||
@ -78,10 +77,10 @@ define(
|
||||
|
||||
mockEditorCapability = jasmine.createSpyObj(
|
||||
"editor",
|
||||
["save", "cancel", "isEditContextRoot"]
|
||||
["save", "finish", "isEditContextRoot"]
|
||||
);
|
||||
mockEditorCapability.cancel.andReturn(mockPromise(undefined));
|
||||
mockEditorCapability.save.andReturn(mockPromise(true));
|
||||
mockEditorCapability.finish.andReturn(mockPromise(true));
|
||||
mockEditorCapability.isEditContextRoot.andReturn(true);
|
||||
capabilities.editor = mockEditorCapability;
|
||||
|
||||
@ -113,16 +112,11 @@ define(
|
||||
]
|
||||
);
|
||||
|
||||
mockUrlService = jasmine.createSpyObj(
|
||||
"urlService",
|
||||
["urlForLocation"]
|
||||
);
|
||||
|
||||
actionContext = {
|
||||
domainObject: mockDomainObject
|
||||
};
|
||||
|
||||
action = new SaveAsAction(undefined, undefined, mockDialogService, undefined, mockCopyService, actionContext);
|
||||
action = new SaveAsAction(undefined, undefined, mockDialogService, mockCopyService, actionContext);
|
||||
|
||||
spyOn(action, "getObjectService");
|
||||
action.getObjectService.andReturn(mockObjectService);
|
||||
@ -156,6 +150,28 @@ define(
|
||||
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
|
||||
});
|
||||
|
||||
it("uses the editor capability to save the object", function () {
|
||||
mockEditorCapability.save.andReturn(new Promise(function () {}));
|
||||
runs(function () {
|
||||
action.perform();
|
||||
});
|
||||
waitsFor(function () {
|
||||
return mockEditorCapability.save.calls.length > 0;
|
||||
}, "perform() should call EditorCapability.save");
|
||||
runs(function () {
|
||||
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
it("uses the editor capability to finish editing the object", function () {
|
||||
runs(function () {
|
||||
action.perform();
|
||||
});
|
||||
waitsFor(function () {
|
||||
return mockEditorCapability.finish.calls.length > 0;
|
||||
}, "perform() should call EditorCapability.finish");
|
||||
});
|
||||
|
||||
it("returns to browse after save", function () {
|
||||
spyOn(action, "save");
|
||||
action.save.andReturn(mockPromise(mockDomainObject));
|
||||
|
@ -134,15 +134,15 @@ define(
|
||||
it("commits the transaction", function () {
|
||||
expect(mockTransactionService.commit).toHaveBeenCalled();
|
||||
});
|
||||
it("resets the edit state", function () {
|
||||
expect(mockStatusCapability.set).toHaveBeenCalledWith('editing', false);
|
||||
it("begins a new transaction", function () {
|
||||
expect(mockTransactionService.startTransaction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("cancel", function () {
|
||||
describe("finish", function () {
|
||||
beforeEach(function () {
|
||||
capability.edit();
|
||||
capability.cancel();
|
||||
capability.finish();
|
||||
});
|
||||
it("cancels the transaction", function () {
|
||||
expect(mockTransactionService.cancel).toHaveBeenCalled();
|
||||
@ -158,7 +158,7 @@ define(
|
||||
beforeEach(function () {
|
||||
mockDomainObject.getModel.andReturn(model);
|
||||
capability.edit();
|
||||
capability.cancel();
|
||||
capability.finish();
|
||||
});
|
||||
it("returns true if the object has been modified since it" +
|
||||
" was last persisted", function () {
|
||||
|
@ -19,22 +19,51 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/controllers/EditActionController"],
|
||||
function (EditActionController) {
|
||||
|
||||
describe("The Edit Action controller", function () {
|
||||
var mockSaveActionMetadata = {
|
||||
name: "mocked-save-action",
|
||||
cssclass: "mocked-save-action-css"
|
||||
};
|
||||
|
||||
function fakeGetActions(actionContext) {
|
||||
if (actionContext.category === "save") {
|
||||
var mockedSaveActions = [
|
||||
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"]),
|
||||
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"])
|
||||
];
|
||||
mockedSaveActions.forEach(function (action) {
|
||||
action.getMetadata.andReturn(mockSaveActionMetadata);
|
||||
});
|
||||
return mockedSaveActions;
|
||||
} else if (actionContext.category === "conclude-editing") {
|
||||
return ["a", "b", "c"];
|
||||
} else {
|
||||
throw "EditActionController uses a context that's not covered by tests.";
|
||||
}
|
||||
}
|
||||
|
||||
var mockScope,
|
||||
mockActions,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
||||
mockActions.getActions.andCallFake(fakeGetActions);
|
||||
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
||||
mockScope.action = mockActions;
|
||||
controller = new EditActionController(mockScope);
|
||||
});
|
||||
|
||||
function makeControllerUpdateActions() {
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
}
|
||||
|
||||
it("watches scope that may change applicable actions", function () {
|
||||
// The action capability
|
||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||
@ -43,16 +72,34 @@ define(
|
||||
);
|
||||
});
|
||||
|
||||
it("populates the scope with grouped and ungrouped actions", function () {
|
||||
mockScope.action = mockActions;
|
||||
it("populates the scope with 'save' actions", function () {
|
||||
makeControllerUpdateActions();
|
||||
expect(mockScope.saveActions.length).toEqual(2);
|
||||
});
|
||||
|
||||
mockActions.getActions.andReturn(["a", "b", "c"]);
|
||||
it("converts 'save' actions to their menu counterparts", function () {
|
||||
makeControllerUpdateActions();
|
||||
var menuOptions = mockScope.saveActionsAsMenuOptions;
|
||||
|
||||
// Call the watch
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
expect(menuOptions.length).toEqual(2);
|
||||
expect(menuOptions[0].key).toEqual(mockScope.saveActions[0]);
|
||||
expect(menuOptions[1].key).toEqual(mockScope.saveActions[1]);
|
||||
menuOptions.forEach(function (option) {
|
||||
expect(option.name).toEqual(mockSaveActionMetadata.name);
|
||||
expect(option.cssclass).toEqual(mockSaveActionMetadata.cssclass);
|
||||
});
|
||||
});
|
||||
|
||||
// Should have grouped and ungrouped actions in scope now
|
||||
expect(mockScope.editActions.length).toEqual(3);
|
||||
it("uses a click handler to perform the clicked action", function () {
|
||||
makeControllerUpdateActions();
|
||||
var sampleSaveAction = mockScope.saveActions[0];
|
||||
mockScope.saveActionMenuClickHandler(sampleSaveAction);
|
||||
expect(sampleSaveAction.perform).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("populates the scope with other editing actions", function () {
|
||||
makeControllerUpdateActions();
|
||||
expect(mockScope.otherEditActions).toEqual(["a", "b", "c"]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -103,7 +103,7 @@ define(
|
||||
[
|
||||
"edit",
|
||||
"save",
|
||||
"cancel"
|
||||
"finish"
|
||||
]
|
||||
);
|
||||
|
||||
@ -142,6 +142,7 @@ define(
|
||||
});
|
||||
|
||||
describe("the perform function", function () {
|
||||
var promise = jasmine.createSpyObj("promise", ["then"]);
|
||||
beforeEach(function () {
|
||||
capabilities.action.getActions.andReturn([mockEditAction]);
|
||||
});
|
||||
@ -156,19 +157,20 @@ define(
|
||||
expect(mockEditAction.perform).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("uses the save action if object does not have an edit action" +
|
||||
it("uses the save-as action if object does not have an edit action" +
|
||||
" available", function () {
|
||||
capabilities.action.getActions.andReturn([]);
|
||||
capabilities.action.perform.andReturn(mockPromise(undefined));
|
||||
capabilities.editor.save.andReturn(promise);
|
||||
action.perform();
|
||||
expect(capabilities.action.perform).toHaveBeenCalledWith("save");
|
||||
expect(capabilities.action.perform).toHaveBeenCalledWith("save-as");
|
||||
});
|
||||
|
||||
describe("uses to editor capability", function () {
|
||||
var promise = jasmine.createSpyObj("promise", ["then"]);
|
||||
beforeEach(function () {
|
||||
capabilities.action.getActions.andReturn([]);
|
||||
capabilities.action.perform.andReturn(promise);
|
||||
capabilities.editor.save.andReturn(promise);
|
||||
});
|
||||
|
||||
it("to save the edit if user saves dialog", function () {
|
||||
@ -178,10 +180,10 @@ define(
|
||||
expect(capabilities.editor.save).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("to cancel the edit if user cancels dialog", function () {
|
||||
it("to finish the edit if user cancels dialog", function () {
|
||||
action.perform();
|
||||
promise.then.mostRecentCall.args[1]();
|
||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
||||
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -195,7 +195,7 @@ define(
|
||||
expect(failure).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("logs an error when mutaton fails", function () {
|
||||
it("logs an error when mutation fails", function () {
|
||||
// If mutation of the parent fails, we've lost the
|
||||
// created object - this is an error.
|
||||
var model = { someKey: "some value" };
|
||||
|
@ -112,7 +112,7 @@ define(
|
||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
||||
|
||||
// Finally, check that the provided mutation function
|
||||
// includes both model and configuratioon
|
||||
// includes both model and configuration
|
||||
expect(
|
||||
mockDomainObject.useCapability.mostRecentCall.args[1]()
|
||||
).toEqual({
|
||||
|
@ -79,7 +79,7 @@ define(
|
||||
it("removes state from parent scope on destroy", function () {
|
||||
// Verify precondition
|
||||
expect(mockScope.$parent.testToolbar).toBeDefined();
|
||||
// Destroy the represeter
|
||||
// Destroy the representer
|
||||
representer.destroy();
|
||||
// Should have removed toolbar state from view
|
||||
expect(mockScope.$parent.testToolbar).toBeUndefined();
|
||||
|
@ -61,6 +61,9 @@ $ueDesktopMinW: 600px;
|
||||
$ovrTopBarH: 45px;
|
||||
$ovrFooterH: 24px;
|
||||
$overlayMargin: 25px;
|
||||
/*************** Progress Overlay */
|
||||
$durEntryMs: 50ms;
|
||||
$delayEntryMs: 100ms;
|
||||
/*************** Items */
|
||||
$ueBrowseGridItemLg: 200px;
|
||||
$ueBrowseGridItemTopBarH: 20px;
|
||||
|
@ -31,23 +31,10 @@
|
||||
.has-control-bar {
|
||||
$btnExportH: $btnFrameH;
|
||||
.l-control-bar {
|
||||
@include trans-prop-nice(opacity, $dur: 50ms);
|
||||
opacity: 0;
|
||||
display: none;
|
||||
}
|
||||
.l-view-section {
|
||||
@include trans-prop-nice(top, $dur: 150ms, $delay: 50ms);
|
||||
top: 0;
|
||||
}
|
||||
&:hover {
|
||||
.l-control-bar {
|
||||
@include trans-prop-nice(opacity, 150ms, 100ms);
|
||||
opacity: 1;
|
||||
}
|
||||
.l-view-section {
|
||||
@include trans-prop-nice(top, $dur: 150ms);
|
||||
top: $btnExportH + $interiorMargin;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -216,6 +216,7 @@ input[type="search"] {
|
||||
.l-input-lg input[type="text"] { width: 100% !important; }
|
||||
.l-input-med input[type="text"] { width: 200px !important; }
|
||||
.l-input-sm input[type="text"] { width: 50px !important; }
|
||||
.l-textarea-sm textarea { position: relative; height: 50px; }
|
||||
.l-numeric input[type="text"] { text-align: right; }
|
||||
|
||||
.input-labeled {
|
||||
|
@ -19,8 +19,17 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
.overlay {
|
||||
font-size: 90%;
|
||||
&.delayEntry100ms {
|
||||
@include keyframes(fadeInFromNone) {
|
||||
0% { display: none; opacity: 0; }
|
||||
100% { display: block; opacity: 1; }
|
||||
}
|
||||
@include animation-delay($delayEntryMs);
|
||||
@include animation(fadeInFromNone $durEntryMs ease-in);
|
||||
}
|
||||
.blocker {
|
||||
background: $colorOvrBlocker;
|
||||
z-index: 100;
|
||||
|
@ -38,7 +38,7 @@ define(
|
||||
$scope.contextutalParents = [];
|
||||
//$scope.isLink = false;
|
||||
|
||||
// Gets an array of the contextual parents/anscestors of the selected object
|
||||
// Gets an array of the contextual parents/ancestors of the selected object
|
||||
function getContextualPath() {
|
||||
var currentObj = $scope.ngModel.selectedObject,
|
||||
currentParent,
|
||||
@ -61,7 +61,7 @@ define(
|
||||
$scope.contextutalParents = parents;
|
||||
}
|
||||
|
||||
// Gets an array of the parents/anscestors of the selected object's
|
||||
// Gets an array of the parents/ancestors of the selected object's
|
||||
// primary location (locational of original non-link)
|
||||
function getPrimaryPath(current) {
|
||||
var location;
|
||||
|
@ -25,7 +25,7 @@ define(function () {
|
||||
/**
|
||||
* Implements the `reverse` filter, which reverses text strings.
|
||||
* Useful in cases where text should be reversed for presentational
|
||||
* reasons (e.g. in conjunction with CSS tricks involing text direction),
|
||||
* reasons (e.g. in conjunction with CSS tricks involving text direction),
|
||||
* allowing such behavior to be handled independently from the controller
|
||||
* layer.
|
||||
*
|
||||
|
@ -35,7 +35,7 @@ define(
|
||||
}
|
||||
|
||||
/**
|
||||
* Options controlling how the popup is displaed.
|
||||
* Options controlling how the popup is displayed.
|
||||
*
|
||||
* @typedef PopupOptions
|
||||
* @memberof platform/commonUI/general
|
||||
|
@ -60,7 +60,7 @@ define(
|
||||
expect(controller.isActive()).toBe(false);
|
||||
});
|
||||
|
||||
it("allows active state to be explictly specified", function () {
|
||||
it("allows active state to be explicitly specified", function () {
|
||||
controller.setState(true);
|
||||
expect(controller.isActive()).toBe(true);
|
||||
controller.setState(true);
|
||||
|
@ -46,7 +46,7 @@ define(
|
||||
expect(controller.isActive()).toBe(false);
|
||||
});
|
||||
|
||||
it("allows active state to be explictly specified", function () {
|
||||
it("allows active state to be explicitly specified", function () {
|
||||
controller.setState(true);
|
||||
expect(controller.isActive()).toBe(true);
|
||||
controller.setState(true);
|
||||
|
@ -72,7 +72,7 @@ define(
|
||||
expect(directive.restrict).toEqual("A");
|
||||
});
|
||||
|
||||
it("transcludes at the elmeent level", function () {
|
||||
it("transcludes at the element level", function () {
|
||||
expect(directive.transclude).toEqual('element');
|
||||
});
|
||||
|
||||
|
@ -361,7 +361,7 @@ define(
|
||||
autodismiss specified), leave it to run. Otherwise force a
|
||||
timeout.
|
||||
|
||||
This notifcation has been added to queue and will be
|
||||
This notification has been added to queue and will be
|
||||
serviced as soon as possible.
|
||||
*/
|
||||
this.active.timeout = this.$timeout(function () {
|
||||
|
@ -45,7 +45,7 @@ define(
|
||||
['getKey', 'getDefinition', 'getInitialModel']
|
||||
);
|
||||
mockType.getKey.andReturn(type);
|
||||
// Return a model to drive apparant capabilities
|
||||
// Return a model to drive apparent capabilities
|
||||
mockType.getInitialModel.andReturn({ id: type });
|
||||
return mockType;
|
||||
});
|
||||
|
@ -50,7 +50,7 @@ define(
|
||||
// third one defines no containership rules
|
||||
contains: (index < 2) ? [{ has: 'b' }] : undefined
|
||||
});
|
||||
// Return a model to drive apparant capabilities
|
||||
// Return a model to drive apparent capabilities
|
||||
mockType.getInitialModel.andReturn({ id: type });
|
||||
return mockType;
|
||||
});
|
||||
|
@ -252,6 +252,14 @@ define([
|
||||
"pattern": "\\S+",
|
||||
"required": true,
|
||||
"cssclass": "l-input-lg"
|
||||
},
|
||||
{
|
||||
"name": "Notes",
|
||||
"key": "notes",
|
||||
"property": "notes",
|
||||
"control": "textarea",
|
||||
"required": false,
|
||||
"cssclass": "l-textarea-sm"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -24,7 +24,7 @@ define([], function () {
|
||||
|
||||
/**
|
||||
* Provides a cache for domain object models which exist in memory,
|
||||
* but may or may not exist in backing persistene stores.
|
||||
* but may or may not exist in backing persistence stores.
|
||||
* @constructor
|
||||
* @memberof platform/core
|
||||
*/
|
||||
|
@ -42,7 +42,7 @@ define(
|
||||
* @implements {ModelService}
|
||||
* @param {Array} roots all `roots[]` extensions
|
||||
* @param $q Angular's $q, for promises
|
||||
* @param $log Anuglar's $log, for logging
|
||||
* @param $log Angular's $log, for logging
|
||||
*/
|
||||
function RootModelProvider(roots, $q, $log) {
|
||||
// Pull out identifiers to used as ROOT's
|
||||
|
@ -49,7 +49,7 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
// Prepoulate maps with models to make subsequent lookup faster.
|
||||
// Prepopulate maps with models to make subsequent lookup faster.
|
||||
models.forEach(addModelToMap);
|
||||
|
||||
this.modelMap = modelMap;
|
||||
|
@ -43,7 +43,7 @@ define(
|
||||
},
|
||||
ARRAY_SUFFIX = '[]';
|
||||
|
||||
// Utility function to handle arrays of conversiions
|
||||
// Utility function to handle arrays of conversions
|
||||
function ArrayConversion(conversion) {
|
||||
return {
|
||||
toModelValue: function (formValue) {
|
||||
|
@ -68,7 +68,7 @@ define(
|
||||
}) : array;
|
||||
}
|
||||
|
||||
// Reduce an array of type definitions to a single type definiton,
|
||||
// Reduce an array of type definitions to a single type definition,
|
||||
// which has merged all properties in order.
|
||||
function collapse(typeDefs) {
|
||||
var collapsed = typeDefs.reduce(function (a, b) {
|
||||
|
@ -3,7 +3,7 @@
|
||||
Entanglement is the process of moving, copying, and linking domain objects
|
||||
in such a way that their relationships are impossible to discern.
|
||||
|
||||
This bundle provides move, copy, and link functionality. Acheiving a state of
|
||||
This bundle provides move, copy, and link functionality. Achieving a state of
|
||||
entanglement is left up to the end user.
|
||||
|
||||
|
||||
|
@ -123,6 +123,18 @@ define([
|
||||
"template": timeConductorTemplate
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"name": "D3: Data-Driven Documents",
|
||||
"version": "4.1.0",
|
||||
"author": "Mike Bostock",
|
||||
"description": "D3 (or D3.js) is a JavaScript library for visualizing data using web standards. D3 helps you bring data to life using SVG, Canvas and HTML. D3 combines powerful visualization and interaction techniques with a data-driven approach to DOM manipulation, giving you the full capabilities of modern browsers and the freedom to design the right visual interface for your data.",
|
||||
"website": "https://d3js.org/",
|
||||
"copyright": "Copyright 2010-2016 Mike Bostock",
|
||||
"license": "BSD-3-Clause",
|
||||
"link": "https://github.com/d3/d3/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"formats": [
|
||||
{
|
||||
"key": "number",
|
||||
|
@ -94,7 +94,7 @@ define(
|
||||
};
|
||||
|
||||
/**
|
||||
* End a drag gesture. This should be callled when a drag
|
||||
* End a drag gesture. This should be called when a drag
|
||||
* concludes to trigger commit of changes.
|
||||
*/
|
||||
FixedDragHandle.prototype.endDrag = function () {
|
||||
|
@ -152,7 +152,7 @@ define(
|
||||
}
|
||||
|
||||
// Convert from { positions: ..., dimensions: ... } to an
|
||||
// apropriate ng-style argument, to position frames.
|
||||
// appropriate ng-style argument, to position frames.
|
||||
LayoutController.prototype.convertPosition = function (raw) {
|
||||
var gridSize = this.gridSize;
|
||||
// Multiply position/dimensions by grid size
|
||||
|
@ -164,7 +164,7 @@ define(
|
||||
// Populate scope
|
||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||
|
||||
// Verify precondtion
|
||||
// Verify precondition
|
||||
expect(testConfiguration.panels.b).not.toBeDefined();
|
||||
|
||||
// Do a drag
|
||||
|
@ -146,16 +146,6 @@ define([
|
||||
"copyright": "Copyright © 2012 Niklas von Hertzen.",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/niklasvh/html2canvas/blob/master/LICENSE"
|
||||
},
|
||||
{
|
||||
"name": "jsPDF",
|
||||
"version": "1.2.61",
|
||||
"author": "James Hall",
|
||||
"description": "JavaScript HTML renderer",
|
||||
"website": "https://github.com/MrRio/jsPDF",
|
||||
"copyright": "Copyright © 2010-2016 James Hall",
|
||||
"license": "license-mit",
|
||||
"link": "https://github.com/MrRio/jsPDF/blob/master/MIT-LICENSE.txt"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -23,11 +23,6 @@
|
||||
class="abs holder holder-plot has-control-bar">
|
||||
<div class="l-control-bar" ng-show="!plot.hideExportButtons">
|
||||
<span class="l-btn-set">
|
||||
<a class="s-button t-export icon-download labeled first"
|
||||
ng-click="plot.exportPDF()"
|
||||
title="Export This View's Data as PDF">
|
||||
PDF
|
||||
</a>
|
||||
<a class="s-button t-export labeled"
|
||||
ng-click="plot.exportPNG()"
|
||||
title="Export This View's Data as PNG">
|
||||
|
@ -380,17 +380,6 @@ define(
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Export the plot to PDF
|
||||
*/
|
||||
PlotController.prototype.exportPDF = function () {
|
||||
var self = this;
|
||||
self.hideExportButtons = true;
|
||||
self.exportImageService.exportPDF(self.$element[0], "plot.pdf").finally(function () {
|
||||
self.hideExportButtons = false;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Export the plot to PNG
|
||||
*/
|
||||
|
@ -26,32 +26,29 @@
|
||||
define(
|
||||
[
|
||||
"html2canvas",
|
||||
"jsPDF",
|
||||
"saveAs"
|
||||
],
|
||||
function (
|
||||
html2canvas,
|
||||
jsPDF,
|
||||
saveAs
|
||||
) {
|
||||
var self = this;
|
||||
|
||||
/**
|
||||
* The export image service will export any HTML node to
|
||||
* PDF, JPG, or PNG.
|
||||
* JPG, or PNG.
|
||||
* @param {object} $q
|
||||
* @param {object} $timeout
|
||||
* @param {object} $log
|
||||
* @param {constant} EXPORT_IMAGE_TIMEOUT time in milliseconds before a timeout error is returned
|
||||
* @constructor
|
||||
*/
|
||||
function ExportImageService($q, $timeout, $log, EXPORT_IMAGE_TIMEOUT, injHtml2Canvas, injJsPDF, injSaveAs, injFileReader) {
|
||||
function ExportImageService($q, $timeout, $log, EXPORT_IMAGE_TIMEOUT, injHtml2Canvas, injSaveAs, injFileReader) {
|
||||
self.$q = $q;
|
||||
self.$timeout = $timeout;
|
||||
self.$log = $log;
|
||||
self.EXPORT_IMAGE_TIMEOUT = EXPORT_IMAGE_TIMEOUT;
|
||||
self.html2canvas = injHtml2Canvas || html2canvas;
|
||||
self.jsPDF = injJsPDF || jsPDF;
|
||||
self.saveAs = injSaveAs || saveAs;
|
||||
self.reader = injFileReader || new FileReader();
|
||||
}
|
||||
@ -128,23 +125,6 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes a screenshot of a DOM node and exports to PDF.
|
||||
* @param {node} element to be exported
|
||||
* @param {string} filename the exported image
|
||||
* @returns {promise}
|
||||
*/
|
||||
ExportImageService.prototype.exportPDF = function (element, filename) {
|
||||
return renderElement(element, "jpeg").then(function (img) {
|
||||
self.reader.readAsDataURL(img);
|
||||
self.reader.onloadend = function () {
|
||||
var pdf = new self.jsPDF("l", "px", [element.offsetHeight, element.offsetWidth]);
|
||||
pdf.addImage(self.reader.result, "JPEG", 0, 0, element.offsetWidth, element.offsetHeight);
|
||||
pdf.save(filename);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Takes a screenshot of a DOM node and exports to JPG.
|
||||
* @param {node} element to be exported
|
||||
|
@ -59,7 +59,7 @@ define(
|
||||
expect(mock2d.clearRect).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("doees not construct if 2D is unavailable", function () {
|
||||
it("does not construct if 2D is unavailable", function () {
|
||||
mockCanvas.getContext.andReturn(undefined);
|
||||
expect(function () {
|
||||
return new Canvas2DChart(mockCanvas);
|
||||
|
@ -82,7 +82,7 @@ define(
|
||||
expect(mockGL.clear).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("doees not construct if WebGL is unavailable", function () {
|
||||
it("does not construct if WebGL is unavailable", function () {
|
||||
mockCanvas.getContext.andReturn(undefined);
|
||||
expect(function () {
|
||||
return new GLChart(mockCanvas);
|
||||
|
@ -73,7 +73,7 @@ define(
|
||||
mockElement = angular.element('<div />');
|
||||
mockExportImageService = jasmine.createSpyObj(
|
||||
"ExportImageService",
|
||||
["exportJPG", "exportPNG", "exportPDF"]
|
||||
["exportJPG", "exportPNG"]
|
||||
);
|
||||
mockFormatter = jasmine.createSpyObj(
|
||||
"formatter",
|
||||
|
@ -33,8 +33,6 @@ define(
|
||||
mockLog,
|
||||
mockHtml2Canvas,
|
||||
mockCanvas,
|
||||
mockJsPDF,
|
||||
mockJsPDFSave,
|
||||
mockSaveAs,
|
||||
mockFileReader,
|
||||
mockExportTimeoutConstant,
|
||||
@ -79,13 +77,6 @@ define(
|
||||
"canvas",
|
||||
["toBlob"]
|
||||
);
|
||||
mockJsPDFSave = jasmine.createSpy("jsPDFSave");
|
||||
mockJsPDF = function () {
|
||||
return {
|
||||
"addImage": function () {},
|
||||
"save": mockJsPDFSave
|
||||
};
|
||||
};
|
||||
mockSaveAs = jasmine.createSpy("saveAs");
|
||||
mockFileReader = jasmine.createSpyObj(
|
||||
"FileReader",
|
||||
@ -100,23 +91,11 @@ define(
|
||||
mockLog,
|
||||
mockExportTimeoutConstant,
|
||||
mockHtml2Canvas,
|
||||
mockJsPDF,
|
||||
mockSaveAs,
|
||||
mockFileReader
|
||||
);
|
||||
});
|
||||
|
||||
it("runs html2canvas and tries to save a pdf", function () {
|
||||
exportImageService.exportPDF(testElement, "plot.pdf");
|
||||
mockFileReader.onloadend();
|
||||
|
||||
expect(mockHtml2Canvas).toHaveBeenCalledWith(testElement, { onrendered: jasmine.any(Function) });
|
||||
expect(mockCanvas.toBlob).toHaveBeenCalledWith(mockDeferred.resolve, "image/jpeg");
|
||||
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
||||
expect(mockJsPDFSave).toHaveBeenCalled();
|
||||
expect(mockPromise.finally).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("runs html2canvas and tries to save a png", function () {
|
||||
exportImageService.exportPNG(testElement, "plot.png");
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
['zepto'],
|
||||
function ($) {
|
||||
|
||||
/**
|
||||
* A controller for the MCTTable directive. Populates scope with
|
||||
@ -16,13 +16,13 @@ define(
|
||||
var self = this;
|
||||
|
||||
this.$scope = $scope;
|
||||
this.element = element;
|
||||
this.element = $(element[0]);
|
||||
this.$timeout = $timeout;
|
||||
this.maxDisplayRows = 50;
|
||||
|
||||
this.scrollable = element.find('div');
|
||||
this.thead = element.find('thead');
|
||||
this.tbody = element.find('tbody');
|
||||
this.scrollable = this.element.find('.l-view-section.scrolling').first();
|
||||
this.resultsHeader = this.element.find('.mct-table>thead').first();
|
||||
this.sizingTableBody = this.element.find('.sizing-table>tbody').first();
|
||||
this.$scope.sizingRow = {};
|
||||
|
||||
this.scrollable.on('scroll', this.onScroll.bind(this));
|
||||
@ -261,8 +261,8 @@ define(
|
||||
* for individual rows.
|
||||
*/
|
||||
MCTTableController.prototype.setElementSizes = function () {
|
||||
var thead = this.thead,
|
||||
tbody = this.tbody,
|
||||
var thead = this.resultsHeader,
|
||||
tbody = this.sizingTableBody,
|
||||
firstRow = tbody.find('tr'),
|
||||
column = firstRow.find('td'),
|
||||
headerHeight = thead.prop('offsetHeight'),
|
||||
|
@ -22,9 +22,16 @@
|
||||
|
||||
define(
|
||||
[
|
||||
"zepto",
|
||||
"../../src/controllers/MCTTableController"
|
||||
],
|
||||
function (MCTTableController) {
|
||||
function ($, MCTTableController) {
|
||||
|
||||
var MOCK_ELEMENT_TEMPLATE =
|
||||
'<div><div class="l-view-section scrolling">' +
|
||||
'<table class="sizing-table"><tbody></tbody></table>' +
|
||||
'<table class="mct-table"><thead></thead></table>' +
|
||||
'</div></div>';
|
||||
|
||||
describe('The MCTTable Controller', function () {
|
||||
|
||||
@ -55,19 +62,7 @@ define(
|
||||
watches[event] = callback;
|
||||
});
|
||||
|
||||
mockElement = jasmine.createSpyObj('element', [
|
||||
'find',
|
||||
'prop',
|
||||
'on'
|
||||
]);
|
||||
mockElement.find.andReturn(mockElement);
|
||||
mockElement.prop.andReturn(0);
|
||||
mockElement[0] = {
|
||||
scrollTop: 0,
|
||||
scrollHeight: 500,
|
||||
offsetHeight: 1000
|
||||
};
|
||||
|
||||
mockElement = $(MOCK_ELEMENT_TEMPLATE);
|
||||
mockExportService = jasmine.createSpyObj('exportService', [
|
||||
'exportCSV'
|
||||
]);
|
||||
|
@ -182,6 +182,16 @@ define([
|
||||
"capacity"
|
||||
],
|
||||
"pattern": "^-?\\d+(\\.\\d*)?$"
|
||||
},
|
||||
{
|
||||
"name": "Battery starting SOC (%)",
|
||||
"control": "textfield",
|
||||
"required": false,
|
||||
"conversion": "number",
|
||||
"property": [
|
||||
"startingSOC"
|
||||
],
|
||||
"pattern": "^([0-9](\\.\\d*)?|[1-9][0-9](\\.\\d*)?|100)%?$"
|
||||
}
|
||||
],
|
||||
"model": {
|
||||
|
@ -37,7 +37,8 @@ define(
|
||||
// Build graphs for this group of utilizations
|
||||
function buildGraphs(utilizations) {
|
||||
var utilizationMap = {},
|
||||
result = {};
|
||||
result = {},
|
||||
startingSOC;
|
||||
|
||||
// Bucket utilizations by type
|
||||
utilizations.forEach(function (u) {
|
||||
@ -55,12 +56,14 @@ define(
|
||||
if (domainObject.getModel().type === 'timeline' &&
|
||||
result.power &&
|
||||
domainObject.getModel().capacity > 0) {
|
||||
startingSOC = isNaN(parseFloat(domainObject.getModel().startingSOC)) ?
|
||||
100 : parseFloat(domainObject.getModel().startingSOC);
|
||||
|
||||
result.battery = new CumulativeGraph(
|
||||
result.power,
|
||||
0,
|
||||
domainObject.getModel().capacity, // Watts
|
||||
domainObject.getModel().capacity,
|
||||
(startingSOC / 100) * domainObject.getModel().capacity,
|
||||
1 / 3600000 // millis-to-hour (since units are watt-hours)
|
||||
);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ define(
|
||||
|
||||
/**
|
||||
* Control for Gantt bars in a timeline view.
|
||||
* Primarily reesponsible for supporting the positioning of Gantt
|
||||
* Primarily responsible for supporting the positioning of Gantt
|
||||
* bars; particularly, this ensures that the left and right edges
|
||||
* never go to far off screen, because in some environments this
|
||||
* will effect rendering performance without visible results.
|
||||
|
@ -28,7 +28,7 @@ define(
|
||||
|
||||
/**
|
||||
* Provides labels for the tick mark area of a timeline view.
|
||||
* Since the tick mark regin is potentially extremeley large,
|
||||
* Since the tick mark region is potentially extremely large,
|
||||
* only the subset of ticks which will actually be shown in
|
||||
* view are provided.
|
||||
* @constructor
|
||||
|
@ -148,7 +148,7 @@ define(
|
||||
var timespan = timespans[toId(id)];
|
||||
// Use as setter if argument is present
|
||||
if ((typeof value === 'number') && timespan) {
|
||||
// Set the end (ensuring it doesn't preceed start)
|
||||
// Set the end (ensuring it doesn't precede start)
|
||||
timespan.setEnd(
|
||||
Math.max(value, timespan.getStart())
|
||||
);
|
||||
|
@ -41,7 +41,7 @@ define(
|
||||
ids,
|
||||
candidates;
|
||||
|
||||
// Filter an id for inclustion
|
||||
// Filter an id for inclusion
|
||||
function include(id) {
|
||||
return id !== exclude;
|
||||
}
|
||||
|
@ -101,6 +101,7 @@ define(
|
||||
it("provides a battery graph for timelines with capacity", function () {
|
||||
var mockCallback = jasmine.createSpy('callback');
|
||||
testModel.capacity = 1000;
|
||||
testModel.startingSOC = 100;
|
||||
testModel.type = "timeline";
|
||||
mockDomainObject.useCapability.andReturn(asPromise([
|
||||
{ key: "power", start: 0, end: 15 }
|
||||
|
@ -32,6 +32,7 @@ define([
|
||||
"text!./res/templates/controls/datetime.html",
|
||||
"text!./res/templates/controls/select.html",
|
||||
"text!./res/templates/controls/textfield.html",
|
||||
"text!./res/templates/controls/textarea.html",
|
||||
"text!./res/templates/controls/button.html",
|
||||
"text!./res/templates/controls/color.html",
|
||||
"text!./res/templates/controls/composite.html",
|
||||
@ -51,6 +52,7 @@ define([
|
||||
datetimeTemplate,
|
||||
selectTemplate,
|
||||
textfieldTemplate,
|
||||
textareaTemplate,
|
||||
buttonTemplate,
|
||||
colorTemplate,
|
||||
compositeTemplate,
|
||||
@ -103,6 +105,10 @@ define([
|
||||
"key": "textfield",
|
||||
"template": textfieldTemplate
|
||||
},
|
||||
{
|
||||
"key": "textarea",
|
||||
"template": textareaTemplate
|
||||
},
|
||||
{
|
||||
"key": "button",
|
||||
"template": buttonTemplate
|
||||
|
31
platform/forms/res/templates/controls/textarea.html
Normal file
31
platform/forms/res/templates/controls/textarea.html
Normal file
@ -0,0 +1,31 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
<span class='form-control shell'>
|
||||
<span class='field control {{structure.cssclass}}'>
|
||||
<textarea ng-required="ngRequired"
|
||||
ng-model="ngModel[field]"
|
||||
ng-pattern="ngPattern"
|
||||
size="{{structure.size}}"
|
||||
name="mctControl">
|
||||
</textarea>
|
||||
</span>
|
||||
</span>
|
@ -174,7 +174,7 @@ define(
|
||||
* category.
|
||||
*
|
||||
* @param {string} category name of the extension category
|
||||
* @returns {Array} extension definitions of that cataegory
|
||||
* @returns {Array} extension definitions of that category
|
||||
*/
|
||||
Bundle.prototype.getExtensions = function (category) {
|
||||
var extensions = this.definition.extensions[category] || [],
|
||||
|
@ -27,7 +27,7 @@ define(
|
||||
/**
|
||||
* A CouchDocument describes domain object model in a format
|
||||
* which is easily read-written to CouchDB. This includes
|
||||
* Couch's _id and _rev fields, as well as a sseparate
|
||||
* Couch's _id and _rev fields, as well as a separate
|
||||
* metadata field which contains a subset of information found
|
||||
* in the model itself (to support search optimization with
|
||||
* CouchDB views.)
|
||||
@ -37,7 +37,7 @@ define(
|
||||
* @param {object} model the model to store
|
||||
* @param {string} rev the revision to include (or undefined,
|
||||
* if no revision should be noted for couch)
|
||||
* @param {boolean} whether or not to mark this documnet as
|
||||
* @param {boolean} whether or not to mark this document as
|
||||
* deleted (see CouchDB docs for _deleted)
|
||||
*/
|
||||
function CouchDocument(id, model, rev, markDeleted) {
|
||||
|
@ -69,7 +69,7 @@ define(
|
||||
initialDescrption = indicator.getDescription(),
|
||||
initialGlyphClass = indicator.getGlyphClass();
|
||||
|
||||
// Nominal just means getting back an objeect, without
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
||||
|
||||
@ -88,7 +88,7 @@ define(
|
||||
initialDescrption = indicator.getDescription(),
|
||||
initialGlyphClass = indicator.getGlyphClass();
|
||||
|
||||
// Nominal just means getting back an objeect, with
|
||||
// Nominal just means getting back an object, with
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[0](
|
||||
{ data: { error: "Uh oh." } }
|
||||
@ -110,7 +110,7 @@ define(
|
||||
initialDescrption = indicator.getDescription(),
|
||||
initialGlyphClass = indicator.getGlyphClass();
|
||||
|
||||
// Nominal just means getting back an objeect, without
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
||||
|
||||
|
@ -51,7 +51,7 @@ define([
|
||||
* Search for domain objects using elasticsearch as a search provider.
|
||||
*
|
||||
* @param {String} searchTerm the term to search by.
|
||||
* @param {Number} [maxResults] the max numer of results to return.
|
||||
* @param {Number} [maxResults] the max number of results to return.
|
||||
* @returns {Promise} promise for a modelResults object.
|
||||
*/
|
||||
ElasticSearchProvider.prototype.query = function (searchTerm, maxResults) {
|
||||
|
@ -71,7 +71,7 @@ define(
|
||||
initialDescrption = indicator.getDescription(),
|
||||
initialGlyphClass = indicator.getGlyphClass();
|
||||
|
||||
// Nominal just means getting back an objeect, without
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
||||
|
||||
@ -90,7 +90,7 @@ define(
|
||||
initialDescrption = indicator.getDescription(),
|
||||
initialGlyphClass = indicator.getGlyphClass();
|
||||
|
||||
// Nominal just means getting back an objeect, without
|
||||
// Nominal just means getting back an object, without
|
||||
// an error field.
|
||||
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
||||
|
||||
|
@ -35,7 +35,7 @@ define(
|
||||
|
||||
/**
|
||||
* The PersistenceQueue is used by the QueuingPersistenceCapability
|
||||
* to aggregrate calls for object persistence. These are then issued
|
||||
* to aggregate calls for object persistence. These are then issued
|
||||
* in a group, such that if some or all are rejected, this result can
|
||||
* be shown to the user (again, in a group.)
|
||||
*
|
||||
|
@ -25,7 +25,7 @@ define(
|
||||
function () {
|
||||
|
||||
/**
|
||||
* Handles actual persistence invocations for queeud persistence
|
||||
* Handles actual persistence invocations for queued persistence
|
||||
* attempts, in a group. Handling in a group in this manner
|
||||
* also allows failure to be handled in a group (e.g. in a single
|
||||
* summary dialog.)
|
||||
|
@ -246,7 +246,7 @@ define([
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @returns {Number} a unique, unusued query Id.
|
||||
* @returns {Number} a unique, unused query Id.
|
||||
*/
|
||||
GenericSearchProvider.prototype.makeQueryId = function () {
|
||||
var queryId = Math.ceil(Math.random() * 100000);
|
||||
|
@ -123,7 +123,7 @@ define([
|
||||
expect(mockScope.results).toContain('a');
|
||||
});
|
||||
|
||||
it('is loading until the service\'s promise fufills', function () {
|
||||
it('is loading until the service\'s promise fulfills', function () {
|
||||
expect(mockScope.loading).toBeTruthy();
|
||||
|
||||
// Then resolve the promises
|
||||
@ -163,7 +163,7 @@ define([
|
||||
// Flag should be true with nonempty input
|
||||
expect(mockScope.ngModel.search).toEqual(true);
|
||||
|
||||
// Flag should be flase with empty input
|
||||
// Flag should be false with empty input
|
||||
mockScope.ngModel.input = '';
|
||||
controller.search();
|
||||
mockPromise.then.mostRecentCall.args[0]({hits: [], total: 0});
|
||||
|
@ -54,7 +54,7 @@ define(
|
||||
controller = new SearchMenuController(mockScope, mockTypes);
|
||||
});
|
||||
|
||||
it("gets types on initiliztion", function () {
|
||||
it("gets types on initialization", function () {
|
||||
expect(mockScope.ngModel.types).toBeDefined();
|
||||
});
|
||||
|
||||
|
@ -31,7 +31,7 @@ define(
|
||||
* `telemetrySubscriber`.
|
||||
*
|
||||
* Subscriptions may also be made directly using the
|
||||
* `telemetry` capability of a domain objcet; the subscriber
|
||||
* `telemetry` capability of a domain object; the subscriber
|
||||
* uses this as well, but additionally handles delegation
|
||||
* (e.g. for telemetry panels) as well as latest-value
|
||||
* extraction.
|
||||
|
@ -57,7 +57,7 @@ define(
|
||||
* `telemetrySubscriber` service.
|
||||
*
|
||||
* Subscriptions may also be made directly using the
|
||||
* `telemetry` capability of a domain objcet; the subscriber
|
||||
* `telemetry` capability of a domain object; the subscriber
|
||||
* uses this as well, but additionally handles delegation
|
||||
* (e.g. for telemetry panels) as well as latest-value
|
||||
* extraction.
|
||||
|
@ -56,7 +56,6 @@ requirejs.config({
|
||||
"EventEmitter": "bower_components/eventemitter3/index",
|
||||
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
||||
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
||||
"jsPDF": "bower_components/jspdf/dist/jspdf.min",
|
||||
"moment": "bower_components/moment/moment",
|
||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
||||
|
Loading…
Reference in New Issue
Block a user