Room remeber size + component permissions

This commit is contained in:
Mo Bitar
2017-12-25 15:39:00 -06:00
parent 2702d88bc2
commit 8569098e8a
7 changed files with 175 additions and 90 deletions

View File

@@ -76,6 +76,14 @@ class Component extends Item {
return this.getAppDataItem("defaultEditor") == true;
}
setRoomLastSize(size) {
this.setAppDataItem("lastRoomSize", size);
}
getRoomLastSize() {
return this.getAppDataItem("lastRoomSize");
}
/*
An associative component depends on being explicitly activated for a given item, compared to a dissaciative component,

View File

@@ -225,89 +225,24 @@ class ComponentManager {
if(message.action === "stream-items") {
this.handleStreamItemsMessage(component, message);
}
else if(message.action === "stream-context-item") {
} else if(message.action === "stream-context-item") {
this.handleStreamContextItemMessage(component, message);
}
else if(message.action === "set-component-data") {
component.componentData = message.data.componentData;
component.setDirty(true);
this.syncManager.sync();
}
else if(message.action === "delete-items") {
var items = message.data.items;
var noun = items.length == 1 ? "item" : "items";
if(confirm(`Are you sure you want to delete ${items.length} ${noun}?`)) {
for(var item of items) {
var model = this.modelManager.findItem(item.uuid);
this.modelManager.setItemToBeDeleted(model);
}
this.syncManager.sync();
}
}
else if(message.action === "create-item") {
var responseItem = message.data.item;
this.removePrivatePropertiesFromResponseItems([responseItem]);
var item = this.modelManager.createItem(responseItem);
if(responseItem.clientData) {
item.setDomainDataItem(component.url, responseItem.clientData, ClientDataDomain);
}
this.modelManager.addItem(item);
this.modelManager.resolveReferencesForItem(item);
item.setDirty(true);
this.syncManager.sync();
this.replyToMessage(component, message, {item: this.jsonForItem(item, component)})
}
else if(message.action === "save-items") {
var responseItems = message.data.items;
this.removePrivatePropertiesFromResponseItems(responseItems);
/*
We map the items here because modelManager is what updates the UI. If you were to instead get the items directly,
this would update them server side via sync, but would never make its way back to the UI.
*/
var localItems = this.modelManager.mapResponseItemsToLocalModels(responseItems, ModelManager.MappingSourceComponentRetrieved);
for(var item of localItems) {
var responseItem = _.find(responseItems, {uuid: item.uuid});
_.merge(item.content, responseItem.content);
if(responseItem.clientData) {
item.setDomainDataItem(component.url, responseItem.clientData, ClientDataDomain);
}
item.setDirty(true);
}
this.syncManager.sync((response) => {
// Allow handlers to be notified when a save begins and ends, to update the UI
var saveMessage = Object.assign({}, message);
saveMessage.action = response && response.error ? "save-error" : "save-success";
this.handleMessage(component, saveMessage);
});
}
else if(message.action === "install-local-component") {
console.log("Received install-local-component event");
this.desktopManager.installOfflineComponentFromData(message.data, (response) => {
console.log("componentManager: installed component:", response);
var component = this.modelManager.mapResponseItemsToLocalModels([response], ModelManager.MappingSourceComponentRetrieved)[0];
// Save updated URL
component.setDirty(true);
this.syncManager.sync();
})
}
else if(message.action === "open-component") {
} else if(message.action === "set-component-data") {
this.handleSetComponentDataMessage(component, message);
} else if(message.action === "delete-items") {
this.handleDeleteItemsMessage(component, message);
} else if(message.action === "create-item") {
this.handleCreateItemMessage(component, message);
} else if(message.action === "save-items") {
this.handleSaveItemsMessage(component, message);
} else if(message.action === "install-local-component") {
this.handleInstallLocalComponentMessage(component, message);
} else if(message.action === "open-component") {
let openComponent = this.modelManager.findItem(message.data.uuid);
console.log("Received open-component event", openComponent);
this.openModalComponent(openComponent);
}
// Notify observers
for(let handler of this.handlers) {
if(handler.areas.includes(component.area)) {
this.timeout(function(){
@@ -390,6 +325,124 @@ class ComponentManager {
}.bind(this))
}
handleSaveItemsMessage(component, message) {
var requiredContentTypes = _.uniq(message.data.items.map((i) => {return i.content_type})).sort();
var requiredPermissions = [
{
name: "stream-items",
content_types: requiredContentTypes
}
];
this.runWithPermissions(component, requiredPermissions, message.permissions, () => {
var responseItems = message.data.items;
this.removePrivatePropertiesFromResponseItems(responseItems);
/*
We map the items here because modelManager is what updates the UI. If you were to instead get the items directly,
this would update them server side via sync, but would never make its way back to the UI.
*/
var localItems = this.modelManager.mapResponseItemsToLocalModels(responseItems, ModelManager.MappingSourceComponentRetrieved);
for(var item of localItems) {
var responseItem = _.find(responseItems, {uuid: item.uuid});
_.merge(item.content, responseItem.content);
if(responseItem.clientData) {
item.setDomainDataItem(component.url, responseItem.clientData, ClientDataDomain);
}
item.setDirty(true);
}
this.syncManager.sync((response) => {
// Allow handlers to be notified when a save begins and ends, to update the UI
var saveMessage = Object.assign({}, message);
saveMessage.action = response && response.error ? "save-error" : "save-success";
this.handleMessage(component, saveMessage);
});
});
}
handleCreateItemMessage(component, message) {
var requiredPermissions = [
{
name: "stream-items",
content_types: [message.data.item.content_type]
}
];
this.runWithPermissions(component, requiredPermissions, message.permissions, () => {
var responseItem = message.data.item;
this.removePrivatePropertiesFromResponseItems([responseItem]);
var item = this.modelManager.createItem(responseItem);
if(responseItem.clientData) {
item.setDomainDataItem(component.url, responseItem.clientData, ClientDataDomain);
}
this.modelManager.addItem(item);
this.modelManager.resolveReferencesForItem(item);
item.setDirty(true);
this.syncManager.sync();
this.replyToMessage(component, message, {item: this.jsonForItem(item, component)})
});
}
handleDeleteItemsMessage(component, message) {
var requiredContentTypes = _.uniq(message.data.items.map((i) => {return i.content_type})).sort();
var requiredPermissions = [
{
name: "stream-items",
content_types: requiredContentTypes
}
];
this.runWithPermissions(component, requiredPermissions, message.permissions, () => {
var items = message.data.items;
var noun = items.length == 1 ? "item" : "items";
if(confirm(`Are you sure you want to delete ${items.length} ${noun}?`)) {
for(var item of items) {
var model = this.modelManager.findItem(item.uuid);
this.modelManager.setItemToBeDeleted(model);
}
this.syncManager.sync();
}
});
}
handleInstallLocalComponentMessage(component, message) {
var requiredPermissions = [
{
name: "stream-items",
content_types: [message.data.content_type]
}
];
this.runWithPermissions(component, requiredPermissions, message.permissions, () => {
console.log("Received install-local-component event");
this.desktopManager.installOfflineComponentFromData(message.data, (response) => {
console.log("componentManager: installed component:", response);
var component = this.modelManager.mapResponseItemsToLocalModels([response], ModelManager.MappingSourceComponentRetrieved)[0];
// Save updated URL
component.setDirty(true);
this.syncManager.sync();
})
});
}
handleSetComponentDataMessage(component, message) {
var requiredPermissions = [
{
name: "stream-items",
content_types: component.content_type
}
];
this.runWithPermissions(component, requiredPermissions, message.permissions, () => {
component.componentData = message.data.componentData;
component.setDirty(true);
this.syncManager.sync();
});
}
runWithPermissions(component, requiredPermissions, requestedPermissions, runFunction) {
var acquiredPermissions = component.permissions;
@@ -407,7 +460,7 @@ class ComponentManager {
if(!requestedMatchesRequired) {
// Error with Component permissions request
console.error("You are requesting permissions", requestedPermissions, "when you need to be requesting", requiredPermissions, ". Component:", component);
return;
return false;
}
if(!component.permissions) {

View File

@@ -11,29 +11,36 @@ class RoomBar {
'ngInject';
$scope.componentManager = componentManager;
$scope.rooms = [];
$rootScope.$on("initial-data-loaded", () => {
$timeout(() => {
$scope.rooms = componentManager.componentsForArea("rooms");
})
modelManager.addItemSyncObserver("room-bar", "SN|Component", (allItems, validItems, deletedItems, source) => {
$scope.rooms = _.uniq($scope.rooms
.concat(allItems
.filter((candidate) => {return candidate.area == "rooms"})))
.filter((candidate) => {return !candidate.deleted});
});
componentManager.registerHandler({identifier: "roomBar", areas: ["rooms"], activationHandler: function(component){
componentManager.registerHandler({identifier: "roomBar", areas: ["rooms"], activationHandler: (component) => {
if(component.active) {
$timeout(function(){
$timeout(() => {
var iframe = componentManager.iframeForComponent(component);
if(iframe) {
var lastSize = component.getRoomLastSize();
if(lastSize) {
componentManager.handleSetSizeEvent(component, lastSize);
}
iframe.onload = function() {
componentManager.registerComponentWindow(component, iframe.contentWindow);
}.bind(this);
}
}.bind(this));
});
}
}.bind(this), actionHandler: function(component, action, data){
}, actionHandler: (component, action, data) => {
if(action == "set-size") {
componentManager.handleSetSizeEvent(component, data);
component.setRoomLastSize(data);
}
}.bind(this)});
}});
$scope.selectRoom = function(room) {
room.show = !room.show;

View File

@@ -16,6 +16,7 @@ class PackageManager {
}
var assembled = this.modelManager.createItem(aPackage);
assembled.package_info = aPackage;
this.modelManager.addItem(assembled);
assembled.setDirty(true);
this.syncManager.sync();

View File

@@ -95,6 +95,21 @@ h2 {
.room-item {
display: inline-block;
position: relative;
vertical-align: middle;
.label {
display: inline-block;
vertical-align: middle;
font-size: 11px;
margin-top: -2px;
}
.icon {
width: 16px;
height: 16px;
display: inline-block;
vertical-align: middle;
}
.room-container {
max-height: 85vh;

View File

@@ -1,4 +1,5 @@
.room-item{"ng-repeat" => "room in rooms", "ng-click" => "selectRoom(room)"}
%span {{room.name}}
%img.icon{"ng-src" => "{{room.package_info.icon_bar}}"}
.label {{room.name}}
.room-container.panel-right{"ng-if" => "room.show && room.active", "ng-attr-id" => "component-{{room.uuid}}"}
%iframe.room-iframe{"ng-src" => "{{componentManager.urlForComponent(room) | trusted}}", "frameBorder" => "0", "sandbox" => "allow-scripts allow-top-navigation-by-user-activation allow-popups allow-popups-to-escape-sandbox allow-modals", "data-component-id" => "{{room.uuid}}"}

View File

@@ -53,7 +53,7 @@ module Neeto
font_src: %w(* 'self'),
form_action: %w('self'),
frame_ancestors: ["*"],
img_src: %w('self' data:),
img_src: %w('self' * data:),
manifest_src: %w('self'),
media_src: %w('self'),
object_src: %w('self'),