Merge branch 'master' into mct1221

This commit is contained in:
Alex M
2016-10-15 14:10:24 +03:00
178 changed files with 9988 additions and 837 deletions

View File

@@ -41,6 +41,7 @@ define([
"text!./res/templates/items/items.html",
"text!./res/templates/browse/object-properties.html",
"text!./res/templates/browse/inspector-region.html",
"text!./res/templates/view-object.html",
'legacyRegistry'
], function (
BrowseController,
@@ -63,6 +64,7 @@ define([
itemsTemplate,
objectPropertiesTemplate,
inspectorRegionTemplate,
viewObjectTemplate,
legacyRegistry
) {
@@ -142,7 +144,7 @@ define([
"representations": [
{
"key": "view-object",
"templateUrl": "templates/view-object.html"
"template": viewObjectTemplate
},
{
"key": "browse-object",

View File

@@ -43,7 +43,7 @@
</mct-representation>
</div>
</div>
<div class="holder l-flex-col flex-elem grows l-object-wrapper">
<div class="holder l-flex-col flex-elem grows l-object-wrapper l-controls-visible l-time-controller-visible">
<div class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
<!-- Toolbar and Save/Cancel buttons -->
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
@@ -59,4 +59,5 @@
</mct-representation>
</div>
</div>
<mct-include key="'conductor'" class="abs holder flex-elem flex-fixed l-flex-row l-time-conductor-holder"></mct-include>
</div>

View File

@@ -22,7 +22,8 @@
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
<span class="l-elem-wrapper l-flex-row flex-elem grows">
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
<span class='title-label flex-elem flex-can-shrink'>{{model.name}}</span>
<span class='title-label flex-elem holder flex-can-shrink'>{{model.name}}</span>
<span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span>
<mct-representation
key="'menu-arrow'"
mct-object='domainObject'

View File

@@ -200,7 +200,6 @@ define([
"name": "Remove",
"description": "Remove this object from its containing object.",
"depends": [
"$q",
"navigationService"
]
},
@@ -245,7 +244,9 @@ define([
"key": "cancel",
"category": "conclude-editing",
"implementation": CancelAction,
"name": "Cancel",
// Because we use the name as label for edit buttons and mct-control buttons need
// the label to be set to undefined in order to not apply the labeled CSS rule.
"name": undefined,
"cssclass": "icon-x no-label",
"description": "Discard changes made to these objects.",
"depends": []

View File

@@ -25,7 +25,7 @@
<mct-control key="'button'"
structure="{
text: saveActions[0].getMetadata().name,
click: saveActions[0].perform,
click: actionPerformer(saveActions[0]),
cssclass: 'major ' + saveActions[0].getMetadata().cssclass
}">
</mct-control>
@@ -42,11 +42,12 @@
</span>
<span ng-repeat="currentAction in otherEditActions">
<a class='s-button {{currentAction.getMetadata().cssclass}}'
title='{{currentAction.getMetadata().name}}'
ng-click="currentAction.perform()"
ng-class="{ major: $index === 0 && saveActions.length === 0 }">
<span class="title-label">{{currentAction.getMetadata().name}}</span>
</a>
<mct-control key="'button'"
structure="{
text: currentAction.getMetadata().name,
click: actionPerformer(currentAction),
cssclass: currentAction.getMetadata().cssclass
}">
</mct-control>
</span>
</span>

View File

@@ -66,4 +66,9 @@
</mct-representation>
</div><!--/ l-object-wrapper-inner -->
</div>
<mct-representation mct-object="domainObject"
key="'time-conductor'"
class="abs holder flex-elem flex-fixed l-flex-row l-time-conductor-holder">
</mct-representation>
</div>

View File

@@ -40,19 +40,11 @@ define(
var self = this,
editAction = this.domainObject.getCapability('action').getActions("edit")[0];
// Persist changes to the domain object
function doPersist() {
var persistence =
self.domainObject.getCapability('persistence');
return persistence.persist();
}
// Link these objects
function doLink() {
var composition = self.domainObject &&
self.domainObject.getCapability('composition');
return composition && composition.add(self.selectedObject)
.then(doPersist);
return composition && composition.add(self.selectedObject);
}
if (editAction) {

View File

@@ -50,12 +50,6 @@ define(
domainObject = this.domainObject,
dialogService = this.dialogService;
// Persist modifications to this domain object
function doPersist() {
var persistence = domainObject.getCapability('persistence');
return persistence && persistence.persist();
}
// Update the domain object model based on user input
function updateModel(userInput, dialog) {
return domainObject.useCapability('mutation', function (model) {
@@ -73,11 +67,9 @@ define(
dialog.getFormStructure(),
dialog.getInitialFormValue()
).then(function (userInput) {
// Update the model, if user input was provided
return userInput && updateModel(userInput, dialog);
}).then(function (result) {
return result && doPersist();
});
// Update the model, if user input was provided
return userInput && updateModel(userInput, dialog);
});
}
return type && showDialog(type);
@@ -94,9 +86,7 @@ define(
creatable = type && type.hasFeature('creation');
// Only allow creatable types to be edited
return domainObject &&
domainObject.hasCapability("persistence") &&
creatable;
return domainObject && creatable;
};
return PropertiesAction;

View File

@@ -39,9 +39,8 @@ define(
* @constructor
* @implements {Action}
*/
function RemoveAction($q, navigationService, context) {
function RemoveAction(navigationService, context) {
this.domainObject = (context || {}).domainObject;
this.$q = $q;
this.navigationService = navigationService;
}
@@ -51,8 +50,7 @@ define(
* fulfilled when the action has completed.
*/
RemoveAction.prototype.perform = function () {
var $q = this.$q,
navigationService = this.navigationService,
var navigationService = this.navigationService,
domainObject = this.domainObject;
/*
* Check whether an object ID matches the ID of the object being
@@ -71,15 +69,6 @@ define(
model.composition = model.composition.filter(isNotObject);
}
/*
* Invoke persistence on a domain object. This will be called upon
* the removed object's parent (as its composition will have changed.)
*/
function doPersist(domainObj) {
var persistence = domainObj.getCapability('persistence');
return persistence && persistence.persist();
}
/*
* Checks current object and ascendants of current
* object with object being removed, if the current
@@ -119,15 +108,10 @@ define(
// navigates to existing object up tree
checkObjectNavigation(object, parent);
return $q.when(
parent.useCapability('mutation', doMutate)
).then(function () {
return doPersist(parent);
});
return parent.useCapability('mutation', doMutate);
}
return $q.when(domainObject)
.then(removeFromContext);
return removeFromContext(domainObject);
};
// Object needs to have a parent for Remove to be applicable

View File

@@ -81,6 +81,10 @@ define(
return this.persistenceCapability.getSpace();
};
TransactionalPersistenceCapability.prototype.persisted = function () {
return this.persistenceCapability.persisted();
};
return TransactionalPersistenceCapability;
}
);

View File

@@ -61,6 +61,12 @@ define(
$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

View File

@@ -50,17 +50,13 @@ define(
this.listenHandle = undefined;
// Mutate and persist a new version of a domain object's model.
function doPersist(model) {
function doMutate(model) {
var domainObject = self.domainObject;
// First, mutate; then, persist.
return $q.when(domainObject.useCapability("mutation", function () {
return model;
})).then(function (result) {
// Only persist when mutation was successful
return result &&
domainObject.getCapability("persistence").persist();
});
}));
}
// Handle changes to model and/or view configuration
@@ -80,14 +76,14 @@ define(
].join(" "));
// Update the configuration stored in the model, and persist.
if (domainObject && domainObject.hasCapability("persistence")) {
if (domainObject) {
// Configurations for specific views are stored by
// key in the "configuration" field of the model.
if (self.key && configuration) {
model.configuration = model.configuration || {};
model.configuration[self.key] = configuration;
}
doPersist(model);
doMutate(model);
}
}

View File

@@ -0,0 +1,48 @@
/*****************************************************************************
* 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(['./Transaction'], function (Transaction) {
/**
* A nested transaction is a transaction which takes place in the context
* of a larger parent transaction. It becomes part of the parent
* transaction when (and only when) committed.
* @param parent
* @constructor
* @extends {platform/commonUI/edit/services.Transaction}
* @memberof platform/commonUI/edit/services
*/
function NestedTransaction(parent) {
this.parent = parent;
Transaction.call(this, parent.$log);
}
NestedTransaction.prototype = Object.create(Transaction.prototype);
NestedTransaction.prototype.commit = function () {
this.parent.add(
Transaction.prototype.commit.bind(this),
Transaction.prototype.cancel.bind(this)
);
return Promise.resolve(true);
};
return NestedTransaction;
});

View File

@@ -0,0 +1,96 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2016, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([], function () {
/**
* A Transaction represents a set of changes that are intended to
* be kept or discarded as a unit.
* @param $log Angular's `$log` service, for logging messages
* @constructor
* @memberof platform/commonUI/edit/services
*/
function Transaction($log) {
this.$log = $log;
this.callbacks = [];
}
/**
* Add a change to the current transaction, as expressed by functions
* to either keep or discard the change.
* @param {Function} commit called when the transaction is committed
* @param {Function} cancel called when the transaction is cancelled
* @returns {Function) a function which may be called to remove this
* pair of callbacks from the transaction
*/
Transaction.prototype.add = function (commit, cancel) {
var callback = { commit: commit, cancel: cancel };
this.callbacks.push(callback);
return function () {
this.callbacks = this.callbacks.filter(function (c) {
return c !== callback;
});
}.bind(this);
};
/**
* Get the number of changes in the current transaction.
* @returns {number} the size of the current transaction
*/
Transaction.prototype.size = function () {
return this.callbacks.length;
};
/**
* Keep all changes associated with this transaction.
* @method {platform/commonUI/edit/services.Transaction#commit}
* @returns {Promise} a promise which will resolve when all callbacks
* have been handled.
*/
/**
* Discard all changes associated with this transaction.
* @method {platform/commonUI/edit/services.Transaction#cancel}
* @returns {Promise} a promise which will resolve when all callbacks
* have been handled.
*/
['commit', 'cancel'].forEach(function (method) {
Transaction.prototype[method] = function () {
var promises = [];
var callback;
while (this.callbacks.length > 0) {
callback = this.callbacks.shift();
try {
promises.push(callback[method]());
} catch (e) {
this.$log
.error("Error trying to " + method + " transaction.");
}
}
return Promise.all(promises);
};
});
return Transaction;
});

View File

@@ -21,8 +21,8 @@
*****************************************************************************/
/*global define*/
define(
[],
function () {
['./Transaction', './NestedTransaction'],
function (Transaction, NestedTransaction) {
/**
* Implements an application-wide transaction state. Once a
* transaction is started, calls to
@@ -37,10 +37,7 @@ define(
function TransactionService($q, $log) {
this.$q = $q;
this.$log = $log;
this.transaction = false;
this.onCommits = [];
this.onCancels = [];
this.transactions = [];
}
/**
@@ -50,18 +47,18 @@ define(
* #cancel} are called
*/
TransactionService.prototype.startTransaction = function () {
if (this.transaction) {
//Log error because this is a programming error if it occurs.
this.$log.error("Transaction already in progress");
}
this.transaction = true;
var transaction = this.isActive() ?
new NestedTransaction(this.transactions[0]) :
new Transaction(this.$log);
this.transactions.push(transaction);
};
/**
* @returns {boolean} If true, indicates that a transaction is in progress
*/
TransactionService.prototype.isActive = function () {
return this.transaction;
return this.transactions.length > 0;
};
/**
@@ -72,24 +69,20 @@ define(
* @param onCancel A function to call on cancel
*/
TransactionService.prototype.addToTransaction = function (onCommit, onCancel) {
if (this.transaction) {
this.onCommits.push(onCommit);
if (onCancel) {
this.onCancels.push(onCancel);
}
if (this.isActive()) {
return this.activeTransaction().add(onCommit, onCancel);
} else {
//Log error because this is a programming error if it occurs.
this.$log.error("No transaction in progress");
}
};
return function () {
this.onCommits = this.onCommits.filter(function (callback) {
return callback !== onCommit;
});
this.onCancels = this.onCancels.filter(function (callback) {
return callback !== onCancel;
});
}.bind(this);
/**
* Get the transaction at the top of the stack.
* @private
*/
TransactionService.prototype.activeTransaction = function () {
return this.transactions[this.transactions.length - 1];
};
/**
@@ -100,24 +93,8 @@ define(
* completed. Will reject if any commit operations fail
*/
TransactionService.prototype.commit = function () {
var self = this,
promises = [],
onCommit;
while (this.onCommits.length > 0) { // ...using a while in case some onCommit adds to transaction
onCommit = this.onCommits.pop();
try { // ...also don't want to fail mid-loop...
promises.push(onCommit());
} catch (e) {
this.$log.error("Error committing transaction.");
}
}
return this.$q.all(promises).then(function () {
self.transaction = false;
self.onCommits = [];
self.onCancels = [];
});
var transaction = this.transactions.pop();
return transaction ? transaction.commit() : Promise.reject();
};
/**
@@ -129,28 +106,17 @@ define(
* @returns {*}
*/
TransactionService.prototype.cancel = function () {
var self = this,
results = [],
onCancel;
while (this.onCancels.length > 0) {
onCancel = this.onCancels.pop();
try {
results.push(onCancel());
} catch (error) {
this.$log.error("Error cancelling transaction.");
}
}
return this.$q.all(results).then(function () {
self.transaction = false;
self.onCommits = [];
self.onCancels = [];
});
var transaction = this.transactions.pop();
return transaction ? transaction.cancel() : Promise.reject();
};
/**
* Get the size (the number of commit/cancel callbacks) of
* the active transaction.
* @returns {number} size of the active transaction
*/
TransactionService.prototype.size = function () {
return this.onCommits.length;
return this.isActive() ? this.activeTransaction().size() : 0;
};
return TransactionService;

View File

@@ -30,7 +30,6 @@ define(
mockParent,
mockContext,
mockComposition,
mockPersistence,
mockActionCapability,
mockEditAction,
mockType,
@@ -68,7 +67,6 @@ define(
};
mockContext = jasmine.createSpyObj("context", ["getParent"]);
mockComposition = jasmine.createSpyObj("composition", ["invoke", "add"]);
mockPersistence = jasmine.createSpyObj("persistence", ["persist"]);
mockType = jasmine.createSpyObj("type", ["hasFeature", "getKey"]);
mockActionCapability = jasmine.createSpyObj("actionCapability", ["getActions"]);
mockEditAction = jasmine.createSpyObj("editAction", ["perform"]);
@@ -84,7 +82,6 @@ define(
capabilities = {
composition: mockComposition,
persistence: mockPersistence,
action: mockActionCapability,
type: mockType
};
@@ -107,11 +104,6 @@ define(
.toHaveBeenCalledWith(mockDomainObject);
});
it("persists changes afterward", function () {
action.perform();
expect(mockPersistence.persist).toHaveBeenCalled();
});
it("enables edit mode for objects that have an edit action", function () {
mockActionCapability.getActions.andReturn([mockEditAction]);
action.perform();

View File

@@ -43,7 +43,6 @@ define(
},
hasFeature: jasmine.createSpy('hasFeature')
},
persistence: jasmine.createSpyObj("persistence", ["persist"]),
mutation: jasmine.createSpy("mutation")
};
model = {};
@@ -78,25 +77,18 @@ define(
action = new PropertiesAction(dialogService, context);
});
it("persists when an action is performed", function () {
action.perform();
expect(capabilities.persistence.persist)
.toHaveBeenCalled();
});
it("does not persist any changes upon cancel", function () {
input = undefined;
action.perform();
expect(capabilities.persistence.persist)
.not.toHaveBeenCalled();
});
it("mutates an object when performed", function () {
action.perform();
expect(capabilities.mutation).toHaveBeenCalled();
capabilities.mutation.mostRecentCall.args[0]({});
});
it("does not muate object upon cancel", function () {
input = undefined;
action.perform();
expect(capabilities.mutation).not.toHaveBeenCalled();
});
it("is only applicable when a domain object is in context", function () {
expect(PropertiesAction.appliesTo(context)).toBeTruthy();
expect(PropertiesAction.appliesTo({})).toBeFalsy();

View File

@@ -37,7 +37,6 @@ define(
mockGrandchildContext,
mockRootContext,
mockMutation,
mockPersistence,
mockType,
actionContext,
model,
@@ -53,8 +52,6 @@ define(
}
beforeEach(function () {
mockDomainObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
@@ -88,7 +85,6 @@ define(
mockGrandchildContext = jasmine.createSpyObj("context", ["getParent"]);
mockRootContext = jasmine.createSpyObj("context", ["getParent"]);
mockMutation = jasmine.createSpyObj("mutation", ["invoke"]);
mockPersistence = jasmine.createSpyObj("persistence", ["persist"]);
mockType = jasmine.createSpyObj("type", ["hasFeature"]);
mockNavigationService = jasmine.createSpyObj(
"navigationService",
@@ -109,7 +105,6 @@ define(
capabilities = {
mutation: mockMutation,
persistence: mockPersistence,
type: mockType
};
model = {
@@ -118,7 +113,7 @@ define(
actionContext = { domainObject: mockDomainObject };
action = new RemoveAction(mockQ, mockNavigationService, actionContext);
action = new RemoveAction(mockNavigationService, actionContext);
});
it("only applies to objects with parents", function () {
@@ -154,9 +149,6 @@ define(
// Should have removed "test" - that was our
// mock domain object's id.
expect(result.composition).toEqual(["a", "b"]);
// Finally, should have persisted
expect(mockPersistence.persist).toHaveBeenCalled();
});
it("removes parent of object currently navigated to", function () {

View File

@@ -30,7 +30,6 @@ define(
mockScope,
testRepresentation,
mockDomainObject,
mockPersistence,
mockStatusCapability,
mockEditorCapability,
mockCapabilities,
@@ -56,15 +55,12 @@ define(
"useCapability",
"hasCapability"
]);
mockPersistence =
jasmine.createSpyObj("persistence", ["persist"]);
mockStatusCapability =
jasmine.createSpyObj("statusCapability", ["listen"]);
mockEditorCapability =
jasmine.createSpyObj("editorCapability", ["isEditContextRoot"]);
mockCapabilities = {
'persistence': mockPersistence,
'status': mockStatusCapability,
'editor': mockEditorCapability
};
@@ -96,7 +92,7 @@ define(
expect(representer.listenHandle).toHaveBeenCalled();
});
it("mutates and persists upon observed changes", function () {
it("mutates upon observed changes", function () {
mockScope.model = { someKey: "some value" };
mockScope.configuration = { someConfiguration: "something" };
@@ -108,9 +104,6 @@ define(
jasmine.any(Function)
);
// ... and should have persisted the mutation
expect(mockPersistence.persist).toHaveBeenCalled();
// Finally, check that the provided mutation function
// includes both model and configuration
expect(

View File

@@ -0,0 +1,78 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(["../../src/services/NestedTransaction"], function (NestedTransaction) {
var TRANSACTION_METHODS = ['add', 'commit', 'cancel', 'size'];
describe("A NestedTransaction", function () {
var mockTransaction,
nestedTransaction;
beforeEach(function () {
mockTransaction =
jasmine.createSpyObj('transaction', TRANSACTION_METHODS);
nestedTransaction = new NestedTransaction(mockTransaction);
});
it("exposes a Transaction's interface", function () {
TRANSACTION_METHODS.forEach(function (method) {
expect(nestedTransaction[method])
.toEqual(jasmine.any(Function));
});
});
describe("when callbacks are added", function () {
var mockCommit,
mockCancel,
remove;
beforeEach(function () {
mockCommit = jasmine.createSpy('commit');
mockCancel = jasmine.createSpy('cancel');
remove = nestedTransaction.add(mockCommit, mockCancel);
});
it("does not interact with its parent transaction", function () {
TRANSACTION_METHODS.forEach(function (method) {
expect(mockTransaction[method])
.not.toHaveBeenCalled();
});
});
describe("and the transaction is committed", function () {
beforeEach(function () {
nestedTransaction.commit();
});
it("adds to its parent transaction", function () {
expect(mockTransaction.add).toHaveBeenCalledWith(
jasmine.any(Function),
jasmine.any(Function)
);
});
});
});
});
});

View File

@@ -57,8 +57,7 @@ define(
transactionService.startTransaction();
transactionService.addToTransaction(onCommit, onCancel);
expect(transactionService.onCommits.length).toBe(1);
expect(transactionService.onCancels.length).toBe(1);
expect(transactionService.size()).toBe(1);
});
it("size function returns size of commit and cancel queues", function () {
@@ -85,7 +84,7 @@ define(
});
it("commit calls all queued commit functions", function () {
expect(transactionService.onCommits.length).toBe(3);
expect(transactionService.size()).toBe(3);
transactionService.commit();
onCommits.forEach(function (spy) {
expect(spy).toHaveBeenCalled();
@@ -95,8 +94,8 @@ define(
it("commit resets active state and clears queues", function () {
transactionService.commit();
expect(transactionService.isActive()).toBe(false);
expect(transactionService.onCommits.length).toBe(0);
expect(transactionService.onCancels.length).toBe(0);
expect(transactionService.size()).toBe(0);
expect(transactionService.size()).toBe(0);
});
});
@@ -116,7 +115,7 @@ define(
});
it("cancel calls all queued cancel functions", function () {
expect(transactionService.onCancels.length).toBe(3);
expect(transactionService.size()).toBe(3);
transactionService.cancel();
onCancels.forEach(function (spy) {
expect(spy).toHaveBeenCalled();
@@ -126,8 +125,7 @@ define(
it("cancel resets active state and clears queues", function () {
transactionService.cancel();
expect(transactionService.isActive()).toBe(false);
expect(transactionService.onCommits.length).toBe(0);
expect(transactionService.onCancels.length).toBe(0);
expect(transactionService.size()).toBe(0);
});
});

View File

@@ -0,0 +1,110 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/services/Transaction"],
function (Transaction) {
describe("A Transaction", function () {
var mockLog,
transaction;
beforeEach(function () {
mockLog = jasmine.createSpyObj(
'$log',
['warn', 'info', 'error', 'debug']
);
transaction = new Transaction(mockLog);
});
it("initially has a size of zero", function () {
expect(transaction.size()).toEqual(0);
});
describe("when callbacks are added", function () {
var mockCommit,
mockCancel,
remove;
beforeEach(function () {
mockCommit = jasmine.createSpy('commit');
mockCancel = jasmine.createSpy('cancel');
remove = transaction.add(mockCommit, mockCancel);
});
it("reports a new size", function () {
expect(transaction.size()).toEqual(1);
});
it("returns a function to remove those callbacks", function () {
expect(remove).toEqual(jasmine.any(Function));
remove();
expect(transaction.size()).toEqual(0);
});
describe("and the transaction is committed", function () {
beforeEach(function () {
transaction.commit();
});
it("triggers the commit callback", function () {
expect(mockCommit).toHaveBeenCalled();
});
it("does not trigger the cancel callback", function () {
expect(mockCancel).not.toHaveBeenCalled();
});
});
describe("and the transaction is cancelled", function () {
beforeEach(function () {
transaction.cancel();
});
it("triggers the cancel callback", function () {
expect(mockCancel).toHaveBeenCalled();
});
it("does not trigger the commit callback", function () {
expect(mockCommit).not.toHaveBeenCalled();
});
});
describe("and an exception is encountered during commit", function () {
beforeEach(function () {
mockCommit.andCallFake(function () {
throw new Error("test error");
});
transaction.commit();
});
it("logs an error", function () {
expect(mockLog.error).toHaveBeenCalled();
});
});
});
});
}
);

View File

@@ -23,10 +23,12 @@
define([
"./src/FormatProvider",
"./src/UTCTimeFormat",
"./src/DurationFormat",
'legacyRegistry'
], function (
FormatProvider,
UTCTimeFormat,
DurationFormat,
legacyRegistry
) {
@@ -48,6 +50,10 @@ define([
{
"key": "utc",
"implementation": UTCTimeFormat
},
{
"key": "duration",
"implementation": DurationFormat
}
],
"constants": [
@@ -55,6 +61,17 @@ define([
"key": "DEFAULT_TIME_FORMAT",
"value": "utc"
}
],
"licenses": [
{
"name": "d3",
"version": "3.0.0",
"description": "Incorporates modified code from d3 Time Scales",
"author": "Mike Bostock",
"copyright": "Copyright 2010-2016 Mike Bostock. " +
"All rights reserved.",
"link": "https://github.com/d3/d3/blob/master/LICENSE"
}
]
}
});

View File

@@ -0,0 +1,62 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define([
'moment'
], function (
moment
) {
var DATE_FORMAT = "HH:mm:ss",
DATE_FORMATS = [
DATE_FORMAT
];
/**
* Formatter for duration. Uses moment to produce a date from a given
* value, but output is formatted to display only time. Can be used for
* specifying a time duration. For specifying duration, it's best to
* specify a date of January 1, 1970, as the ms offset will equal the
* duration represented by the time.
*
* @implements {Format}
* @constructor
* @memberof platform/commonUI/formats
*/
function DurationFormat() {
}
DurationFormat.prototype.format = function (value) {
return moment.utc(value).format(DATE_FORMAT);
};
DurationFormat.prototype.parse = function (text) {
return moment.duration(text).asMilliseconds();
};
DurationFormat.prototype.validate = function (text) {
return moment.utc(text, DATE_FORMATS).isValid();
};
return DurationFormat;
});

View File

@@ -58,6 +58,10 @@ define([
* @method format
* @memberof Format#
* @param {number} value the numeric value to format
* @param {number} [threshold] Optionally provides context to the
* format request, allowing for scale-appropriate formatting. This value
* should be the minimum unit to be represented by this format, in ms. For
* example, to display seconds, a threshold of 1 * 1000 should be provided.
* @returns {string} the text representation of the value
*/

View File

@@ -34,6 +34,11 @@ define([
"YYYY-MM-DD"
];
/**
* @typedef Scale
* @property {number} min the minimum scale value, in ms
* @property {number} max the maximum scale value, in ms
*/
/**
* Formatter for UTC timestamps. Interprets numeric values as
@@ -46,7 +51,64 @@ define([
function UTCTimeFormat() {
}
UTCTimeFormat.prototype.format = function (value) {
/**
* Returns an appropriate time format based on the provided value and
* the threshold required.
* @private
*/
function getScaledFormat(d) {
var momentified = moment.utc(d);
/**
* Uses logic from d3 Time-Scales, v3 of the API. See
* https://github.com/d3/d3-3.x-api-reference/blob/master/Time-Scales.md
*
* Licensed
*/
return [
[".SSS", function (m) {
return m.milliseconds();
}],
[":ss", function (m) {
return m.seconds();
}],
["HH:mm", function (m) {
return m.minutes();
}],
["HH", function (m) {
return m.hours();
}],
["ddd DD", function (m) {
return m.days() &&
m.date() !== 1;
}],
["MMM DD", function (m) {
return m.date() !== 1;
}],
["MMMM", function (m) {
return m.month();
}],
["YYYY", function () {
return true;
}]
].filter(function (row) {
return row[1](momentified);
})[0][0];
}
/**
*
* @param value
* @param {Scale} [scale] Optionally provides context to the
* format request, allowing for scale-appropriate formatting.
* @returns {string} the formatted date
*/
UTCTimeFormat.prototype.format = function (value, scale) {
if (scale !== undefined) {
var scaledFormat = getScaledFormat(value, scale);
if (scaledFormat) {
return moment.utc(value).format(scaledFormat);
}
}
return moment.utc(value).format(DATE_FORMAT) + "Z";
};

View File

@@ -0,0 +1,62 @@
/*****************************************************************************
* 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.
*****************************************************************************/
define([
"./UTCTimeFormat",
"moment"
], function (
UTCTimeFormat,
moment
) {
describe("The UTCTimeFormat class", function () {
var format;
var scale;
beforeEach(function () {
format = new UTCTimeFormat();
scale = {min: 0, max: 0};
});
it("Provides an appropriately scaled time format based on the input" +
" time", function () {
var TWO_HUNDRED_MS = 200;
var THREE_SECONDS = 3000;
var FIVE_MINUTES = 5 * 60 * 1000;
var ONE_HOUR_TWENTY_MINS = (1 * 60 * 60 * 1000) + (20 * 60 * 1000);
var TEN_HOURS = (10 * 60 * 60 * 1000);
var JUNE_THIRD = moment.utc("2016-06-03", "YYYY-MM-DD");
var APRIL = moment.utc("2016-04", "YYYY-MM");
var TWENTY_SIXTEEN = moment.utc("2016", "YYYY");
expect(format.format(TWO_HUNDRED_MS, scale)).toBe(".200");
expect(format.format(THREE_SECONDS, scale)).toBe(":03");
expect(format.format(FIVE_MINUTES, scale)).toBe("00:05");
expect(format.format(ONE_HOUR_TWENTY_MINS, scale)).toBe("01:20");
expect(format.format(TEN_HOURS, scale)).toBe("10");
expect(format.format(JUNE_THIRD, scale)).toBe("Fri 03");
expect(format.format(APRIL, scale)).toBe("April");
expect(format.format(TWENTY_SIXTEEN, scale)).toBe("2016");
});
});
});

View File

@@ -48,6 +48,7 @@ define([
"./src/directives/MCTSplitPane",
"./src/directives/MCTSplitter",
"./src/directives/MCTTree",
"./src/filters/ReverseFilter",
"text!./res/templates/bottombar.html",
"text!./res/templates/controls/action-button.html",
"text!./res/templates/controls/input-filter.html",
@@ -96,6 +97,7 @@ define([
MCTSplitPane,
MCTSplitter,
MCTTree,
ReverseFilter,
bottombarTemplate,
actionButtonTemplate,
inputFilterTemplate,
@@ -146,7 +148,8 @@ define([
"depends": [
"stylesheets[]",
"$document",
"THEME"
"THEME",
"ASSETS_PATH"
]
},
{
@@ -158,7 +161,7 @@ define([
],
"filters": [
{
"implementation": "filters/ReverseFilter.js",
"implementation": ReverseFilter,
"key": "reverse"
}
],
@@ -405,6 +408,11 @@ define([
"key": "THEME",
"value": "unspecified",
"priority": "fallback"
},
{
"key": "ASSETS_PATH",
"value": ".",
"priority": "fallback"
}
],
"containers": [

View File

@@ -0,0 +1,91 @@
@include keyframes(rotation) {
100% { @include transform(rotate(360deg)); }
}
@include keyframes(rotation-centered) {
0% { @include transform(translate(-50%, -50%) rotate(0deg)); }
100% { @include transform(translate(-50%, -50%) rotate(360deg)); }
}
@include keyframes(clock-hands) {
0% { @include transform(translate(-50%, -50%) rotate(0deg)); }
100% { @include transform(translate(-50%, -50%) rotate(360deg)); }
}
@include keyframes(clock-hands-sticky) {
0% {
@include transform(translate(-50%, -50%) rotate(0deg));
}
7% {
@include transform(translate(-50%, -50%) rotate(0deg));
}
8% {
@include transform(translate(-50%, -50%) rotate(30deg));
}
15% {
@include transform(translate(-50%, -50%) rotate(30deg));
}
16% {
@include transform(translate(-50%, -50%) rotate(60deg));
}
24% {
@include transform(translate(-50%, -50%) rotate(60deg));
}
25% {
@include transform(translate(-50%, -50%) rotate(90deg));
}
32% {
@include transform(translate(-50%, -50%) rotate(90deg));
}
33% {
@include transform(translate(-50%, -50%) rotate(120deg));
}
40% {
@include transform(translate(-50%, -50%) rotate(120deg));
}
41% {
@include transform(translate(-50%, -50%) rotate(150deg));
}
49% {
@include transform(translate(-50%, -50%) rotate(150deg));
}
50% {
@include transform(translate(-50%, -50%) rotate(180deg));
}
57% {
@include transform(translate(-50%, -50%) rotate(180deg));
}
58% {
@include transform(translate(-50%, -50%) rotate(210deg));
}
65% {
@include transform(translate(-50%, -50%) rotate(210deg));
}
66% {
@include transform(translate(-50%, -50%) rotate(240deg));
}
74% {
@include transform(translate(-50%, -50%) rotate(240deg));
}
75% {
@include transform(translate(-50%, -50%) rotate(270deg));
}
82% {
@include transform(translate(-50%, -50%) rotate(270deg));
}
83% {
@include transform(translate(-50%, -50%) rotate(300deg));
}
90% {
@include transform(translate(-50%, -50%) rotate(300deg));
}
91% {
@include transform(translate(-50%, -50%) rotate(330deg));
}
99% {
@include transform(translate(-50%, -50%) rotate(330deg));
}
100% {
@include transform(translate(-50%, -50%) rotate(360deg));
}
}

View File

@@ -108,6 +108,9 @@
&.grows {
@include flex(1 1 auto);
}
&.contents-align-right {
text-align: right;
}
}
.flex-container {
// Apply to wrapping elements, mct-includes, etc.

View File

@@ -49,7 +49,6 @@ $uePaneMiniTabFontSize: 8px;
$uePaneMiniTabCollapsedW: 18px;
$ueEditLeftPaneW: 75%;
$treeSearchInputBarH: 25px;
$ueTimeControlH: (33px, 18px, 20px);
/*************** Panes */
$ueBrowseLeftPaneTreeMinW: 150px;
$ueBrowseLeftPaneTreeMaxW: 35%;
@@ -112,6 +111,7 @@ $bubbleMaxW: 300px;
$reqSymbolW: 15px;
$reqSymbolM: $interiorMargin * 2;
$reqSymbolFontSize: 0.75em;
$inputTextP: 3px 5px;
/*************** Wait Spinner Defaults */
$waitSpinnerD: 32px;
$waitSpinnerTreeD: 20px;

View File

@@ -4,4 +4,3 @@
@include s-stale();
}
}

View File

@@ -39,20 +39,20 @@
@include pulse($animName: pulse-subtle, $dur: 500ms, $opacity0: 0.7);
}
@mixin animTo($animName, $propName, $propValStart, $propValEnd, $dur: 500ms, $delay: 0) {
@mixin animTo($animName, $propName, $propValStart, $propValEnd, $dur: 500ms, $delay: 0, $dir: normal, $count: 1) {
@include keyframes($animName) {
from { #{propName}: $propValStart; }
to { #{$propName}: $propValEnd; }
}
@include animToParams($animName, $dur: 500ms, $delay: 0)
@include animToParams($animName, $dur: $dur, $delay: $delay, $dir: $dir, $count: $count)
}
@mixin animToParams($animName, $dur: 500ms, $delay: 0) {
@mixin animToParams($animName, $dur: 500ms, $delay: 0, $dir: normal, $count: 1) {
@include animation-name($animName);
@include animation-duration($dur);
@include animation-delay($delay);
@include animation-fill-mode(both);
@include animation-direction(normal);
@include animation-iteration-count(1);
@include animation-direction($dir);
@include animation-iteration-count($count);
@include animation-timing-function(ease-in-out);
}

View File

@@ -82,7 +82,7 @@ input, textarea {
input[type="text"],
input[type="search"] {
vertical-align: baseline;
padding: 3px 5px;
padding: $inputTextP;
}
h1, h2, h3 {

View File

@@ -30,6 +30,7 @@
.ui-symbol {
font-family: 'symbolsfont';
-webkit-font-smoothing: antialiased;
}
.ui-symbol.icon {
@@ -70,10 +71,21 @@
line-height: inherit;
position: relative;
&.l-icon-link {
.t-item-icon-glyph {
&:after {
color: $colorIconLink;
content: $glyph-icon-link;
height: auto; width: auto;
position: absolute;
left: 0; top: 0; right: 0; bottom: 20%;
@include transform-origin(bottom left);
@include transform(scale(0.3));
z-index: 2;
}
/* .t-item-icon-glyph {
&:after {
color: $colorIconLink;
content: $glyph-icon-link;
content: '\e921'; //$glyph-icon-link;
height: auto; width: auto;
position: absolute;
left: 0; top: 0; right: 0; bottom: 20%;
@@ -81,6 +93,6 @@
@include transform(scale(0.3));
z-index: 2;
}
}
}*/
}
}

View File

@@ -22,6 +22,7 @@
@import "effects";
@import "global";
@import "glyphs";
@import "animations";
@import "archetypes";
@import "about";
@import "text";
@@ -41,7 +42,6 @@
@import "controls/lists";
@import "controls/menus";
@import "controls/messages";
@import "controls/time-controller";
@import "mobile/controls/menus";
/********************************* FORMS */

View File

@@ -185,21 +185,15 @@
}
@mixin sliderTrack($bg: $scrollbarTrackColorBg) {
//$b: 1px solid lighten($bg, 30%);
border-radius: 2px;
box-sizing: border-box;
@include boxIncised(0.7);
background-color: $bg;
//border-bottom: $b;
//border-right: $b;
}
@mixin controlGrippy($b, $direction: horizontal, $w: 1px, $style: dotted) {
//&:before {
//@include trans-prop-nice("border-color", 25ms);
content: '';
display: block;
//height: auto;
pointer-events: none;
position: absolute;
z-index: 2;
@@ -274,16 +268,6 @@
text-shadow: rgba(black, $sVal) 0 3px 7px;
}
@function pullForward($c, $p: 20%) {
// For dark interfaces, lighter things come forward
@return lighten($c, $p);
}
@function pushBack($c, $p: 20%) {
// For dark interfaces, darker things move back
@return darken($c, $p);
}
@function percentToDecimal($p) {
@return $p / 100%;
}
@@ -304,7 +288,6 @@
border-radius: $controlCr;
box-sizing: border-box;
color: $fg;
//display: inline-block;
}
@mixin btnBase($bg: $colorBtnBg, $bgHov: $colorBtnBgHov, $fg: $colorBtnFg, $fgHov: $colorBtnFgHov, $ic: $colorBtnIcon, $icHov: $colorBtnIconHov) {

View File

@@ -296,8 +296,6 @@ input[type="search"] {
.title-label {
color: $colorObjHdrTxt;
@include ellipsize();
@include webkitProp(flex, '0 1 auto');
padding-right: 0.35em; // For context arrow. Done with em's so pad is relative to the scale of the text.
}
.context-available-w {
@@ -308,6 +306,10 @@ input[type="search"] {
font-size: 0.7em;
@include flex(0 0 1);
}
.t-object-alert {
display: none;
}
}
/******************************************************** PROGRESS BAR */
@@ -441,6 +443,63 @@ input[type="search"] {
}
}
@mixin sliderKnob() {
$h: 16px;
cursor: pointer;
width: floor($h/1.75);
height: $h;
margin-top: 1 + floor($h/2) * -1;
@include btnSubtle(pullForward($colorBtnBg, 10%));
//border-radius: 50% !important;
}
@mixin sliderKnobRound() {
$h: 12px;
cursor: pointer;
width: $h;
height: $h;
margin-top: 1 + floor($h/2) * -1;
@include btnSubtle(pullForward($colorBtnBg, 10%));
border-radius: 50% !important;
}
input[type="range"] {
// HTML5 range inputs
-webkit-appearance: none; /* Hides the slider so that custom slider can be made */
background: transparent; /* Otherwise white in Chrome */
&:focus {
outline: none; /* Removes the blue border. */
}
// Thumb
&::-webkit-slider-thumb {
-webkit-appearance: none;
@include sliderKnobRound();
}
&::-moz-range-thumb {
border: none;
@include sliderKnobRound();
}
&::-ms-thumb {
border: none;
@include sliderKnobRound();
}
// Track
&::-webkit-slider-runnable-track {
width: 100%;
height: 3px;
@include sliderTrack();
}
&::-moz-range-track {
width: 100%;
height: 3px;
@include sliderTrack();
}
}
/******************************************************** DATETIME PICKER */
.l-datetime-picker {
$r1H: 15px;

View File

@@ -178,7 +178,7 @@
}
.pane {
box-sizing: border-box;
&.left {
&.menu-items {
border-right: 1px solid pullForward($colorMenuBg, 10%);
left: 0;
padding-right: $interiorMargin;
@@ -194,38 +194,53 @@
}
}
}
&.right {
&.menu-item-description {
left: auto;
right: 0;
padding: $interiorMargin * 5;
width: $prw;
.desc-area {
&.icon {
color: $colorCreateMenuLgIcon;
font-size: 8em;
margin-bottom: $interiorMargin * 3;
position: relative;
text-align: center;
}
&.title {
color: $colorCreateMenuText;
font-size: 1.2em;
margin-bottom: $interiorMargin * 2;
}
&.description {
color: pushBack($colorCreateMenuText, 20%);
font-size: 0.8em;
line-height: 1.5em;
}
}
}
}
.menu-item-description {
.desc-area {
&.icon {
$h: 150px;
color: $colorCreateMenuLgIcon;
position: relative;
font-size: 8em;
left: 0;
height: $h;
line-height: $h;
margin-bottom: $interiorMargin * 5;
text-align: center;
}
&.title {
color: $colorCreateMenuText;
font-size: 1.2em;
margin-bottom: 0.5em;
}
&.description {
color: $colorCreateMenuText;
font-size: 0.8em;
line-height: 1.5em;
}
}
}
&.mini {
width: 400px;
height: 300px;
.pane {
&.menu-items {
font-size: 0.8em;
}
&.menu-item-description {
padding: $interiorMargin * 3;
.desc-area {
&.icon {
font-size: 4em;
}
&.title {
font-size: 1em;
}
}
}
}
}
}
.context-menu {
font-size: 0.80rem;
@@ -262,3 +277,7 @@
right: 0;
width: auto;
}
.menus-up .menu {
bottom: $btnStdH; top: auto;
}

View File

@@ -345,3 +345,29 @@ body.desktop .t-message-single {
body.desktop .t-message-list {
.message-contents .l-message { margin-right: $interiorMarginLg; }
}
// Alert elements in views
.s-unsynced {
$c: $colorPausedBg;
border: 1px solid $c;
@include animTo($animName: pulsePaused, $propName: border-color, $propValStart: rgba($c, 0.8), $propValEnd: rgba($c, 0.5), $dur: $animPausedPulseDur, $dir: alternate, $count: infinite);
}
.s-status-timeconductor-unsynced {
// Plot areas
.gl-plot .gl-plot-display-area {
@extend .s-unsynced;
}
// Object headers
.object-header {
.t-object-alert {
display: inline;
&.t-alert-unsynced {
@extend .icon-alert-triangle;
color: $colorPausedBg;
}
}
}
}

View File

@@ -1,266 +0,0 @@
@mixin toiLineHovEffects() {
&:before,
&:after {
background-color: $timeControllerToiLineColorHov;
}
}
.l-time-controller {
$minW: 500px;
$knobHOffset: 0px;
$knobM: ($sliderKnobW + $knobHOffset) * -1;
$rangeValPad: $interiorMargin;
$rangeValOffset: $sliderKnobW + $interiorMargin;
$timeRangeSliderLROffset: 150px + ($sliderKnobW * 2);
$r1H: nth($ueTimeControlH,1); // Not currently used
$r2H: nth($ueTimeControlH,2);
$r3H: nth($ueTimeControlH,3);
min-width: $minW;
font-size: 0.8rem;
.l-time-range-inputs-holder,
.l-time-range-slider-holder,
.l-time-range-ticks-holder
{
box-sizing: border-box;
position: relative;
&:not(:first-child) {
margin-top: $interiorMargin;
}
}
.l-time-range-slider,
.l-time-range-ticks {
@include absPosDefault(0, visible);
left: $timeRangeSliderLROffset; right: $timeRangeSliderLROffset;
}
.l-time-range-inputs-holder {
border-top: 1px solid $colorInteriorBorder;
padding-top: $interiorMargin;
&.l-flex-row,
.l-flex-row {
@include align-items(center);
.flex-elem {
height: auto;
line-height: normal;
}
}
.type-icon {
font-size: 120%;
vertical-align: middle;
}
.l-time-range-input-w,
.l-time-range-inputs-elem {
margin-right: $interiorMargin;
.lbl {
color: $colorPlotLabelFg;
}
.ui-symbol.icon {
font-size: 11px;
}
}
.l-time-range-input-w {
// Wraps a datetime text input field
position: relative;
input[type="text"] {
width: 200px;
&.picker-icon {
padding-right: 20px;
}
}
.icon-calendar {
position: absolute;
right: 5px;
top: 5px;
}
}
}
.l-time-range-slider-holder {
height: $r2H;
.range-holder {
box-shadow: none;
background: none;
border: none;
.range {
.toi-line {
$myC: $timeControllerToiLineColor;
$myW: 8px;
@include transform(translateX(50%));
position: absolute;
top: 0; right: 0; bottom: 0px; left: auto;
width: $myW;
height: auto;
z-index: 2;
&:before {
// Vert line
background-color: $myC;
position: absolute;
content: "";
top: 0; right: auto; bottom: -10px; left: floor($myW/2) - 1;
width: 1px;
}
}
&:hover .toi-line {
@include toiLineHovEffects;
}
}
}
&:not(:active) {
.knob,
.range {
@include transition-property(left, right);
@include transition-duration(500ms);
@include transition-timing-function(ease-in-out);
}
}
}
.l-time-range-ticks-holder {
height: $r3H;
.l-time-range-ticks {
border-top: 1px solid $colorTick;
.tick {
background-color: $colorTick;
border:none;
height: 5px;
width: 1px;
margin-left: -1px;
position: absolute;
&:first-child {
margin-left: 0;
}
.l-time-range-tick-label {
@include webkitProp(transform, translateX(-50%));
color: $colorPlotLabelFg;
display: inline-block;
font-size: 0.7rem;
position: absolute;
top: 5px;
white-space: nowrap;
z-index: 2;
}
}
}
}
.knob {
z-index: 2;
&:before {
$mTB: 2px;
$grippyW: 3px;
$mLR: ($sliderKnobW - $grippyW)/2;
@include bgStripes($c: pullForward($sliderColorKnob, 20%), $a: 1, $bgsize: 4px, $angle: 0deg);
content: '';
display: block;
position: absolute;
top: $mTB; right: $mLR; bottom: $mTB; left: $mLR;
}
.range-value {
@include trans-prop-nice-fade(.25s);
font-size: 0.7rem;
position: absolute;
height: $r2H;
line-height: $r2H;
white-space: nowrap;
z-index: 1;
}
&:hover {
.range-value {
color: $sliderColorKnobHov;
}
}
&.knob-l {
margin-left: $knobM;
.range-value {
text-align: right;
right: $rangeValOffset;
}
}
&.knob-r {
margin-right: $knobM;
.range-value {
left: $rangeValOffset;
}
&:hover + .range-holder .range .toi-line {
@include toiLineHovEffects;
}
}
}
.l-time-domain-selector {
position: absolute;
right: 0px;
top: $interiorMargin;
}
}
.s-time-range-val {
border-radius: $controlCr;
background-color: $colorInputBg;
padding: 1px 1px 0 $interiorMargin;
}
/******************************************************************** MOBILE */
@include phoneandtablet {
.l-time-controller {
min-width: 0;
.l-time-range-slider-holder,
.l-time-range-ticks-holder {
display: none;
}
}
}
@include phone {
.l-time-controller {
.l-time-range-inputs-holder {
&.l-flex-row,
.l-flex-row {
@include align-items(flex-start);
}
.l-time-range-inputs-elem {
&.type-icon {
margin-top: 3px;
}
}
.t-inputs-w {
@include flex-direction(column);
.l-time-range-input-w:not(:first-child) {
&:not(:first-child) {
margin-top: $interiorMargin;
}
margin-right: 0;
}
.l-time-range-inputs-elem {
&.lbl { display: none; }
}
}
}
}
}
@include phonePortrait {
.l-time-controller {
.l-time-range-inputs-holder {
.t-inputs-w {
@include flex(1 1 auto);
padding-top: 25px; // Make room for the ever lovin' Time Domain Selector
.flex-elem {
@include flex(1 1 auto);
width: 100%;
}
input[type="text"] {
width: 100%;
}
}
}
}
.l-time-domain-selector {
right: auto;
left: 20px;
}
}

View File

@@ -74,7 +74,7 @@
.s-image-main {
border: 1px solid transparent;
&.paused {
border-color: $colorPausedBg;
@extend .s-unsynced;
}
}

View File

@@ -19,15 +19,6 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
@include keyframes(rotation) {
100% { @include transform(rotate(360deg)); }
}
@include keyframes(rotation-centered) {
0% { @include transform(translate(-50%, -50%) rotate(0deg)); }
100% { @include transform(translate(-50%, -50%) rotate(360deg)); }
}
@mixin spinner($b: 5px, $c: $colorKey) {
@include transform-origin(center);
@include animation-name(rotation-centered);

View File

@@ -128,7 +128,7 @@
line-height: $ueTopBarH;
}
.primary-pane {
.t-object.primary-pane {
// Need to lift up this pane to ensure that 'collapsed' panes don't block user interactions
z-index: 4;
}
@@ -212,6 +212,8 @@ body.desktop .pane .mini-tab-icon.toggle-pane {
.holder-object {
top: $bodyMargin;
bottom: $interiorMargin;
// Clip element that have min-widths
overflow: hidden;
}
.holder-inspector {
top: $bodyMargin;

View File

@@ -23,6 +23,8 @@
<input type="text"
ng-model="textValue"
ng-blur="restoreTextValue(); ngBlur()"
ng-mouseup="ngMouseup()"
ng-disabled="ngDisabled"
ng-class="{
error: textInvalid ||
(structure.validate &&

View File

@@ -37,8 +37,10 @@ define(
* @param {object[]} stylesheets stylesheet extension definitions
* @param $document Angular's jqLite-wrapped document element
* @param {string} activeTheme the theme in use
* @param {string} [assetPath] the directory relative to which
* stylesheets will be found
*/
function StyleSheetLoader(stylesheets, $document, activeTheme) {
function StyleSheetLoader(stylesheets, $document, activeTheme, assetPath) {
var head = $document.find('head'),
document = $document[0];
@@ -47,6 +49,7 @@ define(
// Create a link element, and construct full path
var link = document.createElement('link'),
path = [
assetPath,
stylesheet.bundle.path,
stylesheet.bundle.resources,
stylesheet.stylesheetUrl
@@ -68,6 +71,8 @@ define(
stylesheet.theme === activeTheme;
}
assetPath = assetPath || ".";
// Add all stylesheets from extensions
stylesheets.filter(matchesTheme).forEach(addStyleSheet);
}

View File

@@ -69,7 +69,7 @@ define(
it("adjusts link locations", function () {
expect(mockElement.setAttribute)
.toHaveBeenCalledWith('href', "a/b/c/d.css");
.toHaveBeenCalledWith('href', "./a/b/c/d.css");
});
describe("for themed stylesheets", function () {
@@ -95,12 +95,13 @@ define(
it("includes matching themes", function () {
expect(mockElement.setAttribute)
.toHaveBeenCalledWith('href', "a/b/c/themed.css");
.toHaveBeenCalledWith('href', "./a/b/c/themed.css");
});
it("excludes mismatching themes", function () {
expect(mockElement.setAttribute)
.not.toHaveBeenCalledWith('href', "a/b/c/bad-theme.css");
.not
.toHaveBeenCalledWith('href', "./a/b/c/bad-theme.css");
});
});

View File

@@ -116,6 +116,7 @@ $colorProgressBarAmt: $colorKey;
$progressBarHOverlay: 15px;
$progressBarStripeW: 20px;
$shdwStatusIc: rgba(black, 0.4) 0 1px 2px;
$animPausedPulseDur: 500ms;
// Selects
$colorSelectBg: $colorBtnBg;

View File

@@ -116,6 +116,7 @@ $colorProgressBarAmt: #0a0;
$progressBarHOverlay: 15px;
$progressBarStripeW: 20px;
$shdwStatusIc: rgba(white, 0.8) 0 0px 5px;
$animPausedPulseDur: 1s;
// Selects
$colorSelectBg: $colorBtnBg;