Merge branch 'master' into mct1221
This commit is contained in:
@@ -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",
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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": []
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -81,6 +81,10 @@ define(
|
||||
return this.persistenceCapability.getSpace();
|
||||
};
|
||||
|
||||
TransactionalPersistenceCapability.prototype.persisted = function () {
|
||||
return this.persistenceCapability.persisted();
|
||||
};
|
||||
|
||||
return TransactionalPersistenceCapability;
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
48
platform/commonUI/edit/src/services/NestedTransaction.js
Normal file
48
platform/commonUI/edit/src/services/NestedTransaction.js
Normal 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;
|
||||
});
|
||||
96
platform/commonUI/edit/src/services/Transaction.js
Normal file
96
platform/commonUI/edit/src/services/Transaction.js
Normal 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;
|
||||
});
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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 () {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
110
platform/commonUI/edit/test/services/TransactionSpec.js
Normal file
110
platform/commonUI/edit/test/services/TransactionSpec.js
Normal 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();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
|
||||
62
platform/commonUI/formats/src/DurationFormat.js
Normal file
62
platform/commonUI/formats/src/DurationFormat.js
Normal 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;
|
||||
});
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
|
||||
@@ -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";
|
||||
};
|
||||
|
||||
|
||||
62
platform/commonUI/formats/src/UTCTimeFormatSpec.js
Normal file
62
platform/commonUI/formats/src/UTCTimeFormatSpec.js
Normal 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");
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -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": [
|
||||
|
||||
91
platform/commonUI/general/res/sass/_animations.scss
Normal file
91
platform/commonUI/general/res/sass/_animations.scss
Normal 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));
|
||||
}
|
||||
}
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -4,4 +4,3 @@
|
||||
@include s-stale();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -82,7 +82,7 @@ input, textarea {
|
||||
input[type="text"],
|
||||
input[type="search"] {
|
||||
vertical-align: baseline;
|
||||
padding: 3px 5px;
|
||||
padding: $inputTextP;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -74,7 +74,7 @@
|
||||
.s-image-main {
|
||||
border: 1px solid transparent;
|
||||
&.paused {
|
||||
border-color: $colorPausedBg;
|
||||
@extend .s-unsynced;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -116,6 +116,7 @@ $colorProgressBarAmt: $colorKey;
|
||||
$progressBarHOverlay: 15px;
|
||||
$progressBarStripeW: 20px;
|
||||
$shdwStatusIc: rgba(black, 0.4) 0 1px 2px;
|
||||
$animPausedPulseDur: 500ms;
|
||||
|
||||
// Selects
|
||||
$colorSelectBg: $colorBtnBg;
|
||||
|
||||
@@ -116,6 +116,7 @@ $colorProgressBarAmt: #0a0;
|
||||
$progressBarHOverlay: 15px;
|
||||
$progressBarStripeW: 20px;
|
||||
$shdwStatusIc: rgba(white, 0.8) 0 0px 5px;
|
||||
$animPausedPulseDur: 1s;
|
||||
|
||||
// Selects
|
||||
$colorSelectBg: $colorBtnBg;
|
||||
|
||||
Reference in New Issue
Block a user