mirror of
https://github.com/nasa/openmct.git
synced 2024-12-30 18:06:59 +00:00
Merged from master to resolve build issues
This commit is contained in:
commit
3e9c0eb7a5
@ -17,6 +17,7 @@ Differences between the two APIs include a move away from a declarative system o
|
|||||||
## Building and Running Open MCT Locally
|
## Building and Running Open MCT Locally
|
||||||
|
|
||||||
Building and running Open MCT in your local dev environment is very easy. Be sure you have [Git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/) installed, then follow the directions below. Need additional information? Check out the [Getting Started](https://nasa.github.io/openmct/getting-started/) page on our website.
|
Building and running Open MCT in your local dev environment is very easy. Be sure you have [Git](https://git-scm.com/downloads) and [Node.js](https://nodejs.org/) installed, then follow the directions below. Need additional information? Check out the [Getting Started](https://nasa.github.io/openmct/getting-started/) page on our website.
|
||||||
|
(These instructions assume you are installing as a non-root user; developers have [reported issues](https://github.com/nasa/openmct/issues/1151) running these steps with root privileges.)
|
||||||
|
|
||||||
1. Clone the source code
|
1. Clone the source code
|
||||||
|
|
||||||
|
10
app.js
10
app.js
@ -67,14 +67,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.use('/proxyUrl', function proxyRequest(req, res, next) {
|
app.use('/proxyUrl', function proxyRequest(req, res, next) {
|
||||||
var targetUrl = req.query.url;
|
console.log('Proxying request to: ', req.query.url);
|
||||||
var queryParameters = req.query;
|
|
||||||
console.log('Proxying request to: ', targetUrl);
|
|
||||||
delete queryParameters['url'];
|
|
||||||
req.pipe(request({
|
req.pipe(request({
|
||||||
url: targetUrl,
|
url: req.query.url,
|
||||||
strictSSL: false,
|
strictSSL: false
|
||||||
qs: queryParameters
|
|
||||||
}).on('error', next)).pipe(res);
|
}).on('error', next)).pipe(res);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
"zepto": "^1.1.6",
|
"zepto": "^1.1.6",
|
||||||
"eventemitter3": "^1.2.0",
|
"eventemitter3": "^1.2.0",
|
||||||
"d3": "~4.1.0",
|
"d3": "~4.1.0",
|
||||||
"html2canvas": "^0.4.1",
|
"html2canvas": "^0.4.1"
|
||||||
"jspdf": "^1.2.61"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ WEBSITE_DIRECTORY="website"
|
|||||||
BUILD_SHA=`git rev-parse HEAD`
|
BUILD_SHA=`git rev-parse HEAD`
|
||||||
|
|
||||||
# A remote will be created for the git repository we are pushing to.
|
# 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"
|
REMOTE_NAME="documentation"
|
||||||
WEBSITE_BRANCH="master"
|
WEBSITE_BRANCH="master"
|
||||||
|
|
||||||
|
@ -616,7 +616,7 @@ follows:
|
|||||||
part of an action's extension definition.
|
part of an action's extension definition.
|
||||||
* `CreateActionProvider` provides the various Create actions which
|
* `CreateActionProvider` provides the various Create actions which
|
||||||
populate the Create menu. These are driven by the available types,
|
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
|
are generated after looking up which actions are available from the
|
||||||
[`TypeService`](#type-service).
|
[`TypeService`](#type-service).
|
||||||
* `ActionAggregator` merges together actions from multiple providers.
|
* `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
|
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
|
dealing with telemetry are. e.g., what is the difference between just
|
||||||
"Telemetry" and the "Telemetry Service"? There are many
|
"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
|
### Developer Intern 2
|
||||||
|
|
||||||
@ -456,7 +456,7 @@ Instead, propose that:
|
|||||||
For parity with actions, a `View` would be a constructor which
|
For parity with actions, a `View` would be a constructor which
|
||||||
takes an `ActionContext` as a parameter (with similarly-defined
|
takes an `ActionContext` as a parameter (with similarly-defined
|
||||||
properties) and exposes a method to retrieve the HTML elements
|
properties) and exposes a method to retrieve the HTML elements
|
||||||
associateed with it.
|
associated with it.
|
||||||
|
|
||||||
The platform would then additionally expose an `AngularView`
|
The platform would then additionally expose an `AngularView`
|
||||||
implementation to improve compatibility with existing
|
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
|
## 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:
|
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__
|
__tutorials/telemetry/src/ExampleTelemetryServerAdapter.js__
|
||||||
|
|
||||||
Here, we have added `subscribe` and `unsubscribe` methods which issue the
|
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
|
listen for `data` messages as they come in: These will contain the data associated
|
||||||
with these subscriptions.
|
with these subscriptions.
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"LMP: 47 degrees.",
|
"LMP: 47 degrees.",
|
||||||
"CC: Eagle, looking great. You're GO.",
|
"CC: Eagle, looking great. You're GO.",
|
||||||
"CC: Roger. 1202. We copy it.",
|
"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: 700 feet, 21 down, 33 degrees.",
|
||||||
"LMP: 600 feet, down at 19.",
|
"LMP: 600 feet, down at 19.",
|
||||||
"LMP: 540 feet, down at - 30. Down at 15.",
|
"LMP: 540 feet, down at - 30. Down at 15.",
|
||||||
|
@ -103,11 +103,6 @@ gulp.task('stylesheets', function () {
|
|||||||
.pipe(gulp.dest(__dirname));
|
.pipe(gulp.dest(__dirname));
|
||||||
});
|
});
|
||||||
|
|
||||||
gulp.task('nsp', function (done) {
|
|
||||||
var nsp = require('gulp-nsp');
|
|
||||||
nsp({package: __dirname + '/package.json'}, done);
|
|
||||||
});
|
|
||||||
|
|
||||||
gulp.task('lint', function () {
|
gulp.task('lint', function () {
|
||||||
var nonspecs = paths.specs.map(function (glob) {
|
var nonspecs = paths.specs.map(function (glob) {
|
||||||
return "!" + glob;
|
return "!" + glob;
|
||||||
@ -157,6 +152,6 @@ gulp.task('develop', ['serve', 'stylesheets', 'watch']);
|
|||||||
|
|
||||||
gulp.task('install', [ 'static', 'scripts' ]);
|
gulp.task('install', [ 'static', 'scripts' ]);
|
||||||
|
|
||||||
gulp.task('verify', [ 'lint', 'test', 'checkstyle', 'nsp' ]);
|
gulp.task('verify', [ 'lint', 'test', 'checkstyle' ]);
|
||||||
|
|
||||||
gulp.task('build', [ 'verify', 'install' ]);
|
gulp.task('build', [ 'verify', 'install' ]);
|
||||||
|
4
main.js
4
main.js
@ -30,7 +30,6 @@ requirejs.config({
|
|||||||
"EventEmitter": "bower_components/eventemitter3/index",
|
"EventEmitter": "bower_components/eventemitter3/index",
|
||||||
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
||||||
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
||||||
"jsPDF": "bower_components/jspdf/dist/jspdf.min",
|
|
||||||
"moment": "bower_components/moment/moment",
|
"moment": "bower_components/moment/moment",
|
||||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||||
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
||||||
@ -50,9 +49,6 @@ requirejs.config({
|
|||||||
"html2canvas": {
|
"html2canvas": {
|
||||||
"exports": "html2canvas"
|
"exports": "html2canvas"
|
||||||
},
|
},
|
||||||
"jsPDF": {
|
|
||||||
"exports": "jsPDF"
|
|
||||||
},
|
|
||||||
"EventEmitter": {
|
"EventEmitter": {
|
||||||
"exports": "EventEmitter"
|
"exports": "EventEmitter"
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "openmct",
|
"name": "openmct",
|
||||||
"version": "0.11.3-SNAPSHOT",
|
"version": "0.12.0-SNAPSHOT",
|
||||||
"description": "The Open MCT core platform",
|
"description": "The Open MCT core platform",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.13.1",
|
"express": "^4.13.1",
|
||||||
@ -15,7 +15,6 @@
|
|||||||
"gulp-jscs": "^3.0.2",
|
"gulp-jscs": "^3.0.2",
|
||||||
"gulp-jshint": "^2.0.0",
|
"gulp-jshint": "^2.0.0",
|
||||||
"gulp-jshint-html-reporter": "^0.1.3",
|
"gulp-jshint-html-reporter": "^0.1.3",
|
||||||
"gulp-nsp": "^2.4.2",
|
|
||||||
"gulp-rename": "^1.2.2",
|
"gulp-rename": "^1.2.2",
|
||||||
"gulp-replace-task": "^0.11.0",
|
"gulp-replace-task": "^0.11.0",
|
||||||
"gulp-requirejs-optimize": "^0.3.1",
|
"gulp-requirejs-optimize": "^0.3.1",
|
||||||
|
@ -48,20 +48,35 @@ define(
|
|||||||
*/
|
*/
|
||||||
NavigateAction.prototype.perform = function () {
|
NavigateAction.prototype.perform = function () {
|
||||||
var self = this,
|
var self = this,
|
||||||
navigationAllowed = true;
|
navigateTo = this.domainObject,
|
||||||
|
currentObject = self.navigationService.getNavigation();
|
||||||
|
|
||||||
function allow() {
|
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" +
|
navigationAllowed = self.$window.confirm(message + "\r\n\r\n" +
|
||||||
" Are you sure you want to continue?");
|
" Are you sure you want to continue?");
|
||||||
});
|
});
|
||||||
return navigationAllowed;
|
return navigationAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set navigation, and wrap like a promise
|
function cancelIfEditing() {
|
||||||
return this.$q.when(
|
var editing = currentObject.hasCapability('editor') &&
|
||||||
allow() && this.navigationService.setNavigation(this.domainObject)
|
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,
|
mockQ,
|
||||||
mockDomainObject,
|
mockDomainObject,
|
||||||
mockPolicyService,
|
mockPolicyService,
|
||||||
|
mockNavigatedObject,
|
||||||
mockWindow,
|
mockWindow,
|
||||||
|
capabilities,
|
||||||
action;
|
action;
|
||||||
|
|
||||||
function mockPromise(value) {
|
function mockPromise(value) {
|
||||||
@ -44,6 +46,29 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(function () {
|
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(
|
mockNavigationService = jasmine.createSpyObj(
|
||||||
"navigationService",
|
"navigationService",
|
||||||
[
|
[
|
||||||
@ -51,11 +76,14 @@ define(
|
|||||||
"getNavigation"
|
"getNavigation"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
mockNavigationService.getNavigation.andReturn({});
|
mockNavigationService.getNavigation.andReturn(mockNavigatedObject);
|
||||||
mockQ = { when: mockPromise };
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
"domainObject",
|
"domainObject",
|
||||||
["getId", "getModel", "getCapability"]
|
[
|
||||||
|
"getId",
|
||||||
|
"getModel"
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
mockPolicyService = jasmine.createSpyObj("policyService",
|
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 () {
|
it("is only applicable when a domain object is in context", function () {
|
||||||
expect(NavigateAction.appliesTo({})).toBeFalsy();
|
expect(NavigateAction.appliesTo({})).toBeFalsy();
|
||||||
expect(NavigateAction.appliesTo({
|
expect(NavigateAction.appliesTo({
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
this source code distribution or the Licensing information page available
|
this source code distribution or the Licensing information page available
|
||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<div class="abs overlay">
|
<div class="abs overlay" ng-class="{'delayEntry100ms' : ngModel.delay}">
|
||||||
<div class="abs blocker"></div>
|
<div class="abs blocker"></div>
|
||||||
<div class="abs holder">
|
<div class="abs holder">
|
||||||
<a ng-click="ngModel.cancel()"
|
<a ng-click="ngModel.cancel()"
|
||||||
|
@ -187,7 +187,7 @@ define(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A description of the model options that may be passed to the
|
* 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.
|
* here is shared with the Notifications framework.
|
||||||
* @see NotificationService
|
* @see NotificationService
|
||||||
*
|
*
|
||||||
@ -200,6 +200,9 @@ define(
|
|||||||
* shown above a progress bar to indicate what's happening.
|
* shown above a progress bar to indicate what's happening.
|
||||||
* @property {number} progress a percentage value (1-100)
|
* @property {number} progress a percentage value (1-100)
|
||||||
* indicating the completion of the blocking task
|
* 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
|
* @property {string} progressText the message to show below a
|
||||||
* progress bar to indicate progress. For example, this might be
|
* progress bar to indicate progress. For example, this might be
|
||||||
* used to indicate time remaining, or items still to process.
|
* used to indicate time remaining, or items still to process.
|
||||||
|
@ -31,6 +31,7 @@ define([
|
|||||||
"./src/actions/PropertiesAction",
|
"./src/actions/PropertiesAction",
|
||||||
"./src/actions/RemoveAction",
|
"./src/actions/RemoveAction",
|
||||||
"./src/actions/SaveAction",
|
"./src/actions/SaveAction",
|
||||||
|
"./src/actions/SaveAndStopEditingAction",
|
||||||
"./src/actions/SaveAsAction",
|
"./src/actions/SaveAsAction",
|
||||||
"./src/actions/CancelAction",
|
"./src/actions/CancelAction",
|
||||||
"./src/policies/EditActionPolicy",
|
"./src/policies/EditActionPolicy",
|
||||||
@ -70,6 +71,7 @@ define([
|
|||||||
PropertiesAction,
|
PropertiesAction,
|
||||||
RemoveAction,
|
RemoveAction,
|
||||||
SaveAction,
|
SaveAction,
|
||||||
|
SaveAndStopEditingAction,
|
||||||
SaveAsAction,
|
SaveAsAction,
|
||||||
CancelAction,
|
CancelAction,
|
||||||
EditActionPolicy,
|
EditActionPolicy,
|
||||||
@ -203,20 +205,30 @@ define([
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "save",
|
"key": "save-and-stop-editing",
|
||||||
"category": "conclude-editing",
|
"category": "save",
|
||||||
"implementation": SaveAction,
|
"implementation": SaveAndStopEditingAction,
|
||||||
"name": "Save",
|
"name": "Save and Finish Editing",
|
||||||
"cssclass": "icon-save labeled",
|
"cssclass": "icon-save labeled",
|
||||||
"description": "Save changes made to these objects.",
|
"description": "Save changes made to these objects.",
|
||||||
"depends": [
|
"depends": [
|
||||||
"dialogService"
|
"dialogService"
|
||||||
],
|
]
|
||||||
"priority": "mandatory"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "save",
|
"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,
|
"implementation": SaveAsAction,
|
||||||
"name": "Save As...",
|
"name": "Save As...",
|
||||||
"cssclass": "icon-save labeled",
|
"cssclass": "icon-save labeled",
|
||||||
@ -225,7 +237,6 @@ define([
|
|||||||
"$injector",
|
"$injector",
|
||||||
"policyService",
|
"policyService",
|
||||||
"dialogService",
|
"dialogService",
|
||||||
"creationService",
|
|
||||||
"copyService"
|
"copyService"
|
||||||
],
|
],
|
||||||
"priority": "mandatory"
|
"priority": "mandatory"
|
||||||
@ -234,7 +245,9 @@ define([
|
|||||||
"key": "cancel",
|
"key": "cancel",
|
||||||
"category": "conclude-editing",
|
"category": "conclude-editing",
|
||||||
"implementation": CancelAction,
|
"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",
|
"cssclass": "icon-x no-label",
|
||||||
"description": "Discard changes made to these objects.",
|
"description": "Discard changes made to these objects.",
|
||||||
"depends": []
|
"depends": []
|
||||||
|
@ -20,12 +20,34 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<span ng-controller="EditActionController">
|
<span ng-controller="EditActionController">
|
||||||
<span ng-repeat="currentAction in editActions">
|
<!-- If there's a single save action show a button, otherwise show a dropdown with all save actions. -->
|
||||||
<a class='s-button {{currentAction.getMetadata().cssclass}}'
|
<span ng-if="saveActions.length === 1">
|
||||||
title='{{currentAction.getMetadata().name}}'
|
<mct-control key="'button'"
|
||||||
ng-click="currentAction.perform()"
|
structure="{
|
||||||
ng-class="{ major: $index === 0 }">
|
text: saveActions[0].getMetadata().name,
|
||||||
<span class="title-label">{{currentAction.getMetadata().name}}</span>
|
click: actionPerformer(saveActions[0]),
|
||||||
</a>
|
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>
|
||||||
</span>
|
</span>
|
@ -62,7 +62,7 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function cancel(allowed) {
|
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
|
//Do navigation first in order to trigger unsaved changes dialog
|
||||||
|
@ -69,18 +69,13 @@ define(
|
|||||||
* Enter edit mode.
|
* Enter edit mode.
|
||||||
*/
|
*/
|
||||||
EditAction.prototype.perform = function () {
|
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
|
//If this is not the currently navigated object, then navigate
|
||||||
// to it.
|
// to it.
|
||||||
if (this.navigationService.getNavigation() !== this.domainObject) {
|
if (this.navigationService.getNavigation() !== this.domainObject) {
|
||||||
this.navigationService.setNavigation(this.domainObject);
|
this.navigationService.setNavigation(this.domainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.navigationService.addListener(cancelEditing);
|
|
||||||
this.domainObject.useCapability("editor");
|
this.domainObject.useCapability("editor");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,9 +25,8 @@ define(
|
|||||||
function (SaveInProgressDialog) {
|
function (SaveInProgressDialog) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "Save" action; the action triggered by clicking Save from
|
* The "Save" action; it invokes object capabilities to persist
|
||||||
* Edit Mode. Exits the editing user interface and invokes object
|
* the changes that have been made.
|
||||||
* capabilities to persist the changes that have been made.
|
|
||||||
* @constructor
|
* @constructor
|
||||||
* @implements {Action}
|
* @implements {Action}
|
||||||
* @memberof platform/commonUI/edit
|
* @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
|
* @returns {Promise} a promise that will be fulfilled when
|
||||||
* cancellation has completed
|
* cancellation has completed
|
||||||
@ -51,40 +50,22 @@ define(
|
|||||||
var domainObject = this.domainObject,
|
var domainObject = this.domainObject,
|
||||||
dialog = new SaveInProgressDialog(this.dialogService);
|
dialog = new SaveInProgressDialog(this.dialogService);
|
||||||
|
|
||||||
function resolveWith(object) {
|
|
||||||
return function () {
|
|
||||||
return object;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invoke any save behavior introduced by the editor capability;
|
// Invoke any save behavior introduced by the editor capability;
|
||||||
// this is introduced by EditableDomainObject which is
|
// this is introduced by EditableDomainObject which is
|
||||||
// used to insulate underlying objects from changes made
|
// used to insulate underlying objects from changes made
|
||||||
// during editing.
|
// during editing.
|
||||||
function doSave() {
|
function doSave() {
|
||||||
return domainObject.getCapability("editor").save()
|
return domainObject.getCapability("editor").save();
|
||||||
.then(resolveWith(domainObject));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Discard the current root view (which will be the editing
|
function hideBlockingDialog() {
|
||||||
// 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) {
|
|
||||||
dialog.hide();
|
dialog.hide();
|
||||||
return object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.show();
|
dialog.show();
|
||||||
|
|
||||||
return doSave()
|
return doSave()
|
||||||
.then(hideBlockingDialog)
|
.then(hideBlockingDialog)
|
||||||
.then(returnToBrowse)
|
|
||||||
.catch(hideBlockingDialog);
|
.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,
|
$injector,
|
||||||
policyService,
|
policyService,
|
||||||
dialogService,
|
dialogService,
|
||||||
creationService,
|
|
||||||
copyService,
|
copyService,
|
||||||
context
|
context
|
||||||
) {
|
) {
|
||||||
@ -52,7 +51,6 @@ define([
|
|||||||
};
|
};
|
||||||
this.policyService = policyService;
|
this.policyService = policyService;
|
||||||
this.dialogService = dialogService;
|
this.dialogService = dialogService;
|
||||||
this.creationService = creationService;
|
|
||||||
this.copyService = copyService;
|
this.copyService = copyService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,11 +164,16 @@ define([
|
|||||||
.then(resolveWith(object));
|
.then(resolveWith(object));
|
||||||
}
|
}
|
||||||
|
|
||||||
function commitEditingAfterClone(clonedObject) {
|
function saveAfterClone(clonedObject) {
|
||||||
return domainObject.getCapability("editor").save()
|
return domainObject.getCapability("editor").save()
|
||||||
.then(resolveWith(clonedObject));
|
.then(resolveWith(clonedObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function finishEditing(clonedObject) {
|
||||||
|
return domainObject.getCapability("editor").finish()
|
||||||
|
.then(resolveWith(clonedObject));
|
||||||
|
}
|
||||||
|
|
||||||
function onFailure() {
|
function onFailure() {
|
||||||
hideBlockingDialog();
|
hideBlockingDialog();
|
||||||
return false;
|
return false;
|
||||||
@ -182,7 +185,8 @@ define([
|
|||||||
.then(getParent)
|
.then(getParent)
|
||||||
.then(cloneIntoParent)
|
.then(cloneIntoParent)
|
||||||
.then(undirtyOriginals)
|
.then(undirtyOriginals)
|
||||||
.then(commitEditingAfterClone)
|
.then(saveAfterClone)
|
||||||
|
.then(finishEditing)
|
||||||
.then(hideBlockingDialog)
|
.then(hideBlockingDialog)
|
||||||
.catch(onFailure);
|
.catch(onFailure);
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,8 @@ define([], function () {
|
|||||||
title: "Saving...",
|
title: "Saving...",
|
||||||
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
|
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
|
||||||
unknownProgress: true,
|
unknownProgress: true,
|
||||||
severity: "info"
|
severity: "info",
|
||||||
|
delay: true
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ define(
|
|||||||
* A capability that implements an editing 'session' for a domain
|
* A capability that implements an editing 'session' for a domain
|
||||||
* object. An editing session is initiated via a call to .edit().
|
* object. An editing session is initiated via a call to .edit().
|
||||||
* Once initiated, any persist operations will be queued pending a
|
* Once initiated, any persist operations will be queued pending a
|
||||||
* subsequent call to [.save()](@link #save) or [.cancel()](@link
|
* subsequent call to [.save()](@link #save) or [.finish()](@link
|
||||||
* #cancel).
|
* #finish).
|
||||||
* @param transactionService
|
* @param transactionService
|
||||||
* @param domainObject
|
* @param domainObject
|
||||||
* @constructor
|
* @constructor
|
||||||
@ -45,7 +45,7 @@ define(
|
|||||||
/**
|
/**
|
||||||
* Initiate an editing session. This will start a transaction during
|
* Initiate an editing session. This will start a transaction during
|
||||||
* which any persist operations will be deferred until either save()
|
* which any persist operations will be deferred until either save()
|
||||||
* or cancel() are called.
|
* or finish() are called.
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.edit = function () {
|
EditorCapability.prototype.edit = function () {
|
||||||
this.transactionService.startTransaction();
|
this.transactionService.startTransaction();
|
||||||
@ -81,25 +81,25 @@ define(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Save any changes from this editing session. This will flush all
|
* Save any unsaved changes from this editing session. This will
|
||||||
* pending persists and end the current transaction
|
* end the current transaction and continue with a new one.
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.save = function () {
|
EditorCapability.prototype.save = function () {
|
||||||
var domainObject = this.domainObject;
|
var transactionService = this.transactionService;
|
||||||
return this.transactionService.commit().then(function () {
|
return transactionService.commit().then(function () {
|
||||||
domainObject.getCapability('status').set('editing', false);
|
transactionService.startTransaction();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
EditorCapability.prototype.invoke = EditorCapability.prototype.edit;
|
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
|
* persist operations
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
EditorCapability.prototype.cancel = function () {
|
EditorCapability.prototype.finish = function () {
|
||||||
var domainObject = this.domainObject;
|
var domainObject = this.domainObject;
|
||||||
return this.transactionService.cancel().then(function () {
|
return this.transactionService.cancel().then(function () {
|
||||||
domainObject.getCapability("status").set("editing", false);
|
domainObject.getCapability("status").set("editing", false);
|
||||||
|
@ -27,7 +27,8 @@ define(
|
|||||||
[],
|
[],
|
||||||
function () {
|
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.
|
* Controller which supplies action instances for Save/Cancel.
|
||||||
@ -35,12 +36,37 @@ define(
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function EditActionController($scope) {
|
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() {
|
function updateActions() {
|
||||||
$scope.editActions = $scope.action ?
|
$scope.saveActions = $scope.action ?
|
||||||
$scope.action.getActions(ACTION_CONTEXT) :
|
$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
|
// Update set of actions whenever the action capability
|
||||||
|
@ -67,12 +67,17 @@ define(
|
|||||||
editAction,
|
editAction,
|
||||||
editorCapability;
|
editorCapability;
|
||||||
|
|
||||||
|
function closeEditor() {
|
||||||
|
return editorCapability.finish();
|
||||||
|
}
|
||||||
|
|
||||||
function onSave() {
|
function onSave() {
|
||||||
return editorCapability.save();
|
return editorCapability.save()
|
||||||
|
.then(closeEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
function onCancel() {
|
function onCancel() {
|
||||||
return editorCapability.cancel();
|
return closeEditor();
|
||||||
}
|
}
|
||||||
|
|
||||||
newModel.type = this.type.getKey();
|
newModel.type = this.type.getKey();
|
||||||
@ -85,9 +90,9 @@ define(
|
|||||||
if (editAction) {
|
if (editAction) {
|
||||||
return editAction.perform();
|
return editAction.perform();
|
||||||
} else if (editorCapability) {
|
} else if (editorCapability) {
|
||||||
//otherwise, use the save action
|
//otherwise, use the save as action
|
||||||
editorCapability.edit();
|
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 {
|
try {
|
||||||
results.push(onCancel());
|
results.push(onCancel());
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.$log.error("Error committing transaction.");
|
this.$log.error("Error cancelling transaction.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return this.$q.all(results).then(function () {
|
return this.$q.all(results).then(function () {
|
||||||
|
@ -63,7 +63,7 @@ define(
|
|||||||
|
|
||||||
capabilities.editor = jasmine.createSpyObj(
|
capabilities.editor = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "cancel", "isEditContextRoot"]
|
["save", "finish", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
capabilities.action = jasmine.createSpyObj(
|
capabilities.action = jasmine.createSpyObj(
|
||||||
"actionCapability",
|
"actionCapability",
|
||||||
@ -105,7 +105,7 @@ define(
|
|||||||
return !!capabilities[name];
|
return !!capabilities[name];
|
||||||
});
|
});
|
||||||
|
|
||||||
capabilities.editor.cancel.andReturn(mockPromise(true));
|
capabilities.editor.finish.andReturn(mockPromise(true));
|
||||||
|
|
||||||
action = new CancelAction(actionContext);
|
action = new CancelAction(actionContext);
|
||||||
|
|
||||||
@ -130,8 +130,8 @@ define(
|
|||||||
capabilities.action.perform.andReturn(mockPromise(true));
|
capabilities.action.perform.andReturn(mockPromise(true));
|
||||||
action.perform();
|
action.perform();
|
||||||
|
|
||||||
// Should have called cancel
|
// Should have called finish
|
||||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||||
|
|
||||||
// Definitely shouldn't call save!
|
// Definitely shouldn't call save!
|
||||||
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
||||||
|
@ -58,7 +58,7 @@ define(
|
|||||||
);
|
);
|
||||||
mockEditor = jasmine.createSpyObj(
|
mockEditor = jasmine.createSpyObj(
|
||||||
"editorCapability",
|
"editorCapability",
|
||||||
["edit", "isEditContextRoot", "cancel"]
|
["edit", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
|
|
||||||
capabilities = {
|
capabilities = {
|
||||||
@ -98,13 +98,6 @@ define(
|
|||||||
expect(EditAction.appliesTo(actionContext)).toBe(false);
|
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 () {
|
it ("invokes the Edit capability on the object", function () {
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(mockDomainObject.useCapability).toHaveBeenCalledWith("editor");
|
expect(mockDomainObject.useCapability).toHaveBeenCalledWith("editor");
|
||||||
|
@ -56,7 +56,7 @@ define(
|
|||||||
);
|
);
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
mockEditorCapability = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "cancel", "isEditContextRoot"]
|
["save", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
mockActionCapability = jasmine.createSpyObj(
|
mockActionCapability = jasmine.createSpyObj(
|
||||||
"actionCapability",
|
"actionCapability",
|
||||||
@ -105,12 +105,6 @@ define(
|
|||||||
expect(mockEditorCapability.save).toHaveBeenCalled();
|
expect(mockEditorCapability.save).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("navigates to the object after saving",
|
|
||||||
function () {
|
|
||||||
action.perform();
|
|
||||||
expect(mockActionCapability.perform).toHaveBeenCalledWith("navigate");
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("a blocking dialog", function () {
|
describe("a blocking dialog", function () {
|
||||||
var mockDialogHandle;
|
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
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/*global describe,it,expect,beforeEach,jasmine*/
|
/*global describe,it,expect,beforeEach,jasmine,runs,waitsFor,spyOn*/
|
||||||
|
|
||||||
define(
|
define(
|
||||||
["../../src/actions/SaveAsAction"],
|
["../../src/actions/SaveAsAction"],
|
||||||
@ -33,7 +33,6 @@ define(
|
|||||||
mockDialogService,
|
mockDialogService,
|
||||||
mockCopyService,
|
mockCopyService,
|
||||||
mockParent,
|
mockParent,
|
||||||
mockUrlService,
|
|
||||||
actionContext,
|
actionContext,
|
||||||
capabilities = {},
|
capabilities = {},
|
||||||
action;
|
action;
|
||||||
@ -78,10 +77,10 @@ define(
|
|||||||
|
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
mockEditorCapability = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "cancel", "isEditContextRoot"]
|
["save", "finish", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
mockEditorCapability.cancel.andReturn(mockPromise(undefined));
|
|
||||||
mockEditorCapability.save.andReturn(mockPromise(true));
|
mockEditorCapability.save.andReturn(mockPromise(true));
|
||||||
|
mockEditorCapability.finish.andReturn(mockPromise(true));
|
||||||
mockEditorCapability.isEditContextRoot.andReturn(true);
|
mockEditorCapability.isEditContextRoot.andReturn(true);
|
||||||
capabilities.editor = mockEditorCapability;
|
capabilities.editor = mockEditorCapability;
|
||||||
|
|
||||||
@ -113,16 +112,11 @@ define(
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
mockUrlService = jasmine.createSpyObj(
|
|
||||||
"urlService",
|
|
||||||
["urlForLocation"]
|
|
||||||
);
|
|
||||||
|
|
||||||
actionContext = {
|
actionContext = {
|
||||||
domainObject: mockDomainObject
|
domainObject: mockDomainObject
|
||||||
};
|
};
|
||||||
|
|
||||||
action = new SaveAsAction(undefined, undefined, mockDialogService, undefined, mockCopyService, actionContext);
|
action = new SaveAsAction(undefined, undefined, mockDialogService, mockCopyService, actionContext);
|
||||||
|
|
||||||
spyOn(action, "getObjectService");
|
spyOn(action, "getObjectService");
|
||||||
action.getObjectService.andReturn(mockObjectService);
|
action.getObjectService.andReturn(mockObjectService);
|
||||||
@ -156,6 +150,28 @@ define(
|
|||||||
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
|
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 () {
|
it("returns to browse after save", function () {
|
||||||
spyOn(action, "save");
|
spyOn(action, "save");
|
||||||
action.save.andReturn(mockPromise(mockDomainObject));
|
action.save.andReturn(mockPromise(mockDomainObject));
|
||||||
|
@ -134,15 +134,15 @@ define(
|
|||||||
it("commits the transaction", function () {
|
it("commits the transaction", function () {
|
||||||
expect(mockTransactionService.commit).toHaveBeenCalled();
|
expect(mockTransactionService.commit).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
it("resets the edit state", function () {
|
it("begins a new transaction", function () {
|
||||||
expect(mockStatusCapability.set).toHaveBeenCalledWith('editing', false);
|
expect(mockTransactionService.startTransaction).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("cancel", function () {
|
describe("finish", function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
capability.edit();
|
capability.edit();
|
||||||
capability.cancel();
|
capability.finish();
|
||||||
});
|
});
|
||||||
it("cancels the transaction", function () {
|
it("cancels the transaction", function () {
|
||||||
expect(mockTransactionService.cancel).toHaveBeenCalled();
|
expect(mockTransactionService.cancel).toHaveBeenCalled();
|
||||||
@ -158,7 +158,7 @@ define(
|
|||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockDomainObject.getModel.andReturn(model);
|
mockDomainObject.getModel.andReturn(model);
|
||||||
capability.edit();
|
capability.edit();
|
||||||
capability.cancel();
|
capability.finish();
|
||||||
});
|
});
|
||||||
it("returns true if the object has been modified since it" +
|
it("returns true if the object has been modified since it" +
|
||||||
" was last persisted", function () {
|
" was last persisted", function () {
|
||||||
|
@ -19,22 +19,51 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
/*global describe,it,expect,beforeEach,jasmine*/
|
||||||
|
|
||||||
define(
|
define(
|
||||||
["../../src/controllers/EditActionController"],
|
["../../src/controllers/EditActionController"],
|
||||||
function (EditActionController) {
|
function (EditActionController) {
|
||||||
|
|
||||||
describe("The Edit Action controller", function () {
|
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,
|
var mockScope,
|
||||||
mockActions,
|
mockActions,
|
||||||
controller;
|
controller;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
||||||
|
mockActions.getActions.andCallFake(fakeGetActions);
|
||||||
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
||||||
|
mockScope.action = mockActions;
|
||||||
controller = new EditActionController(mockScope);
|
controller = new EditActionController(mockScope);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function makeControllerUpdateActions() {
|
||||||
|
mockScope.$watch.mostRecentCall.args[1]();
|
||||||
|
}
|
||||||
|
|
||||||
it("watches scope that may change applicable actions", function () {
|
it("watches scope that may change applicable actions", function () {
|
||||||
// The action capability
|
// The action capability
|
||||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||||
@ -43,16 +72,34 @@ define(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("populates the scope with grouped and ungrouped actions", function () {
|
it("populates the scope with 'save' actions", function () {
|
||||||
mockScope.action = mockActions;
|
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
|
expect(menuOptions.length).toEqual(2);
|
||||||
mockScope.$watch.mostRecentCall.args[1]();
|
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
|
it("uses a click handler to perform the clicked action", function () {
|
||||||
expect(mockScope.editActions.length).toEqual(3);
|
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",
|
"edit",
|
||||||
"save",
|
"save",
|
||||||
"cancel"
|
"finish"
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -142,6 +142,7 @@ define(
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("the perform function", function () {
|
describe("the perform function", function () {
|
||||||
|
var promise = jasmine.createSpyObj("promise", ["then"]);
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
capabilities.action.getActions.andReturn([mockEditAction]);
|
capabilities.action.getActions.andReturn([mockEditAction]);
|
||||||
});
|
});
|
||||||
@ -156,19 +157,20 @@ define(
|
|||||||
expect(mockEditAction.perform).toHaveBeenCalled();
|
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 () {
|
" available", function () {
|
||||||
capabilities.action.getActions.andReturn([]);
|
capabilities.action.getActions.andReturn([]);
|
||||||
capabilities.action.perform.andReturn(mockPromise(undefined));
|
capabilities.action.perform.andReturn(mockPromise(undefined));
|
||||||
|
capabilities.editor.save.andReturn(promise);
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(capabilities.action.perform).toHaveBeenCalledWith("save");
|
expect(capabilities.action.perform).toHaveBeenCalledWith("save-as");
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("uses to editor capability", function () {
|
describe("uses to editor capability", function () {
|
||||||
var promise = jasmine.createSpyObj("promise", ["then"]);
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
capabilities.action.getActions.andReturn([]);
|
capabilities.action.getActions.andReturn([]);
|
||||||
capabilities.action.perform.andReturn(promise);
|
capabilities.action.perform.andReturn(promise);
|
||||||
|
capabilities.editor.save.andReturn(promise);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("to save the edit if user saves dialog", function () {
|
it("to save the edit if user saves dialog", function () {
|
||||||
@ -178,10 +180,10 @@ define(
|
|||||||
expect(capabilities.editor.save).toHaveBeenCalled();
|
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();
|
action.perform();
|
||||||
promise.then.mostRecentCall.args[1]();
|
promise.then.mostRecentCall.args[1]();
|
||||||
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
expect(capabilities.editor.finish).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -195,7 +195,7 @@ define(
|
|||||||
expect(failure).toHaveBeenCalled();
|
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
|
// If mutation of the parent fails, we've lost the
|
||||||
// created object - this is an error.
|
// created object - this is an error.
|
||||||
var model = { someKey: "some value" };
|
var model = { someKey: "some value" };
|
||||||
|
@ -112,7 +112,7 @@ define(
|
|||||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
expect(mockPersistence.persist).toHaveBeenCalled();
|
||||||
|
|
||||||
// Finally, check that the provided mutation function
|
// Finally, check that the provided mutation function
|
||||||
// includes both model and configuratioon
|
// includes both model and configuration
|
||||||
expect(
|
expect(
|
||||||
mockDomainObject.useCapability.mostRecentCall.args[1]()
|
mockDomainObject.useCapability.mostRecentCall.args[1]()
|
||||||
).toEqual({
|
).toEqual({
|
||||||
|
@ -79,7 +79,7 @@ define(
|
|||||||
it("removes state from parent scope on destroy", function () {
|
it("removes state from parent scope on destroy", function () {
|
||||||
// Verify precondition
|
// Verify precondition
|
||||||
expect(mockScope.$parent.testToolbar).toBeDefined();
|
expect(mockScope.$parent.testToolbar).toBeDefined();
|
||||||
// Destroy the represeter
|
// Destroy the representer
|
||||||
representer.destroy();
|
representer.destroy();
|
||||||
// Should have removed toolbar state from view
|
// Should have removed toolbar state from view
|
||||||
expect(mockScope.$parent.testToolbar).toBeUndefined();
|
expect(mockScope.$parent.testToolbar).toBeUndefined();
|
||||||
|
@ -61,6 +61,9 @@ $ueDesktopMinW: 600px;
|
|||||||
$ovrTopBarH: 45px;
|
$ovrTopBarH: 45px;
|
||||||
$ovrFooterH: 24px;
|
$ovrFooterH: 24px;
|
||||||
$overlayMargin: 25px;
|
$overlayMargin: 25px;
|
||||||
|
/*************** Progress Overlay */
|
||||||
|
$durEntryMs: 50ms;
|
||||||
|
$delayEntryMs: 100ms;
|
||||||
/*************** Items */
|
/*************** Items */
|
||||||
$ueBrowseGridItemLg: 200px;
|
$ueBrowseGridItemLg: 200px;
|
||||||
$ueBrowseGridItemTopBarH: 20px;
|
$ueBrowseGridItemTopBarH: 20px;
|
||||||
|
@ -31,23 +31,10 @@
|
|||||||
.has-control-bar {
|
.has-control-bar {
|
||||||
$btnExportH: $btnFrameH;
|
$btnExportH: $btnFrameH;
|
||||||
.l-control-bar {
|
.l-control-bar {
|
||||||
@include trans-prop-nice(opacity, $dur: 50ms);
|
display: none;
|
||||||
opacity: 0;
|
|
||||||
}
|
}
|
||||||
.l-view-section {
|
.l-view-section {
|
||||||
@include trans-prop-nice(top, $dur: 150ms, $delay: 50ms);
|
|
||||||
top: 0;
|
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-lg input[type="text"] { width: 100% !important; }
|
||||||
.l-input-med input[type="text"] { width: 200px !important; }
|
.l-input-med input[type="text"] { width: 200px !important; }
|
||||||
.l-input-sm input[type="text"] { width: 50px !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; }
|
.l-numeric input[type="text"] { text-align: right; }
|
||||||
|
|
||||||
.input-labeled {
|
.input-labeled {
|
||||||
|
@ -19,8 +19,17 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
.overlay {
|
.overlay {
|
||||||
font-size: 90%;
|
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 {
|
.blocker {
|
||||||
background: $colorOvrBlocker;
|
background: $colorOvrBlocker;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
@ -38,7 +38,7 @@ define(
|
|||||||
$scope.contextutalParents = [];
|
$scope.contextutalParents = [];
|
||||||
//$scope.isLink = false;
|
//$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() {
|
function getContextualPath() {
|
||||||
var currentObj = $scope.ngModel.selectedObject,
|
var currentObj = $scope.ngModel.selectedObject,
|
||||||
currentParent,
|
currentParent,
|
||||||
@ -61,7 +61,7 @@ define(
|
|||||||
$scope.contextutalParents = parents;
|
$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)
|
// primary location (locational of original non-link)
|
||||||
function getPrimaryPath(current) {
|
function getPrimaryPath(current) {
|
||||||
var location;
|
var location;
|
||||||
|
@ -25,7 +25,7 @@ define(function () {
|
|||||||
/**
|
/**
|
||||||
* Implements the `reverse` filter, which reverses text strings.
|
* Implements the `reverse` filter, which reverses text strings.
|
||||||
* Useful in cases where text should be reversed for presentational
|
* 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
|
* allowing such behavior to be handled independently from the controller
|
||||||
* layer.
|
* layer.
|
||||||
*
|
*
|
||||||
|
@ -35,7 +35,7 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Options controlling how the popup is displaed.
|
* Options controlling how the popup is displayed.
|
||||||
*
|
*
|
||||||
* @typedef PopupOptions
|
* @typedef PopupOptions
|
||||||
* @memberof platform/commonUI/general
|
* @memberof platform/commonUI/general
|
||||||
|
@ -60,7 +60,7 @@ define(
|
|||||||
expect(controller.isActive()).toBe(false);
|
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);
|
controller.setState(true);
|
||||||
expect(controller.isActive()).toBe(true);
|
expect(controller.isActive()).toBe(true);
|
||||||
controller.setState(true);
|
controller.setState(true);
|
||||||
|
@ -46,7 +46,7 @@ define(
|
|||||||
expect(controller.isActive()).toBe(false);
|
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);
|
controller.setState(true);
|
||||||
expect(controller.isActive()).toBe(true);
|
expect(controller.isActive()).toBe(true);
|
||||||
controller.setState(true);
|
controller.setState(true);
|
||||||
|
@ -72,7 +72,7 @@ define(
|
|||||||
expect(directive.restrict).toEqual("A");
|
expect(directive.restrict).toEqual("A");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("transcludes at the elmeent level", function () {
|
it("transcludes at the element level", function () {
|
||||||
expect(directive.transclude).toEqual('element');
|
expect(directive.transclude).toEqual('element');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -361,7 +361,7 @@ define(
|
|||||||
autodismiss specified), leave it to run. Otherwise force a
|
autodismiss specified), leave it to run. Otherwise force a
|
||||||
timeout.
|
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.
|
serviced as soon as possible.
|
||||||
*/
|
*/
|
||||||
this.active.timeout = this.$timeout(function () {
|
this.active.timeout = this.$timeout(function () {
|
||||||
|
@ -45,7 +45,7 @@ define(
|
|||||||
['getKey', 'getDefinition', 'getInitialModel']
|
['getKey', 'getDefinition', 'getInitialModel']
|
||||||
);
|
);
|
||||||
mockType.getKey.andReturn(type);
|
mockType.getKey.andReturn(type);
|
||||||
// Return a model to drive apparant capabilities
|
// Return a model to drive apparent capabilities
|
||||||
mockType.getInitialModel.andReturn({ id: type });
|
mockType.getInitialModel.andReturn({ id: type });
|
||||||
return mockType;
|
return mockType;
|
||||||
});
|
});
|
||||||
|
@ -50,7 +50,7 @@ define(
|
|||||||
// third one defines no containership rules
|
// third one defines no containership rules
|
||||||
contains: (index < 2) ? [{ has: 'b' }] : undefined
|
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 });
|
mockType.getInitialModel.andReturn({ id: type });
|
||||||
return mockType;
|
return mockType;
|
||||||
});
|
});
|
||||||
|
@ -252,6 +252,14 @@ define([
|
|||||||
"pattern": "\\S+",
|
"pattern": "\\S+",
|
||||||
"required": true,
|
"required": true,
|
||||||
"cssclass": "l-input-lg"
|
"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,
|
* 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
|
* @constructor
|
||||||
* @memberof platform/core
|
* @memberof platform/core
|
||||||
*/
|
*/
|
||||||
|
@ -42,7 +42,7 @@ define(
|
|||||||
* @implements {ModelService}
|
* @implements {ModelService}
|
||||||
* @param {Array} roots all `roots[]` extensions
|
* @param {Array} roots all `roots[]` extensions
|
||||||
* @param $q Angular's $q, for promises
|
* @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) {
|
function RootModelProvider(roots, $q, $log) {
|
||||||
// Pull out identifiers to used as ROOT's
|
// 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);
|
models.forEach(addModelToMap);
|
||||||
|
|
||||||
this.modelMap = modelMap;
|
this.modelMap = modelMap;
|
||||||
|
@ -43,7 +43,7 @@ define(
|
|||||||
},
|
},
|
||||||
ARRAY_SUFFIX = '[]';
|
ARRAY_SUFFIX = '[]';
|
||||||
|
|
||||||
// Utility function to handle arrays of conversiions
|
// Utility function to handle arrays of conversions
|
||||||
function ArrayConversion(conversion) {
|
function ArrayConversion(conversion) {
|
||||||
return {
|
return {
|
||||||
toModelValue: function (formValue) {
|
toModelValue: function (formValue) {
|
||||||
|
@ -68,7 +68,7 @@ define(
|
|||||||
}) : array;
|
}) : 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.
|
// which has merged all properties in order.
|
||||||
function collapse(typeDefs) {
|
function collapse(typeDefs) {
|
||||||
var collapsed = typeDefs.reduce(function (a, b) {
|
var collapsed = typeDefs.reduce(function (a, b) {
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
Entanglement is the process of moving, copying, and linking domain objects
|
Entanglement is the process of moving, copying, and linking domain objects
|
||||||
in such a way that their relationships are impossible to discern.
|
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.
|
entanglement is left up to the end user.
|
||||||
|
|
||||||
|
|
||||||
|
@ -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.
|
* concludes to trigger commit of changes.
|
||||||
*/
|
*/
|
||||||
FixedDragHandle.prototype.endDrag = function () {
|
FixedDragHandle.prototype.endDrag = function () {
|
||||||
|
@ -152,7 +152,7 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert from { positions: ..., dimensions: ... } to an
|
// 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) {
|
LayoutController.prototype.convertPosition = function (raw) {
|
||||||
var gridSize = this.gridSize;
|
var gridSize = this.gridSize;
|
||||||
// Multiply position/dimensions by grid size
|
// Multiply position/dimensions by grid size
|
||||||
|
@ -164,7 +164,7 @@ define(
|
|||||||
// Populate scope
|
// Populate scope
|
||||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||||
|
|
||||||
// Verify precondtion
|
// Verify precondition
|
||||||
expect(testConfiguration.panels.b).not.toBeDefined();
|
expect(testConfiguration.panels.b).not.toBeDefined();
|
||||||
|
|
||||||
// Do a drag
|
// Do a drag
|
||||||
|
@ -146,16 +146,6 @@ define([
|
|||||||
"copyright": "Copyright © 2012 Niklas von Hertzen.",
|
"copyright": "Copyright © 2012 Niklas von Hertzen.",
|
||||||
"license": "license-mit",
|
"license": "license-mit",
|
||||||
"link": "https://github.com/niklasvh/html2canvas/blob/master/LICENSE"
|
"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">
|
class="abs holder holder-plot has-control-bar">
|
||||||
<div class="l-control-bar" ng-show="!plot.hideExportButtons">
|
<div class="l-control-bar" ng-show="!plot.hideExportButtons">
|
||||||
<span class="l-btn-set">
|
<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"
|
<a class="s-button t-export labeled"
|
||||||
ng-click="plot.exportPNG()"
|
ng-click="plot.exportPNG()"
|
||||||
title="Export This View's Data as PNG">
|
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
|
* Export the plot to PNG
|
||||||
*/
|
*/
|
||||||
|
@ -26,32 +26,29 @@
|
|||||||
define(
|
define(
|
||||||
[
|
[
|
||||||
"html2canvas",
|
"html2canvas",
|
||||||
"jsPDF",
|
|
||||||
"saveAs"
|
"saveAs"
|
||||||
],
|
],
|
||||||
function (
|
function (
|
||||||
html2canvas,
|
html2canvas,
|
||||||
jsPDF,
|
|
||||||
saveAs
|
saveAs
|
||||||
) {
|
) {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The export image service will export any HTML node to
|
* The export image service will export any HTML node to
|
||||||
* PDF, JPG, or PNG.
|
* JPG, or PNG.
|
||||||
* @param {object} $q
|
* @param {object} $q
|
||||||
* @param {object} $timeout
|
* @param {object} $timeout
|
||||||
* @param {object} $log
|
* @param {object} $log
|
||||||
* @param {constant} EXPORT_IMAGE_TIMEOUT time in milliseconds before a timeout error is returned
|
* @param {constant} EXPORT_IMAGE_TIMEOUT time in milliseconds before a timeout error is returned
|
||||||
* @constructor
|
* @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.$q = $q;
|
||||||
self.$timeout = $timeout;
|
self.$timeout = $timeout;
|
||||||
self.$log = $log;
|
self.$log = $log;
|
||||||
self.EXPORT_IMAGE_TIMEOUT = EXPORT_IMAGE_TIMEOUT;
|
self.EXPORT_IMAGE_TIMEOUT = EXPORT_IMAGE_TIMEOUT;
|
||||||
self.html2canvas = injHtml2Canvas || html2canvas;
|
self.html2canvas = injHtml2Canvas || html2canvas;
|
||||||
self.jsPDF = injJsPDF || jsPDF;
|
|
||||||
self.saveAs = injSaveAs || saveAs;
|
self.saveAs = injSaveAs || saveAs;
|
||||||
self.reader = injFileReader || new FileReader();
|
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.
|
* Takes a screenshot of a DOM node and exports to JPG.
|
||||||
* @param {node} element to be exported
|
* @param {node} element to be exported
|
||||||
|
@ -59,7 +59,7 @@ define(
|
|||||||
expect(mock2d.clearRect).toHaveBeenCalled();
|
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);
|
mockCanvas.getContext.andReturn(undefined);
|
||||||
expect(function () {
|
expect(function () {
|
||||||
return new Canvas2DChart(mockCanvas);
|
return new Canvas2DChart(mockCanvas);
|
||||||
|
@ -82,7 +82,7 @@ define(
|
|||||||
expect(mockGL.clear).toHaveBeenCalled();
|
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);
|
mockCanvas.getContext.andReturn(undefined);
|
||||||
expect(function () {
|
expect(function () {
|
||||||
return new GLChart(mockCanvas);
|
return new GLChart(mockCanvas);
|
||||||
|
@ -73,7 +73,7 @@ define(
|
|||||||
mockElement = angular.element('<div />');
|
mockElement = angular.element('<div />');
|
||||||
mockExportImageService = jasmine.createSpyObj(
|
mockExportImageService = jasmine.createSpyObj(
|
||||||
"ExportImageService",
|
"ExportImageService",
|
||||||
["exportJPG", "exportPNG", "exportPDF"]
|
["exportJPG", "exportPNG"]
|
||||||
);
|
);
|
||||||
mockFormatter = jasmine.createSpyObj(
|
mockFormatter = jasmine.createSpyObj(
|
||||||
"formatter",
|
"formatter",
|
||||||
|
@ -33,8 +33,6 @@ define(
|
|||||||
mockLog,
|
mockLog,
|
||||||
mockHtml2Canvas,
|
mockHtml2Canvas,
|
||||||
mockCanvas,
|
mockCanvas,
|
||||||
mockJsPDF,
|
|
||||||
mockJsPDFSave,
|
|
||||||
mockSaveAs,
|
mockSaveAs,
|
||||||
mockFileReader,
|
mockFileReader,
|
||||||
mockExportTimeoutConstant,
|
mockExportTimeoutConstant,
|
||||||
@ -79,13 +77,6 @@ define(
|
|||||||
"canvas",
|
"canvas",
|
||||||
["toBlob"]
|
["toBlob"]
|
||||||
);
|
);
|
||||||
mockJsPDFSave = jasmine.createSpy("jsPDFSave");
|
|
||||||
mockJsPDF = function () {
|
|
||||||
return {
|
|
||||||
"addImage": function () {},
|
|
||||||
"save": mockJsPDFSave
|
|
||||||
};
|
|
||||||
};
|
|
||||||
mockSaveAs = jasmine.createSpy("saveAs");
|
mockSaveAs = jasmine.createSpy("saveAs");
|
||||||
mockFileReader = jasmine.createSpyObj(
|
mockFileReader = jasmine.createSpyObj(
|
||||||
"FileReader",
|
"FileReader",
|
||||||
@ -100,23 +91,11 @@ define(
|
|||||||
mockLog,
|
mockLog,
|
||||||
mockExportTimeoutConstant,
|
mockExportTimeoutConstant,
|
||||||
mockHtml2Canvas,
|
mockHtml2Canvas,
|
||||||
mockJsPDF,
|
|
||||||
mockSaveAs,
|
mockSaveAs,
|
||||||
mockFileReader
|
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 () {
|
it("runs html2canvas and tries to save a png", function () {
|
||||||
exportImageService.exportPNG(testElement, "plot.png");
|
exportImageService.exportPNG(testElement, "plot.png");
|
||||||
|
|
||||||
|
@ -182,6 +182,16 @@ define([
|
|||||||
"capacity"
|
"capacity"
|
||||||
],
|
],
|
||||||
"pattern": "^-?\\d+(\\.\\d*)?$"
|
"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": {
|
"model": {
|
||||||
|
@ -37,7 +37,8 @@ define(
|
|||||||
// Build graphs for this group of utilizations
|
// Build graphs for this group of utilizations
|
||||||
function buildGraphs(utilizations) {
|
function buildGraphs(utilizations) {
|
||||||
var utilizationMap = {},
|
var utilizationMap = {},
|
||||||
result = {};
|
result = {},
|
||||||
|
startingSOC;
|
||||||
|
|
||||||
// Bucket utilizations by type
|
// Bucket utilizations by type
|
||||||
utilizations.forEach(function (u) {
|
utilizations.forEach(function (u) {
|
||||||
@ -55,12 +56,14 @@ define(
|
|||||||
if (domainObject.getModel().type === 'timeline' &&
|
if (domainObject.getModel().type === 'timeline' &&
|
||||||
result.power &&
|
result.power &&
|
||||||
domainObject.getModel().capacity > 0) {
|
domainObject.getModel().capacity > 0) {
|
||||||
|
startingSOC = isNaN(parseFloat(domainObject.getModel().startingSOC)) ?
|
||||||
|
100 : parseFloat(domainObject.getModel().startingSOC);
|
||||||
|
|
||||||
result.battery = new CumulativeGraph(
|
result.battery = new CumulativeGraph(
|
||||||
result.power,
|
result.power,
|
||||||
0,
|
0,
|
||||||
domainObject.getModel().capacity, // Watts
|
domainObject.getModel().capacity, // Watts
|
||||||
domainObject.getModel().capacity,
|
(startingSOC / 100) * domainObject.getModel().capacity,
|
||||||
1 / 3600000 // millis-to-hour (since units are watt-hours)
|
1 / 3600000 // millis-to-hour (since units are watt-hours)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ define(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Control for Gantt bars in a timeline view.
|
* 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
|
* bars; particularly, this ensures that the left and right edges
|
||||||
* never go to far off screen, because in some environments this
|
* never go to far off screen, because in some environments this
|
||||||
* will effect rendering performance without visible results.
|
* will effect rendering performance without visible results.
|
||||||
|
@ -28,7 +28,7 @@ define(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides labels for the tick mark area of a timeline view.
|
* 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
|
* only the subset of ticks which will actually be shown in
|
||||||
* view are provided.
|
* view are provided.
|
||||||
* @constructor
|
* @constructor
|
||||||
|
@ -148,7 +148,7 @@ define(
|
|||||||
var timespan = timespans[toId(id)];
|
var timespan = timespans[toId(id)];
|
||||||
// Use as setter if argument is present
|
// Use as setter if argument is present
|
||||||
if ((typeof value === 'number') && timespan) {
|
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(
|
timespan.setEnd(
|
||||||
Math.max(value, timespan.getStart())
|
Math.max(value, timespan.getStart())
|
||||||
);
|
);
|
||||||
|
@ -41,7 +41,7 @@ define(
|
|||||||
ids,
|
ids,
|
||||||
candidates;
|
candidates;
|
||||||
|
|
||||||
// Filter an id for inclustion
|
// Filter an id for inclusion
|
||||||
function include(id) {
|
function include(id) {
|
||||||
return id !== exclude;
|
return id !== exclude;
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,7 @@ define(
|
|||||||
it("provides a battery graph for timelines with capacity", function () {
|
it("provides a battery graph for timelines with capacity", function () {
|
||||||
var mockCallback = jasmine.createSpy('callback');
|
var mockCallback = jasmine.createSpy('callback');
|
||||||
testModel.capacity = 1000;
|
testModel.capacity = 1000;
|
||||||
|
testModel.startingSOC = 100;
|
||||||
testModel.type = "timeline";
|
testModel.type = "timeline";
|
||||||
mockDomainObject.useCapability.andReturn(asPromise([
|
mockDomainObject.useCapability.andReturn(asPromise([
|
||||||
{ key: "power", start: 0, end: 15 }
|
{ key: "power", start: 0, end: 15 }
|
||||||
|
@ -32,6 +32,7 @@ define([
|
|||||||
"text!./res/templates/controls/datetime.html",
|
"text!./res/templates/controls/datetime.html",
|
||||||
"text!./res/templates/controls/select.html",
|
"text!./res/templates/controls/select.html",
|
||||||
"text!./res/templates/controls/textfield.html",
|
"text!./res/templates/controls/textfield.html",
|
||||||
|
"text!./res/templates/controls/textarea.html",
|
||||||
"text!./res/templates/controls/button.html",
|
"text!./res/templates/controls/button.html",
|
||||||
"text!./res/templates/controls/color.html",
|
"text!./res/templates/controls/color.html",
|
||||||
"text!./res/templates/controls/composite.html",
|
"text!./res/templates/controls/composite.html",
|
||||||
@ -51,6 +52,7 @@ define([
|
|||||||
datetimeTemplate,
|
datetimeTemplate,
|
||||||
selectTemplate,
|
selectTemplate,
|
||||||
textfieldTemplate,
|
textfieldTemplate,
|
||||||
|
textareaTemplate,
|
||||||
buttonTemplate,
|
buttonTemplate,
|
||||||
colorTemplate,
|
colorTemplate,
|
||||||
compositeTemplate,
|
compositeTemplate,
|
||||||
@ -103,6 +105,10 @@ define([
|
|||||||
"key": "textfield",
|
"key": "textfield",
|
||||||
"template": textfieldTemplate
|
"template": textfieldTemplate
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "textarea",
|
||||||
|
"template": textareaTemplate
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "button",
|
"key": "button",
|
||||||
"template": buttonTemplate
|
"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.
|
* category.
|
||||||
*
|
*
|
||||||
* @param {string} category name of the extension 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) {
|
Bundle.prototype.getExtensions = function (category) {
|
||||||
var extensions = this.definition.extensions[category] || [],
|
var extensions = this.definition.extensions[category] || [],
|
||||||
|
@ -27,7 +27,7 @@ define(
|
|||||||
/**
|
/**
|
||||||
* A CouchDocument describes domain object model in a format
|
* A CouchDocument describes domain object model in a format
|
||||||
* which is easily read-written to CouchDB. This includes
|
* 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
|
* metadata field which contains a subset of information found
|
||||||
* in the model itself (to support search optimization with
|
* in the model itself (to support search optimization with
|
||||||
* CouchDB views.)
|
* CouchDB views.)
|
||||||
@ -37,7 +37,7 @@ define(
|
|||||||
* @param {object} model the model to store
|
* @param {object} model the model to store
|
||||||
* @param {string} rev the revision to include (or undefined,
|
* @param {string} rev the revision to include (or undefined,
|
||||||
* if no revision should be noted for couch)
|
* 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)
|
* deleted (see CouchDB docs for _deleted)
|
||||||
*/
|
*/
|
||||||
function CouchDocument(id, model, rev, markDeleted) {
|
function CouchDocument(id, model, rev, markDeleted) {
|
||||||
|
@ -69,7 +69,7 @@ define(
|
|||||||
initialDescrption = indicator.getDescription(),
|
initialDescrption = indicator.getDescription(),
|
||||||
initialGlyphClass = indicator.getGlyphClass();
|
initialGlyphClass = indicator.getGlyphClass();
|
||||||
|
|
||||||
// Nominal just means getting back an objeect, without
|
// Nominal just means getting back an object, without
|
||||||
// an error field.
|
// an error field.
|
||||||
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
||||||
|
|
||||||
@ -88,7 +88,7 @@ define(
|
|||||||
initialDescrption = indicator.getDescription(),
|
initialDescrption = indicator.getDescription(),
|
||||||
initialGlyphClass = indicator.getGlyphClass();
|
initialGlyphClass = indicator.getGlyphClass();
|
||||||
|
|
||||||
// Nominal just means getting back an objeect, with
|
// Nominal just means getting back an object, with
|
||||||
// an error field.
|
// an error field.
|
||||||
mockPromise.then.mostRecentCall.args[0](
|
mockPromise.then.mostRecentCall.args[0](
|
||||||
{ data: { error: "Uh oh." } }
|
{ data: { error: "Uh oh." } }
|
||||||
@ -110,7 +110,7 @@ define(
|
|||||||
initialDescrption = indicator.getDescription(),
|
initialDescrption = indicator.getDescription(),
|
||||||
initialGlyphClass = indicator.getGlyphClass();
|
initialGlyphClass = indicator.getGlyphClass();
|
||||||
|
|
||||||
// Nominal just means getting back an objeect, without
|
// Nominal just means getting back an object, without
|
||||||
// an error field.
|
// an error field.
|
||||||
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ define([
|
|||||||
* Search for domain objects using elasticsearch as a search provider.
|
* Search for domain objects using elasticsearch as a search provider.
|
||||||
*
|
*
|
||||||
* @param {String} searchTerm the term to search by.
|
* @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.
|
* @returns {Promise} promise for a modelResults object.
|
||||||
*/
|
*/
|
||||||
ElasticSearchProvider.prototype.query = function (searchTerm, maxResults) {
|
ElasticSearchProvider.prototype.query = function (searchTerm, maxResults) {
|
||||||
|
@ -71,7 +71,7 @@ define(
|
|||||||
initialDescrption = indicator.getDescription(),
|
initialDescrption = indicator.getDescription(),
|
||||||
initialGlyphClass = indicator.getGlyphClass();
|
initialGlyphClass = indicator.getGlyphClass();
|
||||||
|
|
||||||
// Nominal just means getting back an objeect, without
|
// Nominal just means getting back an object, without
|
||||||
// an error field.
|
// an error field.
|
||||||
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
mockPromise.then.mostRecentCall.args[0]({ data: {} });
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ define(
|
|||||||
initialDescrption = indicator.getDescription(),
|
initialDescrption = indicator.getDescription(),
|
||||||
initialGlyphClass = indicator.getGlyphClass();
|
initialGlyphClass = indicator.getGlyphClass();
|
||||||
|
|
||||||
// Nominal just means getting back an objeect, without
|
// Nominal just means getting back an object, without
|
||||||
// an error field.
|
// an error field.
|
||||||
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
mockPromise.then.mostRecentCall.args[1]({ data: {} });
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ define(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* The PersistenceQueue is used by the QueuingPersistenceCapability
|
* 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
|
* in a group, such that if some or all are rejected, this result can
|
||||||
* be shown to the user (again, in a group.)
|
* be shown to the user (again, in a group.)
|
||||||
*
|
*
|
||||||
|
@ -25,7 +25,7 @@ define(
|
|||||||
function () {
|
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
|
* 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
|
* also allows failure to be handled in a group (e.g. in a single
|
||||||
* summary dialog.)
|
* summary dialog.)
|
||||||
|
@ -246,7 +246,7 @@ define([
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @returns {Number} a unique, unusued query Id.
|
* @returns {Number} a unique, unused query Id.
|
||||||
*/
|
*/
|
||||||
GenericSearchProvider.prototype.makeQueryId = function () {
|
GenericSearchProvider.prototype.makeQueryId = function () {
|
||||||
var queryId = Math.ceil(Math.random() * 100000);
|
var queryId = Math.ceil(Math.random() * 100000);
|
||||||
|
@ -123,7 +123,7 @@ define([
|
|||||||
expect(mockScope.results).toContain('a');
|
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();
|
expect(mockScope.loading).toBeTruthy();
|
||||||
|
|
||||||
// Then resolve the promises
|
// Then resolve the promises
|
||||||
@ -163,7 +163,7 @@ define([
|
|||||||
// Flag should be true with nonempty input
|
// Flag should be true with nonempty input
|
||||||
expect(mockScope.ngModel.search).toEqual(true);
|
expect(mockScope.ngModel.search).toEqual(true);
|
||||||
|
|
||||||
// Flag should be flase with empty input
|
// Flag should be false with empty input
|
||||||
mockScope.ngModel.input = '';
|
mockScope.ngModel.input = '';
|
||||||
controller.search();
|
controller.search();
|
||||||
mockPromise.then.mostRecentCall.args[0]({hits: [], total: 0});
|
mockPromise.then.mostRecentCall.args[0]({hits: [], total: 0});
|
||||||
|
@ -54,7 +54,7 @@ define(
|
|||||||
controller = new SearchMenuController(mockScope, mockTypes);
|
controller = new SearchMenuController(mockScope, mockTypes);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("gets types on initiliztion", function () {
|
it("gets types on initialization", function () {
|
||||||
expect(mockScope.ngModel.types).toBeDefined();
|
expect(mockScope.ngModel.types).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ define(
|
|||||||
* `telemetrySubscriber`.
|
* `telemetrySubscriber`.
|
||||||
*
|
*
|
||||||
* Subscriptions may also be made directly using the
|
* 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
|
* uses this as well, but additionally handles delegation
|
||||||
* (e.g. for telemetry panels) as well as latest-value
|
* (e.g. for telemetry panels) as well as latest-value
|
||||||
* extraction.
|
* extraction.
|
||||||
|
@ -57,7 +57,7 @@ define(
|
|||||||
* `telemetrySubscriber` service.
|
* `telemetrySubscriber` service.
|
||||||
*
|
*
|
||||||
* Subscriptions may also be made directly using the
|
* 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
|
* uses this as well, but additionally handles delegation
|
||||||
* (e.g. for telemetry panels) as well as latest-value
|
* (e.g. for telemetry panels) as well as latest-value
|
||||||
* extraction.
|
* extraction.
|
||||||
|
@ -56,7 +56,6 @@ requirejs.config({
|
|||||||
"EventEmitter": "bower_components/eventemitter3/index",
|
"EventEmitter": "bower_components/eventemitter3/index",
|
||||||
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
"es6-promise": "bower_components/es6-promise/es6-promise.min",
|
||||||
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
|
||||||
"jsPDF": "bower_components/jspdf/dist/jspdf.min",
|
|
||||||
"moment": "bower_components/moment/moment",
|
"moment": "bower_components/moment/moment",
|
||||||
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
|
||||||
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
|
||||||
|
Loading…
Reference in New Issue
Block a user