Room remeber size + component permissions
This commit is contained in:
@@ -76,6 +76,14 @@ class Component extends Item {
|
|||||||
return this.getAppDataItem("defaultEditor") == true;
|
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,
|
An associative component depends on being explicitly activated for a given item, compared to a dissaciative component,
|
||||||
|
|||||||
@@ -225,89 +225,24 @@ class ComponentManager {
|
|||||||
|
|
||||||
if(message.action === "stream-items") {
|
if(message.action === "stream-items") {
|
||||||
this.handleStreamItemsMessage(component, message);
|
this.handleStreamItemsMessage(component, message);
|
||||||
}
|
} else if(message.action === "stream-context-item") {
|
||||||
|
|
||||||
else if(message.action === "stream-context-item") {
|
|
||||||
this.handleStreamContextItemMessage(component, message);
|
this.handleStreamContextItemMessage(component, message);
|
||||||
}
|
} else if(message.action === "set-component-data") {
|
||||||
|
this.handleSetComponentDataMessage(component, message);
|
||||||
else if(message.action === "set-component-data") {
|
} else if(message.action === "delete-items") {
|
||||||
component.componentData = message.data.componentData;
|
this.handleDeleteItemsMessage(component, message);
|
||||||
component.setDirty(true);
|
} else if(message.action === "create-item") {
|
||||||
this.syncManager.sync();
|
this.handleCreateItemMessage(component, message);
|
||||||
}
|
} else if(message.action === "save-items") {
|
||||||
|
this.handleSaveItemsMessage(component, message);
|
||||||
else if(message.action === "delete-items") {
|
} else if(message.action === "install-local-component") {
|
||||||
var items = message.data.items;
|
this.handleInstallLocalComponentMessage(component, message);
|
||||||
var noun = items.length == 1 ? "item" : "items";
|
} else if(message.action === "open-component") {
|
||||||
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") {
|
|
||||||
let openComponent = this.modelManager.findItem(message.data.uuid);
|
let openComponent = this.modelManager.findItem(message.data.uuid);
|
||||||
console.log("Received open-component event", openComponent);
|
|
||||||
this.openModalComponent(openComponent);
|
this.openModalComponent(openComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Notify observers
|
||||||
for(let handler of this.handlers) {
|
for(let handler of this.handlers) {
|
||||||
if(handler.areas.includes(component.area)) {
|
if(handler.areas.includes(component.area)) {
|
||||||
this.timeout(function(){
|
this.timeout(function(){
|
||||||
@@ -390,6 +325,124 @@ class ComponentManager {
|
|||||||
}.bind(this))
|
}.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) {
|
runWithPermissions(component, requiredPermissions, requestedPermissions, runFunction) {
|
||||||
|
|
||||||
var acquiredPermissions = component.permissions;
|
var acquiredPermissions = component.permissions;
|
||||||
@@ -407,7 +460,7 @@ class ComponentManager {
|
|||||||
if(!requestedMatchesRequired) {
|
if(!requestedMatchesRequired) {
|
||||||
// Error with Component permissions request
|
// Error with Component permissions request
|
||||||
console.error("You are requesting permissions", requestedPermissions, "when you need to be requesting", requiredPermissions, ". Component:", component);
|
console.error("You are requesting permissions", requestedPermissions, "when you need to be requesting", requiredPermissions, ". Component:", component);
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!component.permissions) {
|
if(!component.permissions) {
|
||||||
|
|||||||
@@ -11,29 +11,36 @@ class RoomBar {
|
|||||||
'ngInject';
|
'ngInject';
|
||||||
|
|
||||||
$scope.componentManager = componentManager;
|
$scope.componentManager = componentManager;
|
||||||
|
$scope.rooms = [];
|
||||||
|
|
||||||
$rootScope.$on("initial-data-loaded", () => {
|
modelManager.addItemSyncObserver("room-bar", "SN|Component", (allItems, validItems, deletedItems, source) => {
|
||||||
$timeout(() => {
|
$scope.rooms = _.uniq($scope.rooms
|
||||||
$scope.rooms = componentManager.componentsForArea("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) {
|
if(component.active) {
|
||||||
$timeout(function(){
|
$timeout(() => {
|
||||||
var iframe = componentManager.iframeForComponent(component);
|
var iframe = componentManager.iframeForComponent(component);
|
||||||
if(iframe) {
|
if(iframe) {
|
||||||
|
var lastSize = component.getRoomLastSize();
|
||||||
|
if(lastSize) {
|
||||||
|
componentManager.handleSetSizeEvent(component, lastSize);
|
||||||
|
}
|
||||||
iframe.onload = function() {
|
iframe.onload = function() {
|
||||||
componentManager.registerComponentWindow(component, iframe.contentWindow);
|
componentManager.registerComponentWindow(component, iframe.contentWindow);
|
||||||
}.bind(this);
|
}.bind(this);
|
||||||
}
|
}
|
||||||
}.bind(this));
|
});
|
||||||
}
|
}
|
||||||
}.bind(this), actionHandler: function(component, action, data){
|
}, actionHandler: (component, action, data) => {
|
||||||
if(action == "set-size") {
|
if(action == "set-size") {
|
||||||
componentManager.handleSetSizeEvent(component, data);
|
componentManager.handleSetSizeEvent(component, data);
|
||||||
|
component.setRoomLastSize(data);
|
||||||
}
|
}
|
||||||
}.bind(this)});
|
}});
|
||||||
|
|
||||||
$scope.selectRoom = function(room) {
|
$scope.selectRoom = function(room) {
|
||||||
room.show = !room.show;
|
room.show = !room.show;
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ class PackageManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var assembled = this.modelManager.createItem(aPackage);
|
var assembled = this.modelManager.createItem(aPackage);
|
||||||
|
assembled.package_info = aPackage;
|
||||||
this.modelManager.addItem(assembled);
|
this.modelManager.addItem(assembled);
|
||||||
assembled.setDirty(true);
|
assembled.setDirty(true);
|
||||||
this.syncManager.sync();
|
this.syncManager.sync();
|
||||||
|
|||||||
@@ -95,6 +95,21 @@ h2 {
|
|||||||
.room-item {
|
.room-item {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
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 {
|
.room-container {
|
||||||
max-height: 85vh;
|
max-height: 85vh;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
.room-item{"ng-repeat" => "room in rooms", "ng-click" => "selectRoom(room)"}
|
.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}}"}
|
.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}}"}
|
%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}}"}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ module Neeto
|
|||||||
font_src: %w(* 'self'),
|
font_src: %w(* 'self'),
|
||||||
form_action: %w('self'),
|
form_action: %w('self'),
|
||||||
frame_ancestors: ["*"],
|
frame_ancestors: ["*"],
|
||||||
img_src: %w('self' data:),
|
img_src: %w('self' * data:),
|
||||||
manifest_src: %w('self'),
|
manifest_src: %w('self'),
|
||||||
media_src: %w('self'),
|
media_src: %w('self'),
|
||||||
object_src: %w('self'),
|
object_src: %w('self'),
|
||||||
|
|||||||
Reference in New Issue
Block a user