Skip to content
This repository was archived by the owner on Oct 26, 2021. It is now read-only.

Navigation performance #3

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion bower.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"angular-animate": "1.2.14",
"angular-loading-bar": "0.4.2",
"angular-sanitize": "1.2.14",
"angular-bootstrap": "0.10.0"
"angular-bootstrap": "0.10.0",
"angular-bootstrap-nav-tree": "*"
}
}
36 changes: 36 additions & 0 deletions src/plone/app/angularjs/api/api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# -*- coding: utf-8 -*-
from Acquisition import aq_chain
from Products.CMFCore.interfaces import IContentish
from Products.CMFCore.interfaces import IFolderish
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from Products.Five.browser import BrowserView
from zope.component.hooks import getSite
Expand Down Expand Up @@ -118,3 +121,36 @@ def _get_children(context):
) if brain.exclude_from_nav is not True
]
)

def folder_children(self, request):
portal = getSite()
portal_path = '/'.join(portal.getPhysicalPath())
path = request.get('path')
if not path:
path = portal_path
else:
path = portal_path + path
try:
folder = portal.restrictedTraverse(path)
except KeyError:
return json.dumps([])
if not IFolderish.providedBy(folder):
for item in aq_chain(folder):
if IFolderish.providedBy(item):
folder = item
break
return json.dumps(
[
{
'id': obj[1].id,
'title': obj[1].title,
'label': obj[1].title,
'description': obj[1].description,
'url': '/'.join(obj[1].getPhysicalPath()),
'children': []
}
for obj in folder.objectItems()
if IContentish.providedBy(obj[1])
and obj[1].exclude_from_nav is not True
]
)
4 changes: 4 additions & 0 deletions src/plone/app/angularjs/app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
<base tal:attributes="href view/base">
<link rel="stylesheet" href="++theme++plone.app.angularjs/bower_components/bootstrap/dist/css/bootstrap.min.css" />
<link rel="stylesheet" href="++theme++plone.app.angularjs/bower_components/angular-loading-bar/build/loading-bar.min.css" />
<link rel="stylesheet" href="++theme++plone.app.angularjs/bower_components/angular-bootstrap-nav-tree/dist/abn_tree.css">
<link rel="stylesheet" href="styles/main.css" />

<script src="++theme++plone.app.angularjs/bower_components/jquery/dist/jquery.min.js"></script>
<script src="++theme++plone.app.angularjs/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="++theme++plone.app.angularjs/bower_components/angular/angular.min.js"></script>
Expand All @@ -16,9 +18,11 @@
<script src="++theme++plone.app.angularjs/bower_components/angular-sanitize/angular-sanitize.js"></script>
<script src="++theme++plone.app.angularjs/bower_components/angular-bootstrap/ui-bootstrap.min.js"></script>
<script src="++theme++plone.app.angularjs/bower_components/angular-bootstrap/ui-bootstrap-tpls.min.js"></script>
<script src="++theme++plone.app.angularjs/bower_components/angular-bootstrap-nav-tree/dist/abn_tree_directive.js"></script>
<script src="++theme++plone.app.angularjs/scripts/app.js"></script>
<script src="++theme++plone.app.angularjs/scripts/directives.js"></script>
<script src="++theme++plone.app.angularjs/scripts/controller.js"></script>
<script src="++theme++plone.app.angularjs/scripts/navigation-portlet.js"></script>
</head>
<body>
<div id="top-navigation-directive" navigation-directive></div>
Expand Down
8 changes: 6 additions & 2 deletions src/plone/app/angularjs/app/navigation-portlet.tpl.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<ul id="portlet-navigation-directive" class="nav nav-pills nav-stacked">
<!--<ul id="portlet-navigation-directive" class="nav nav-pills nav-stacked">
<li ng-repeat="item in items"
ng-class="{active: activeItem == item.url.slice(1)}">
<a ng-href="{{item.url}}">{{item.title}}</a>
Expand All @@ -9,4 +9,8 @@
</li>
</ul>
</li>
</ul>
</ul>-->
<div id="portlet-navigation-directive" class="nav nav-pills nav-stacked">
<abn-tree tree-data="folders" tree-control="my_tree" on-select="my_tree_handler(branch)" expand-level="0"></abn-tree>
<div style="width: 100%" class="alert alert-warning">{{ output }}</div>
</div>
1 change: 1 addition & 0 deletions src/plone/app/angularjs/app/scripts/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var ploneModule = angular.module(
'ngRoute',
'ngSanitize',
'ui.bootstrap',
'angularBootstrapNavTree'
]
);

Expand Down
20 changes: 0 additions & 20 deletions src/plone/app/angularjs/app/scripts/directives.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,3 @@ ploneModule.directive('navigationDirective',
};
}
);

