mirror of
https://github.com/nasa/openmct.git
synced 2025-01-19 03:06:54 +00:00
Merge remote-tracking branch 'origin/master' into table-export-934
Conflicts: platform/commonUI/general/res/sass/controls/_buttons.scss platform/features/table/res/templates/mct-table.html
This commit is contained in:
commit
50bd233b0a
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "openmct",
|
"name": "openmct",
|
||||||
"version": "0.10.2-SNAPSHOT",
|
"version": "0.10.3-SNAPSHOT",
|
||||||
"description": "The Open MCT core platform",
|
"description": "The Open MCT core platform",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.13.1",
|
"express": "^4.13.1",
|
||||||
|
@ -170,7 +170,7 @@ define([
|
|||||||
"navigationService",
|
"navigationService",
|
||||||
"$log"
|
"$log"
|
||||||
],
|
],
|
||||||
"description": "Edit this object.",
|
"description": "Edit",
|
||||||
"category": "view-control",
|
"category": "view-control",
|
||||||
"glyph": "p"
|
"glyph": "p"
|
||||||
},
|
},
|
||||||
|
@ -67,10 +67,17 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function onCancel() {
|
function onCancel() {
|
||||||
|
if (self.domainObject.getModel().persisted !== undefined) {
|
||||||
|
//Fetch clean model from persistence
|
||||||
return self.persistenceCapability.refresh().then(function (result) {
|
return self.persistenceCapability.refresh().then(function (result) {
|
||||||
self.persistPending = false;
|
self.persistPending = false;
|
||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
self.persistPending = false;
|
||||||
|
//Model is undefined in persistence, so return undefined.
|
||||||
|
return self.$q.when(undefined);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.transactionService.isActive()) {
|
if (this.transactionService.isActive()) {
|
||||||
|
@ -24,12 +24,11 @@ define(
|
|||||||
["../../src/actions/CancelAction"],
|
["../../src/actions/CancelAction"],
|
||||||
function (CancelAction) {
|
function (CancelAction) {
|
||||||
|
|
||||||
//TODO: Disabled for NEM Beta
|
describe("The Cancel action", function () {
|
||||||
xdescribe("The Cancel action", function () {
|
var mockDomainObject,
|
||||||
var mockLocation,
|
mockParentObject,
|
||||||
mockDomainObject,
|
capabilities = {},
|
||||||
mockEditorCapability,
|
parentCapabilities = {},
|
||||||
mockUrlService,
|
|
||||||
actionContext,
|
actionContext,
|
||||||
action;
|
action;
|
||||||
|
|
||||||
@ -42,61 +41,109 @@ define(
|
|||||||
}
|
}
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockLocation = jasmine.createSpyObj(
|
|
||||||
"$location",
|
|
||||||
["path"]
|
|
||||||
);
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
"domainObject",
|
"domainObject",
|
||||||
["getCapability", "hasCapability"]
|
[
|
||||||
|
"getCapability",
|
||||||
|
"hasCapability",
|
||||||
|
"getModel"
|
||||||
|
]
|
||||||
);
|
);
|
||||||
mockEditorCapability = jasmine.createSpyObj(
|
mockDomainObject.getModel.andReturn({});
|
||||||
|
|
||||||
|
mockParentObject = jasmine.createSpyObj(
|
||||||
|
"parentObject",
|
||||||
|
[
|
||||||
|
"getCapability"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockParentObject.getCapability.andCallFake(function (name) {
|
||||||
|
return parentCapabilities[name];
|
||||||
|
});
|
||||||
|
|
||||||
|
capabilities.editor = jasmine.createSpyObj(
|
||||||
"editor",
|
"editor",
|
||||||
["save", "cancel"]
|
["save", "cancel", "isEditContextRoot"]
|
||||||
);
|
);
|
||||||
mockUrlService = jasmine.createSpyObj(
|
capabilities.action = jasmine.createSpyObj(
|
||||||
"urlService",
|
"actionCapability",
|
||||||
["urlForLocation"]
|
[
|
||||||
|
"perform"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
capabilities.location = jasmine.createSpyObj(
|
||||||
|
"locationCapability",
|
||||||
|
[
|
||||||
|
"getOriginal"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
capabilities.location.getOriginal.andReturn(mockPromise(mockDomainObject));
|
||||||
|
capabilities.context = jasmine.createSpyObj(
|
||||||
|
"contextCapability",
|
||||||
|
[
|
||||||
|
"getParent"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
capabilities.context.getParent.andReturn(mockParentObject);
|
||||||
|
|
||||||
|
parentCapabilities.action = jasmine.createSpyObj(
|
||||||
|
"actionCapability",
|
||||||
|
[
|
||||||
|
"perform"
|
||||||
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
actionContext = {
|
actionContext = {
|
||||||
domainObject: mockDomainObject
|
domainObject: mockDomainObject
|
||||||
};
|
};
|
||||||
|
|
||||||
mockDomainObject.hasCapability.andReturn(true);
|
mockDomainObject.getCapability.andCallFake(function (name) {
|
||||||
mockDomainObject.getCapability.andReturn(mockEditorCapability);
|
return capabilities[name];
|
||||||
mockEditorCapability.cancel.andReturn(mockPromise(true));
|
});
|
||||||
|
|
||||||
action = new CancelAction(mockLocation, mockUrlService, actionContext);
|
mockDomainObject.hasCapability.andCallFake(function (name) {
|
||||||
|
return !!capabilities[name];
|
||||||
|
});
|
||||||
|
|
||||||
|
capabilities.editor.cancel.andReturn(mockPromise(true));
|
||||||
|
|
||||||
|
action = new CancelAction(actionContext);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("only applies to domain object with an editor capability", function () {
|
it("only applies to domain object that is being edited", function () {
|
||||||
|
capabilities.editor.isEditContextRoot.andReturn(true);
|
||||||
expect(CancelAction.appliesTo(actionContext)).toBeTruthy();
|
expect(CancelAction.appliesTo(actionContext)).toBeTruthy();
|
||||||
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
|
||||||
|
|
||||||
|
capabilities.editor.isEditContextRoot.andReturn(false);
|
||||||
|
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
|
||||||
|
|
||||||
mockDomainObject.hasCapability.andReturn(false);
|
mockDomainObject.hasCapability.andReturn(false);
|
||||||
mockDomainObject.getCapability.andReturn(undefined);
|
|
||||||
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
|
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("invokes the editor capability's save functionality when performed", function () {
|
it("invokes the editor capability's cancel functionality when" +
|
||||||
// Verify precondition
|
" performed", function () {
|
||||||
expect(mockEditorCapability.cancel).not.toHaveBeenCalled();
|
|
||||||
action.perform();
|
action.perform();
|
||||||
|
|
||||||
// Should have called cancel
|
// Should have called cancel
|
||||||
expect(mockEditorCapability.cancel).toHaveBeenCalled();
|
expect(capabilities.editor.cancel).toHaveBeenCalled();
|
||||||
|
|
||||||
// Definitely shouldn't call save!
|
// Definitely shouldn't call save!
|
||||||
expect(mockEditorCapability.save).not.toHaveBeenCalled();
|
expect(capabilities.editor.save).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("returns to browse when performed", function () {
|
it("navigates to object if existing", function () {
|
||||||
|
mockDomainObject.getModel.andReturn({persisted: 1});
|
||||||
action.perform();
|
action.perform();
|
||||||
expect(mockLocation.path).toHaveBeenCalledWith(
|
expect(capabilities.action.perform).toHaveBeenCalledWith("navigate");
|
||||||
mockUrlService.urlForLocation("browse", mockDomainObject)
|
});
|
||||||
);
|
|
||||||
|
it("navigates to parent if new", function () {
|
||||||
|
mockDomainObject.getModel.andReturn({persisted: undefined});
|
||||||
|
action.perform();
|
||||||
|
expect(parentCapabilities.action.perform).toHaveBeenCalledWith("navigate");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -57,6 +57,15 @@ define(
|
|||||||
);
|
);
|
||||||
mockPersistence.persist.andReturn(fastPromise());
|
mockPersistence.persist.andReturn(fastPromise());
|
||||||
mockPersistence.refresh.andReturn(fastPromise());
|
mockPersistence.refresh.andReturn(fastPromise());
|
||||||
|
|
||||||
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
|
"domainObject",
|
||||||
|
[
|
||||||
|
"getModel"
|
||||||
|
]
|
||||||
|
);
|
||||||
|
mockDomainObject.getModel.andReturn({persisted: 1});
|
||||||
|
|
||||||
capability = new TransactionalPersistenceCapability(mockQ, mockTransactionService, mockPersistence, mockDomainObject);
|
capability = new TransactionalPersistenceCapability(mockQ, mockTransactionService, mockPersistence, mockDomainObject);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -78,6 +87,20 @@ define(
|
|||||||
expect(mockPersistence.refresh).toHaveBeenCalled();
|
expect(mockPersistence.refresh).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("if transaction is active, cancel call is queued that refreshes model when appropriate", function () {
|
||||||
|
mockTransactionService.isActive.andReturn(true);
|
||||||
|
capability.persist();
|
||||||
|
expect(mockTransactionService.addToTransaction).toHaveBeenCalled();
|
||||||
|
|
||||||
|
mockDomainObject.getModel.andReturn({});
|
||||||
|
mockTransactionService.addToTransaction.mostRecentCall.args[1]();
|
||||||
|
expect(mockPersistence.refresh).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
mockDomainObject.getModel.andReturn({persisted: 1});
|
||||||
|
mockTransactionService.addToTransaction.mostRecentCall.args[1]();
|
||||||
|
expect(mockPersistence.refresh).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
it("persist call is only added to transaction once", function () {
|
it("persist call is only added to transaction once", function () {
|
||||||
mockTransactionService.isActive.andReturn(true);
|
mockTransactionService.isActive.andReturn(true);
|
||||||
capability.persist();
|
capability.persist();
|
||||||
|
@ -124,6 +124,8 @@ $dirImgs: $dirCommonRes + 'images/';
|
|||||||
|
|
||||||
/************************** TIMINGS */
|
/************************** TIMINGS */
|
||||||
$controlFadeMs: 100ms;
|
$controlFadeMs: 100ms;
|
||||||
|
$browseToEditAnimMs: 400ms;
|
||||||
|
$editBorderPulseMs: 500ms;
|
||||||
|
|
||||||
/************************** LIMITS */
|
/************************** LIMITS */
|
||||||
$glyphLimit: '\e603';
|
$glyphLimit: '\e603';
|
||||||
|
@ -39,15 +39,20 @@
|
|||||||
@include pulse($animName: pulse-subtle, $dur: 500ms, $opacity0: 0.7);
|
@include pulse($animName: pulse-subtle, $dur: 500ms, $opacity0: 0.7);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin pulseBorder($c: red, $dur: 500ms, $iteration: infinite, $delay: 0s, $opacity0: 0, $opacity100: 1) {
|
@mixin animTo($animName, $propName, $propValStart, $propValEnd, $dur: 500ms, $delay: 0) {
|
||||||
@include keyframes(pulseBorder) {
|
@include keyframes($animName) {
|
||||||
0% { border-color: rgba($c, $opacity0); }
|
from { #{propName}: $propValStart; }
|
||||||
100% { border-color: rgba($c, $opacity100); }
|
to { #{$propName}: $propValEnd; }
|
||||||
}
|
}
|
||||||
@include animation-name(pulseBorder);
|
@include animToParams($animName, $dur: 500ms, $delay: 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin animToParams($animName, $dur: 500ms, $delay: 0) {
|
||||||
|
@include animation-name($animName);
|
||||||
@include animation-duration($dur);
|
@include animation-duration($dur);
|
||||||
@include animation-direction(alternate);
|
|
||||||
@include animation-iteration-count($iteration);
|
|
||||||
@include animation-timing-function(ease);
|
|
||||||
@include animation-delay($delay);
|
@include animation-delay($delay);
|
||||||
|
@include animation-fill-mode(both);
|
||||||
|
@include animation-direction(normal);
|
||||||
|
@include animation-iteration-count(1);
|
||||||
|
@include animation-timing-function(ease-in-out);
|
||||||
}
|
}
|
@ -36,15 +36,7 @@ $pad: $interiorMargin * $baseRatio;
|
|||||||
padding: 0 $pad;
|
padding: 0 $pad;
|
||||||
font-size: 0.7rem;
|
font-size: 0.7rem;
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
|
@include btnSubtle($colorBtnBg, $colorBtnBgHov, $colorBtnFg, $colorBtnIcon);
|
||||||
.icon {
|
|
||||||
font-size: 0.8rem;
|
|
||||||
color: $colorKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title-label {
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.lg {
|
&.lg {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
@ -58,19 +50,13 @@ $pad: $interiorMargin * $baseRatio;
|
|||||||
padding: 0 ($pad / $baseRatio) / 2;
|
padding: 0 ($pad / $baseRatio) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.major {
|
&.major,
|
||||||
|
&.key-edit {
|
||||||
$bg: $colorBtnMajorBg;
|
$bg: $colorBtnMajorBg;
|
||||||
$hc: lighten($bg, 10%);
|
$hc: lighten($bg, 10%);
|
||||||
@include btnSubtle($bg, $hc, $colorBtnMajorFg, $colorBtnMajorFg);
|
@include btnSubtle($bg, $hc, $colorBtnMajorFg, $colorBtnMajorFg);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(.major) {
|
|
||||||
// bg, bgHov, fg, ic
|
|
||||||
@include btnSubtle($colorBtnBg, $colorBtnBgHov, $colorBtnFg, $colorBtnIcon);
|
|
||||||
}
|
|
||||||
&.pause-play {
|
|
||||||
|
|
||||||
}
|
|
||||||
&.t-save:before {
|
&.t-save:before {
|
||||||
content:'\e612';
|
content:'\e612';
|
||||||
font-family: symbolsfont;
|
font-family: symbolsfont;
|
||||||
@ -117,6 +103,15 @@ $pad: $interiorMargin * $baseRatio;
|
|||||||
content: '\e623';
|
content: '\e623';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-size: 0.8rem;
|
||||||
|
color: $colorKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
.title-label {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.s-icon-btn {
|
.s-icon-btn {
|
||||||
@ -283,4 +278,3 @@ body.desktop .mini-tab-icon {
|
|||||||
color: $colorPausedBg !important;
|
color: $colorPausedBg !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,30 +237,10 @@ body.desktop .pane .mini-tab-icon.toggle-pane {
|
|||||||
top: $ueTopBarH + $interiorMarginLg;
|
top: $ueTopBarH + $interiorMarginLg;
|
||||||
}
|
}
|
||||||
|
|
||||||
.l-object-wrapper {
|
|
||||||
@extend .abs;
|
|
||||||
|
|
||||||
.object-holder-main {
|
|
||||||
@extend .abs;
|
|
||||||
}
|
|
||||||
.l-edit-controls {
|
|
||||||
//@include trans-prop-nice((opacity, height), 0.25s);
|
|
||||||
border-bottom: 1px solid $colorInteriorBorder;
|
|
||||||
line-height: $ueEditToolBarH;
|
|
||||||
height: 0px;
|
|
||||||
opacity: 0;
|
|
||||||
.tool-bar {
|
|
||||||
right: $interiorMargin;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.l-object-wrapper-inner {
|
.l-object-wrapper-inner {
|
||||||
@include trans-prop-nice-resize(0.25s);
|
@include trans-prop-nice-resize(0.25s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.object-browse-bar .s-btn,
|
.object-browse-bar .s-btn,
|
||||||
.top-bar .buttons-main .s-btn,
|
.top-bar .buttons-main .s-btn,
|
||||||
.top-bar .s-menu-btn,
|
.top-bar .s-menu-btn,
|
||||||
@ -377,19 +357,50 @@ body.desktop {
|
|||||||
|
|
||||||
.s-status-editing {
|
.s-status-editing {
|
||||||
.l-object-wrapper {
|
.l-object-wrapper {
|
||||||
@include pulseBorder($colorEditAreaFg, $dur: 1s, $opacity0: 0.3);
|
$t2Dur: $browseToEditAnimMs;
|
||||||
border-radius: $controlCr;
|
$t1Dur: $t2Dur / 2;
|
||||||
|
$pulseDur: $editBorderPulseMs;
|
||||||
|
$bC0: rgba($colorEditAreaFg, 0.5);
|
||||||
|
$bC100: rgba($colorEditAreaFg, 1);
|
||||||
|
|
||||||
background-color: $colorEditAreaBg;
|
background-color: $colorEditAreaBg;
|
||||||
border-color: $colorEditAreaFg;
|
border-radius: $controlCr;
|
||||||
border-width: 2px;
|
border: 1px dotted $bC0;
|
||||||
border-style: dotted;
|
|
||||||
.l-object-wrapper-inner {
|
// Transition 1
|
||||||
@include absPosDefault(3px, hidden);
|
@include keyframes(wrapperIn) {
|
||||||
|
from { border: 0px dotted transparent; padding: 0; }
|
||||||
|
to { border: 1px dotted $bC0; padding: 5px; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do last
|
||||||
|
@include keyframes(pulseNew) {
|
||||||
|
from { border-color: $bC0; }
|
||||||
|
to { border-color: $bC100; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@include animation-name(wrapperIn, pulseNew);
|
||||||
|
@include animation-duration($t1Dur, $pulseDur);
|
||||||
|
@include animation-delay(0s, $t1Dur + $t2Dur);
|
||||||
|
@include animation-direction(normal, alternate);
|
||||||
|
@include animation-fill-mode(both, none);
|
||||||
|
@include animation-iteration-count(1, infinite);
|
||||||
|
@include animation-timing-function(ease-in-out, linear);
|
||||||
|
|
||||||
|
|
||||||
.l-edit-controls {
|
.l-edit-controls {
|
||||||
height: $ueEditToolBarH + $interiorMargin;
|
height: 0;
|
||||||
margin-bottom: $interiorMargin;
|
border-bottom: 1px solid $colorInteriorBorder;
|
||||||
opacity: 1;
|
overflow: hidden;
|
||||||
|
// Transition 2: reveal edit controls
|
||||||
|
@include keyframes(editIn) {
|
||||||
|
from { border-bottom: 0px solid transparent; height: 0; margin-bottom: 0; }
|
||||||
|
to { border-bottom: 1px solid $colorInteriorBorder; height: $ueEditToolBarH + $interiorMargin; margin-bottom: $interiorMargin; }
|
||||||
|
}
|
||||||
|
@include animToParams(editIn, $dur: $t2Dur, $delay: $t1Dur);
|
||||||
|
.tool-bar {
|
||||||
|
right: $interiorMargin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,10 +29,12 @@
|
|||||||
!structure.validate(ngModel[field])),
|
!structure.validate(ngModel[field])),
|
||||||
'picker-icon': structure.format === 'utc' || !structure.format
|
'picker-icon': structure.format === 'utc' || !structure.format
|
||||||
}">
|
}">
|
||||||
</input><a class="ui-symbol icon icon-calendar"
|
</input>
|
||||||
ng-if="structure.format === 'utc' || !structure.format"
|
<a class="ui-symbol icon icon-calendar"
|
||||||
ng-click="picker.active = !picker.active">
|
ng-if="!picker.active && (structure.format === 'utc' || !structure.format)"
|
||||||
</a>
|
ng-click="picker.active = !picker.active"></a>
|
||||||
|
<!-- If picker active show icon with no onclick to prevent double registration of clicks -->
|
||||||
|
<a class="ui-symbol icon icon-calendar" ng-if="picker.active"></a>
|
||||||
<mct-popup ng-if="picker.active">
|
<mct-popup ng-if="picker.active">
|
||||||
<div mct-click-elsewhere="picker.active = false">
|
<div mct-click-elsewhere="picker.active = false">
|
||||||
<mct-control key="'datetime-picker'"
|
<mct-control key="'datetime-picker'"
|
||||||
|
@ -72,6 +72,17 @@ define(
|
|||||||
if ($scope.ngBlur) {
|
if ($scope.ngBlur) {
|
||||||
$scope.ngBlur();
|
$scope.ngBlur();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If picker is active, dismiss it when valid value has been selected
|
||||||
|
// This 'if' is to avoid unnecessary validation if picker is not active
|
||||||
|
if ($scope.picker.active) {
|
||||||
|
if ($scope.structure.validate && $scope.structure.validate($scope.ngModel[$scope.field])) {
|
||||||
|
$scope.picker.active = false;
|
||||||
|
} else if (!$scope.structure.validate) {
|
||||||
|
//If picker visible, but no validation function, hide picker
|
||||||
|
$scope.picker.active = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +104,6 @@ define(
|
|||||||
$scope.$watch('ngModel[field]', updateFromModel);
|
$scope.$watch('ngModel[field]', updateFromModel);
|
||||||
$scope.$watch('pickerModel.value', updateFromPicker);
|
$scope.$watch('pickerModel.value', updateFromPicker);
|
||||||
$scope.$watch('textValue', updateFromView);
|
$scope.$watch('textValue', updateFromView);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DateTimeFieldController;
|
return DateTimeFieldController;
|
||||||
|
@ -51,7 +51,9 @@ define(
|
|||||||
yMax = yMin + rect.height;
|
yMax = yMin + rect.height;
|
||||||
|
|
||||||
if (x < xMin || x > xMax || y < yMin || y > yMax) {
|
if (x < xMin || x > xMax || y < yMin || y > yMax) {
|
||||||
|
scope.$apply(function () {
|
||||||
scope.$eval(attrs.mctClickElsewhere);
|
scope.$eval(attrs.mctClickElsewhere);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +104,8 @@ define(
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("triggers an evaluation of its related Angular expression", function () {
|
it("triggers an evaluation of its related Angular expression", function () {
|
||||||
|
expect(mockScope.$apply).toHaveBeenCalled();
|
||||||
|
mockScope.$apply.mostRecentCall.args[0]();
|
||||||
expect(mockScope.$eval)
|
expect(mockScope.$eval)
|
||||||
.toHaveBeenCalledWith(testAttrs.mctClickElsewhere);
|
.toHaveBeenCalledWith(testAttrs.mctClickElsewhere);
|
||||||
});
|
});
|
||||||
|
@ -14,7 +14,7 @@ $colorAHov: #fff;
|
|||||||
$contrastRatioPercent: 7%;
|
$contrastRatioPercent: 7%;
|
||||||
$hoverRatioPercent: 10%;
|
$hoverRatioPercent: 10%;
|
||||||
$basicCr: 3px;
|
$basicCr: 3px;
|
||||||
$controlCr: 3px;
|
$controlCr: 2px;
|
||||||
$smallCr: 2px;
|
$smallCr: 2px;
|
||||||
|
|
||||||
// Buttons and Controls
|
// Buttons and Controls
|
||||||
|
@ -82,16 +82,6 @@ define(
|
|||||||
expect(result.a.getModel()).toEqual(model);
|
expect(result.a.getModel()).toEqual(model);
|
||||||
});
|
});
|
||||||
|
|
||||||
//TODO: Disabled for NEM Beta
|
|
||||||
xit("provides a new, fully constituted domain object for a" +
|
|
||||||
" provided model", function () {
|
|
||||||
var model = { someKey: "some value"},
|
|
||||||
result;
|
|
||||||
result = provider.newObject("a", model);
|
|
||||||
expect(result.getId()).toEqual("a");
|
|
||||||
expect(result.getModel()).toEqual(model);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -81,6 +81,7 @@ define(
|
|||||||
if (phase.toLowerCase() === 'preparing' && !this.dialog) {
|
if (phase.toLowerCase() === 'preparing' && !this.dialog) {
|
||||||
this.dialog = this.dialogService.showBlockingMessage({
|
this.dialog = this.dialogService.showBlockingMessage({
|
||||||
title: "Preparing to copy objects",
|
title: "Preparing to copy objects",
|
||||||
|
hint: "Do not navigate away from this page or close this browser tab while this message is displayed.",
|
||||||
unknownProgress: true,
|
unknownProgress: true,
|
||||||
severity: "info"
|
severity: "info"
|
||||||
});
|
});
|
||||||
|
@ -24,10 +24,7 @@ define(
|
|||||||
[],
|
[],
|
||||||
function () {
|
function () {
|
||||||
|
|
||||||
var DISALLOWED_ACTIONS = [
|
var DISALLOWED_ACTIONS = ["move"];
|
||||||
"move",
|
|
||||||
"copy"
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This policy prevents performing move/copy/link actions across
|
* This policy prevents performing move/copy/link actions across
|
||||||
|
@ -70,10 +70,9 @@ define(
|
|||||||
policy = new CrossSpacePolicy();
|
policy = new CrossSpacePolicy();
|
||||||
});
|
});
|
||||||
|
|
||||||
['move', 'copy'].forEach(function (key) {
|
describe("for move actions", function () {
|
||||||
describe("for " + key + " actions", function () {
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
testActionMetadata.key = key;
|
testActionMetadata.key = 'move';
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows same-space changes", function () {
|
it("allows same-space changes", function () {
|
||||||
@ -92,7 +91,6 @@ define(
|
|||||||
})).toBe(true);
|
})).toBe(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
describe("for other actions", function () {
|
describe("for other actions", function () {
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
|
@ -42,7 +42,7 @@ define(
|
|||||||
'parent'
|
'parent'
|
||||||
];
|
];
|
||||||
|
|
||||||
xdescribe("ConductorRepresenter", function () {
|
describe("ConductorRepresenter", function () {
|
||||||
var mockThrottle,
|
var mockThrottle,
|
||||||
mockConductorService,
|
mockConductorService,
|
||||||
mockCompile,
|
mockCompile,
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
title="Export This View's Data">
|
title="Export This View's Data">
|
||||||
Export
|
Export
|
||||||
</a>
|
</a>
|
||||||
<div class="l-view-section scrolling" style="overflow: auto;">
|
<div class="l-view-section scrolling" style="overflow: auto;" mct-resize="resize()">
|
||||||
<table class="sizing-table">
|
<table class="sizing-table">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -86,6 +86,12 @@ define(
|
|||||||
*/
|
*/
|
||||||
$scope.$on('add:row', this.addRow.bind(this));
|
$scope.$on('add:row', this.addRow.bind(this));
|
||||||
$scope.$on('remove:row', this.removeRow.bind(this));
|
$scope.$on('remove:row', this.removeRow.bind(this));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Listen for resize events to trigger recalculation of table width
|
||||||
|
*/
|
||||||
|
$scope.resize = this.setElementSizes.bind(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,23 +30,21 @@ define(
|
|||||||
var TEST_DOMAIN_VALUE = "some formatted domain value";
|
var TEST_DOMAIN_VALUE = "some formatted domain value";
|
||||||
|
|
||||||
describe("A domain column", function () {
|
describe("A domain column", function () {
|
||||||
var mockDataSet,
|
var mockDatum,
|
||||||
testMetadata,
|
testMetadata,
|
||||||
mockFormatter,
|
mockFormatter,
|
||||||
column;
|
column;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockDataSet = jasmine.createSpyObj(
|
|
||||||
"data",
|
|
||||||
["getDomainValue"]
|
|
||||||
);
|
|
||||||
mockFormatter = jasmine.createSpyObj(
|
mockFormatter = jasmine.createSpyObj(
|
||||||
"formatter",
|
"formatter",
|
||||||
["formatDomainValue", "formatRangeValue"]
|
["formatDomainValue", "formatRangeValue"]
|
||||||
);
|
);
|
||||||
testMetadata = {
|
testMetadata = {
|
||||||
key: "testKey",
|
key: "testKey",
|
||||||
name: "Test Name"
|
name: "Test Name",
|
||||||
|
format: "Test Format"
|
||||||
};
|
};
|
||||||
mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE);
|
mockFormatter.formatDomainValue.andReturn(TEST_DOMAIN_VALUE);
|
||||||
|
|
||||||
@ -57,24 +55,24 @@ define(
|
|||||||
expect(column.getTitle()).toEqual("Test Name");
|
expect(column.getTitle()).toEqual("Test Name");
|
||||||
});
|
});
|
||||||
|
|
||||||
xit("looks up data from a data set", function () {
|
describe("when given a datum", function () {
|
||||||
column.getValue(undefined, mockDataSet, 42);
|
beforeEach(function () {
|
||||||
expect(mockDataSet.getDomainValue)
|
mockDatum = {
|
||||||
.toHaveBeenCalledWith(42, "testKey");
|
testKey: "testKeyValue"
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
xit("formats domain values as time", function () {
|
it("looks up data from the given datum", function () {
|
||||||
mockDataSet.getDomainValue.andReturn(402513731000);
|
expect(column.getValue(undefined, mockDatum))
|
||||||
|
.toEqual({ text: TEST_DOMAIN_VALUE });
|
||||||
|
});
|
||||||
|
|
||||||
// Should have just given the value the formatter gave
|
it("uses formatter to format domain values as requested", function () {
|
||||||
expect(column.getValue(undefined, mockDataSet, 42).text)
|
column.getValue(undefined, mockDatum);
|
||||||
.toEqual(TEST_DOMAIN_VALUE);
|
|
||||||
|
|
||||||
// Make sure that service interactions were as expected
|
|
||||||
expect(mockFormatter.formatDomainValue)
|
expect(mockFormatter.formatDomainValue)
|
||||||
.toHaveBeenCalledWith(402513731000);
|
.toHaveBeenCalledWith("testKeyValue", "Test Format");
|
||||||
expect(mockFormatter.formatRangeValue)
|
});
|
||||||
.not.toHaveBeenCalled();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -472,6 +472,7 @@ define([
|
|||||||
"implementation": TimelineZoomController,
|
"implementation": TimelineZoomController,
|
||||||
"depends": [
|
"depends": [
|
||||||
"$scope",
|
"$scope",
|
||||||
|
"$window",
|
||||||
"TIMELINE_ZOOM_CONFIGURATION"
|
"TIMELINE_ZOOM_CONFIGURATION"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<div class="t-timeline-gantt l-timeline-gantt s-timeline-gantt"
|
<div class="t-timeline-gantt l-timeline-gantt s-timeline-gantt"
|
||||||
ng-class="{ sm: gantt.width(timespan, parameters.scroll, parameters.toPixels) < 25 }"
|
ng-class="timespan ? { sm: gantt.width(timespan, parameters.scroll, parameters.toPixels) < 25 } : {}"
|
||||||
title="{{model.name}}"
|
title="{{model.name}}"
|
||||||
ng-controller="TimelineGanttController as gantt"
|
ng-controller="TimelineGanttController as gantt"
|
||||||
ng-style="timespan ? {
|
ng-style="timespan ? {
|
||||||
|
@ -128,7 +128,7 @@
|
|||||||
<div style="overflow: hidden; position: absolute; left: 0; top: 0; right: 0; height: 30px;" mct-scroll-x="scroll.x">
|
<div style="overflow: hidden; position: absolute; left: 0; top: 0; right: 0; height: 30px;" mct-scroll-x="scroll.x">
|
||||||
<mct-include key="'timeline-ticks'"
|
<mct-include key="'timeline-ticks'"
|
||||||
parameters="{
|
parameters="{
|
||||||
fullWidth: timelineController.width(zoomController),
|
fullWidth: zoomController.width(timelineController.end()),
|
||||||
start: scroll.x,
|
start: scroll.x,
|
||||||
width: scroll.width,
|
width: scroll.width,
|
||||||
step: zoomController.toPixels(zoomController.zoom()),
|
step: zoomController.toPixels(zoomController.zoom()),
|
||||||
@ -141,7 +141,7 @@
|
|||||||
mct-scroll-x="scroll.x"
|
mct-scroll-x="scroll.x"
|
||||||
mct-scroll-y="scroll.y">
|
mct-scroll-y="scroll.y">
|
||||||
<div class="l-width-control"
|
<div class="l-width-control"
|
||||||
ng-style="{ width: timelineController.width(zoomController) + 'px' }">
|
ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
|
||||||
<div class="t-swimlane s-swimlane l-swimlane"
|
<div class="t-swimlane s-swimlane l-swimlane"
|
||||||
ng-repeat="swimlane in timelineController.swimlanes()"
|
ng-repeat="swimlane in timelineController.swimlanes()"
|
||||||
ng-class="{
|
ng-class="{
|
||||||
@ -197,7 +197,7 @@
|
|||||||
<div mct-scroll-x="scroll.x"
|
<div mct-scroll-x="scroll.x"
|
||||||
class="t-pane-r-scroll-h-control l-scroll-control s-scroll-control">
|
class="t-pane-r-scroll-h-control l-scroll-control s-scroll-control">
|
||||||
<div class="l-width-control"
|
<div class="l-width-control"
|
||||||
ng-style="{ width: timelineController.width(zoomController) + 'px' }">
|
ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -79,15 +79,6 @@ define(
|
|||||||
graphPopulator.populate(swimlanePopulator.get());
|
graphPopulator.populate(swimlanePopulator.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get pixel width for right pane, using zoom controller
|
|
||||||
function width(zoomController) {
|
|
||||||
var start = swimlanePopulator.start(),
|
|
||||||
end = swimlanePopulator.end();
|
|
||||||
return zoomController.toPixels(zoomController.duration(
|
|
||||||
Math.max(end - start, MINIMUM_DURATION)
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Refresh resource graphs
|
// Refresh resource graphs
|
||||||
function refresh() {
|
function refresh() {
|
||||||
if (graphPopulator) {
|
if (graphPopulator) {
|
||||||
@ -121,10 +112,10 @@ define(
|
|||||||
// Expose active set of swimlanes
|
// Expose active set of swimlanes
|
||||||
return {
|
return {
|
||||||
/**
|
/**
|
||||||
* Get the width, in pixels, of the timeline area
|
* Get the end of the displayed timeline, in milliseconds.
|
||||||
* @returns {number} width, in pixels
|
* @returns {number} the end of the displayed timeline
|
||||||
*/
|
*/
|
||||||
width: width,
|
end: swimlanePopulator.end.bind(swimlanePopulator),
|
||||||
/**
|
/**
|
||||||
* Get the swimlanes which should currently be displayed.
|
* Get the swimlanes which should currently be displayed.
|
||||||
* @returns {TimelineSwimlane[]} the swimlanes
|
* @returns {TimelineSwimlane[]} the swimlanes
|
||||||
|
@ -22,27 +22,17 @@
|
|||||||
define(
|
define(
|
||||||
[],
|
[],
|
||||||
function () {
|
function () {
|
||||||
|
var PADDING = 0.25;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls the pan-zoom state of a timeline view.
|
* Controls the pan-zoom state of a timeline view.
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function TimelineZoomController($scope, ZOOM_CONFIGURATION) {
|
function TimelineZoomController($scope, $window, ZOOM_CONFIGURATION) {
|
||||||
// Prefer to start with the middle index
|
// Prefer to start with the middle index
|
||||||
var zoomLevels = ZOOM_CONFIGURATION.levels || [1000],
|
var zoomLevels = ZOOM_CONFIGURATION.levels || [1000],
|
||||||
zoomIndex = Math.floor(zoomLevels.length / 2),
|
zoomIndex = Math.floor(zoomLevels.length / 2),
|
||||||
tickWidth = ZOOM_CONFIGURATION.width || 200,
|
tickWidth = ZOOM_CONFIGURATION.width || 200;
|
||||||
bounds = { x: 0, width: tickWidth },
|
|
||||||
duration = 86400000; // Default duration in view
|
|
||||||
|
|
||||||
// Round a duration to a larger value, to ensure space for editing
|
|
||||||
function roundDuration(value) {
|
|
||||||
// Ensure there's always an extra day or so
|
|
||||||
var tickCount = bounds.width / tickWidth,
|
|
||||||
sz = zoomLevels[zoomLevels.length - 1] * tickCount;
|
|
||||||
value *= 1.25; // Add 25% padding to start
|
|
||||||
return Math.ceil(value / sz) * sz;
|
|
||||||
}
|
|
||||||
|
|
||||||
function toMillis(pixels) {
|
function toMillis(pixels) {
|
||||||
return (pixels / tickWidth) * zoomLevels[zoomIndex];
|
return (pixels / tickWidth) * zoomLevels[zoomIndex];
|
||||||
@ -63,14 +53,21 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setScroll(x) {
|
||||||
|
$window.requestAnimationFrame(function () {
|
||||||
|
$scope.scroll.x = x;
|
||||||
|
$scope.$apply();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function initializeZoomFromTimespan(timespan) {
|
function initializeZoomFromTimespan(timespan) {
|
||||||
var timelineDuration = timespan.getDuration();
|
var timelineDuration = timespan.getDuration();
|
||||||
zoomIndex = 0;
|
zoomIndex = 0;
|
||||||
while (toMillis(bounds.width) < timelineDuration &&
|
while (toMillis($scope.scroll.width) < timelineDuration &&
|
||||||
zoomIndex < zoomLevels.length - 1) {
|
zoomIndex < zoomLevels.length - 1) {
|
||||||
zoomIndex += 1;
|
zoomIndex += 1;
|
||||||
}
|
}
|
||||||
bounds.x = toPixels(timespan.getStart());
|
setScroll(toPixels(timespan.getStart()));
|
||||||
}
|
}
|
||||||
|
|
||||||
function initializeZoom() {
|
function initializeZoom() {
|
||||||
@ -80,9 +77,6 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$scope.$watch("scroll", function (scroll) {
|
|
||||||
bounds = scroll;
|
|
||||||
});
|
|
||||||
$scope.$watch("domainObject", initializeZoom);
|
$scope.$watch("domainObject", initializeZoom);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -100,9 +94,10 @@ define(
|
|||||||
zoom: function (amount) {
|
zoom: function (amount) {
|
||||||
// Update the zoom level if called with an argument
|
// Update the zoom level if called with an argument
|
||||||
if (arguments.length > 0 && !isNaN(amount)) {
|
if (arguments.length > 0 && !isNaN(amount)) {
|
||||||
|
var bounds = $scope.scroll;
|
||||||
var center = this.toMillis(bounds.x + bounds.width / 2);
|
var center = this.toMillis(bounds.x + bounds.width / 2);
|
||||||
setZoomLevel(zoomIndex + amount);
|
setZoomLevel(zoomIndex + amount);
|
||||||
bounds.x = this.toPixels(center) - bounds.width / 2;
|
setScroll(this.toPixels(center) - bounds.width / 2);
|
||||||
}
|
}
|
||||||
return zoomLevels[zoomIndex];
|
return zoomLevels[zoomIndex];
|
||||||
},
|
},
|
||||||
@ -124,16 +119,14 @@ define(
|
|||||||
*/
|
*/
|
||||||
toMillis: toMillis,
|
toMillis: toMillis,
|
||||||
/**
|
/**
|
||||||
* Get or set the current displayed duration. If used as a
|
* Get the pixel width necessary to fit the specified
|
||||||
* setter, this will typically be rounded up to ensure extra
|
* timestamp, expressed as an offset in milliseconds from
|
||||||
* space is available at the right.
|
* the start of the timeline.
|
||||||
* @returns {number} duration, in milliseconds
|
* @param {number} timestamp the time to display
|
||||||
*/
|
*/
|
||||||
duration: function (value) {
|
width: function (timestamp) {
|
||||||
if (arguments.length > 0) {
|
var pixels = Math.ceil(toPixels(timestamp * (1 + PADDING)));
|
||||||
duration = roundDuration(value);
|
return Math.max($scope.scroll.width, pixels);
|
||||||
}
|
|
||||||
return duration;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -214,23 +214,6 @@ define(
|
|||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("reports full scrollable width using zoom controller", function () {
|
|
||||||
var mockZoom = jasmine.createSpyObj('zoom', ['toPixels', 'duration']);
|
|
||||||
mockZoom.toPixels.andReturn(54321);
|
|
||||||
mockZoom.duration.andReturn(12345);
|
|
||||||
|
|
||||||
// Initially populate
|
|
||||||
fireWatch('domainObject', mockDomainObject);
|
|
||||||
|
|
||||||
expect(controller.width(mockZoom)).toEqual(54321);
|
|
||||||
// Verify interactions; we took zoom's duration for our start/end,
|
|
||||||
// and converted it to pixels.
|
|
||||||
// First, check that we used the start/end (from above)
|
|
||||||
expect(mockZoom.duration).toHaveBeenCalledWith(12321 - 42);
|
|
||||||
// Next, verify that the result was passed to toPixels
|
|
||||||
expect(mockZoom.toPixels).toHaveBeenCalledWith(12345);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("provides drag handles", function () {
|
it("provides drag handles", function () {
|
||||||
// TimelineDragPopulator et al are tested for these,
|
// TimelineDragPopulator et al are tested for these,
|
||||||
// so just verify that handles are indeed exposed.
|
// so just verify that handles are indeed exposed.
|
||||||
|
@ -28,6 +28,7 @@ define(
|
|||||||
describe("The timeline zoom state controller", function () {
|
describe("The timeline zoom state controller", function () {
|
||||||
var testConfiguration,
|
var testConfiguration,
|
||||||
mockScope,
|
mockScope,
|
||||||
|
mockWindow,
|
||||||
controller;
|
controller;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
@ -35,10 +36,16 @@ define(
|
|||||||
levels: [1000, 2000, 3500],
|
levels: [1000, 2000, 3500],
|
||||||
width: 12321
|
width: 12321
|
||||||
};
|
};
|
||||||
mockScope = jasmine.createSpyObj("$scope", ['$watch']);
|
mockScope =
|
||||||
|
jasmine.createSpyObj("$scope", ['$watch', '$apply']);
|
||||||
mockScope.commit = jasmine.createSpy('commit');
|
mockScope.commit = jasmine.createSpy('commit');
|
||||||
|
mockScope.scroll = { x: 0, width: 1000 };
|
||||||
|
mockWindow = {
|
||||||
|
requestAnimationFrame: jasmine.createSpy('raf')
|
||||||
|
};
|
||||||
controller = new TimelineZoomController(
|
controller = new TimelineZoomController(
|
||||||
mockScope,
|
mockScope,
|
||||||
|
mockWindow,
|
||||||
testConfiguration
|
testConfiguration
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@ -47,12 +54,6 @@ define(
|
|||||||
expect(controller.zoom()).toEqual(2000);
|
expect(controller.zoom()).toEqual(2000);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("allows duration to be changed", function () {
|
|
||||||
var initial = controller.duration();
|
|
||||||
controller.duration(initial * 3.33);
|
|
||||||
expect(controller.duration() > initial).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("handles time-to-pixel conversions", function () {
|
it("handles time-to-pixel conversions", function () {
|
||||||
var zoomLevel = controller.zoom();
|
var zoomLevel = controller.zoom();
|
||||||
expect(controller.toPixels(zoomLevel)).toEqual(12321);
|
expect(controller.toPixels(zoomLevel)).toEqual(12321);
|
||||||
@ -70,11 +71,6 @@ define(
|
|||||||
expect(controller.zoom()).toEqual(3500);
|
expect(controller.zoom()).toEqual(3500);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("observes scroll bounds", function () {
|
|
||||||
expect(mockScope.$watch)
|
|
||||||
.toHaveBeenCalledWith("scroll", jasmine.any(Function));
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when watches have fired", function () {
|
describe("when watches have fired", function () {
|
||||||
var mockDomainObject,
|
var mockDomainObject,
|
||||||
mockPromise,
|
mockPromise,
|
||||||
@ -115,6 +111,10 @@ define(
|
|||||||
mockScope.$watch.calls.forEach(function (call) {
|
mockScope.$watch.calls.forEach(function (call) {
|
||||||
call.args[1](mockScope[call.args[0]]);
|
call.args[1](mockScope[call.args[0]]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mockWindow.requestAnimationFrame.calls.forEach(function (call) {
|
||||||
|
call.args[0]();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it("zooms to fit the timeline", function () {
|
it("zooms to fit the timeline", function () {
|
||||||
@ -125,6 +125,27 @@ define(
|
|||||||
expect(Math.round(controller.toMillis(x2)))
|
expect(Math.round(controller.toMillis(x2)))
|
||||||
.toBeGreaterThan(testEnd);
|
.toBeGreaterThan(testEnd);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("provides a width which is not less than scroll area width", function () {
|
||||||
|
var testPixel = mockScope.scroll.width / 4,
|
||||||
|
testMillis = controller.toMillis(testPixel);
|
||||||
|
expect(controller.width(testMillis))
|
||||||
|
.not.toBeLessThan(mockScope.scroll.width);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("provides a width with some margin past timestamp", function () {
|
||||||
|
var testPixel = mockScope.scroll.width * 4,
|
||||||
|
testMillis = controller.toMillis(testPixel);
|
||||||
|
expect(controller.width(testMillis))
|
||||||
|
.toBeGreaterThan(controller.toPixels(testMillis));
|
||||||
|
});
|
||||||
|
|
||||||
|
it("provides a width which does not greatly exceed timestamp", function () {
|
||||||
|
var testPixel = mockScope.scroll.width * 4,
|
||||||
|
testMillis = controller.toMillis(testPixel);
|
||||||
|
expect(controller.width(testMillis))
|
||||||
|
.toBeLessThan(controller.toPixels(testMillis * 2));
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -61,8 +61,7 @@ define(
|
|||||||
{
|
{
|
||||||
x: event.pageX - rect.left,
|
x: event.pageX - rect.left,
|
||||||
y: event.pageY - rect.top
|
y: event.pageY - rect.top
|
||||||
},
|
}
|
||||||
domainObject
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,8 +34,7 @@ define(
|
|||||||
TEST_ID = "test-id",
|
TEST_ID = "test-id",
|
||||||
DROP_ID = "drop-id";
|
DROP_ID = "drop-id";
|
||||||
|
|
||||||
//TODO: Disabled for NEM Beta
|
describe("The drop gesture", function () {
|
||||||
xdescribe("The drop gesture", function () {
|
|
||||||
var mockDndService,
|
var mockDndService,
|
||||||
mockQ,
|
mockQ,
|
||||||
mockElement,
|
mockElement,
|
||||||
@ -144,23 +143,6 @@ define(
|
|||||||
expect(mockCompose.perform).toHaveBeenCalled();
|
expect(mockCompose.perform).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it("does not invoke compose on drop in browse mode for non-folders", function () {
|
|
||||||
// Set the mockDomainObject to not have the editor capability
|
|
||||||
mockDomainObject.hasCapability.andReturn(false);
|
|
||||||
// Set the mockDomainObject to not have a type of folder
|
|
||||||
mockDomainObject.getModel.andReturn({type: 'notAFolder'});
|
|
||||||
|
|
||||||
callbacks.dragover(mockEvent);
|
|
||||||
expect(mockAction.getActions).toHaveBeenCalledWith({
|
|
||||||
key: 'compose',
|
|
||||||
selectedObject: mockDraggedObject
|
|
||||||
});
|
|
||||||
callbacks.drop(mockEvent);
|
|
||||||
expect(mockCompose.perform).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
it("invokes compose on drop in browse mode for folders", function () {
|
it("invokes compose on drop in browse mode for folders", function () {
|
||||||
// Set the mockDomainObject to not have the editor capability
|
// Set the mockDomainObject to not have the editor capability
|
||||||
mockDomainObject.hasCapability.andReturn(false);
|
mockDomainObject.hasCapability.andReturn(false);
|
||||||
|
@ -34,8 +34,8 @@ var EditItem = (function () {
|
|||||||
EditItem.prototype.EditButton = function () {
|
EditItem.prototype.EditButton = function () {
|
||||||
return element.all(by.css('[ng-click="parameters.action.perform()"]')).filter(function (arg) {
|
return element.all(by.css('[ng-click="parameters.action.perform()"]')).filter(function (arg) {
|
||||||
return arg.getAttribute("title").then(function (title){
|
return arg.getAttribute("title").then(function (title){
|
||||||
//expect(title).toEqual("Edit this object.");
|
//expect(title).toEqual("Edit");
|
||||||
return title == 'Edit this object.';
|
return title == 'Edit';
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user