mirror of
https://github.com/nasa/openmct.git
synced 2025-06-18 15:18:12 +00:00
[Common UI] Initial commonUI bundles
Bring in work on general-purpose and over-arching user interface bundles from the sandbox transition branch. WTD-574.
This commit is contained in:
31
platform/commonUI/edit/src/EditActionController.js
Normal file
31
platform/commonUI/edit/src/EditActionController.js
Normal file
@ -0,0 +1,31 @@
|
||||
/*global define,Promise*/
|
||||
|
||||
/**
|
||||
* Module defining EditActionController. Created by vwoeltje on 11/17/14.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Controller which supplies action instances for Save/Cancel.
|
||||
* @constructor
|
||||
*/
|
||||
function EditActionController($scope) {
|
||||
function updateActions() {
|
||||
if (!$scope.action) {
|
||||
$scope.editActions = [];
|
||||
} else {
|
||||
$scope.editActions = $scope.action.getActions({
|
||||
category: 'conclude-editing'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$watch("action", updateActions);
|
||||
}
|
||||
|
||||
return EditActionController;
|
||||
}
|
||||
);
|
27
platform/commonUI/edit/src/EditController.js
Normal file
27
platform/commonUI/edit/src/EditController.js
Normal file
@ -0,0 +1,27 @@
|
||||
/*global define,Promise*/
|
||||
|
||||
/**
|
||||
* Module defining EditController. Created by vwoeltje on 11/14/14.
|
||||
*/
|
||||
define(
|
||||
["./objects/EditableDomainObject"],
|
||||
function (EditableDomainObject) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function EditController($scope, navigationService) {
|
||||
function setNavigation(domainObject) {
|
||||
$scope.navigatedObject =
|
||||
domainObject && new EditableDomainObject(domainObject);
|
||||
}
|
||||
|
||||
setNavigation(navigationService.getNavigation());
|
||||
navigationService.addListener(setNavigation);
|
||||
}
|
||||
|
||||
return EditController;
|
||||
}
|
||||
);
|
51
platform/commonUI/edit/src/actions/CancelAction.js
Normal file
51
platform/commonUI/edit/src/actions/CancelAction.js
Normal file
@ -0,0 +1,51 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* The "Save" action; the action triggered by clicking Save from
|
||||
* Edit Mode. Exits the editing user interface and invokes object
|
||||
* capabilities to persist the changes that have been made.
|
||||
*/
|
||||
define(
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
function CancelAction($location, context) {
|
||||
var domainObject = context.domainObject;
|
||||
|
||||
// Look up the object's "editor.completion" capability;
|
||||
// this is introduced by EditableDomainObject which is
|
||||
// used to insulate underlying objects from changes made
|
||||
// during editing.
|
||||
function getEditorCapability() {
|
||||
return domainObject.getCapability("editor");
|
||||
}
|
||||
|
||||
// Invoke any save behavior introduced by the editor.completion
|
||||
// capability.
|
||||
function doCancel(editor) {
|
||||
return editor.cancel();
|
||||
}
|
||||
|
||||
// Discard the current root view (which will be the editing
|
||||
// UI, which will have been pushed atop the Browise UI.)
|
||||
function returnToBrowse() {
|
||||
$location.path("/browse");
|
||||
}
|
||||
|
||||
return {
|
||||
perform: function () {
|
||||
return doCancel(getEditorCapability())
|
||||
.then(returnToBrowse);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
CancelAction.appliesTo = function (context) {
|
||||
var domainObject = (context || {}).domainObject;
|
||||
return domainObject !== undefined &&
|
||||
domainObject.hasCapability("editor");
|
||||
};
|
||||
|
||||
return CancelAction;
|
||||
}
|
||||
);
|
47
platform/commonUI/edit/src/actions/EditAction.js
Normal file
47
platform/commonUI/edit/src/actions/EditAction.js
Normal file
@ -0,0 +1,47 @@
|
||||
/*global define,Promise*/
|
||||
|
||||
/**
|
||||
* Module defining EditAction. Created by vwoeltje on 11/14/14.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
var NULL_ACTION = {
|
||||
perform: function () {
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function EditAction($location, navigationService, $log, context) {
|
||||
var domainObject = (context || {}).domainObject;
|
||||
|
||||
if (!domainObject) {
|
||||
$log.error([
|
||||
"No domain object to edit; ",
|
||||
"edit action is not valid."
|
||||
].join(""));
|
||||
|
||||
return NULL_ACTION;
|
||||
}
|
||||
|
||||
return {
|
||||
perform: function () {
|
||||
navigationService.setNavigation(domainObject);
|
||||
$location.path("/edit");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
EditAction.appliesTo = function (context) {
|
||||
return (context || {}).domainObject !== undefined;
|
||||
};
|
||||
|
||||
return EditAction;
|
||||
}
|
||||
);
|
90
platform/commonUI/edit/src/actions/RemoveAction.js
Normal file
90
platform/commonUI/edit/src/actions/RemoveAction.js
Normal file
@ -0,0 +1,90 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Module defining RemoveAction. Created by vwoeltje on 11/17/14.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Construct an action which will remove the provided object manifestation.
|
||||
* The object will be removed from its parent's composition; the parent
|
||||
* is looked up via the "context" capability (so this will be the
|
||||
* immediate ancestor by which this specific object was reached.)
|
||||
*
|
||||
* @param {DomainObject} object the object to be removed
|
||||
* @param {ActionContext} context the context in which this action is performed
|
||||
* @constructor
|
||||
* @memberof module:editor/actions/remove-action
|
||||
*/
|
||||
function RemoveAction($q, context) {
|
||||
var object = (context || {}).domainObject;
|
||||
|
||||
/**
|
||||
* Check whether an object ID matches the ID of the object being
|
||||
* removed (used to filter a parent's composition to handle the
|
||||
* removal.)
|
||||
*/
|
||||
function isNotObject(otherObjectId) {
|
||||
return otherObjectId !== object.getId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutate a parent object such that it no longer contains the object
|
||||
* which is being removed.
|
||||
*/
|
||||
function doMutate(model) {
|
||||
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(domainObject) {
|
||||
var persistence = domainObject.getCapability('persistence');
|
||||
return persistence && persistence.persist();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the object from its parent, as identified by its context
|
||||
* capability.
|
||||
* @param {ContextCapability} contextCapability the "context" capability
|
||||
* of the domain object being removed.
|
||||
*/
|
||||
function removeFromContext(contextCapability) {
|
||||
var parent = contextCapability.getParent();
|
||||
$q.when(
|
||||
parent.useCapability('mutation', doMutate)
|
||||
).then(function () {
|
||||
return doPersist(parent);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Perform this action.
|
||||
* @return {module:core/promises.Promise} a promise which will be
|
||||
* fulfilled when the action has completed.
|
||||
*/
|
||||
perform: function () {
|
||||
return $q.when(object.getCapability('context'))
|
||||
.then(removeFromContext);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Object needs to have a parent for Remove to be applicable
|
||||
/*RemoveAction.appliesTo = function (context) {
|
||||
var object = context.domainObject,
|
||||
contextCapability = object && object.getCapability("context"),
|
||||
parent = contextCapability && contextCapability.getParent();
|
||||
return parent !== undefined &&
|
||||
Array.isArray(parent.getModel().composition);
|
||||
};*/
|
||||
|
||||
return RemoveAction;
|
||||
}
|
||||
);
|
50
platform/commonUI/edit/src/actions/SaveAction.js
Normal file
50
platform/commonUI/edit/src/actions/SaveAction.js
Normal file
@ -0,0 +1,50 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* The "Save" action; the action triggered by clicking Save from
|
||||
* Edit Mode. Exits the editing user interface and invokes object
|
||||
* capabilities to persist the changes that have been made.
|
||||
*/
|
||||
define(
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
function SaveAction($location, context) {
|
||||
var domainObject = context.domainObject;
|
||||
|
||||
// Look up the object's "editor.completion" capability;
|
||||
// this is introduced by EditableDomainObject which is
|
||||
// used to insulate underlying objects from changes made
|
||||
// during editing.
|
||||
function getEditorCapability() {
|
||||
return domainObject.getCapability("editor");
|
||||
}
|
||||
|
||||
// Invoke any save behavior introduced by the editor.completion
|
||||
// capability.
|
||||
function doSave(editor) {
|
||||
return editor.save();
|
||||
}
|
||||
|
||||
// Discard the current root view (which will be the editing
|
||||
// UI, which will have been pushed atop the Browise UI.)
|
||||
function returnToBrowse() {
|
||||
$location.path("/browse");
|
||||
}
|
||||
|
||||
return {
|
||||
perform: function () {
|
||||
return doSave(getEditorCapability()).then(returnToBrowse);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
SaveAction.appliesTo = function (context) {
|
||||
var domainObject = (context || {}).domainObject;
|
||||
return domainObject !== undefined &&
|
||||
domainObject.hasCapability("editor");
|
||||
};
|
||||
|
||||
return SaveAction;
|
||||
}
|
||||
);
|
@ -0,0 +1,56 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Wrapper for both "context" and "composition" capabilities;
|
||||
* ensures that any domain objects reachable in Edit mode
|
||||
* are also wrapped as EditableDomainObjects
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
return function EditableContextCapability(
|
||||
contextCapability,
|
||||
editableObject,
|
||||
domainObject,
|
||||
factory
|
||||
) {
|
||||
var capability = Object.create(contextCapability);
|
||||
|
||||
function isDomainObject(obj) {
|
||||
return typeof obj.getId === 'function' &&
|
||||
typeof obj.getModel === 'function' &&
|
||||
typeof obj.getCapability === 'function';
|
||||
}
|
||||
|
||||
function makeEditableObject(obj) {
|
||||
return isDomainObject(obj) ?
|
||||
factory.getEditableObject(obj) :
|
||||
obj;
|
||||
}
|
||||
|
||||
function makeEditable(obj) {
|
||||
return Array.isArray(obj) ?
|
||||
obj.map(makeEditableObject) :
|
||||
makeEditableObject(obj);
|
||||
}
|
||||
|
||||
// Replace all methods; return only editable domain objects.
|
||||
Object.keys(contextCapability).forEach(function (k) {
|
||||
capability[k] = function () {
|
||||
var result = contextCapability[k].apply(
|
||||
capability,
|
||||
arguments
|
||||
);
|
||||
|
||||
return result.then ? // promise-like
|
||||
result.then(makeEditable) :
|
||||
makeEditable(result);
|
||||
};
|
||||
});
|
||||
|
||||
return capability;
|
||||
};
|
||||
}
|
||||
);
|
@ -0,0 +1,30 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Editable Persistence Capability. Overrides the persistence capability
|
||||
* normally exhibited by a domain object to ensure that changes made
|
||||
* during edit mode are not immediately stored to the database or other
|
||||
* backing storage.
|
||||
*/
|
||||
define(
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
return function EditablePersistenceCapability(
|
||||
persistenceCapability,
|
||||
editableObject,
|
||||
domainObject,
|
||||
cache
|
||||
) {
|
||||
var persistence = Object.create(persistenceCapability);
|
||||
|
||||
// Simply trigger refresh of in-view objects; do not
|
||||
// write anything to database.
|
||||
persistence.persist = function () {
|
||||
cache.markDirty(editableObject);
|
||||
};
|
||||
|
||||
return persistence;
|
||||
};
|
||||
}
|
||||
);
|
55
platform/commonUI/edit/src/capabilities/EditorCapability.js
Normal file
55
platform/commonUI/edit/src/capabilities/EditorCapability.js
Normal file
@ -0,0 +1,55 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Implements "save" and "cancel" as capabilities of
|
||||
* the object. In editing mode, user is seeing/using
|
||||
* a copy of the object (an EditableDomainObject)
|
||||
* which is disconnected from persistence; the Save
|
||||
* and Cancel actions can use this capability to
|
||||
* propagate changes from edit mode to the underlying
|
||||
* actual persistable object.
|
||||
*/
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
return function EditorCapability(
|
||||
persistenceCapability,
|
||||
editableObject,
|
||||
domainObject,
|
||||
cache
|
||||
) {
|
||||
|
||||
function doMutate() {
|
||||
return domainObject.useCapability('mutation', function () {
|
||||
return editableObject.getModel();
|
||||
});
|
||||
}
|
||||
|
||||
function doPersist() {
|
||||
return persistenceCapability.persist();
|
||||
}
|
||||
|
||||
function saveOthers() {
|
||||
return cache.saveAll();
|
||||
}
|
||||
|
||||
function markClean() {
|
||||
return cache.markClean(editableObject);
|
||||
}
|
||||
|
||||
return {
|
||||
save: function () {
|
||||
return Promise.resolve(doMutate())
|
||||
.then(doPersist)
|
||||
.then(markClean)
|
||||
.then(saveOthers);
|
||||
},
|
||||
cancel: function () {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
84
platform/commonUI/edit/src/objects/EditableDomainObject.js
Normal file
84
platform/commonUI/edit/src/objects/EditableDomainObject.js
Normal file
@ -0,0 +1,84 @@
|
||||
/*global define*/
|
||||
|
||||
/**
|
||||
* Defines EditableDomainObject, which wraps domain objects
|
||||
* such that user code may work with and mutate a copy of the
|
||||
* domain object model; these changes may then be propagated
|
||||
* up to the real domain object (or not) by way of invoking
|
||||
* save or cancel behaviors of the "editor.completion"
|
||||
* capability (a capability intended as internal to edit
|
||||
* mode; invoked by way of the Save and Cancel actions.)
|
||||
*/
|
||||
define(
|
||||
[
|
||||
'../capabilities/EditablePersistenceCapability',
|
||||
'../capabilities/EditableContextCapability',
|
||||
'../capabilities/EditorCapability',
|
||||
'./EditableDomainObjectCache'
|
||||
],
|
||||
function (
|
||||
EditablePersistenceCapability,
|
||||
EditableContextCapability,
|
||||
EditorCapability,
|
||||
EditableDomainObjectCache
|
||||
) {
|
||||
"use strict";
|
||||
|
||||
var capabilityFactories = {
|
||||
persistence: EditablePersistenceCapability,
|
||||
context: EditableContextCapability,
|
||||
composition: EditableContextCapability,
|
||||
editor: EditorCapability
|
||||
};
|
||||
|
||||
// Handle special case where "editor.completion" wraps persistence
|
||||
// (other capability overrides wrap capabilities of the same type.)
|
||||
function getDelegateArguments(name, args) {
|
||||
return name === "editor" ? ['persistence'] : args;
|
||||
}
|
||||
|
||||
/**
|
||||
* An EditableDomainObject overrides capabilities
|
||||
* which need to behave differently in edit mode,
|
||||
* and provides a "working copy" of the object's
|
||||
* model to allow changes to be easily cancelled.
|
||||
*/
|
||||
function EditableDomainObject(domainObject) {
|
||||
// The cache will hold all domain objects reached from
|
||||
// the initial EditableDomainObject; this ensures that
|
||||
// different versions of the same editable domain object
|
||||
// are not shown in different sections of the same Edit
|
||||
// UI, which might thereby fall out of sync.
|
||||
var cache;
|
||||
|
||||
// Constructor for EditableDomainObject, which adheres
|
||||
// to the same shared cache.
|
||||
function EditableDomainObjectImpl(domainObject) {
|
||||
var model = JSON.parse(JSON.stringify(domainObject.getModel())),
|
||||
editableObject = Object.create(domainObject);
|
||||
|
||||
// Only provide the cloned model.
|
||||
editableObject.getModel = function () { return model; };
|
||||
|
||||
// Override certain capabilities
|
||||
editableObject.getCapability = function (name) {
|
||||
var delegateArguments = getDelegateArguments(name, arguments),
|
||||
capability = domainObject.getCapability.apply(this, delegateArguments),
|
||||
factory = capabilityFactories[name];
|
||||
|
||||
return (factory && capability) ?
|
||||
factory(capability, editableObject, domainObject, cache) :
|
||||
capability;
|
||||
};
|
||||
|
||||
return editableObject;
|
||||
}
|
||||
|
||||
cache = new EditableDomainObjectCache(EditableDomainObjectImpl);
|
||||
|
||||
return cache.getEditableObject(domainObject);
|
||||
}
|
||||
|
||||
return EditableDomainObject;
|
||||
}
|
||||
);
|
102
platform/commonUI/edit/src/objects/EditableDomainObjectCache.js
Normal file
102
platform/commonUI/edit/src/objects/EditableDomainObjectCache.js
Normal file
@ -0,0 +1,102 @@
|
||||
/*global define*/
|
||||
|
||||
|
||||
/**
|
||||
* An editable domain object cache stores domain objects that have been
|
||||
* made editable, in a group that can be saved all-at-once. This supports
|
||||
* Edit mode, which is launched for a specific object but may contain
|
||||
* changes across many objects.
|
||||
*
|
||||
* Editable domain objects have certain specific capabilities overridden
|
||||
* to ensure that changes made while in edit mode do not propagate up
|
||||
* to the objects used in browse mode (or to persistence) until the user
|
||||
* initiates a Save.
|
||||
*
|
||||
* @module editor/object/editable-domain-object-cache
|
||||
*/
|
||||
define(
|
||||
function () {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Construct a new cache for editable domain objects. This can be used
|
||||
* to get-or-create editable objects, particularly to support wrapping
|
||||
* of objects retrieved via composition or context capabilities as
|
||||
* editable domain objects.
|
||||
*
|
||||
* @param {Constructor<EditableDomainObject>} EditableDomainObject a
|
||||
* constructor function which takes a regular domain object as
|
||||
* an argument, and returns an editable domain object as its
|
||||
* result.
|
||||
* @constructor
|
||||
* @memberof module:editor/object/editable-domain-object-cache
|
||||
*/
|
||||
function EditableDomainObjectCache(EditableDomainObject) {
|
||||
var cache = {},
|
||||
dirty = {};
|
||||
|
||||
return {
|
||||
/**
|
||||
* Wrap this domain object in an editable form, or pull such
|
||||
* an object from the cache if one already exists.
|
||||
*
|
||||
* @param {DomainObject} domainObject the regular domain object
|
||||
* @returns {DomainObject} the domain object in an editable form
|
||||
*/
|
||||
getEditableObject: function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (cache[id] =
|
||||
cache[id] || new EditableDomainObject(domainObject));
|
||||
},
|
||||
/**
|
||||
* Mark an editable domain object (presumably already cached)
|
||||
* as having received modifications during editing; it should be
|
||||
* included in the bulk save invoked when editing completes.
|
||||
*
|
||||
* @param {DomainObject} domainObject the domain object
|
||||
*/
|
||||
markDirty: function (domainObject) {
|
||||
dirty[domainObject.getId()] = domainObject;
|
||||
},
|
||||
/**
|
||||
* Mark an object (presumably already cached) as having had its
|
||||
* changes saved (and thus no longer needing to be subject to a
|
||||
* save operation.)
|
||||
*
|
||||
* @param {DomainObject} domainObject the domain object
|
||||
*/
|
||||
markClean: function (domainObject) {
|
||||
delete dirty[domainObject.getId()];
|
||||
},
|
||||
/**
|
||||
* Initiate a save on all objects that have been cached.
|
||||
*/
|
||||
saveAll: function () {
|
||||
var object;
|
||||
|
||||
// Most save logic is handled by the "editor.completion"
|
||||
// capability, but this in turn will typically invoke
|
||||
// Save All. An infinite loop is avoided by marking
|
||||
// objects as clean as we go.
|
||||
|
||||
function doSave(editCapability) {
|
||||
return editCapability.save();
|
||||
}
|
||||
|
||||
while (Object.keys(dirty).length > 0) {
|
||||
// Pick the first dirty object
|
||||
object = dirty[Object.keys(dirty)[0]];
|
||||
|
||||
// Mark non-dirty to avoid successive invocations
|
||||
this.markClean(object);
|
||||
|
||||
// Invoke its save behavior
|
||||
object.getCapability('editor.completion').then(doSave);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return EditableDomainObjectCache;
|
||||
}
|
||||
);
|
Reference in New Issue
Block a user