Canh Ngo pushed to branch feature/cmng-psp1-CHANNELMGR-467 at cms-community / 
hippo-addon-channel-manager


Commits:
10e6e8a7 by Canh Ngo at 2016-03-17T14:18:29+01:00
CHANNELMGR-467: Moved all render calls to RenderingService

Moved Hst calls to remove, add components to the HstService

- - - - -


8 changed files:

- frontend-ng/src/angularjs/api/hst.service.js
- frontend-ng/src/angularjs/channel/page/componentRendering.service.js
- frontend-ng/src/angularjs/channel/page/componentRendering.service.spec.js
- frontend-ng/src/angularjs/channel/page/element/containerElement.js
- frontend-ng/src/angularjs/channel/page/page.js
- frontend-ng/src/angularjs/channel/page/pageStructure.service.js
- + frontend-ng/src/angularjs/channel/page/rendering.service.js
- + frontend-ng/src/angularjs/channel/page/rendering.service.spec.js


Changes:

=====================================
frontend-ng/src/angularjs/api/hst.service.js
=====================================
--- a/frontend-ng/src/angularjs/api/hst.service.js
+++ b/frontend-ng/src/angularjs/api/hst.service.js
@@ -83,4 +83,29 @@ export class HstService {
     return apiUrl;
   }
 
+  /**
+   * Add a component to the specified container.
+   *
+   * @param catalogComponent
+   * @param containerId
+   * @returns {*} the request promise
+   */
+  addHstComponent(catalogComponent, containerId) {
+    const requestPayload = `data: {
+      parentId: ${containerId},
+      id: ${catalogComponent.id},
+      name: ${catalogComponent.name},
+      label: ${catalogComponent.label},
+      type: ${catalogComponent.type},
+      template: ${catalogComponent.template},
+      componentClassName: ${catalogComponent.componentClassName},
+      xtype: ${catalogComponent.xtype},
+      children: []
+    }`;
+    return this.doPost(requestPayload, containerId, 'create', 
catalogComponent.id);
+  }
+
+  removeHstComponent(containerId, componentId) {
+    return this.doGet(containerId, 'delete', componentId);
+  }
 }