ploneModule.controller('NavigationPortletController',
function($scope, $http) {
'use strict';
var url = '++api++v1/navigation_tree';
$http.get(url).success(function(data) {
$scope.items = data;
});
}
);

ploneModule.directive('navigationPortletDirective',
function() {
'use strict';
return {
templateUrl: 'navigation-portlet.tpl.html',
controller: 'NavigationPortletController'
};
}
);
65 changes: 65 additions & 0 deletions src/plone/app/angularjs/app/scripts/navigation-portlet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
var ploneModule;

ploneModule.factory('reportTreeService', function($q, $http) {

var getTreeData = function(path) {
console.log('getTreeData(' + path + ')');
var deferred = $q.defer();
$http({
method: 'GET',
url: '++api++v1/folder_children',
params: {
path: path
}
}).then(function (response) {
deferred.resolve(response.data);
});
return deferred.promise;
};

return {
getTreeData: getTreeData
};

});


ploneModule.controller('NavigationPortletController',
function($scope, $location, reportTreeService) {
'use strict';
$scope.location = $location;
$scope.folders = [];
var path = $scope.location.path();
console.log("PATH: " + path);
reportTreeService.getTreeData(path).then(function(data) {
$scope.folders = data;

$scope.my_tree_handler = function(branch) {
console.log('my_tree_handler(' + branch + ')');
$scope.output = "You selected: " + branch.label;
if (branch.label == 'Nachrichten') {
reportTreeService.getTreeData('/news').then(function(data) {
branch.children = data;
});
}
if (branch.label == 'Termine') {
reportTreeService.getTreeData('/events').then(function(data) {
branch.children = data;
});
}
};
});

}
);


ploneModule.directive('navigationPortletDirective',
function() {
'use strict';
return {
templateUrl: 'navigation-portlet.tpl.html',
controller: 'NavigationPortletController'
};
}
);
89 changes: 89 additions & 0 deletions src/plone/app/angularjs/tests/test_api_folder_children.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# -*- coding: utf-8 -*-
from plone.app.angularjs.interfaces import IRestApi
from plone.app.testing import setRoles
from plone.app.testing import TEST_USER_ID
from plone.app.angularjs.testing import\
PLONE_APP_ANGULARJS_INTEGRATION_TESTING
from zope.component import getUtility

import json
import unittest2 as unittest


class TestAngularJsFolderChildren(unittest.TestCase):

layer = PLONE_APP_ANGULARJS_INTEGRATION_TESTING

def setUp(self):
self.app = self.layer['app']
self.portal = self.layer['portal']
self.request = self.layer['request']
setRoles(self.portal, TEST_USER_ID, ['Manager'])
self.api = getUtility(IRestApi)

def test_empty_navigation(self):
self.assertEqual(
json.loads(self.api.folder_children(self.request)),
[]
)

def test_folder_in_navigation(self):
self.portal.invokeFactory('Folder', 'folder1', title='Folder 1')

self.assertTrue(self.api.folder_children(self.request))
self.assertEqual(
json.loads(self.api.folder_children(self.request)),
[{
u'id': u'folder1',
u'title': u'Folder 1',
u'label': u'Folder 1',
u'description': u'',
u'url': '/plone/folder1',
u'children': []
}]
)

def test_do_not_show_excluded_from_nav_documents(self):
self.portal.invokeFactory('Folder', 'folder1', title='Folder 1')
self.portal.folder1.exclude_from_nav = True
self.portal.folder1.reindexObject(idxs=['exclude_from_nav'])

self.assertEqual(
len(json.loads(self.api.folder_children(self.request))),
0
)

def test_folder_in_navigation_with_path(self):
self.portal.invokeFactory('Folder', 'folder1', title='Folder 1')
self.portal.folder1.invokeFactory(
'Folder', 'folder2', title='Folder 2')
self.request.set('path', '/folder1')
self.assertTrue(
self.api.folder_children(self.request))
self.assertEqual(
json.loads(
self.api.folder_children(self.request)
),
[{
u'id': u'folder2',
u'title': u'Folder 2',
u'label': u'Folder 2',
u'description': u'',
u'url': '/plone/folder1/folder2',
u'children': []
}]
)

def test_document_returns_parent_folder(self):
self.portal.invokeFactory('Folder', 'folder1', title='Folder 1')
self.portal.folder1.invokeFactory(
'Document', 'doc1', title='Document 1')
self.request.set('path', '/folder1/doc1')
self.assertTrue(
self.api.folder_children(self.request))
self.assertEqual(
json.loads(
self.api.folder_children(self.request)
)[0]['id'],
u'doc1'
)