mirror of
https://github.com/nasa/openmct.git
synced 2025-05-08 11:38:35 +00:00
[Edit] Introduce dropdown Save menu
And fix style issues in SaveAsActionSpec
This commit is contained in:
parent
31ee92b711
commit
d1f67fd8b9
@ -30,6 +30,7 @@ define([
|
|||||||
"./src/actions/EditAction",
|
"./src/actions/EditAction",
|
||||||
"./src/actions/PropertiesAction",
|
"./src/actions/PropertiesAction",
|
||||||
"./src/actions/RemoveAction",
|
"./src/actions/RemoveAction",
|
||||||
|
"./src/actions/SaveAction",
|
||||||
"./src/actions/SaveAndStopEditingAction",
|
"./src/actions/SaveAndStopEditingAction",
|
||||||
"./src/actions/SaveAsAction",
|
"./src/actions/SaveAsAction",
|
||||||
"./src/actions/CancelAction",
|
"./src/actions/CancelAction",
|
||||||
@ -69,6 +70,7 @@ define([
|
|||||||
EditAction,
|
EditAction,
|
||||||
PropertiesAction,
|
PropertiesAction,
|
||||||
RemoveAction,
|
RemoveAction,
|
||||||
|
SaveAction,
|
||||||
SaveAndStopEditingAction,
|
SaveAndStopEditingAction,
|
||||||
SaveAsAction,
|
SaveAsAction,
|
||||||
CancelAction,
|
CancelAction,
|
||||||
@ -203,20 +205,30 @@ define([
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "save",
|
"key": "save-and-stop-editing",
|
||||||
"category": "conclude-editing",
|
"category": "save",
|
||||||
"implementation": SaveAndStopEditingAction,
|
"implementation": SaveAndStopEditingAction,
|
||||||
"name": "Save",
|
"name": "Save and Done Editing",
|
||||||
"cssclass": "icon-save labeled",
|
"cssclass": "icon-save labeled",
|
||||||
"description": "Save changes made to these objects.",
|
"description": "Save changes made to these objects.",
|
||||||
"depends": [
|
"depends": [
|
||||||
"dialogService"
|
"dialogService"
|
||||||
],
|
]
|
||||||
"priority": "mandatory"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "save",
|
"key": "save",
|
||||||
"category": "conclude-editing",
|
"category": "save",
|
||||||
|
"implementation": SaveAction,
|
||||||
|
"name": "Save and Continue Editing",
|
||||||
|
"cssclass": "icon-save labeled",
|
||||||
|
"description": "Save changes made to these objects.",
|
||||||
|
"depends": [
|
||||||
|
"dialogService"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "save-as",
|
||||||
|
"category": "save",
|
||||||
"implementation": SaveAsAction,
|
"implementation": SaveAsAction,
|
||||||
"name": "Save As...",
|
"name": "Save As...",
|
||||||
"cssclass": "icon-save labeled",
|
"cssclass": "icon-save labeled",
|
||||||
|
@ -20,11 +20,30 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<span ng-controller="EditActionController">
|
<span ng-controller="EditActionController">
|
||||||
<span ng-repeat="currentAction in editActions">
|
<!-- If there's a single save action show a button, otherwise show a dropdown with all save actions. -->
|
||||||
|
<span ng-if="saveActions.length === 1">
|
||||||
|
<a class='s-button major {{saveActions[0].getMetadata().cssclass}}'
|
||||||
|
title='{{saveActions[0].getMetadata().name}}'
|
||||||
|
ng-click="saveActions[0].perform()">
|
||||||
|
<span class="title-label">{{saveActions[0].getMetadata().name}}</span>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span ng-if="saveActions.length > 1">
|
||||||
|
<mct-control key="'menu-button'"
|
||||||
|
structure="{
|
||||||
|
options: saveActionsAsMenuOptions,
|
||||||
|
click: saveActionMenuClickHandler,
|
||||||
|
cssclass: 'btn-bar right icon-save no-label major'
|
||||||
|
}">
|
||||||
|
</mct-control>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span ng-repeat="currentAction in otherEditActions">
|
||||||
<a class='s-button {{currentAction.getMetadata().cssclass}}'
|
<a class='s-button {{currentAction.getMetadata().cssclass}}'
|
||||||
title='{{currentAction.getMetadata().name}}'
|
title='{{currentAction.getMetadata().name}}'
|
||||||
ng-click="currentAction.perform()"
|
ng-click="currentAction.perform()"
|
||||||
ng-class="{ major: $index === 0 }">
|
ng-class="{ major: $index === 0 && saveActions.length === 0 }">
|
||||||
<span class="title-label">{{currentAction.getMetadata().name}}</span>
|
<span class="title-label">{{currentAction.getMetadata().name}}</span>
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
@ -27,7 +27,8 @@ define(
|
|||||||
[],
|
[],
|
||||||
function () {
|
function () {
|
||||||
|
|
||||||
var ACTION_CONTEXT = { category: 'conclude-editing' };
|
var SAVE_ACTION_CONTEXT = { category: 'save' };
|
||||||
|
var OTHERS_ACTION_CONTEXT = { category: 'conclude-editing' };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controller which supplies action instances for Save/Cancel.
|
* Controller which supplies action instances for Save/Cancel.
|
||||||
@ -35,11 +36,30 @@ define(
|
|||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function EditActionController($scope) {
|
function EditActionController($scope) {
|
||||||
// Maintain all "conclude-editing" actions in the present
|
|
||||||
// context.
|
function actionToMenuOption(action) {
|
||||||
|
return {
|
||||||
|
key: action,
|
||||||
|
name: action.getMetadata().name,
|
||||||
|
cssclass: action.getMetadata().cssclass
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Maintain all "conclude-editing" and "save" actions in the
|
||||||
|
// present context.
|
||||||
function updateActions() {
|
function updateActions() {
|
||||||
$scope.editActions = $scope.action ?
|
$scope.saveActions = $scope.action ?
|
||||||
$scope.action.getActions(ACTION_CONTEXT) :
|
$scope.action.getActions(SAVE_ACTION_CONTEXT) :
|
||||||
|
[];
|
||||||
|
|
||||||
|
$scope.saveActionsAsMenuOptions = $scope.saveActions.map(actionToMenuOption);
|
||||||
|
|
||||||
|
$scope.saveActionMenuClickHandler = function (clickedAction) {
|
||||||
|
clickedAction.perform();
|
||||||
|
};
|
||||||
|
|
||||||
|
$scope.otherEditActions = $scope.action ?
|
||||||
|
$scope.action.getActions(OTHERS_ACTION_CONTEXT) :
|
||||||
[];
|
[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,22 +19,54 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
/*global describe,it,expect,beforeEach,jasmine,spyOn*/
|
||||||
|
|
||||||
define(
|
define(
|
||||||
["../../src/controllers/EditActionController"],
|
["../../src/controllers/EditActionController"],
|
||||||
function (EditActionController) {
|
function (EditActionController) {
|
||||||
|
|
||||||
describe("The Edit Action controller", function () {
|
describe("The Edit Action controller", function () {
|
||||||
|
function FakeSaveAction() {
|
||||||
|
}
|
||||||
|
|
||||||
|
var fakeSaveActionMetadata = {
|
||||||
|
name: "mocked-save-action",
|
||||||
|
cssclass: "mocked-save-action-css"
|
||||||
|
};
|
||||||
|
|
||||||
|
FakeSaveAction.prototype.getMetadata = function () {
|
||||||
|
return fakeSaveActionMetadata;
|
||||||
|
};
|
||||||
|
|
||||||
|
FakeSaveAction.prototype.perform = function () {
|
||||||
|
};
|
||||||
|
|
||||||
|
function fakeGetActions(actionContext) {
|
||||||
|
if (actionContext.category === "save") {
|
||||||
|
return [new FakeSaveAction(), new FakeSaveAction()];
|
||||||
|
} else if (actionContext.category === "conclude-editing") {
|
||||||
|
return ["a", "b", "c"];
|
||||||
|
} else {
|
||||||
|
throw "EditActionController uses a context that's not covered by tests.";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var mockScope,
|
var mockScope,
|
||||||
mockActions,
|
mockActions,
|
||||||
controller;
|
controller;
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
mockActions = jasmine.createSpyObj("action", ["getActions"]);
|
||||||
|
mockActions.getActions.andCallFake(fakeGetActions);
|
||||||
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
|
||||||
|
mockScope.action = mockActions;
|
||||||
controller = new EditActionController(mockScope);
|
controller = new EditActionController(mockScope);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function makeControllerUpdateActions() {
|
||||||
|
mockScope.$watch.mostRecentCall.args[1]();
|
||||||
|
}
|
||||||
|
|
||||||
it("watches scope that may change applicable actions", function () {
|
it("watches scope that may change applicable actions", function () {
|
||||||
// The action capability
|
// The action capability
|
||||||
expect(mockScope.$watch).toHaveBeenCalledWith(
|
expect(mockScope.$watch).toHaveBeenCalledWith(
|
||||||
@ -43,16 +75,36 @@ define(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("populates the scope with grouped and ungrouped actions", function () {
|
it("populates the scope with 'save' actions", function () {
|
||||||
mockScope.action = mockActions;
|
makeControllerUpdateActions();
|
||||||
|
expect(mockScope.saveActions.length).toEqual(2);
|
||||||
|
});
|
||||||
|
|
||||||
mockActions.getActions.andReturn(["a", "b", "c"]);
|
it("converts 'save' actions to their menu counterparts", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
var menuOptions = mockScope.saveActionsAsMenuOptions;
|
||||||
|
|
||||||
// Call the watch
|
expect(menuOptions.length).toEqual(2);
|
||||||
mockScope.$watch.mostRecentCall.args[1]();
|
expect(menuOptions[0].key).toEqual(mockScope.saveActions[0]);
|
||||||
|
expect(menuOptions[1].key).toEqual(mockScope.saveActions[1]);
|
||||||
|
menuOptions.forEach(function (option) {
|
||||||
|
expect(option.name).toEqual(fakeSaveActionMetadata.name);
|
||||||
|
expect(option.cssclass).toEqual(fakeSaveActionMetadata.cssclass);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// Should have grouped and ungrouped actions in scope now
|
it("uses a click handler to perform the clicked action", function () {
|
||||||
expect(mockScope.editActions.length).toEqual(3);
|
makeControllerUpdateActions();
|
||||||
|
var sampleSaveAction = mockScope.saveActions[0];
|
||||||
|
|
||||||
|
spyOn(sampleSaveAction, "perform");
|
||||||
|
mockScope.saveActionMenuClickHandler(sampleSaveAction);
|
||||||
|
expect(sampleSaveAction.perform).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("populates the scope with other 'conclude-editing' actions", function () {
|
||||||
|
makeControllerUpdateActions();
|
||||||
|
expect(mockScope.otherEditActions).toEqual(["a", "b", "c"]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user