wcs/wcs/admin/categories.py

285 lines
10 KiB
Python

# w.c.s. - web application for online forms
# Copyright (C) 2005-2010 Entr'ouvert
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see <http://www.gnu.org/licenses/>.
from quixote import get_request
from quixote import get_response
from quixote import redirect
from quixote.directory import Directory
from quixote.html import TemplateIO
from quixote.html import htmltext
from wcs.carddef import CardDef
from wcs.categories import CardDefCategory
from wcs.categories import Category
from wcs.formdef import FormDef
from wcs.qommon import N_
from wcs.qommon import _
from wcs.qommon.backoffice.menu import html_top
from wcs.qommon.form import Form
from wcs.qommon.form import HtmlWidget
from wcs.qommon.form import StringWidget
from wcs.qommon.form import WysiwygTextWidget
class CategoryUI:
category_class = Category
def __init__(self, category):
self.category = category
if self.category is None:
self.category = self.category_class()
def get_form(self):
form = Form(enctype='multipart/form-data')
form.add(
StringWidget, 'name', title=_('Category Name'), required=True, size=30, value=self.category.name
)
form.add(
WysiwygTextWidget,
'description',
title=_('Description'),
cols=80,
rows=10,
value=self.category.description,
)
if self.category_class == Category:
form.add(
StringWidget,
'redirect_url',
size=32,
title=_('URL Redirection'),
hint=_('If set, redirect the site category page to the given URL.'),
value=self.category.redirect_url,
)
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
return form
def submit_form(self, form):
self.category.name = form.get_widget('name').parse()
name = form.get_widget('name').parse()
category_names = [x.name for x in self.category_class.select() if x.id != self.category.id]
if name in category_names:
form.get_widget('name').set_error(_('This name is already used'))
raise ValueError()
self.category.description = form.get_widget('description').parse()
if form.get_widget('redirect_url'):
self.category.redirect_url = form.get_widget('redirect_url').parse()
self.category.store()
class CardDefCategoryUI(CategoryUI):
category_class = CardDefCategory
class CategoryPage(Directory):
category_class = Category
category_ui_class = CategoryUI
formdef_class = FormDef
usage_title = N_('Forms in this category')
empty_message = N_('no form associated to this category')
_q_exports = ['', 'edit', 'delete', 'description']
def __init__(self, component):
self.category = self.category_class.get(component)
self.category_ui = self.category_ui_class(self.category)
get_response().breadcrumb.append((component + '/', self.category.name))
def _q_index(self):
html_top('categories', title=self.category.name)
r = TemplateIO(html=True)
r += htmltext('<div id="appbar">')
r += htmltext('<h2>%s</h2>') % self.category.name
r += htmltext('<span class="actions">')
r += htmltext('<a href="delete" rel="popup">%s</a>') % _('Delete')
r += htmltext('<a href="edit">%s</a>') % _('Edit')
r += htmltext('</span>')
r += htmltext('</div>')
if self.category.description:
r += htmltext('<div class="bo-block">')
r += self.category.get_description_html_text()
r += htmltext('</div>')
formdefs = self.formdef_class.select(order_by='name')
formdefs = [x for x in formdefs if x.category_id == self.category.id]
r += htmltext('<div class="bo-block">')
r += htmltext('<h3>%s</h3>') % _(self.usage_title)
r += htmltext('<ul>')
for formdef in formdefs:
r += htmltext('<li><a href="../../%s/">') % str(formdef.id)
r += formdef.name
r += htmltext('</a></li>')
if not formdefs:
r += htmltext('<li>%s</li>') % _(self.empty_message)
r += htmltext('</ul>')
r += htmltext('</div>')
return r.getvalue()
def edit(self):
form = self.category_ui.get_form()
if form.get_widget('cancel').parse():
return redirect('..')
if form.is_submitted() and not form.has_errors():
try:
self.category_ui.submit_form(form)
except ValueError:
pass
else:
return redirect('..')
get_response().breadcrumb.append(('edit', _('Edit')))
html_top('categories', title=_('Edit Category'))
r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('Edit Category')
r += form.render()
return r.getvalue()
def delete(self):
form = Form(enctype='multipart/form-data')
form.widgets.append(HtmlWidget('<p>%s</p>' % _('You are about to irrevocably delete this category.')))
form.add_submit('delete', _('Delete'))
form.add_submit('cancel', _('Cancel'))
if form.get_widget('cancel').parse():
return redirect('.')
if not form.is_submitted() or form.has_errors():
get_response().breadcrumb.append(('delete', _('Delete')))
html_top('categories', title=_('Delete Category'))
r = TemplateIO(html=True)
r += htmltext('<h2>%s %s</h2>') % (_('Deleting Category:'), self.category.name)
r += form.render()
return r.getvalue()
else:
self.category.remove_self()
return redirect('..')
def description(self):
displayed_text = self.category.description
form = Form(enctype='multipart/form-data')
form.add(
WysiwygTextWidget, 'description', title=_('Description'), value=displayed_text, cols=80, rows=10
)
form.add_submit('submit', _('Submit'))
form.add_submit('cancel', _('Cancel'))
if form.get_submit() == 'cancel':
return redirect('.')
if form.is_submitted() and not form.has_errors():
self.category.description = form.get_widget('description').parse()
self.category.store()
return redirect('.')
get_response().breadcrumb.append(('description', _('Description')))
html_top('categories', title=_('Edit Category Description'))
r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('Edit Category Description')
r += form.render()
return r.getvalue()
class CardDefCategoryPage(CategoryPage):
category_class = CardDefCategory
category_ui_class = CardDefCategoryUI
formdef_class = CardDef
usage_title = N_('Card models in this category')
empty_message = N_('no card model associated to this category')
class CategoriesDirectory(Directory):
_q_exports = ['', 'new', 'update_order']
category_class = Category
category_ui_class = CategoryUI
category_page_class = CategoryPage
category_explanation = N_('Categories are used to sort the different forms.')
def _q_index(self):
get_response().add_javascript(['jquery.js', 'jquery-ui.js', 'biglist.js', 'qommon.wysiwyg.js'])
html_top('categories', title=_('Categories'))
r = TemplateIO(html=True)
r += htmltext('<div id="appbar">')
r += htmltext('<h2>%s</h2>') % _('Categories')
r += htmltext('<span class="actions">')
r += htmltext('<a class="new-item" href="new" rel="popup">%s</a>') % _('New Category')
r += htmltext('</span>')
r += htmltext('</div>')
r += htmltext('<div class="explanation bo-block"><p>%s</p></div>') % _(self.category_explanation)
categories = self.category_class.select()
r += htmltext('<ul class="biglist sortable" id="category-list">')
self.category_class.sort_by_position(categories)
for category in categories:
r += htmltext('<li class="biglistitem" id="itemId_%s">') % category.id
r += htmltext('<strong class="label"><a href="%s/">%s</a></strong>') % (
category.id,
category.name,
)
r += htmltext('</li>')
r += htmltext('</ul>')
return r.getvalue()
def update_order(self):
request = get_request()
new_order = request.form['order'].strip(';').split(';')
categories = self.category_class.select()
dict = {}
for l in categories:
dict[str(l.id)] = l
for i, o in enumerate(new_order):
dict[o].position = i + 1
dict[o].store()
return 'ok'
def new(self):
get_response().breadcrumb.append(('new', _('New')))
category_ui = self.category_ui_class(None)
form = category_ui.get_form()
if form.get_widget('cancel').parse():
return redirect('.')
if form.is_submitted() and not form.has_errors():
try:
category_ui.submit_form(form)
except ValueError:
pass
else:
return redirect('.')
html_top('categories', title=_('New Category'))
r = TemplateIO(html=True)
r += htmltext('<h2>%s</h2>') % _('New Category')
r += form.render()
return r.getvalue()
def _q_lookup(self, component):
return self.category_page_class(component)
def _q_traverse(self, path):
get_response().breadcrumb.append(('categories/', _('Categories')))
return super()._q_traverse(path)
class CardDefCategoriesDirectory(CategoriesDirectory):
category_class = CardDefCategory
category_ui_class = CardDefCategoryUI
category_page_class = CardDefCategoryPage
category_explanation = N_('Categories are used to sort the different card models.')