[Checkins] SVN: grokapps/SmallELearningDemo/ Added a small e-learning demo application.
Yusei Tahara
yusei at domen.cx
Mon Sep 15 18:30:29 EDT 2008
Log message for revision 91184:
Added a small e-learning demo application.
Changed:
A grokapps/SmallELearningDemo/
A grokapps/SmallELearningDemo/README.txt
A grokapps/SmallELearningDemo/TODO.txt
A grokapps/SmallELearningDemo/buildout.cfg
A grokapps/SmallELearningDemo/setup.py
A grokapps/SmallELearningDemo/src/
A grokapps/SmallELearningDemo/src/smallelearningdemo/
A grokapps/SmallELearningDemo/src/smallelearningdemo/__init__.py
A grokapps/SmallELearningDemo/src/smallelearningdemo/answer.py
A grokapps/SmallELearningDemo/src/smallelearningdemo/answer_templates/
A grokapps/SmallELearningDemo/src/smallelearningdemo/answer_templates/index.pt
A grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer.py
A grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer_templates/
A grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer_templates/index.pt
A grokapps/SmallELearningDemo/src/smallelearningdemo/app.py
A grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/
A grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/index.pt
A grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/master.pt
A grokapps/SmallELearningDemo/src/smallelearningdemo/configure.zcml
A grokapps/SmallELearningDemo/src/smallelearningdemo/exercise.py
A grokapps/SmallELearningDemo/src/smallelearningdemo/exercise_templates/
A grokapps/SmallELearningDemo/src/smallelearningdemo/exercise_templates/index.pt
A grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer.py
A grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer_templates/
A grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer_templates/index.pt
A grokapps/SmallELearningDemo/src/smallelearningdemo/ftesting.zcml
A grokapps/SmallELearningDemo/src/smallelearningdemo/testing.py
-=-
Added: grokapps/SmallELearningDemo/README.txt
===================================================================
--- grokapps/SmallELearningDemo/README.txt (rev 0)
+++ grokapps/SmallELearningDemo/README.txt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,7 @@
+This is a demo application of small e-learning system.
+There are two user types, one is a teacher and the other is a student.
+Teacher can upload exercise and student can upload answer,
+and also teacher can make a comments on student's answer.
+
+The purpose of this application is to show beginners how to make
+a real application by grok.
Property changes on: grokapps/SmallELearningDemo/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: grokapps/SmallELearningDemo/TODO.txt
===================================================================
--- grokapps/SmallELearningDemo/TODO.txt (rev 0)
+++ grokapps/SmallELearningDemo/TODO.txt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,5 @@
+TODO
+
+ * Implement security.
+ * Implement user account management.
+ * Write tests.
Property changes on: grokapps/SmallELearningDemo/TODO.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: grokapps/SmallELearningDemo/buildout.cfg
===================================================================
--- grokapps/SmallELearningDemo/buildout.cfg (rev 0)
+++ grokapps/SmallELearningDemo/buildout.cfg 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,86 @@
+[buildout]
+develop = .
+parts = app data zopectl i18n test
+find-links = http://download.zope.org/zope3.4
+newest = false
+extends= http://grok.zope.org/releaseinfo/grok-0.13.cfg
+versions = versions
+
+[versions]
+lovely.recipe = 0.3.1b5
+zc.recipe.testrunner = 1.0.0
+
+[data]
+recipe = zc.recipe.filestorage
+
+[app]
+recipe = zc.zope3recipes>=0.5.3:application
+eggs = SmallELearningDemo
+site.zcml = <include package="smallelearningdemo" />
+ <include package="zope.app.twisted" />
+
+ <configure i18n_domain="smallelearning">
+ <unauthenticatedPrincipal id="zope.anybody"
+ title="Unauthenticated User" />
+ <unauthenticatedGroup id="zope.Anybody"
+ title="Unauthenticated Users" />
+ <authenticatedGroup id="zope.Authenticated"
+ title="Authenticated Users" />
+ <everybodyGroup id="zope.Everybody"
+ title="All Users" />
+ <principal id="zope.manager"
+ title="Manager"
+ login="zope"
+ password_manager="Plain Text"
+ password="zope"
+ />
+
+ <!-- Debugging -->
+ <include package="zope.app.zcmlfiles" file="meta.zcml" />
+ <include package="zope.app.preference" file="meta.zcml" />
+ <include package="zope.app.onlinehelp" file="meta.zcml" />
+ <include package="zope.app.apidoc" file="meta.zcml" />
+
+ <include package="zope.app.zcmlfiles" />
+ <include package="zope.app.tree" />
+ <include package="zope.app.onlinehelp" />
+ <include package="zope.app.renderer" />
+ <include package="zope.app.preference" />
+ <include package="zope.app.apidoc" />
+
+ <!-- Replace the following directive if you don't want
+ public access -->
+ <grant permission="zope.View"
+ principal="zope.Anybody" />
+ <grant permission="zope.app.dublincore.view"
+ principal="zope.Anybody" />
+
+ <role id="zope.Manager" title="Site Manager" />
+ <role id="zope.Member" title="Site Member" />
+ <grantAll role="zope.Manager" />
+ <grant role="zope.Manager"
+ principal="zope.manager" />
+ </configure>
+
+[data]
+recipe = zc.recipe.filestorage
+
+# this section named so that the start/stop script is called bin/zopectl
+[zopectl]
+recipe = zc.zope3recipes:instance
+application = app
+zope.conf = ${data:zconfig}
+ devmode on
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = SmallELearningDemo
+defaults = ['--tests-pattern', '^f?tests$', '-v']
+
+# this section named so that the i18n scripts are called bin/i18n...
+[i18n]
+recipe = lovely.recipe:i18n
+package = smallelearningdemo
+domain = smallelearningdemo
+location = src/smallelearningdemo
+output = locales
Added: grokapps/SmallELearningDemo/setup.py
===================================================================
--- grokapps/SmallELearningDemo/setup.py (rev 0)
+++ grokapps/SmallELearningDemo/setup.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,28 @@
+from setuptools import setup, find_packages
+
+version = '0.0'
+
+setup(name='SmallELearningDemo',
+ version=version,
+ description="",
+ long_description="""\
+""",
+ # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers
+ classifiers=[],
+ keywords="",
+ author="Yusei Tahara",
+ author_email="yusei at domen.cx",
+ url="http://qwik.jp/zope3study/",
+ license="ZPL2.1",
+ package_dir={'': 'src'},
+ packages=find_packages('src'),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=['setuptools',
+ 'grok',
+ # Add extra requirements here
+ ],
+ entry_points="""
+ # Add entry points here
+ """,
+ )
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/__init__.py
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/__init__.py (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/__init__.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1 @@
+# this directory is a package
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/answer.py
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/answer.py (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/answer.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,69 @@
+import grok
+import answercontainer
+import filecontainer
+import zope.interface
+import zope.schema
+import zope.schema
+import zope.component
+
+
+class IAnswer(zope.interface.Interface):
+
+ name = zope.schema.ASCIILine(title=u'Name')
+
+ title = zope.schema.TextLine(title=u'Title')
+
+ comment = zope.schema.Text(title=u'Comment')
+
+
+class Answer(grok.Container):
+
+ grok.implements(IAnswer)
+
+ def __init__(self, name, title, comment):
+ super(Answer, self).__init__()
+
+ self.name = name
+ self.title = title
+ self.comment = comment
+
+ self['files'] = filecontainer.FileContainer()
+
+
+class Add(grok.AddForm):
+
+ grok.context(answercontainer.AnswerContainer)
+
+ form_fields = (grok.AutoFields(Answer) +
+ grok.Fields(data=zope.schema.Bytes(title=u'Data',
+ default=None,
+ required=False))
+ )
+
+ @grok.action('Add answer')
+ def add(self, name, title, comment, data):
+ answer = Answer(name=name, title=title, comment=comment)
+
+ # Use add view defined in filecontainer.Add.
+ addview = zope.component.getMultiAdapter((answer['files'], self.request),
+ name='add')
+ addview.upload(data=data)
+
+ self.context[answer.name] = answer
+ self.redirect(self.url(answer))
+
+
+class Index(grok.View):
+
+ def getFiles(self):
+ return self.context['files'].values()
+
+
+class Edit(grok.EditForm):
+
+ form_fields = grok.AutoFields(Answer).omit('name')
+
+ @grok.action('Save')
+ def save(self, **data):
+ self.applyData(self.context, **data)
+ self.redirect(self.url(self.context))
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/answer_templates/index.pt
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/answer_templates/index.pt (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/answer_templates/index.pt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,31 @@
+<html metal:use-macro="context/@@master/macros/master">
+<div metal:fill-slot="content">
+
+<h1>Answer</h1>
+
+<div tal:content="context/title"></div>
+
+<pre tal:content="context/comment"></pre>
+
+<h2>Attachments</h2>
+
+<ul>
+<li tal:repeat="i view/getFiles">
+<a tal:attributes="href i/@@absolute_url" tal:content="i/zope:name"></a>
+</li>
+</ul>
+
+<div>
+<a href="answers/add" tal:attributes="href python:view.url('files/add')">Add File</a>
+</div>
+
+<div>
+<a href="edit" tal:attributes="href python:view.url('edit')">Edit</a>
+</div>
+
+<div>
+<a tal:attributes="href context/__parent__/@@absolute_url">Back</a>
+</div>
+
+</div>
+</html>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer.py
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer.py (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,11 @@
+import grok
+
+
+class AnswerContainer(grok.Container):
+
+ pass
+
+
+class Index(grok.View):
+
+ pass
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer_templates/index.pt
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer_templates/index.pt (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/answercontainer_templates/index.pt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,15 @@
+<html metal:use-macro="context/@@master/macros/master">
+<div metal:fill-slot="content">
+
+<h1>Answers</h1>
+
+<ul>
+<li tal:repeat="i context/values">
+<a tal:attributes="href i/@@absolute_url" tal:content="i/zope:name"></a>
+</li>
+</ul>
+
+<a tal:attributes="href python:view.url(context.__parent__)">Back</a>
+
+</div>
+</html>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/app.py
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/app.py (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/app.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,18 @@
+import grok
+import zope.interface
+
+
+class SmallELearningDemo(grok.Application, grok.Container):
+
+ pass
+
+
+class Index(grok.View):
+
+ pass
+
+
+class Master(grok.View):
+ """A view class provides page template macro."""
+
+ grok.context(zope.interface.Interface)
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/index.pt
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/index.pt (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/index.pt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,23 @@
+<html metal:use-macro="context/@@master/macros/master">
+<div metal:fill-slot="content">
+
+<h1>Exercise List</h1>
+
+
+<form action="delete" tal:attributes="action python:view.url('delete')">
+<ul>
+ <li tal:repeat="i context/values">
+ <input type="checkbox" name="names:list" tal:attributes="value i/__name__">
+ <a tal:attributes="href i/@@absolute_url" tal:content="i/title"></a>
+ </li>
+</ul>
+<input tal:condition="python:len(context)" type="submit" value="Delete">
+</form>
+
+
+<div>
+<a href="add" tal:attributes="href python:view.url(name='add')">Add new exercise</a>
+</div>
+
+</div>
+</html>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/master.pt
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/master.pt (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/app_templates/master.pt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,15 @@
+<html metal:define-macro="master">
+<head>
+<title>Simple e-Learning Demo</title>
+</head>
+<body style="padding:0;">
+<div style="margin:0; padding:0; height:50px; font-size:24pt; background-color:#bbf">
+Simple e-Learning Demo
+</div>
+
+<div metal:define-slot="content">
+
+</div>
+
+</body>
+</html>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/configure.zcml
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/configure.zcml (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/configure.zcml 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,6 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+ xmlns:grok="http://namespaces.zope.org/grok">
+ <include package="grok" />
+ <grok:grok package="." />
+ <include package="zope.app.file" />
+</configure>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/exercise.py
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/exercise.py (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/exercise.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,80 @@
+import grok
+import app
+import answercontainer
+import filecontainer
+import zope.interface
+import zope.schema
+import zope.component
+
+
+class IExercise(zope.interface.Interface):
+
+ name = zope.schema.ASCIILine(title=u'Name')
+
+ title = zope.schema.TextLine(title=u'Title')
+
+ description = zope.schema.Text(title=u'Description')
+
+
+class Exercise(grok.Container):
+
+ grok.implements(IExercise)
+
+ def __init__(self, name, title, description):
+ super(Exercise, self).__init__()
+ self.name = name
+ self.title = title
+ self.description = description
+
+ self['answers'] = answercontainer.AnswerContainer()
+ self['files'] = filecontainer.FileContainer()
+
+
+class Add(grok.AddForm):
+
+ grok.context(app.SmallELearningDemo)
+
+ form_fields = (grok.AutoFields(Exercise) +
+ grok.Fields(data=zope.schema.Bytes(title=u'Data',
+ default=None,
+ required=False))
+ )
+
+ @grok.action('Add exercise')
+ def add(self, name, title, description, data):
+ exercise = Exercise(name=name, title=title, description=description)
+
+ # Use add view defined in filecontainer.Add.
+ addview = zope.component.getMultiAdapter((exercise['files'], self.request),
+ name='add')
+ addview.upload(data=data)
+
+ self.context[exercise.name] = exercise
+ self.redirect(self.url(exercise))
+
+
+class Index(grok.View):
+
+ def getFiles(self):
+ return self.context['files'].values()
+
+
+class Edit(grok.EditForm):
+
+ form_fields = grok.AutoFields(Exercise).omit('name')
+
+ @grok.action('Save')
+ def save(self, **data):
+ self.applyData(self.context, **data)
+ self.redirect(self.url(self.context))
+
+
+class Delete(grok.View):
+
+ grok.context(app.SmallELearningDemo)
+
+ def render(self):
+ for name in self.request.form.get('names', ()):
+ if name in self.context:
+ del self.context[name]
+ self.redirect(self.url(self.context))
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/exercise_templates/index.pt
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/exercise_templates/index.pt (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/exercise_templates/index.pt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,34 @@
+<html metal:use-macro="context/@@master/macros/master">
+<div metal:fill-slot="content">
+
+<h1 tal:content="context/title"></h1>
+
+<pre tal:content="context/description"></pre>
+
+<div>
+ <a href="edit" tal:attributes="href python:view.url(name='edit')">Edit</a>
+</div>
+
+<h2><a href="files" tal:attributes="href python:view.url(name='files')">Attachments</a></h2>
+
+
+<ul>
+ <li tal:repeat="i view/getFiles">
+ <a tal:attributes="href i/@@absolute_url" tal:content="i/zope:name"></a>
+ </li>
+</ul>
+
+<div>
+ <a href="answers" tal:attributes="href python:view.url('answers')">Answer List</a>
+</div>
+
+<div>
+ <a href="answers/add" tal:attributes="href python:view.url('answers/add')">Add Answer</a>
+</div>
+
+<div>
+<a tal:attributes="href python:view.url(context.__parent__)">Back</a>
+</div>
+
+</div>
+</html>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer.py
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer.py (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,31 @@
+import grok
+import zope.app.file
+
+
+class FileContainer(grok.Container):
+
+ pass
+
+
+class Add(grok.AddForm):
+
+ grok.context(FileContainer)
+
+ form_fields = grok.AutoFields(zope.app.file.interfaces.IFile).select('data')
+
+ @grok.action('Add file')
+ def add(self, **data):
+ self.upload(**data)
+ self.redirect(self.url(self.context.__parent__))
+
+ def upload(self, **data):
+ fileupload = self.request['form.data']
+ if fileupload and fileupload.filename:
+ contenttype = fileupload.headers.get('Content-Type')
+ file_ = zope.app.file.File(data['data'], contenttype)
+ self.context[fileupload.filename] = file_
+
+
+class Index(grok.View):
+
+ pass
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer_templates/index.pt
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer_templates/index.pt (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/filecontainer_templates/index.pt 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,13 @@
+<html metal:use-macro="context/@@master/macros/master">
+<div metal:fill-slot="content">
+
+<ul>
+<li tal:repeat="i context/values">
+<a tal:attributes="href i/@@absolute_url" tal:content="i/zope:name"></a>
+</li>
+</ul>
+
+<a href="add" tal:attributes="href python:view.url(name='add')">Add File</a>
+
+</div>
+</html>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/ftesting.zcml
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/ftesting.zcml (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/ftesting.zcml 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,35 @@
+<configure
+ xmlns="http://namespaces.zope.org/zope"
+ i18n_domain="smallelearningdemo"
+ package="smallelearningdemo"
+ >
+
+ <include package="grok" />
+ <include package="smallelearningdemo" />
+
+ <!-- Typical functional testing security setup -->
+ <securityPolicy
+ component="zope.app.securitypolicy.zopepolicy.ZopeSecurityPolicy"
+ />
+
+ <unauthenticatedPrincipal
+ id="zope.anybody"
+ title="Unauthenticated User"
+ />
+ <grant
+ permission="zope.View"
+ principal="zope.anybody"
+ />
+
+ <principal
+ id="zope.mgr"
+ title="Manager"
+ login="mgr"
+ password="mgrpw"
+ />
+
+ <role id="zope.Manager" title="Site Manager" />
+ <grantAll role="zope.Manager" />
+ <grant role="zope.Manager" principal="zope.mgr" />
+
+</configure>
Added: grokapps/SmallELearningDemo/src/smallelearningdemo/testing.py
===================================================================
--- grokapps/SmallELearningDemo/src/smallelearningdemo/testing.py (rev 0)
+++ grokapps/SmallELearningDemo/src/smallelearningdemo/testing.py 2008-09-15 22:30:28 UTC (rev 91184)
@@ -0,0 +1,7 @@
+import os.path
+import smallelearningdemo
+from zope.app.testing.functional import ZCMLLayer
+
+ftesting_zcml = os.path.join(
+ os.path.dirname(smallelearningdemo.__file__), 'ftesting.zcml')
+FunctionalLayer = ZCMLLayer(ftesting_zcml, __name__, 'FunctionalLayer')
More information about the Checkins
mailing list