=====================================
frontend-ng/src/angularjs/channel/page/componentRendering.service.js
=====================================
--- a/frontend-ng/src/angularjs/channel/page/componentRendering.service.js
+++ b/frontend-ng/src/angularjs/channel/page/componentRendering.service.js
@@ -16,13 +16,14 @@
 
 export class ComponentRenderingService {
 
-  constructor($http, $log, CmsService, PageStructureService) {
+  constructor($http, $log, CmsService, PageStructureService, RenderingService) 
{
     'ngInject';
 
     this.$http = $http;
     this.$log = $log;
     this.CmsService = CmsService;
     this.PageStructureService = PageStructureService;
+    this.RenderingService = RenderingService;
   }
 
   initialize() {
@@ -32,37 +33,11 @@ export class ComponentRenderingService {
   _renderComponent(componentId, propertiesMap) {
     const component = this.PageStructureService.getComponentById(componentId);
     if (component) {
-      this._fetchHtml(component, propertiesMap).then((response) => {
-        this.PageStructureService.replaceComponent(component, response.data);
+      this.RenderingService.fetchComponentMarkup(component, 
propertiesMap).then((response) => {
+        this.PageStructureService.updateComponent(component, response.data);
       });
     } else {
       this.$log.warn(`Cannot render unknown component '${componentId}'`);
     }
   }
-
-  _fetchHtml(component, propertiesMap) {
-    function toUrlEncodedFormData(json) {
-      const keyValuePairs = [];
-      for (const property in json) {
-        if (json.hasOwnProperty(property)) {
-          const key = encodeURIComponent(property);
-          const value = encodeURIComponent(json[property]);
-          keyValuePairs.push(`${key}=${value}`);
-        }
-      }
-      return keyValuePairs.join('&');
-    }
-
-    return this.$http({
-      method: 'POST',
-      url: component.getRenderUrl(),
-      headers: {
-        Accept: 'text/html, */*',
-        'Content-Type': 'application/x-www-form-urlencoded',
-      },
-      data: propertiesMap,
-      transformRequest: toUrlEncodedFormData,
-    });
-  }
-
 }


=====================================
frontend-ng/src/angularjs/channel/page/componentRendering.service.spec.js
=====================================
--- a/frontend-ng/src/angularjs/channel/page/componentRendering.service.spec.js
+++ b/frontend-ng/src/angularjs/channel/page/componentRendering.service.spec.js
@@ -18,16 +18,18 @@ describe('ComponentRenderingService', () => {
   'use strict';
 
   let PageStructureService;
-  let $httpBackend;
+  let RenderingService;
   let $log;
+  let $q;
 
   beforeEach(() => {
     module('hippo-cm.channel.page');
 
-    inject((_$httpBackend_, _$log_, _PageStructureService_) => {
-      $httpBackend = _$httpBackend_;
+    inject((_$httpBackend_, _$q_, _$log_, _PageStructureService_, 
_RenderingService_) => {
       $log = _$log_;
+      $q = _$q_;
       PageStructureService = _PageStructureService_;
+      RenderingService = _RenderingService_;
     });
   });
 
@@ -35,29 +37,18 @@ describe('ComponentRenderingService', () => {
     
jasmine.getFixtures().load('channel/page/componentRendering.service.fixture.html');
   });
 
-  afterEach(() => {
-    $httpBackend.verifyNoOutstandingExpectation();
-    $httpBackend.verifyNoOutstandingRequest();
-  });
-
   it('renders a component', () => {
-    const component = jasmine.createSpyObj('component', ['getRenderUrl', 
'getJQueryElement']);
+    const component = jasmine.createSpyObj('component', ['getJQueryElement']);
     const iframeElement = $j('#component');
 
-    component.getRenderUrl.and.returnValue('/test-render-url');
     component.getJQueryElement.and.returnValue(iframeElement);
     spyOn(PageStructureService, 'getComponent').and.returnValue(component);
-    spyOn(PageStructureService, 'replaceComponent');
-    $httpBackend.whenPOST('/test-render-url').respond('<div>component 
markup</div>');
+    spyOn(PageStructureService, 'updateComponent');
+    spyOn(RenderingService, 'fetchComponentMarkup').and.returnValue($q.when('{ 
data: <div>component markup</div> }'));
 
     window.CMS_TO_APP.publish('render-component', '1234', { foo: 1, bar: 'a:b' 
});
 
-    $httpBackend.expectPOST('/test-render-url', 'foo=1&bar=a%3Ab', {
-      Accept: 'text/html, */*',
-      'Content-Type': 'application/x-www-form-urlencoded',
-    });
-    $httpBackend.flush();
-
+    
expect(RenderingService.fetchComponentMarkup).toHaveBeenCalledWith(component, { 
foo: 1, bar: 'a:b' });
     
expect(PageStructureService.replaceComponent).toHaveBeenCalledWith(component, 
'<div>component markup</div>');
   });
 


=====================================
frontend-ng/src/angularjs/channel/page/element/containerElement.js
=====================================
--- a/frontend-ng/src/angularjs/channel/page/element/containerElement.js
+++ b/frontend-ng/src/angularjs/channel/page/element/containerElement.js
@@ -80,6 +80,17 @@ export class ContainerElement extends PageStructureElement {
     return this.items.find((item) => 
item.getJQueryElement('iframeBoxElement').is(iframeElement));
   }
 
+  replaceComponent(oldComponent, newComponent) {
+    const index = this.items.indexOf(oldComponent);
+    if (index !== -1) {
+      this.items[index] = newComponent;
+    }
+  }
+
+  hasComponent(component) {
+    return this.items.indexOf(component) !== -1;
+  }
+
   getHstRepresentation() {
     return {
       data: {


=====================================
frontend-ng/src/angularjs/channel/page/page.js
=====================================
--- a/frontend-ng/src/angularjs/channel/page/page.js
+++ b/frontend-ng/src/angularjs/channel/page/page.js
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+import { RenderingService } from './rendering.service';
 import { ComponentRenderingService } from './componentRendering.service';
 import { PageMetaDataService } from './pageMetaData.service';
 import { PageStructureService } from './pageStructure.service';
@@ -21,6 +22,7 @@ import { run } from './page.run';
 
 export const channelPageModule = angular
   .module('hippo-cm.channel.page', [])
+  .service('RenderingService', RenderingService)
   .service('ComponentRenderingService', ComponentRenderingService)
   .service('PageMetaDataService', PageMetaDataService)
   .service('PageStructureService', PageStructureService)


=====================================
frontend-ng/src/angularjs/channel/page/pageStructure.service.js
=====================================
--- a/frontend-ng/src/angularjs/channel/page/pageStructure.service.js
+++ b/frontend-ng/src/angularjs/channel/page/pageStructure.service.js
@@ -21,18 +21,18 @@ import { ComponentElement } from 
'./element/componentElement';
 
 export class PageStructureService {
 
-  constructor($log, $q, $http, HstConstants, hstCommentsProcessorService, 
OverlaySyncService, ChannelService, CmsService, PageMetaDataService, 
HstService) {
+  constructor($log, $q, HstConstants, hstCommentsProcessorService, 
RenderingService, OverlaySyncService, ChannelService, CmsService, 
PageMetaDataService, HstService) {
     'ngInject';
 
     // Injected
     this.$log = $log;
-    this.$http = $http;
     this.$q = $q;
     this.HST = HstConstants;
     this.HstService = HstService;
     this.ChannelService = ChannelService;
     this.CmsService = CmsService;
     this.hstCommentsProcessorService = hstCommentsProcessorService;
+    this.RenderingService = RenderingService;
     this.OverlaySyncService = OverlaySyncService;
     this.pageMetaData = PageMetaDataService;
 
@@ -94,6 +94,10 @@ export class PageStructureService {
     return component;
   }
 
+  hasContainer(container) {
+    return this.containers.indexOf(container) !== -1;
+  }
+
   /**
    * Remove the component identified by given Id
    * @param componentId
@@ -104,18 +108,14 @@ export class PageStructureService {
 
     if (component) {
       const container = component.getContainer();
-      return this._removeHstComponent(container.getId(), componentId)
-        .then(() => this.reloadContainer(container));
+      this.HstService.removeHstComponent(container.getId(), componentId)
+        .then(() => this._renderContainer(container));
       // TODO handle error
     } else {
       this.$log.debug(`Was asked to remove component with ID '${componentId}', 
but couldn't find it in the page structure.`);
     }
   }
 
-  _removeHstComponent(containerId, componentId) {
-    return this.HstService.doGet(containerId, 'delete', componentId);
-  }
-
   getContainerByIframeElement(containerIFrameElement) {
     return this.containers.find((container) => 
container.getJQueryElement('iframeBoxElement').is(containerIFrameElement));
   }
@@ -144,67 +144,48 @@ export class PageStructureService {
     });
   }
 
-  replaceComponent(component, newMarkup) {
+  /**
+   * Update the component with the new markup
+   */
+  updateComponent(component, newMarkup) {
     const jQueryNodeCollection = component.replaceDOM(newMarkup);
     this._replaceComponent(component, 
this._createComponent(jQueryNodeCollection, component.getContainer()));
     this.OverlaySyncService.syncIframe();
   }
 
-  _createComponent(jQueryNodeCollection, container) {
-    let component = null;
-
-    this.hstCommentsProcessorService.processFragment(jQueryNodeCollection, 
(commentDomElement, metaData) => {
-      switch (metaData[this.HST.TYPE]) {
-        case this.HST.TYPE_COMPONENT:
-          try {
-            component = new ComponentElement(commentDomElement, metaData, 
container, this.hstCommentsProcessorService);
-          } catch (exception) {
-            this.$log.debug(exception, metaData);
-          }
-          break;
-
-        default:
-          break;
-      }
+  _renderContainer(container) {
+    this.RenderingService.fetchContainerMarkup(container).then((response) => {
+      this._updateContainer(container, response.data);
     });
+  }
 
-    if (!component) {
-      this.$log.error('Failed to create a new component');
-    }
-
-    return component;
+  _updateContainer(container, newMarkup) {
+    const jQueryContainerElement = container.replaceDOM(newMarkup);
+    this._replaceContainer(container, 
this._createContainer(jQueryContainerElement));
+    this.OverlaySyncService.syncIframe(); // necessary? mutation observer 
should trigger this...
   }
 
   _replaceComponent(oldComponent, newComponent) {
     const container = oldComponent.getContainer();
-    const index = container.items.indexOf(oldComponent);
-    if (index === -1) {
+    if (this.hasContainer(container) && container.hasComponent(oldComponent)) {
+      container.replaceComponent(oldComponent, newComponent);
+    } else {
       this.$log.warn('Cannot find component', oldComponent);
-      return;
     }
-    container.items[index] = newComponent;
   }
 
   addComponentToContainer(catalogComponent, overlayDomElementOfContainer) {
-    const oldContainer = this.containers.find((c) => 
c.getJQueryElement('overlay')[0] === overlayDomElementOfContainer);
+    const container = this.containers.find((c) => 
c.getJQueryElement('overlay')[0] === overlayDomElementOfContainer);
 
-    if (oldContainer) {
-      this._addHstComponent(catalogComponent, oldContainer.getId())
-        .then(() => this.reloadContainer(oldContainer));
+    if (container) {
+      this.HstService.addHstComponent(catalogComponent, container.getId())
+        .then(() => this._renderContainer(container));
       // TODO: handle error
     } else {
-      console.log('oldContainer not found');
+      console.log('container not found');
     }
   }
 
-  reloadContainer(container) {
-    this._fetchContainerMarkup(container).then((response) => {
-      const jQueryContainerElement = container.replaceDOM(response.data);
-      this._replaceContainer(container, 
this._createContainer(jQueryContainerElement));
-      this.OverlaySyncService.syncIframe(); // necessary? mutation observer 
should trigger this...
-    });
-  }
-
   _replaceContainer(oldContainer, newContainer) {
     const index = this.containers.indexOf(oldContainer);
     if (index === -1) {
@@ -214,27 +195,16 @@ export class PageStructureService {
     this.containers[index] = newContainer;
   }
 
-  _fetchContainerMarkup(container) {
-    return this.$http({
-      method: 'GET',
-      url: container.getRenderUrl(),
-      header: {
-        Accept: 'text/html, */* ',
-        'Content-Type': 'application/x-www-form-urlencoded',
-      },
-    });
-  }
-
   /**
    * Create a new container with meta-data from the given markup value
    * @param markup
    * @returns {*}
    * @private
    */
-  _createContainer(jQueryContainerElement) {
+  _createContainer(jQueryNodeCollection) {
     let container = null;
 
-    this.hstCommentsProcessorService.processFragment(jQueryContainerElement, 
function (commentDomElement, metaData) {
+    this.hstCommentsProcessorService.processFragment(jQueryNodeCollection, 
(commentDomElement, metaData) => {
       switch (metaData[this.HST.TYPE]) {
         case this.HST.TYPE_CONTAINER:
           if (!container) {
@@ -262,7 +232,7 @@ export class PageStructureService {
         default:
           break;
       }
-    }.bind(this));
+    });
 
     if (!container) {
       this.$log.error('Failed to create a new container');
@@ -272,23 +242,30 @@ export class PageStructureService {
   }
 
   /**
-   * Add the component to the container at back-end
-   * @param componentId
-   * @param containerId
-   * @returns {*}
-   * @private
+   * Create a new component with meta-data from the given markup value
    */
-  _addHstComponent(catalogComponent, containerId) {
-    const requestPayload = `data: {
-      parentId: ${containerId},
-      id: ${catalogComponent.id},
-      name: ${catalogComponent.name},
-      label: ${catalogComponent.label},
-      type: ${catalogComponent.type},
-      template: ${catalogComponent.template},
-      componentClassName: ${catalogComponent.componentClassName},
-      xtype: ${catalogComponent.xtype},
-    }`;
-    return this.HstService.doPost(requestPayload, containerId, 'create', 
catalogComponent.id);
+  _createComponent(jQueryNodeCollection, container) {
+    let component = null;
+
+    this.hstCommentsProcessorService.processFragment(jQueryNodeCollection, 
(commentDomElement, metaData) => {
+      switch (metaData[this.HST.TYPE]) {
+        case this.HST.TYPE_COMPONENT:
+          try {
+            component = new ComponentElement(commentDomElement, metaData, 
container, this.hstCommentsProcessorService);
+          } catch (exception) {
+            this.$log.debug(exception, metaData);
+          }
+          break;
+
+        default:
+          break;
+      }
+    });
+
+    if (!component) {
+      this.$log.error('Failed to create a new component');
+    }
+
+    return component;
   }
 }


=====================================
frontend-ng/src/angularjs/channel/page/rendering.service.js
=====================================
--- /dev/null
+++ b/frontend-ng/src/angularjs/channel/page/rendering.service.js
@@ -0,0 +1,64 @@
+/*
+ *
+ *  * Copyright 2016 Hippo B.V. (http://www.onehippo.com)
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *  http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+export class RenderingService {
+
+  constructor($http, $log) {
+    'ngInject';
+
+    this.$http = $http;
+    this.$log = $log;
+  }
+
+  fetchContainerMarkup(container) {
+    return this.$http({
+      method: 'GET',
+      url: container.getRenderUrl(),
+      header: {
+        Accept: 'text/html, */* ',
+        'Content-Type': 'application/x-www-form-urlencoded',
+      },
+    });
+  }
+
+  fetchComponentMarkup(component, propertiesMap) {
+    function toUrlEncodedFormData(json) {
+      const keyValuePairs = [];
+      for (const property in json) {
+        if (json.hasOwnProperty(property)) {
+          const key = encodeURIComponent(property);
+          const value = encodeURIComponent(json[property]);
+          keyValuePairs.push(`${key}=${value}`);
+        }
+      }
+      return keyValuePairs.join('&');
+    }
+
+    return this.$http({
+      method: 'POST',
+      url: component.getRenderUrl(),
+      headers: {
+        Accept: 'text/html, */*',
+        'Content-Type': 'application/x-www-form-urlencoded',
+      },
+      data: propertiesMap,
+      transformRequest: toUrlEncodedFormData,
+    });
+  }
+
+}


=====================================
frontend-ng/src/angularjs/channel/page/rendering.service.spec.js
=====================================
--- /dev/null
+++ b/frontend-ng/src/angularjs/channel/page/rendering.service.spec.js
@@ -0,0 +1,69 @@
+/*
+ *
+ *  * Copyright 2016 Hippo B.V. (http://www.onehippo.com)
+ *  *
+ *  * Licensed under the Apache License, Version 2.0 (the "License");
+ *  * you may not use this file except in compliance with the License.
+ *  * You may obtain a copy of the License at
+ *  *
+ *  *  http://www.apache.org/licenses/LICENSE-2.0
+ *  *
+ *  * Unless required by applicable law or agreed to in writing, software
+ *  * distributed under the License is distributed on an "AS IS" BASIS,
+ *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  * See the License for the specific language governing permissions and
+ *  * limitations under the License.
+ *
+ */
+
+describe('RenderingService', () => {
+  'use strict';
+
+  let RenderingService;
+  let $httpBackend;
+
+  beforeEach(() => {
+    module('hippo-cm.channel.page');
+
+    inject((_RenderingService_, _$httpBackend_) => {
+      $httpBackend = _$httpBackend_;
+      RenderingService = _RenderingService_;
+    });
+  });
+
+
+  afterEach(() => {
+    $httpBackend.verifyNoOutstandingExpectation();
+    $httpBackend.verifyNoOutstandingRequest();
+  });
+
+  it('fetch a component markup', () => {
+    const component = jasmine.createSpyObj('component', ['getRenderUrl']);
+
+    component.getRenderUrl.and.returnValue('/test-render-url');
+    $httpBackend.whenPOST('/test-render-url').respond('<div>component 
markup</div>');
+
+    RenderingService.fetchComponentMarkup(component, { foo: 1, bar: 'a:b' });
+
+    $httpBackend.expectPOST('/test-render-url', 'foo=1&bar=a%3Ab', {
+      Accept: 'text/html, */*',
+      'Content-Type': 'application/x-www-form-urlencoded',
+    });
+    $httpBackend.flush();
+  });
+
+  it('fetch a container markup', () => {
+    const container = jasmine.createSpyObj('container', ['getRenderUrl']);
+
+    container.getRenderUrl.and.returnValue('/test-render-url');
+    $httpBackend.whenGET('/test-render-url').respond('<div>container 
markup</div>');
+
+    RenderingService.fetchContainerMarkup(container);
+
+    $httpBackend.expectGET('/test-render-url', {
+      Accept: 'text/html, */*',
+      'Content-Type': 'application/x-www-form-urlencoded',
+    });
+    $httpBackend.flush();
+  });
+});



View it on GitLab: 
https://code.onehippo.org/cms-community/hippo-addon-channel-manager/commit/10e6e8a7c47c49335b7903004e20a7838458be35
_______________________________________________
Hippocms-svn mailing list
Hippocms-svn@lists.onehippo.org
https://lists.onehippo.org/mailman/listinfo/hippocms-svn

Reply via email to