mirror of
https://github.com/nasa/openmct.git
synced 2025-04-26 22:10:03 +00:00
Merge branch 'open-master' into open1170
This commit is contained in:
commit
bc6b3f8902
3
.gitignore
vendored
3
.gitignore
vendored
@ -17,3 +17,6 @@ target
|
|||||||
# Closed source libraries
|
# Closed source libraries
|
||||||
closed-lib
|
closed-lib
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
|
62
app.js
Normal file
62
app.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*global require,process,console*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Usage:
|
||||||
|
*
|
||||||
|
* npm install minimist express
|
||||||
|
* node app.js [options]
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
var BUNDLE_FILE = 'bundles.json',
|
||||||
|
options = require('minimist')(process.argv.slice(2)),
|
||||||
|
express = require('express'),
|
||||||
|
app = express(),
|
||||||
|
fs = require('fs'),
|
||||||
|
bundles = JSON.parse(fs.readFileSync(BUNDLE_FILE, 'utf8'));
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
options.port = options.port || options.p || 8080;
|
||||||
|
['include', 'exclude', 'i', 'x'].forEach(function (opt) {
|
||||||
|
options[opt] = options[opt] || [];
|
||||||
|
// Make sure includes/excludes always end up as arrays
|
||||||
|
options[opt] = Array.isArray(options[opt]) ?
|
||||||
|
options[opt] : [options[opt]];
|
||||||
|
});
|
||||||
|
options.include = options.include.concat(options.i);
|
||||||
|
options.exclude = options.exclude.concat(options.x);
|
||||||
|
|
||||||
|
// Show command line options
|
||||||
|
if (options.help || options.h) {
|
||||||
|
console.log("\nUsage: node app.js [options]\n");
|
||||||
|
console.log("Options:");
|
||||||
|
console.log(" --help, -h Show this message.");
|
||||||
|
console.log(" --port, -p <number> Specify port.");
|
||||||
|
console.log(" --include, -i <bundle> Include the specified bundle.");
|
||||||
|
console.log(" --exclude, -x <bundle> Exclude the specified bundle.");
|
||||||
|
console.log("");
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle command line inclusions/exclusions
|
||||||
|
bundles = bundles.concat(options.include);
|
||||||
|
bundles = bundles.filter(function (bundle) {
|
||||||
|
return options.exclude.indexOf(bundle) === -1;
|
||||||
|
});
|
||||||
|
bundles = bundles.filter(function (bundle, index) { // Uniquify
|
||||||
|
return bundles.indexOf(bundle) === index;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Override bundles.json for HTTP requests
|
||||||
|
app.use('/' + BUNDLE_FILE, function (req, res) {
|
||||||
|
res.send(JSON.stringify(bundles));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Expose everything else as static files
|
||||||
|
app.use(express['static']('.'));
|
||||||
|
|
||||||
|
// Finally, open the HTTP server
|
||||||
|
app.listen(options.port);
|
||||||
|
}());
|
@ -15,8 +15,8 @@
|
|||||||
"platform/features/scrolling",
|
"platform/features/scrolling",
|
||||||
"platform/forms",
|
"platform/forms",
|
||||||
"platform/persistence/queue",
|
"platform/persistence/queue",
|
||||||
"platform/persistence/elastic",
|
|
||||||
"platform/policy",
|
"platform/policy",
|
||||||
|
|
||||||
|
"example/persistence",
|
||||||
"example/generator"
|
"example/generator"
|
||||||
]
|
]
|
||||||
|
@ -121,6 +121,12 @@
|
|||||||
"depends": [ "typeService", "dialogService", "creationService", "policyService" ]
|
"depends": [ "typeService", "dialogService", "creationService", "policyService" ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"runs": [
|
||||||
|
{
|
||||||
|
"implementation": "windowing/WindowTitler.js",
|
||||||
|
"depends": [ "navigationService", "$rootScope", "$document" ]
|
||||||
|
}
|
||||||
|
],
|
||||||
"licenses": [
|
"licenses": [
|
||||||
{
|
{
|
||||||
"name": "screenfull.js",
|
"name": "screenfull.js",
|
||||||
|
@ -46,6 +46,7 @@ define(
|
|||||||
function setNavigation(domainObject) {
|
function setNavigation(domainObject) {
|
||||||
$scope.navigatedObject = domainObject;
|
$scope.navigatedObject = domainObject;
|
||||||
$scope.treeModel.selectedObject = domainObject;
|
$scope.treeModel.selectedObject = domainObject;
|
||||||
|
navigationService.setNavigation(domainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the root object, put it in the scope.
|
// Load the root object, put it in the scope.
|
||||||
|
@ -45,8 +45,9 @@ define(
|
|||||||
properties = type.getProperties();
|
properties = type.getProperties();
|
||||||
|
|
||||||
function validateLocation(locatingObject) {
|
function validateLocation(locatingObject) {
|
||||||
var locatingType = locatingObject.getCapability('type');
|
var locatingType = locatingObject &&
|
||||||
return policyService.allow(
|
locatingObject.getCapability('type');
|
||||||
|
return locatingType && policyService.allow(
|
||||||
"composition",
|
"composition",
|
||||||
locatingType,
|
locatingType,
|
||||||
type
|
type
|
||||||
|
@ -45,11 +45,13 @@ define(
|
|||||||
|
|
||||||
// Setter for navigation; invokes callbacks
|
// Setter for navigation; invokes callbacks
|
||||||
function setNavigation(value) {
|
function setNavigation(value) {
|
||||||
|
if (navigated !== value) {
|
||||||
navigated = value;
|
navigated = value;
|
||||||
callbacks.forEach(function (callback) {
|
callbacks.forEach(function (callback) {
|
||||||
callback(value);
|
callback(value);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Adds a callback
|
// Adds a callback
|
||||||
function addListener(callback) {
|
function addListener(callback) {
|
||||||
|
52
platform/commonUI/browse/src/windowing/WindowTitler.js
Normal file
52
platform/commonUI/browse/src/windowing/WindowTitler.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,Promise*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the title of the current window to reflect the name
|
||||||
|
* of the currently navigated-to domain object.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function WindowTitler(navigationService, $rootScope, $document) {
|
||||||
|
// Look up name of the navigated domain object...
|
||||||
|
function getNavigatedObjectName() {
|
||||||
|
var navigatedObject = navigationService.getNavigation();
|
||||||
|
return navigatedObject && navigatedObject.getModel().name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the window title...
|
||||||
|
function setTitle(name) {
|
||||||
|
$document[0].title = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Watch the former, and invoke the latter
|
||||||
|
$rootScope.$watch(getNavigatedObjectName, setTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
return WindowTitler;
|
||||||
|
}
|
||||||
|
);
|
@ -62,6 +62,16 @@ define(
|
|||||||
expect(callback).toHaveBeenCalledWith(testObject);
|
expect(callback).toHaveBeenCalledWith(testObject);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("does not notify listeners when no changes occur", function () {
|
||||||
|
var testObject = { someKey: 42 },
|
||||||
|
callback = jasmine.createSpy("callback");
|
||||||
|
|
||||||
|
navigationService.addListener(callback);
|
||||||
|
navigationService.setNavigation(testObject);
|
||||||
|
navigationService.setNavigation(testObject);
|
||||||
|
expect(callback.calls.length).toEqual(1);
|
||||||
|
});
|
||||||
|
|
||||||
it("stops notifying listeners after removal", function () {
|
it("stops notifying listeners after removal", function () {
|
||||||
var testObject = { someKey: 42 },
|
var testObject = { someKey: 42 },
|
||||||
callback = jasmine.createSpy("callback");
|
callback = jasmine.createSpy("callback");
|
||||||
|
@ -8,5 +8,6 @@
|
|||||||
"creation/LocatorController",
|
"creation/LocatorController",
|
||||||
"navigation/NavigateAction",
|
"navigation/NavigateAction",
|
||||||
"navigation/NavigationService",
|
"navigation/NavigationService",
|
||||||
"windowing/FullscreenAction"
|
"windowing/FullscreenAction",
|
||||||
|
"windowing/WindowTitler"
|
||||||
]
|
]
|
80
platform/commonUI/browse/test/windowing/WindowTitlerSpec.js
Normal file
80
platform/commonUI/browse/test/windowing/WindowTitlerSpec.js
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
|
* Administration. All rights reserved.
|
||||||
|
*
|
||||||
|
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*
|
||||||
|
* Open MCT Web includes source code licensed under additional open source
|
||||||
|
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||||
|
* this source code distribution or the Licensing information page available
|
||||||
|
* at runtime from the About dialog for additional information.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WindowTitlerSpec. Created by vwoeltje on 11/6/14.
|
||||||
|
*/
|
||||||
|
define(
|
||||||
|
["../../src/windowing/WindowTitler"],
|
||||||
|
function (WindowTitler) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("The window titler", function () {
|
||||||
|
var mockNavigationService,
|
||||||
|
mockRootScope,
|
||||||
|
mockDocument,
|
||||||
|
mockDomainObject,
|
||||||
|
titler;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockNavigationService = jasmine.createSpyObj(
|
||||||
|
'navigationService',
|
||||||
|
[ 'getNavigation' ]
|
||||||
|
);
|
||||||
|
mockRootScope = jasmine.createSpyObj(
|
||||||
|
'$rootScope',
|
||||||
|
[ '$watch' ]
|
||||||
|
);
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
'domainObject',
|
||||||
|
['getModel']
|
||||||
|
);
|
||||||
|
mockDocument = [{}];
|
||||||
|
|
||||||
|
mockDomainObject.getModel.andReturn({ name: 'Test name' });
|
||||||
|
mockNavigationService.getNavigation.andReturn(mockDomainObject);
|
||||||
|
|
||||||
|
titler = new WindowTitler(
|
||||||
|
mockNavigationService,
|
||||||
|
mockRootScope,
|
||||||
|
mockDocument
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("listens for changes to the name of the navigated object", function () {
|
||||||
|
expect(mockRootScope.$watch).toHaveBeenCalledWith(
|
||||||
|
jasmine.any(Function),
|
||||||
|
jasmine.any(Function)
|
||||||
|
);
|
||||||
|
expect(mockRootScope.$watch.mostRecentCall.args[0]())
|
||||||
|
.toEqual('Test name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it("sets the title to the name of the navigated object", function () {
|
||||||
|
mockRootScope.$watch.mostRecentCall.args[1]("Some name");
|
||||||
|
expect(mockDocument[0].title).toEqual("Some name");
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
@ -12,6 +12,11 @@
|
|||||||
"implementation": "CompositionMutabilityPolicy.js",
|
"implementation": "CompositionMutabilityPolicy.js",
|
||||||
"message": "Objects of this type cannot be modified."
|
"message": "Objects of this type cannot be modified."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"category": "composition",
|
||||||
|
"implementation": "CompositionModelPolicy.js",
|
||||||
|
"message": "Objects of this type cannot contain other objects."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"category": "action",
|
"category": "action",
|
||||||
"implementation": "ComposeActionPolicy.js",
|
"implementation": "ComposeActionPolicy.js",
|
||||||
|
28
platform/containment/src/CompositionModelPolicy.js
Normal file
28
platform/containment/src/CompositionModelPolicy.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
[],
|
||||||
|
function () {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Policy allowing composition only for domain object types which
|
||||||
|
* have a composition property.
|
||||||
|
*/
|
||||||
|
function CompositionModelPolicy() {
|
||||||
|
return {
|
||||||
|
/**
|
||||||
|
* Is the type identified by the candidate allowed to
|
||||||
|
* contain the type described by the context?
|
||||||
|
*/
|
||||||
|
allow: function (candidate, context) {
|
||||||
|
return Array.isArray(
|
||||||
|
(candidate.getInitialModel() || {}).composition
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return CompositionModelPolicy;
|
||||||
|
}
|
||||||
|
);
|
26
platform/containment/test/CompositionModelPolicySpec.js
Normal file
26
platform/containment/test/CompositionModelPolicySpec.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||||
|
|
||||||
|
define(
|
||||||
|
["../src/CompositionModelPolicy"],
|
||||||
|
function (CompositionModelPolicy) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
describe("The composition model policy", function () {
|
||||||
|
var mockType,
|
||||||
|
policy;
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
mockType = jasmine.createSpyObj('type', ['getInitialModel']);
|
||||||
|
policy = new CompositionModelPolicy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("only allows composition for types which will have a composition property", function () {
|
||||||
|
mockType.getInitialModel.andReturn({});
|
||||||
|
expect(policy.allow(mockType)).toBeFalsy();
|
||||||
|
mockType.getInitialModel.andReturn({ composition: [] });
|
||||||
|
expect(policy.allow(mockType)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
@ -35,7 +35,7 @@ define(
|
|||||||
policy = new CompositionMutabilityPolicy();
|
policy = new CompositionMutabilityPolicy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("only allows composition for types which will have a composition capability", function () {
|
it("only allows composition for types which can be created/modified", function () {
|
||||||
expect(policy.allow(mockType)).toBeFalsy();
|
expect(policy.allow(mockType)).toBeFalsy();
|
||||||
mockType.hasFeature.andReturn(true);
|
mockType.hasFeature.andReturn(true);
|
||||||
expect(policy.allow(mockType)).toBeTruthy();
|
expect(policy.allow(mockType)).toBeTruthy();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[
|
[
|
||||||
"CapabilityTable",
|
"CapabilityTable",
|
||||||
"ComposeActionPolicy",
|
"ComposeActionPolicy",
|
||||||
|
"CompositionModelPolicy",
|
||||||
"CompositionMutabilityPolicy",
|
"CompositionMutabilityPolicy",
|
||||||
"CompositionPolicy",
|
"CompositionPolicy",
|
||||||
"ContainmentTable"
|
"ContainmentTable"
|
||||||
|
@ -77,7 +77,8 @@ define(
|
|||||||
// Get the object's model and clone it, so the
|
// Get the object's model and clone it, so the
|
||||||
// mutator function has a temporary copy to work with.
|
// mutator function has a temporary copy to work with.
|
||||||
var model = domainObject.getModel(),
|
var model = domainObject.getModel(),
|
||||||
clone = JSON.parse(JSON.stringify(model));
|
clone = JSON.parse(JSON.stringify(model)),
|
||||||
|
useTimestamp = arguments.length > 1;
|
||||||
|
|
||||||
// Function to handle copying values to the actual
|
// Function to handle copying values to the actual
|
||||||
function handleMutation(mutationResult) {
|
function handleMutation(mutationResult) {
|
||||||
@ -94,8 +95,7 @@ define(
|
|||||||
if (model !== result) {
|
if (model !== result) {
|
||||||
copyValues(model, result);
|
copyValues(model, result);
|
||||||
}
|
}
|
||||||
model.modified = (typeof timestamp === 'number') ?
|
model.modified = useTimestamp ? timestamp : now();
|
||||||
timestamp : now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report the result of the mutation
|
// Report the result of the mutation
|
||||||
|
@ -38,7 +38,7 @@
|
|||||||
placeholder="YYYY-DDD"
|
placeholder="YYYY-DDD"
|
||||||
ng-pattern="/\d\d\d\d-\d\d\d/"
|
ng-pattern="/\d\d\d\d-\d\d\d/"
|
||||||
ng-model='datetime.date'
|
ng-model='datetime.date'
|
||||||
ng-required='true'/>
|
ng-required='ngRequired || partiallyComplete'/>
|
||||||
</span>
|
</span>
|
||||||
<span class='field control time sm'>
|
<span class='field control time sm'>
|
||||||
<input type='text'
|
<input type='text'
|
||||||
@ -49,7 +49,7 @@
|
|||||||
integer
|
integer
|
||||||
ng-pattern='/\d+/'
|
ng-pattern='/\d+/'
|
||||||
ng-model="datetime.hour"
|
ng-model="datetime.hour"
|
||||||
ng-required='true'/>
|
ng-required='ngRequired || partiallyComplete'/>
|
||||||
</span>
|
</span>
|
||||||
<span class='field control time sm'>
|
<span class='field control time sm'>
|
||||||
<input type='text'
|
<input type='text'
|
||||||
@ -60,7 +60,7 @@
|
|||||||
integer
|
integer
|
||||||
ng-pattern='/\d+/'
|
ng-pattern='/\d+/'
|
||||||
ng-model="datetime.min"
|
ng-model="datetime.min"
|
||||||
ng-required='true'/>
|
ng-required='ngRequired || partiallyComplete'/>
|
||||||
</span>
|
</span>
|
||||||
<span class='field control time sm'>
|
<span class='field control time sm'>
|
||||||
<input type='text'
|
<input type='text'
|
||||||
@ -71,7 +71,7 @@
|
|||||||
integer
|
integer
|
||||||
ng-pattern='/\d+/'
|
ng-pattern='/\d+/'
|
||||||
ng-model="datetime.sec"
|
ng-model="datetime.sec"
|
||||||
ng-required='true'/>
|
ng-required='ngRequired || partiallyComplete'/>
|
||||||
</span>
|
</span>
|
||||||
<span class='field control timezone'>
|
<span class='field control timezone'>
|
||||||
UTC
|
UTC
|
||||||
|
@ -52,7 +52,39 @@ define(
|
|||||||
if (fullDateTime.isValid()) {
|
if (fullDateTime.isValid()) {
|
||||||
$scope.ngModel[$scope.field] = fullDateTime.valueOf();
|
$scope.ngModel[$scope.field] = fullDateTime.valueOf();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If anything is complete, say so in scope; there are
|
||||||
|
// ng-required usages that will update off of this (to
|
||||||
|
// allow datetime to be optional while still permitting
|
||||||
|
// incomplete input)
|
||||||
|
$scope.partiallyComplete =
|
||||||
|
Object.keys($scope.datetime).some(function (key) {
|
||||||
|
return $scope.datetime[key];
|
||||||
|
});
|
||||||
|
|
||||||
|
// Treat empty input as an undefined value
|
||||||
|
if (!$scope.partiallyComplete) {
|
||||||
|
$scope.ngModel[$scope.field] = undefined;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDateTime(value) {
|
||||||
|
var m;
|
||||||
|
if (value !== undefined) {
|
||||||
|
m = moment.utc(value);
|
||||||
|
$scope.datetime = {
|
||||||
|
date: m.format(DATE_FORMAT),
|
||||||
|
hour: m.format("H"),
|
||||||
|
min: m.format("m"),
|
||||||
|
sec: m.format("s")
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
$scope.datetime = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ...and update form values when actual field in model changes
|
||||||
|
$scope.$watch("ngModel[field]", updateDateTime);
|
||||||
|
|
||||||
// Update value whenever any field changes.
|
// Update value whenever any field changes.
|
||||||
$scope.$watch("datetime.date", update);
|
$scope.$watch("datetime.date", update);
|
||||||
@ -60,7 +92,11 @@ define(
|
|||||||
$scope.$watch("datetime.min", update);
|
$scope.$watch("datetime.min", update);
|
||||||
$scope.$watch("datetime.sec", update);
|
$scope.$watch("datetime.sec", update);
|
||||||
|
|
||||||
$scope.datetime = {};
|
// Initialize forms values
|
||||||
|
updateDateTime(
|
||||||
|
($scope.ngModel && $scope.field) ?
|
||||||
|
$scope.ngModel[$scope.field] : undefined
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return DateTimeController;
|
return DateTimeController;
|
||||||
|
@ -57,6 +57,33 @@ define(
|
|||||||
expect(mockScope.ngModel.test).toEqual(1417215313000);
|
expect(mockScope.ngModel.test).toEqual(1417215313000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("reports when form input is partially complete", function () {
|
||||||
|
// This is needed to flag the control's state as invalid
|
||||||
|
// when it is partially complete without having it treated
|
||||||
|
// as required.
|
||||||
|
mockScope.ngModel = {};
|
||||||
|
mockScope.field = "test";
|
||||||
|
mockScope.datetime.date = "2014-332";
|
||||||
|
mockScope.datetime.hour = 22;
|
||||||
|
mockScope.datetime.min = 55;
|
||||||
|
// mockScope.datetime.sec = 13;
|
||||||
|
|
||||||
|
mockScope.$watch.mostRecentCall.args[1]();
|
||||||
|
|
||||||
|
expect(mockScope.partiallyComplete).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("reports 'undefined' for empty input", function () {
|
||||||
|
mockScope.ngModel = { test: 12345 };
|
||||||
|
mockScope.field = "test";
|
||||||
|
mockScope.$watch.mostRecentCall.args[1]();
|
||||||
|
// Clear all inputs
|
||||||
|
mockScope.datetime = {};
|
||||||
|
mockScope.$watch.mostRecentCall.args[1]();
|
||||||
|
|
||||||
|
// Should have cleared out the time stamp
|
||||||
|
expect(mockScope.ngModel.test).toBeUndefined();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
@ -17,15 +17,18 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "ELASTIC_ROOT",
|
"key": "ELASTIC_ROOT",
|
||||||
"value": "/elastic"
|
"value": "/elastic",
|
||||||
|
"priority": "fallback"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "ELASTIC_PATH",
|
"key": "ELASTIC_PATH",
|
||||||
"value": "mct/domain_object"
|
"value": "mct/domain_object",
|
||||||
|
"priority": "fallback"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "ELASTIC_INDICATOR_INTERVAL",
|
"key": "ELASTIC_INDICATOR_INTERVAL",
|
||||||
"value": 15000
|
"value": 15000,
|
||||||
|
"priority": "fallback"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"indicators": [
|
"indicators": [
|
||||||
|
2
pom.xml
2
pom.xml
@ -160,6 +160,8 @@
|
|||||||
<sourceJsFolder>${basedir}</sourceJsFolder>
|
<sourceJsFolder>${basedir}</sourceJsFolder>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/lib/**</exclude>
|
<exclude>**/lib/**</exclude>
|
||||||
|
<exclude>app.js</exclude>
|
||||||
|
<exclude>node_modules/**/*</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</configuration>
|
</configuration>
|
||||||
<executions>
|
<executions>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user