Skip to content

Commit

Permalink
Merge pull request #56 from ploneintranet/feature/create_document
Browse files Browse the repository at this point in the history
add forms&view to allow creation of folders and arbitrary content
  • Loading branch information
pbauer committed Feb 18, 2015
2 parents ed5e646 + af79f7d commit 31d1fe0
Show file tree
Hide file tree
Showing 6 changed files with 221 additions and 28 deletions.
49 changes: 49 additions & 0 deletions src/ploneintranet/workspace/browser/add_content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
from Products.CMFPlone.utils import safe_unicode
from Products.Five import BrowserView
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from plone import api
from plone.protect import CheckAuthenticator, PostOnly


class AddContent(BrowserView):
"""Evaluate simple form and add arbitrary content.
"""

template = ViewPageTemplateFile('templates/add_content.pt')

def __call__(self, portal_type=None, title=None, description=None):
"""Evaluate form and redirect"""
if title is not None:
CheckAuthenticator(self.request)
PostOnly(self.request)
self.portal_type = portal_type
self.title = title.strip()
self.description = description.strip()
if self.portal_type in api.portal.get_tool('portal_types'):
url = self.create()
return self.redirect(url)
return self.template()

def create(self):
"""Create content and return url"""
container = self.context
new = api.content.create(
container=container,
type=self.portal_type,
title=self.title,
safe_id=True,
)
if new:
new.description = safe_unicode(self.description)
return new.absolute_url()

def redirect(self, url):
"""Has its own method to allow overriding"""
url = '{}/edit'.format(url)
return self.request.response.redirect(url)


class AddFolder(AddContent):

template = ViewPageTemplateFile('templates/add_folder.pt')
16 changes: 16 additions & 0 deletions src/ploneintranet/workspace/browser/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,22 @@
permission="ploneintranet.workspace.ManageWorkspace"
/>

<browser:page
name="add_content"
for="Products.CMFCore.interfaces.IFolderish"
class=".add_content.AddContent"
template="templates/add_content.pt"
permission="cmf.AddPortalContent"
/>

<browser:page
name="add_folder"
for="Products.CMFCore.interfaces.IFolderish"
class=".add_content.AddFolder"
template="templates/add_folder.pt"
permission="cmf.AddPortalContent"
/>

<browser:viewlet
name="ploneintranet.workspace.sharinginfo"
for="ploneintranet.workspace.workspacefolder.IWorkspaceFolder"
Expand Down
36 changes: 36 additions & 0 deletions src/ploneintranet/workspace/browser/templates/add_content.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@

<h1>
Create document
</h1>
<form method="POST" action="#" tal:attributes="action request/URL" class="wizard-box pat-inject" data-pat-inject="source: #content; target: #document-body && source: #sidebar-content; target: #sidebar-content">
<div class="panel-body">
<fieldset class="icon-tabs">
<label class="icon-doc-text">
<input checked="checked" name="portal_type" value="Document" type="radio"> Rich text
</label>
<label class="icon-slides">
<input name="portal_type" value="Slideshow" type="radio"> Slideshow
</label>
<label class="icon-calendar">
<input name="portal_type" value="Event" type="radio"> Event
</label>
<label class="icon-file-image">
<input name="portal_type" value="Image" type="radio"> Image
</label>
</fieldset>
<fieldset class="vertical">
<input type="text" name="title" placeholder="Document title" autofocus />
<textarea name="description" rows="6" placeholder="Description for search results (Optional)"></textarea>
<input type="hidden" name="form.widgets.IExcludeFromNavigation.exclude_from_nav" value="selected">
</fieldset>
</div>
<div class="buttons panel-footer">
<span tal:replace="structure context/@@authenticator/authenticator"/>
<button id="form-buttons-create" name="form.buttons.create" type="submit" value="Create" class="icon-ok-circle close-panel focus">
Create
</button>
<button id="form-buttons-cancel" name="form.buttons.cancel" type="button" value="Cancel" class="icon-cancel-circle close-panel">
Cancel
</button>
</div>
</form>
21 changes: 21 additions & 0 deletions src/ploneintranet/workspace/browser/templates/add_folder.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<h1>
Create folder
</h1>
<form method="POST" action="#" tal:attributes="action request/URL" class="wizard-box pat-inject" data-pat-inject="source: #sidebar-content; target: #sidebar-content">
<div class="panel-body">
<fieldset class="vertical">
<input type="hidden" name="portal_type" value="Folder" />
<input type="text" name="title" placeholder="Folder name" autofocus />
<textarea name="description" rows="6" placeholder="Description for search results (Optional)"></textarea>
</fieldset>
</div>
<div class="buttons panel-footer">
<span tal:replace="structure context/@@authenticator/authenticator"/>
<button id="form-buttons-create" name="form.buttons.create" type="submit" value="Create" class="icon-ok-circle close-panel focus">
Create
</button>
<button id="form-buttons-cancel" name="form.buttons.cancel" type="button" value="Cancel" class="icon-cancel-circle close-panel">
Cancel
</button>
</div>
</form>
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@
<div id="workspace-documents">
<div class="item-selector mode-follow" id="selector">
<!-- <div class="item-selector mode-select" id="selector"> -->
<div class="button-bar functions" id="selector-functions">
<div class="button-bar functions" id="selector-functions">
<div class="contextual buttons float-before" id="selector-contextual-functions">
<a href="/open-market-committee"
class="button icon-left-open pat-inject"
<a href="/open-market-committee"
class="button icon-left-open pat-inject"
data-pat-inject="source: #sidebar-content; target: #sidebar-content"
tal:define="parent view/parent"
tal:condition="parent"
Expand Down Expand Up @@ -58,7 +58,7 @@

