Merge pull request #1029 from nasa/api-toolbar-add-only

[API Prototype] Add toolbar
This commit is contained in:
Victor Woeltjen 2016-07-01 10:13:29 -07:00 committed by GitHub
commit 06f87c1472
8 changed files with 235 additions and 33 deletions

View File

@ -3,12 +3,16 @@ define([
'legacyRegistry', 'legacyRegistry',
'uuid', 'uuid',
'./api/api', './api/api',
'text!./adapter/templates/edit-object-replacement.html',
'./ui/Dialog',
'./api/objects/bundle' './api/objects/bundle'
], function ( ], function (
EventEmitter, EventEmitter,
legacyRegistry, legacyRegistry,
uuid, uuid,
api api,
editObjectTemplate,
Dialog
) { ) {
function MCT() { function MCT() {
EventEmitter.call(this); EventEmitter.call(this);
@ -22,25 +26,34 @@ define([
}); });
MCT.prototype.MCT = MCT; MCT.prototype.MCT = MCT;
MCT.prototype.legacyExtension = function (category, extension) {
this.legacyBundle.extensions[category] =
this.legacyBundle.extensions[category] || [];
this.legacyBundle.extensions[category].push(extension);
};
MCT.prototype.view = function (region, factory) { MCT.prototype.view = function (region, factory) {
var viewKey = region + uuid(); var viewKey = region + uuid();
var adaptedViewKey = "adapted-view-" + viewKey; var adaptedViewKey = "adapted-view-" + region;
this.legacyBundle.extensions.views = this.legacyExtension(
this.legacyBundle.extensions.views || []; region === this.regions.main ? 'views' : 'representations',
this.legacyBundle.extensions.views.push({ {
name: "A view", name: "A view",
key: adaptedViewKey, key: adaptedViewKey,
template: '<mct-view key="\'' + editable: true,
template: '<mct-view region="\'' +
region +
'\'" ' +
'key="\'' +
viewKey + viewKey +
'\'" ' + '\'" ' +
'mct-object="domainObject">' + 'mct-object="domainObject">' +
'</mct-view>' '</mct-view>'
}); }
);
this.legacyBundle.extensions.policies = this.legacyExtension('policies', {
this.legacyBundle.extensions.policies || [];
this.legacyBundle.extensions.policies.push({
category: "view", category: "view",
implementation: function Policy() { implementation: function Policy() {
this.allow = function (view, domainObject) { this.allow = function (view, domainObject) {
@ -52,10 +65,9 @@ define([
} }
}); });
this.legacyBundle.extensions.newViews = this.legacyExtension('newViews', {
this.legacyBundle.extensions.newViews || [];
this.legacyBundle.extensions.newViews.push({
factory: factory, factory: factory,
region: region,
key: viewKey key: viewKey
}); });
}; };
@ -63,11 +75,19 @@ define([
MCT.prototype.type = function (key, type) { MCT.prototype.type = function (key, type) {
var legacyDef = type.toLegacyDefinition(); var legacyDef = type.toLegacyDefinition();
legacyDef.key = key; legacyDef.key = key;
this.legacyBundle.extensions.types =
this.legacyBundle.extensions.types || [];
this.legacyBundle.extensions.types.push(legacyDef);
type.key = key; type.key = key;
this.legacyExtension('types', legacyDef);
this.legacyExtension('representations', {
key: "edit-object",
priority: "preferred",
template: editObjectTemplate,
type: key
});
};
MCT.prototype.dialog = function (view, title) {
return new Dialog(view, title).show();
}; };
MCT.prototype.start = function () { MCT.prototype.start = function () {
@ -76,7 +96,8 @@ define([
}; };
MCT.prototype.regions = { MCT.prototype.regions = {
main: "MAIN" main: "MAIN",
toolbar: "TOOLBAR"
}; };
MCT.prototype.verbs = { MCT.prototype.verbs = {
@ -86,6 +107,10 @@ define([
var persistence = domainObject.getCapability('persistence'); var persistence = domainObject.getCapability('persistence');
return persistence.persist(); return persistence.persist();
}); });
},
observe: function (domainObject, callback) {
var mutation = domainObject.getCapability('mutation');
return mutation.listen(callback);
} }
}; };

View File

@ -3,24 +3,21 @@ define(['angular'], function (angular) {
var factories = {}; var factories = {};
newViews.forEach(function (newView) { newViews.forEach(function (newView) {
factories[newView.key] = newView.factory; factories[newView.region] = factories[newView.region] || {};
factories[newView.region][newView.key] = newView.factory;
}); });
return { return {
restrict: 'E', restrict: 'E',
link: function (scope, element, attrs) { link: function (scope, element, attrs) {
var key = undefined; var key, mctObject, region;
var mctObject = undefined;
function maybeShow() { function maybeShow() {
if (!factories[key]) { if (!factories[region] || !factories[region][key] || !mctObject) {
return;
}
if (!mctObject) {
return; return;
} }
var view = factories[key](mctObject); var view = factories[region][key](mctObject);
view.show(element[0]); view.show(element[0]);
} }
@ -34,12 +31,19 @@ define(['angular'], function (angular) {
maybeShow(); maybeShow();
} }
function setRegion(r) {
region = r;
maybeShow();
}
scope.$watch('key', setKey); scope.$watch('key', setKey);
scope.$watch('region', setRegion);
scope.$watch('mctObject', setObject); scope.$watch('mctObject', setObject);
}, },
scope: { scope: {
key: "=", key: "=",
region: "=",
mctObject: "=" mctObject: "="
} }
}; };

View File

@ -0,0 +1,46 @@
<div class="abs l-flex-col" ng-controller="EditObjectController as EditObjectController">
<div mct-before-unload="EditObjectController.getUnloadWarning()"
class="holder flex-elem l-flex-row object-browse-bar ">
<div class="items-select left flex-elem l-flex-row grows">
<mct-representation key="'back-arrow'"
mct-object="domainObject"
class="flex-elem l-back"></mct-representation>
<mct-representation key="'object-header'"
mct-object="domainObject"
class="l-flex-row flex-elem grows object-header">
</mct-representation>
</div>
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
<mct-representation key="'switcher'"
mct-object="domainObject"
ng-model="representation">
</mct-representation>
<!-- Temporarily, on mobile, the action buttons are hidden-->
<mct-representation key="'action-group'"
mct-object="domainObject"
parameters="{ category: 'view-control' }"
class="mobile-hide">
</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-inner">
<!-- Toolbar and Save/Cancel buttons -->
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
<mct-representation key="'adapted-view-TOOLBAR'"
mct-object="domainObject"
class="flex-elem grows">
</mct-representation>
<mct-representation key="'edit-action-buttons'"
mct-object="domainObject"
class='flex-elem conclude-editing'>
</mct-representation>
</div>
<mct-representation key="representation.selected.key"
mct-object="representation.selected.key && domainObject"
class="abs flex-elem grows object-holder-main scroll"
toolbar="toolbar">
</mct-representation>
</div><!--/ l-object-wrapper-inner -->
</div>
</div>

43
src/ui/Dialog.js Normal file
View File

@ -0,0 +1,43 @@
define(['text!./dialog.html', 'zepto'], function (dialogTemplate, $) {
function Dialog(view, title) {
this.view = view;
this.title = title;
}
Dialog.prototype.show = function () {
var $body = $('body');
var $dialog = $(dialogTemplate);
var $contents = $dialog.find('.contents .editor');
var $close = $dialog.find('.close');
var $ok = $dialog.find('.ok');
var $cancel = $dialog.find('.cancel');
var view = this.view;
function dismiss() {
$dialog.remove();
view.destroy();
}
if (this.title) {
$dialog.find('.title').text(this.title);
}
$body.append($dialog);
this.view.show($contents[0]);
return new Promise(function (resolve, reject) {
$ok.on('click', resolve);
$ok.on('click', dismiss);
$cancel.on('click', reject);
$cancel.on('click', dismiss);
$close.on('click', reject);
$close.on('click', dismiss);
});
};
return Dialog;
});

21
src/ui/dialog.html Normal file
View File

@ -0,0 +1,21 @@
<div class="abs overlay">
<div class="abs blocker"></div>
<div class="abs holder">
<a class="clk-icon icon ui-symbol close">x</a>
<div class="abs contents">
<div class="abs top-bar">
<div class="title"></div>
<div class="hint"></div>
</div>
<div class='abs editor'>
</div>
<div class="abs bottom-bar">
<a class='s-btn major ok'>OK</a>
<a class='s-btn cancel'>Cancel</a>
</div>
</div>
</div>
</div>

View File

@ -0,0 +1,3 @@
<label>Description:
<input type="text" class="description">
</label>

View File

@ -0,0 +1,9 @@
<div class="tool-bar btn-bar contents abs">
<a class="s-btn labeled example-add">
<span class="ui-symbol icon">+</span>
<span class="title-label">Add Task</span>
</a>
<a class="s-btn example-remove">
<span class="ui-symbol icon">Z</span>
</a>
</div>

View File

@ -1,8 +1,10 @@
define([ define([
"text!./todo.html", "text!./todo.html",
"text!./todo-task.html", "text!./todo-task.html",
"text!./todo-toolbar.html",
"text!./todo-dialog.html",
"zepto" "zepto"
], function (todoTemplate, taskTemplate, $) { ], function (todoTemplate, taskTemplate, toolbarTemplate, dialogTemplate, $) {
/** /**
* @param {mct.MCT} mct * @param {mct.MCT} mct
*/ */
@ -27,6 +29,8 @@ define([
} }
TodoView.prototype.show = function (container) { TodoView.prototype.show = function (container) {
this.destroy();
this.$els = $(todoTemplate); this.$els = $(todoTemplate);
this.$buttons = { this.$buttons = {
all: this.$els.find('.example-todo-button-all'), all: this.$els.find('.example-todo-button-all'),
@ -38,9 +42,15 @@ define([
this.initialize(); this.initialize();
this.render(); this.render();
mct.verbs.observe(this.domainObject, this.render.bind(this));
}; };
TodoView.prototype.destroy = function () { TodoView.prototype.destroy = function () {
if (this.unlisten) {
this.unlisten();
this.unlisten = undefined;
}
}; };
TodoView.prototype.setFilter = function (value) { TodoView.prototype.setFilter = function (value) {
@ -100,10 +110,51 @@ define([
$message.toggle(tasks.length < 1); $message.toggle(tasks.length < 1);
}; };
function TodoToolbarView(domainObject) {
this.domainObject = domainObject;
}
TodoToolbarView.prototype.show = function (container) {
var $els = $(toolbarTemplate);
var $add = $els.find('a.example-add');
var $remove = $els.find('a.example-remove');
var domainObject = this.domainObject;
$(container).append($els);
$add.on('click', function () {
var $dialog = $(dialogTemplate),
view = {
show: function (container) {
$(container).append($dialog);
},
destroy: function () {}
};
mct.dialog(view, "Add a Task").then(function () {
var description = $dialog.find('input').val();
mct.verbs.mutate(domainObject, function (model) {
model.tasks.push({ description: description });
console.log(model);
});
});
});
$remove.on('click', window.alert.bind(window, "Remove!"));
};
TodoToolbarView.prototype.destroy = function () {
};
mct.type('example.todo', todoType); mct.type('example.todo', todoType);
mct.view(mct.regions.main, function (domainObject) { mct.view(mct.regions.main, function (domainObject) {
return todoType.check(domainObject) && new TodoView(domainObject); return todoType.check(domainObject) && new TodoView(domainObject);
}); });
mct.view(mct.regions.toolbar, function (domainObject) {
return todoType.check(domainObject) && new TodoToolbarView(domainObject);
});
return mct; return mct;
}; };