[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:
Victor Woeltjen
2014-11-23 15:41:20 -08:00
parent 0cd331e8a5
commit 1b0303e517
73 changed files with 6035 additions and 0 deletions

View File

@ -0,0 +1,53 @@
/*global define,Promise*/
/**
* Module defining BrowseController. Created by vwoeltje on 11/7/14.
*/
define(
[],
function () {
"use strict";
var ROOT_OBJECT = "ROOT";
/**
*
* @constructor
*/
function BrowseController($scope, objectService, navigationService) {
function setNavigation(domainObject) {
$scope.navigatedObject = domainObject;
//$scope.$apply("navigatedObject");
}
objectService.getObjects([ROOT_OBJECT]).then(function (objects) {
var composition = objects[ROOT_OBJECT].useCapability("composition");
$scope.domainObject = objects[ROOT_OBJECT];
if (composition) {
composition.then(function (c) {
// Navigate to the last root level component (usually "mine")
if (!navigationService.getNavigation()) {
navigationService.setNavigation(c[c.length - 1]);
} else {
$scope.navigatedObject = navigationService.getNavigation();
}
});
}
});
$scope.$on("$destroy", function () {
navigationService.removeListener(setNavigation);
});
navigationService.addListener(setNavigation);
return {
setNavigation: function (domainObject) {
navigationService.setNavigation(domainObject);
}
};
}
return BrowseController;
}
);

View File

@ -0,0 +1,48 @@
/*global define,Promise*/
/**
* Module defining ViewSwitcherController. Created by vwoeltje on 11/7/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function ViewSwitcherController($scope) {
// If the view capability gets refreshed, try to
// keep the same option chosen.
function findMatchingOption(options, selected) {
var i;
if (selected) {
for (i = 0; i < options.length; i += 1) {
if (options[i].key === selected.key) {
return options[i];
}
}
}
return options[0];
}
// Get list of views, read from capability
$scope.$watch("view", function () {
var options = $scope.view || [ {} ];
$scope.switcher = {
options: options,
selected: findMatchingOption(
options,
($scope.switcher || {}).selected
)
};
});
}
return ViewSwitcherController;
}
);

View File

@ -0,0 +1,67 @@
/*global define,Promise*/
/**
* Module defining CreateAction. Created by vwoeltje on 11/10/14.
*/
define(
['./CreateWizard'],
function (CreateWizard) {
"use strict";
/**
*
* @constructor
*/
function CreateAction(type, parent, context, dialogService, creationService) {
/*
1. Show dialog
a. Prepare dialog contents
b. Invoke dialogService
2. Create new object in persistence service
a. Generate UUID
b. Store model
3. Mutate destination container
a. Get mutation capability
b. Add new id to composition
4. Persist destination container
a. ...use persistence capability.
*/
function perform() {
var wizard = new CreateWizard(type, parent);
function persistResult(formValue) {
var parent = wizard.getLocation(formValue),
newModel = wizard.createModel(formValue);
return creationService.createObject(newModel, parent);
}
function doNothing() {
// Create cancelled, do nothing
return false;
}
return dialogService.getUserInput(
wizard.getFormModel()
).then(persistResult, doNothing);
}
return {
perform: perform,
getMetadata: function () {
return {
key: 'create',
glyph: type.getGlyph(),
name: type.getName(),
description: type.getDescription(),
context: context
};
}
};
}
return CreateAction;
}
);

View File

@ -0,0 +1,41 @@
/*global define,Promise*/
/**
* Module defining CreateActionProvider.js. Created by vwoeltje on 11/10/14.
*/
define(
["./CreateAction"],
function (CreateAction) {
"use strict";
/**
*
* @constructor
*/
function CreateActionProvider(typeService, dialogService, creationService) {
return {
getActions: function (actionContext) {
var context = actionContext || {},
key = context.key,
destination = context.domainObject;
if (key !== 'create' || !destination) {
return [];
}
return typeService.listTypes().map(function (type) {
return new CreateAction(
type,
destination,
context,
dialogService,
creationService
);
});
}
};
}
return CreateActionProvider;
}
);

View File

@ -0,0 +1,36 @@
/*global define,Promise*/
/**
* Module defining CreateController. Created by vwoeltje on 11/10/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function CreateButtonController($scope, $document) {
function collapse() {
$scope.createState.visible = false;
$scope.$apply("createState.visible");
$document.off("mouseup", collapse);
return false;
}
$scope.createState = { visible: false };
$scope.toggle = function () {
$scope.createState.visible = !$scope.createState.visible;
if ($scope.createState.visible) {
$document.on("mouseup", collapse);
}
};
}
return CreateButtonController;
}
);

View File

@ -0,0 +1,29 @@
/*global define,Promise*/
/**
* Module defining CreateMenuController. Created by vwoeltje on 11/10/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function CreateMenuController($scope) {
function refreshActions() {
var actionCapability = $scope.action;
if (actionCapability) {
$scope.createActions =
actionCapability.getActions('create');
}
}
$scope.$watch("action", refreshActions);
}
return CreateMenuController;
}
);

View File

@ -0,0 +1,79 @@
/*global define*/
/**
* Defines the CreateWizard, used by the CreateAction to
* populate the form shown in dialog based on the created type.
*
* @module core/action/create-wizard
*/
define(
function () {
'use strict';
/**
* Construct a new CreateWizard.
*
* @param {TypeImpl} type the type of domain object to be created
* @param {DomainObject} parent the domain object to serve as
* the initial parent for the created object, in the dialog
* @constructor
* @memberof module:core/action/create-wizard
*/
function CreateWizard(type, parent) {
var model = type.getInitialModel(),
properties = type.getProperties();
return {
getFormModel: function () {
var parentRow = Object.create(parent),
sections = [];
sections.push({
name: "Properties",
rows: properties.map(function (property) {
// Property definition is same as form row definition
var row = Object.create(property.getDefinition());
// But pull an initial value from the model
row.value = property.getValue(model);
return row;
})
});
// Ensure there is always a "save in" section
parentRow.name = "Save In";
parentRow.cssclass = "selector-list";
parentRow.control = "_locator";
parentRow.key = "createParent";
sections.push({ label: 'Location', rows: [parentRow]});
return {
sections: sections,
name: "Create a New " + type.getName()
};
},
getLocation: function (formValue) {
return formValue.createParent || parent;
},
createModel: function (formValue) {
// Clone
var newModel = JSON.parse(JSON.stringify(model));
// Always use the type from the type definition
newModel.type = type.getKey();
// Update all properties
properties.forEach(function (property) {
var value = formValue[property.getDefinition().key];
property.setValue(newModel, value);
});
return newModel;
}
};
}
return CreateWizard;
}
);

View File

@ -0,0 +1,90 @@
/*global define,Promise*/
/**
* Module defining CreateService. Created by vwoeltje on 11/10/14.
*/
define(
[],
function () {
"use strict";
var NON_PERSISTENT_WARNING =
"Tried to create an object in non-persistent container.",
NO_COMPOSITION_WARNING =
"Could not add to composition; no composition in ";
/**
*
* @constructor
*/
function CreationService(persistenceService, uuidService, $q, $log) {
function doPersist(space, id, model) {
return persistenceService.createObject(
space,
id,
model
).then(function () { return id; });
}
function addToComposition(id, parent) {
var mutatationResult = parent.useCapability("mutation", function (model) {
if (Array.isArray(model.composition)) {
if (model.composition.indexOf(id) === -1) {
model.composition.push(id);
}
} else {
$log.warn(NO_COMPOSITION_WARNING + parent.getId());
}
});
return $q.when(mutatationResult).then(function (result) {
var persistence = parent.getCapability("persistence");
if (!result) {
$log.error("Could not mutate " + parent.getId());
}
if (!persistence) {
$log.error([
"Expected to be able to persist ",
parent.getId(),
" but could not."
].join(""));
return undefined;
}
return persistence.persist();
});
}
function createObject(model, parent) {
var persistence = parent.getCapability("persistence"),
result = $q.defer(),
space;
if (persistence) {
space = persistence.getSpace();
return $q.when(
uuidService.getUUID()
).then(function (id) {
return doPersist(space, id, model);
}).then(function (id) {
return addToComposition(id, parent);
});
} else {
$log.warn(NON_PERSISTENT_WARNING);
$q.reject(new Error(NON_PERSISTENT_WARNING));
}
return result.promise;
}
return {
createObject: createObject
};
}
return CreationService;
}
);

View File

@ -0,0 +1,29 @@
/*global define,Promise*/
/**
* Module defining UUIDService. Created by vwoeltje on 11/12/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function UUIDService() {
var counter = Date.now();
return {
getUUID: function () {
counter += 1;
return counter.toString(36);
}
};
}
return UUIDService;
}
);

View File

@ -0,0 +1,35 @@
/*global define,Promise*/
/**
* Module defining NavigateAction. Created by vwoeltje on 11/10/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function NavigateAction(navigationService, context) {
var domainObject = context.domainObject;
function perform() {
return Promise.resolve(
navigationService.setNavigation(domainObject)
);
}
return {
perform: perform
};
}
NavigateAction.appliesTo = function (context) {
return context.domainObject !== undefined;
};
return NavigateAction;
}
);

View File

@ -0,0 +1,50 @@
/*global define,Promise*/
/**
* Module defining NavigationService. Created by vwoeltje on 11/10/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function NavigationService() {
var navigated,
callbacks = [];
function getNavigation() {
return navigated;
}
function setNavigation(value) {
navigated = value;
callbacks.forEach(function (callback) {
callback(value);
});
}
function addListener(callback) {
callbacks.push(callback);
}
function removeListener(callback) {
callbacks = callbacks.filter(function (cb) {
return cb !== callback;
});
}
return {
getNavigation: getNavigation,
setNavigation: setNavigation,
addListener: addListener,
removeListener: removeListener
};
}
return NavigationService;
}
);

View File

@ -0,0 +1,41 @@
/*global define,screenfull,Promise*/
/**
* Module defining FullscreenAction. Created by vwoeltje on 11/18/14.
*/
define(
["../../lib/screenfull.min"],
function () {
"use strict";
var ENTER_FULLSCREEN = "Enter full screen mode.",
EXIT_FULLSCREEN = "Exit full screen mode.";
/**
*
* @constructor
*/
function FullscreenAction(context) {
return {
perform: function () {
screenfull.toggle();
},
getMetadata: function () {
// We override getMetadata, because the glyph and
// description need to be determined at run-time
// based on whether or not we are currently
// full screen.
var metadata = Object.create(FullscreenAction);
metadata.glyph = screenfull.isFullscreen ? "_" : "z";
metadata.description = screenfull.isFullscreen ?
EXIT_FULLSCREEN : ENTER_FULLSCREEN;
metadata.group = "windowing";
metadata.context = context;
return metadata;
}
};
}
return FullscreenAction;
}
);

View File

@ -0,0 +1,25 @@
/*global define,Promise*/
/**
* Module defining NewWindowAction. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
"use strict";
/**
*
* @constructor
*/
function NewWindowAction($window) {
return {
perform: function () {
$window.alert("Not yet functional. This will open objects in a new window.");
}
};
}
return NewWindowAction;
}
);