<form class="search-result docs pat-inject" data-pat-inject="target: body::after" action="/feedback/batch-rename.html#content" id="items">
<fieldset class="checklist pat-checklist docs ">

<div class="batch-functions">
<div class="button-bar">
<span class="float-before button-cluster select-buttons">
Expand Down Expand Up @@ -121,7 +121,7 @@
title="Share">Share</button>
</div>
</div>

<!-- Each document has a class name on the label element that indicates the document type.
Supported types include (class names):
Expand Down Expand Up @@ -150,15 +150,15 @@
<label class="item document type-event has-description"
tal:attributes="class item/cls">
<input name="event-traces-through-time" tal:attributes="name item/id" type="checkbox" />
<a href="/event-traces-through-time#document-body"
class="pat-inject follow"
data-pat-inject="target: #document-body"
<a href="/event-traces-through-time#document-body"
class="pat-inject follow"
data-pat-inject="target: #document-body"
tal:attributes="href string:${item/url};
data-pat-inject item/dpi">
<strong class="title" tal:content="item/title">Traces through Time data workshop</strong>

<dfn class="byline" tal:content="item/description" tal:condition="item/description">An interactive workshop to test new and innovative tools to trace people through time.</dfn>

</a>
</label>
</tal:block>
Expand All @@ -167,12 +167,12 @@
<input name="event-traces-through-time" type="checkbox" />
<a href="/event-traces-through-time#document-body" class="pat-inject follow" data-pat-inject="target: #document-body">
<strong class="title">Traces through Time data workshop</strong>
<dfn class="byline">An interactive workshop to test new and innovative tools to trace people through time.</dfn>
</a>
</label-->


<!-- Each group has a class 'group'. The following class — which is prefixed by 'type-' is dynanmic. If the grouping of the items selector is on date for instance, the class becomes 'type-date'. If the grouping is by user, then it's 'type-user' and the user avatar is there as an image. In case the grouping is by document type, then each group gets the icon of the document type it represents. For intance the group with PowerPoint files gets 'type-powerpoint' and a rich document gets 'type-rich'. The same type-* class names are supported as for a document.
-->
Expand All @@ -185,10 +185,10 @@
source: #context-title; target: #context-title"
>
<strong class="title">Projection Materials</strong>
</a>
</label-->

<!-- Each group has a class 'group'. The following class — which is prefixed by 'type-' is dynanmic. If the grouping of the items selector is on date for instance, the class becomes 'type-date'. If the grouping is by user, then it's 'type-user' and the user avatar is there as an image. In case the grouping is by document type, then each group gets the icon of the document type it represents. For intance the group with PowerPoint files gets 'type-powerpoint' and a rich document gets 'type-rich'. The same type-* class names are supported as for a document.
-->
<!-- Notice that there is a dynamic class 'has-description/has no description which depends on whether a description of the object is available' -->
Expand All @@ -200,12 +200,12 @@
source: #context-title; target: #context-title"
>
<strong class="title">2014 Meetings</strong>
<dfn class="byline">Meeting documents, statements, and minutes</dfn>
</a>
</label-->

<!-- Each group has a class 'group'. The following class — which is prefixed by 'type-' is dynanmic. If the grouping of the items selector is on date for instance, the class becomes 'type-date'. If the grouping is by user, then it's 'type-user' and the user avatar is there as an image. In case the grouping is by document type, then each group gets the icon of the document type it represents. For intance the group with PowerPoint files gets 'type-powerpoint' and a rich document gets 'type-rich'. The same type-* class names are supported as for a document.
-->
<!-- Notice that there is a dynamic class 'has-description/has no description which depends on whether a description of the object is available' -->
Expand All @@ -217,12 +217,12 @@
source: #context-title; target: #context-title"
>
<strong class="title">Manage Information</strong>
</a>
</label-->

</fieldset>
<!--
<!--
<div class="button-bar bottom form-submit pat-bumper">
<button type="submit" class="close-panel">Save</button>
<button type="reset" class="close-panel">Cancel</button>
Expand All @@ -231,8 +231,8 @@
</form>

