From e4e455443f248d3fbce69f91c06b1eb1b9ac8ba9 Mon Sep 17 00:00:00 2001 From: nttuyen Date: Fri, 18 Oct 2013 18:31:20 +0700 Subject: [PATCH] EXOGTN-1593 [Edit-InPlace] D&D to add new window from composer --- .../org/gatein/portal/web/assets/editor.css | 11 +-- .../gatein/portal/web/page/PageEditor.java | 11 ++- .../gatein/portal/web/templates/site.gtmpl | 15 +++- .../web/assets/javascripts/layout-model.js | 68 +++++++++++++++--- .../web/assets/javascripts/layout-view.js | 70 +++++++++++++++++-- 5 files changed, 152 insertions(+), 23 deletions(-) diff --git a/portal/web/src/main/java/org/gatein/portal/web/assets/editor.css b/portal/web/src/main/java/org/gatein/portal/web/assets/editor.css index dc11fe563..636fcf01a 100644 --- a/portal/web/src/main/java/org/gatein/portal/web/assets/editor.css +++ b/portal/web/src/main/java/org/gatein/portal/web/assets/editor.css @@ -50,13 +50,16 @@ } #composers .in { border-top: solid 1px #ccc; + overflow: visible; } -#composers ul, .composers ul li { +#composers ul, .composers ul li, .sortable li { list-style: none; } #composers ul li { float: left; - margin-left: 5px; - width: 130px; - text-align: center; + margin-left: 30px; +} +#composers ul li .draggable { + text-align: center; + float: left; } diff --git a/portal/web/src/main/java/org/gatein/portal/web/page/PageEditor.java b/portal/web/src/main/java/org/gatein/portal/web/page/PageEditor.java index f9432b466..aaa9e69a4 100644 --- a/portal/web/src/main/java/org/gatein/portal/web/page/PageEditor.java +++ b/portal/web/src/main/java/org/gatein/portal/web/page/PageEditor.java @@ -45,6 +45,8 @@ import juzu.request.ResourceContext; import org.exoplatform.portal.config.model.ApplicationState; +import org.exoplatform.portal.config.model.ApplicationType; +import org.exoplatform.portal.config.model.TransientApplicationState; import org.exoplatform.portal.pom.data.ApplicationData; import org.exoplatform.portal.pom.data.ComponentData; import org.exoplatform.portal.pom.data.ContainerAdapter; @@ -59,6 +61,7 @@ import org.gatein.pc.api.PortletInvoker; import org.gatein.pc.api.PortletInvokerException; import org.gatein.pc.api.URLFormat; +import org.gatein.pc.api.info.MetaInfo; import org.gatein.pc.api.info.PortletInfo; import org.gatein.pc.api.invocation.RenderInvocation; import org.gatein.pc.api.invocation.response.FragmentResponse; @@ -140,9 +143,11 @@ public Response getAllPortlets() throws Exception { Set portlets = this.portletAppManager.getAllPortlets(); for(Portlet portlet : portlets) { PortletInfo info = portlet.getInfo(); + MetaInfo meta = info.getMeta(); JSON item = new JSON(); item.set("name", info.getName()); + item.set("title", meta.getMetaValue("title").getDefaultString()); item.set("applicationName", info.getApplicationName()); items.add(item); @@ -349,7 +354,11 @@ private void buildComponentTree(NodeContext context if ("container".equalsIgnoreCase(type)) { componentData = new ContainerData(null, id, null, null, null, null, null, null, null, null, null, new ArrayList(), new LinkedList()); } else if ("application".equalsIgnoreCase(type)) { - //TODO: process when add new portlet + String name = json.getString("name"); + String applicationName = json.getString("applicationName"); + String contentId = applicationName + "/" + name; + TransientApplicationState state = new TransientApplicationState(contentId); + componentData = new ApplicationData(null, id, ApplicationType.PORTLET, state, null, null, null, null, false, false, false, null, null, null, null, null); } } else { componentData = this.buildComponentData(ctx); diff --git a/portal/web/src/main/java/org/gatein/portal/web/templates/site.gtmpl b/portal/web/src/main/java/org/gatein/portal/web/templates/site.gtmpl index aa2d74263..33947e4e8 100644 --- a/portal/web/src/main/java/org/gatein/portal/web/templates/site.gtmpl +++ b/portal/web/src/main/java/org/gatein/portal/web/templates/site.gtmpl @@ -42,7 +42,7 @@ -
+
Drag and drop to add new portlet!
    @@ -51,12 +51,21 @@
    + + + <%}%> diff --git a/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-model.js b/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-model.js index 1ac377298..0440cf2a5 100644 --- a/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-model.js +++ b/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-model.js @@ -44,24 +44,67 @@ this.set({ draggable : true, name : options.name || '', + applicationName : options.applicationName || '', + title : options.title || '', + content: options.content || "loading....", logo : '/portal/assets/org/gatein/portal/web/assets/images/DefaultPortlet.png' }); + if(options.id) { + this.set('id', options.id); + } }, + setId: function(id) { + this.set('id', id); + }, getName : function() { return this.get('name'); }, - + getApplicationName: function() { + return this.get("applicationName"); + }, + getTitle: function() { + return this.get("title"); + }, getLogo : function() { return this.get('logo'); }, - + setContent: function(content) { + this.set("content", content); + }, + getContent: function(){ + return this.get("content"); + }, + fetchContent: function() { + //TODO: need to refactor + var contentId = this.getApplicationName() + "/" + this.getName(); + var url = "/portal/getContent?javax.portlet.content=" + contentId; + var _this = this; + $.ajax({ + url : url, + dataType : "json", + success: function(result) { + _this.setContent(result.content); + } + }); + }, + clone: function() { + return new Application({ + id: this.getId(), + name : this.getName(), + applicationName : this.getApplicationName(), + title : this.getTitle(), + logo : this.getLogo(), + content: this.getContent() + }); + }, // Return the JSON object that contains metadata information toJSON : function() { return { id : this.getId(), - "type" : "application", - name : this.getName() + type : "application", + name : this.getName(), + applicationName: this.getApplicationName() }; }, @@ -70,8 +113,10 @@ toJSONForRenderer : function() { return { id : this.getId(), - "type" : "application", + type : "application", name : this.getName(), + title : this.getTitle(), + content : this.getContent(), logo : this.getLogo() }; } @@ -234,7 +279,7 @@ toJSON : function() { var data = { id : this.getId(), - "type" : "container", + type : "container", childrens : [] }; this.get('_childrens').each(function(elem) { @@ -251,7 +296,7 @@ var cont = this; $(apps).each(function() { var newCont = newContainer.getChild(id); - var newApp = new Application(this); + var newApp = this.clone(); if (newCont) { newCont.addChild(newApp); } else { @@ -287,7 +332,7 @@ var data = { id : this.getId(), layout_id : this.getLayoutId(), - 'type' : 'container', + type : 'container', childrens : [] }; this.get('_childrens').each(function(elem) { @@ -304,6 +349,9 @@ initialize : function() { Container.prototype.initialize.call(this); }, + findChildByName : function(name) { + return this.get('_childrens').where({name: name}); + }, fetch : function() { var _this = this; @@ -319,7 +367,9 @@ var portlets = result.data.portlets; $(portlets).each(function(i, portlet) { _this.addChild(new Application({ - name : portlet.name + name : portlet.name, + applicationName: portlet.applicationName, + title: portlet.title })); }); } diff --git a/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-view.js b/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-view.js index c3f6d89ff..5badc3c6f 100644 --- a/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-view.js +++ b/portal/web/src/main/resources/org/gatein/portal/web/assets/javascripts/layout-view.js @@ -1,7 +1,7 @@ (function() { // An item in composer - var ApplicationView = Backbone.View.extend({ + var ComposerApplicationView = Backbone.View.extend({ tagName : "li", // TODO: Can this be removed, an empty method ? @@ -11,6 +11,8 @@ render : function() { this.template = _.template($("#portlet-template").html()); this.$el.html(this.template(this.model.toJSONForRenderer())); + this.$el.attr("id", ""); + this.$el.attr("data-name", this.model.getName()); return this; } }); @@ -30,20 +32,50 @@ this.model.fetch(); }, + getModel: function() { + return this.model; + }, + onAddChild : function(child) { var container = $('#portlet-list'); - var view = new ApplicationView({model : child}); + var view = new ComposerApplicationView({model : child}); container.append(view.render().$el); + + //Enable draggable + $(view.$el).draggable({ + connectToSortable: ".sortable", + revert: "invalid", + helper: "clone" + }); } }); + var ApplicationView = Backbone.View.extend({ + tagName: "div", + className: "portlet", + initialize: function() { + this.model.on('change', this.updateContent, this); + this.model.fetchContent(); + }, + render: function() { + this.template = _.template($("#application-template").html()); + this.$el.html(this.template(this.model.toJSONForRenderer())); + this.$el.attr("id", this.model.getId()); + return this; + }, + updateContent: function() { + var id = this.model.getId(); + var selector = "#" + id + " div"; + $(selector).html(this.model.getContent()); + } + }); // var LayoutView = Backbone.View.extend({ el : '.pageBody', events : { - "click .close" : "deleteApp", + "click .close" : "deleteApp" }, initialize : function(options) { @@ -97,6 +129,14 @@ var $cont = $('#' + container.getId()); var $app = $('#' + child.getId()); var prev = container.at(child.getIndex() - 1); + + if(!$app.html()) { + //Create new view of application + var appView = new ApplicationView({model: child}); + appView = appView.render(); + $app = $(appView.$el); + } + if (prev) { $app.insertAfter($('#' + prev.getId())); } else { @@ -130,9 +170,23 @@ } // Modify the model - cont.addChild(ui.item.attr('id'), { - at : idx - }); + if(!dragObj.attr("id")) { + //Add new application + var composerView = window.editorView.getComposerView(); + var application = composerView.getModel().findChildByName(dragObj.attr("data-name"))[0]; + + //Clone and generate id for new application + var newChild = application.clone(); + newChild.setId(newChild.getName() + new Date().getTime()); + cont.addChild(newChild, {at: idx}); + + //Remove dropped item + $(ui.item).remove(); + } else { + cont.addChild(ui.item.attr('id'), { + at : idx + }); + } // Update snapshot this.snapshotModel = this.model; @@ -255,6 +309,10 @@ } }, + getComposerView: function() { + return this.composerView; + }, + // Delegate to the LayoutView save saveLayout : function() { this.layoutView.save();