<div class="button-bar create-buttons">
<a href="/++add++Document#document-content" tal:attributes="href string:${context/absolute_url}/++add++Document#document-content" class="button create-document pat-modal icon-doc-text" data-pat-modal="class: large">Create document</a>
<a href="/panel-create-folder.html#document-content" class="button create-folder pat-modal icon-folder" data-pat-modal="class: large">Create folder</a>
<a href="@@add_content" tal:attributes="href string:${context/absolute_url}/add_content" class="button create-document pat-modal icon-doc-text" data-pat-modal="class: large">Create document</a>
<a href="@@add_folder" tal:attributes="href string:${context/absolute_url}/add_folder" class="button create-folder pat-modal icon-folder" data-pat-modal="class: large">Create folder</a>
</div>
<form action="./">
<fieldset class="pat-upload" data-pat-upload="url: https://example.org/upload; label: Drop files here or click to browse…; trigger: auto;">
Expand All @@ -248,18 +248,16 @@
</h3> -->
<ul class="menu">
<li>
<a href="/++add++Document#document-content" tal:attributes="href string:${context/absolute_url}/++add++Document#document-content" class="icon-doc-text create-document pat-modal" data-pat-modal="class: large">Create document</a>
<a href="@@add_content" tal:attributes="href string:${context/absolute_url}/add_content" class="icon-doc-text create-document pat-modal" data-pat-modal="class: large">Create document</a>
</li>
<li>
<a href="/panel-create-folder.html#document-content" class="icon-folder create-folder pat-modal" data-pat-modal="class: large">Create folder</a>
<a href="@@add_folder" tal:attributes="href string:${context/absolute_url}/add_folder" class="icon-folder create-folder pat-modal" data-pat-modal="class: large">Create folder</a>
</li>
<li>
<label class=" icon-upload-cloud"><input multiple type="file"> Upload file(s)</label>
</li>
<li>

<a class="pat-toggle icon-ok selector-toggle-select" data-pat-toggle="selector: #selector; value: mode-select mode-follow">Select</a>

<a class="pat-toggle icon-ok selector-toggle-select" data-pat-toggle="selector: #selector; value: mode-select mode-follow">Select</a>
</li>
</ul>
</div>
Expand Down
73 changes: 73 additions & 0 deletions src/ploneintranet/workspace/tests/test_add_content.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# -*- coding: utf-8 -*-
from plone import api
from ploneintranet.workspace.tests.base import FunctionalBaseTestCase


class TestAddContent(FunctionalBaseTestCase):

def setUp(self):
super(TestAddContent, self).setUp()
self.login_as_portal_owner()
workspace_folder = api.content.create(
self.portal,
'ploneintranet.workspace.workspacefolder',
'example-workspace'
)
self.workspace = workspace_folder

# Commit so the testbrowser can see the workspace
import transaction
transaction.commit()

def test_add_content_form(self):
form = api.content.get_view(
'add_content', self.workspace, self.request)
result = form()
self.assertIn('Create document', result)
self.assertIn('<button id="form-buttons-create"', result)

def test_add_folder_form(self):
form = api.content.get_view(
'add_folder', self.workspace, self.request)
result = form()
self.assertIn('Create folder', result)
self.assertIn('<button id="form-buttons-create"', result)

def test_add_content_document(self):
self.browser_login_as_site_administrator()
self.browser.open('%s/@@add_content' % self.workspace.absolute_url())
self.browser.getControl(name='title').value = 'Some Title'
self.browser.getControl(name='description').value = 'My Desc'
self.browser.getControl(name='form.buttons.create').click()
new = self.workspace['some-title']
self.assertEqual(new.portal_type, 'Document')
self.assertEqual(new.title, u'Some Title')
self.assertEqual(new.description, u'My Desc')

def test_add_content_event(self):
self.browser_login_as_site_administrator()
self.browser.open('%s/@@add_content' % self.workspace.absolute_url())
self.browser.getControl(name='portal_type').value = ['Event']
self.browser.getControl(name='title').value = 'My Event'
self.browser.getControl(name='form.buttons.create').click()
new = self.workspace['my-event']
self.assertEqual(new.portal_type, 'Event')

def test_add_content_image(self):
self.browser_login_as_site_administrator()
self.browser.open('%s/@@add_content' % self.workspace.absolute_url())
self.browser.getControl(name='portal_type').value = ['Image']
self.browser.getControl(name='title').value = 'My Image'
self.browser.getControl(name='form.buttons.create').click()
new = self.workspace['my-image']
self.assertEqual(new.portal_type, 'Image')

def test_add_folder(self):
self.browser_login_as_site_administrator()
self.browser.open('%s/@@add_folder' % self.workspace.absolute_url())
self.assertEqual(
self.browser.getControl(name='portal_type').value, 'Folder')
self.browser.getControl(name='title').value = 'My Folder'
self.browser.getControl(name='form.buttons.create').click()
new = self.workspace['my-folder']
self.assertEqual(new.portal_type, 'Folder')

0 comments on commit 31d1fe0

Please sign in to comment.