Skip to content

Commit

Permalink
Merge pull request #15 from tahajahangir/bootstrap3
Browse files Browse the repository at this point in the history
Bootstrap style <select>s and optional better renderers for relations
  • Loading branch information
amleczko committed Apr 25, 2014
2 parents 973b1d0 + e9a733f commit 8b982f9
Show file tree
Hide file tree
Showing 21 changed files with 2,281 additions and 51 deletions.
23 changes: 21 additions & 2 deletions fa/bootstrap/fanstatic_resources.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,31 @@
from fanstatic import Group, Library, Resource
from js.jquery import jquery
from js.jqueryui import jqueryui
from js.bootstrap import bootstrap
from js.bootstrap import bootstrap as bootstrap_orig
from js.jquery_tablesorter import tablesorter
from fa.jquery.fanstatic_resources import fa_js

fa_bootstrap_library = Library('fa_bootstrap', 'static')
listing = Resource(fa_bootstrap_library, 'js/listing.js', depends=[jquery])
autocomplete = Resource(fa_bootstrap_library, 'js/autocomplete.js', depends=[jqueryui, fa_js])

bootstrap = Group([listing, bootstrap, tablesorter])

# bootstrap-select
select_picker_js = Resource(fa_bootstrap_library, 'js/bootstrap-select.js', depends=[bootstrap_orig],
minified='js/bootstrap-select.min.js')
select_picker_css = Resource(fa_bootstrap_library, 'css/bootstrap-select.css')
bselect_initializer = Resource(fa_bootstrap_library, 'bootstrap_select/..',
renderer=lambda _: "<script>$(function(){$('.selectpicker').selectpicker()})</script>")
select_picker = Group([select_picker_js, select_picker_css, bselect_initializer])


# dual list box
duallistbox_js = Resource(fa_bootstrap_library, 'js/jquery.bootstrap-duallistbox.js', depends=[bootstrap_orig],
minified='js/jquery.bootstrap-duallistbox.min.js')
duallistbox_css = Resource(fa_bootstrap_library, 'css/bootstrap-duallistbox.css')
duallistbox_initializer_renderer = lambda _: "<script>$(function(){$('.duallistbox').bootstrapDualListbox()})</script>"
duallistbox_initializer = Resource(fa_bootstrap_library, 'dual_init/..', renderer=duallistbox_initializer_renderer)
duallistbox = Group([duallistbox_js, duallistbox_css, duallistbox_initializer])


bootstrap = Group([listing, bootstrap_orig, tablesorter])
3 changes: 3 additions & 0 deletions fa/bootstrap/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@ class BootstrapFieldSet(FieldSet):
fatypes.Numeric: renderers.BootstrapFloatFieldRenderer,
fatypes.Interval: renderers.BootstrapIntervalFieldRenderer,
fatypes.Boolean: renderers.BootstrapBooleanFieldRenderer,
fatypes.Set: renderers.BootstrapSelectFieldRenderer,
fatypes.List: renderers.BootstrapSelectFieldRenderer,
'dropdown': renderers.BootstrapSelectFieldRenderer,
})
Binary file modified fa/bootstrap/locale/de/LC_MESSAGES/fa_bootstrap.mo
Binary file not shown.
20 changes: 12 additions & 8 deletions fa/bootstrap/locale/de/LC_MESSAGES/fa_bootstrap.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fa.bootstrap 0.3.4.dev0\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-04-06 14:57+0430\n"
"POT-Creation-Date: 2014-04-22 18:34+0430\n"
"PO-Revision-Date: 2014-04-06 15:13+0430\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: de <[email protected]>\n"
Expand All @@ -18,31 +18,35 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"

#: fa/bootstrap/actions.py:76
#: fa/bootstrap/actions.py:87
msgid "New ${model_label}"
msgstr "Hinzufügen: ${model_label}"

#: fa/bootstrap/actions.py:86
#: fa/bootstrap/actions.py:97
msgid "Save"
msgstr "Speichern"

#: fa/bootstrap/actions.py:95
#: fa/bootstrap/actions.py:105
msgid "Save and add another"
msgstr "Speichern und weitere Hinzufügen"

#: fa/bootstrap/actions.py:106
#: fa/bootstrap/actions.py:116
msgid "Edit"
msgstr "Bearbeiten"

#: fa/bootstrap/actions.py:115
#: fa/bootstrap/actions.py:125
msgid "Back"
msgstr "Zurück"

#: fa/bootstrap/actions.py:122
#: fa/bootstrap/actions.py:132
msgid "Delete"
msgstr "Löschen"

#: fa/bootstrap/actions.py:133
#: fa/bootstrap/actions.py:143
msgid "Cancel"
msgstr "Abbrechen"

#: fa/bootstrap/templates/admin/new.pt:6
msgid "Add new item"
msgstr "Neues Element hinzufügen"

Binary file modified fa/bootstrap/locale/fa/LC_MESSAGES/fa_bootstrap.mo
Binary file not shown.
20 changes: 12 additions & 8 deletions fa/bootstrap/locale/fa/LC_MESSAGES/fa_bootstrap.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fa.bootstrap 0.3.4.dev0\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-04-06 14:57+0430\n"
"POT-Creation-Date: 2014-04-22 18:34+0430\n"
"PO-Revision-Date: 2014-04-06 17:07+0430\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: fa <[email protected]>\n"
Expand All @@ -18,31 +18,35 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"

#: fa/bootstrap/actions.py:76
#: fa/bootstrap/actions.py:87
msgid "New ${model_label}"
msgstr "${model_label} جدید"

#: fa/bootstrap/actions.py:86
#: fa/bootstrap/actions.py:97
msgid "Save"
msgstr "ذخیره"

#: fa/bootstrap/actions.py:95
#: fa/bootstrap/actions.py:105
msgid "Save and add another"
msgstr "ذخیره و ایجاد بعدی"

#: fa/bootstrap/actions.py:106
#: fa/bootstrap/actions.py:116
msgid "Edit"
msgstr "ویرایش"

#: fa/bootstrap/actions.py:115
#: fa/bootstrap/actions.py:125
msgid "Back"
msgstr "بازگشت"

#: fa/bootstrap/actions.py:122
#: fa/bootstrap/actions.py:132
msgid "Delete"
msgstr "حذف"

#: fa/bootstrap/actions.py:133
#: fa/bootstrap/actions.py:143
msgid "Cancel"
msgstr "انصراف"

#: fa/bootstrap/templates/admin/new.pt:6
msgid "Add new item"
msgstr "اضافه کردن مورد جدید"

22 changes: 13 additions & 9 deletions fa/bootstrap/locale/fa_bootstrap.pot
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: fa.bootstrap 0.3.4.dev0\n"
"Project-Id-Version: fa.bootstrap 0.3.4.dev1\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-04-06 14:57+0430\n"
"POT-Creation-Date: 2014-04-22 18:34+0430\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand All @@ -17,31 +17,35 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"

#: fa/bootstrap/actions.py:76
#: fa/bootstrap/actions.py:87
msgid "New ${model_label}"
msgstr ""

#: fa/bootstrap/actions.py:86
#: fa/bootstrap/actions.py:97
msgid "Save"
msgstr ""

#: fa/bootstrap/actions.py:95
#: fa/bootstrap/actions.py:105
msgid "Save and add another"
msgstr ""

#: fa/bootstrap/actions.py:106
#: fa/bootstrap/actions.py:116
msgid "Edit"
msgstr ""

#: fa/bootstrap/actions.py:115
#: fa/bootstrap/actions.py:125
msgid "Back"
msgstr ""

#: fa/bootstrap/actions.py:122
#: fa/bootstrap/actions.py:132
msgid "Delete"
msgstr ""

#: fa/bootstrap/actions.py:133
#: fa/bootstrap/actions.py:143
msgid "Cancel"
msgstr ""

#: fa/bootstrap/templates/admin/new.pt:6
msgid "Add new item"
msgstr ""

Binary file modified fa/bootstrap/locale/fr/LC_MESSAGES/fa_bootstrap.mo
Binary file not shown.
20 changes: 12 additions & 8 deletions fa/bootstrap/locale/fr/LC_MESSAGES/fa_bootstrap.po
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: fa.bootstrap 0.3.4.dev0\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2014-04-06 14:57+0430\n"
"POT-Creation-Date: 2014-04-22 18:34+0430\n"
"PO-Revision-Date: 2014-04-06 16:45+0430\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: fr <[email protected]>\n"
Expand All @@ -18,31 +18,35 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 1.3\n"

#: fa/bootstrap/actions.py:76
#: fa/bootstrap/actions.py:87
msgid "New ${model_label}"
msgstr "Nouveau ${model_label}"

#: fa/bootstrap/actions.py:86
#: fa/bootstrap/actions.py:97
msgid "Save"
msgstr "Sauver"

#: fa/bootstrap/actions.py:95
#: fa/bootstrap/actions.py:105
msgid "Save and add another"
msgstr "Sauver et ajouter un autre"

#: fa/bootstrap/actions.py:106
#: fa/bootstrap/actions.py:116
msgid "Edit"
msgstr "Editer"

#: fa/bootstrap/actions.py:115
#: fa/bootstrap/actions.py:125
msgid "Back"
msgstr "Retour"

#: fa/bootstrap/actions.py:122
#: fa/bootstrap/actions.py:132
msgid "Delete"
msgstr "Supprimer"

#: fa/bootstrap/actions.py:133
#: fa/bootstrap/actions.py:143
msgid "Cancel"
msgstr "Annuler"

#: fa/bootstrap/templates/admin/new.pt:6
msgid "Add new item"
msgstr "Ajouter un nouvel élément"

31 changes: 30 additions & 1 deletion fa/bootstrap/renderers.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def render(self, **kwargs):
if 'class' in kwargs:
kwargs['class'] += ' form-control'
else:
kwargs['class'] = ' form-control'
kwargs['class'] = 'form-control'
return super(BootstrapFieldMixin, self).render(**kwargs)


Expand All @@ -84,3 +84,32 @@ class BootstrapFloatFieldRenderer(BootstrapFieldMixin, fields.FloatFieldRenderer

class BootstrapIntervalFieldRenderer(BootstrapFieldMixin, fields.IntervalFieldRenderer):
pass


class BootstrapSelectFieldRenderer(BootstrapFieldMixin, fields.SelectFieldRenderer):
"""
accepts "width" option add applies it by patching style attribute
"""
def render(self, **kwargs):
auto_width = kwargs.pop('width', None)
if auto_width:
kwargs['style'] = kwargs.get('style', '') + '; width: ' + str(auto_width)
return super(BootstrapSelectFieldRenderer, self).render(**kwargs)


class BootstrapSelectPickerFieldRenderer(BootstrapSelectFieldRenderer):
"""
Options can be configured via data-* attributes
"""
def render(self, **kwargs):
fanstatic_resources.select_picker.need()
kwargs['class'] = kwargs.get('class', '') + ' selectpicker'
# kwargs['data-live-search'] = 'true'
return fields.SelectFieldRenderer.render(self, **kwargs)


class DualListBoxFieldRenderer(BootstrapSelectFieldRenderer):
def render(self, **kwargs):
fanstatic_resources.duallistbox.need()
kwargs['class'] = kwargs.get('class', '') + ' duallistbox'
return fields.SelectFieldRenderer.render(self, **kwargs)
Original file line number Diff line number Diff line change
@@ -1,16 +1,57 @@
from datetime import timedelta
from sqlalchemy.sql.schema import ForeignKey

import transaction
from sqlalchemy.orm import scoped_session
from fa.bootstrap import renderers
from formalchemy import Column as FAColumn
from sqlalchemy.orm import scoped_session, relationship
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.exc import IntegrityError
from sqlalchemy import Integer, Unicode, Column, Float, Interval, Boolean
from sqlalchemy import Integer, Unicode, Column, Float, Interval, Boolean, Table
from zope.sqlalchemy import ZopeTransactionExtension
from pyramid_formalchemy import events

DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
Base = declarative_base()


class ModelGroup(Base):
__tablename__ = 'gropus'
id = Column(Integer, primary_key=True)
name = Column(Unicode(255), unique=True)

def __unicode__(self):
return self.name

def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)


class ModelItem(Base):
__tablename__ = 'items'
id = Column(Integer, primary_key=True)
name = Column(Unicode(255), unique=True)

def __unicode__(self):
return self.name

def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)

model_items_1_table = Table('model_items_1', Base.metadata,
Column('item_id', Integer, ForeignKey(ModelItem.id), primary_key=True),
Column('model_id', Integer, ForeignKey('models.id'), primary_key=True))
model_items_2_table = Table('model_items_2', Base.metadata,
Column('item_id', Integer, ForeignKey(ModelItem.id), primary_key=True),
Column('model_id', Integer, ForeignKey('models.id'), primary_key=True))
model_items_3_table = Table('model_items_3', Base.metadata,
Column('item_id', Integer, ForeignKey(ModelItem.id), primary_key=True),
Column('model_id', Integer, ForeignKey('models.id'), primary_key=True))


class MyModel(Base):
__tablename__ = 'models'
id = Column(Integer, primary_key=True)
Expand All @@ -19,16 +60,38 @@ class MyModel(Base):
float_value = Column(Float)
boolean = Column(Boolean)
interval = Column(Interval)
many_to_one_1_id = Column(Integer, ForeignKey(ModelGroup.id))
many_to_one_1 = relationship(ModelGroup, foreign_keys=many_to_one_1_id)
many_to_one_2_id = FAColumn(Integer, ForeignKey(ModelGroup.id), html={'width': 'auto'})
many_to_one_2 = relationship(ModelGroup, foreign_keys=many_to_one_2_id)
many_to_one_3_id = FAColumn(Integer, ForeignKey(ModelGroup.id),
renderer=renderers.BootstrapSelectPickerFieldRenderer)
many_to_one_3 = relationship(ModelGroup, foreign_keys=many_to_one_3_id)
many_to_many_1 = relationship(ModelItem, secondary=model_items_1_table)
many_to_many_2 = relationship(ModelItem, secondary=model_items_2_table)
many_to_many_3 = relationship(ModelItem, secondary=model_items_3_table)

def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)


@events.subscriber([MyModel, events.IBeforeEditRenderEvent])
def before_my_model_render(context, event):
# change renderer for many_to_many fields, unfortunely this is not possible via `Column` attributes
# see: https://github.com/FormAlchemy/formalchemy/issues/57
fs = event.kwargs['fs']
fs['many_to_many_2'].set(renderer=renderers.BootstrapSelectPickerFieldRenderer)
fs['many_to_many_3'].set(renderer=renderers.DualListBoxFieldRenderer)


def populate():
session = DBSession()
model = MyModel(name=u'test name', value=55, float_value=3.5, interval=timedelta(4), boolean=True)
session.add(model)
session.add(ModelGroup(name='Group1'))
session.add(ModelGroup(name='Group2'))
for i in range(500):
session.add(ModelItem(name='Item ' + str(i)))
session.add(MyModel(name=u'test name', value=55, float_value=3.5, interval=timedelta(4), boolean=True))
session.flush()
transaction.commit()

Expand Down
Loading

0 comments on commit 8b982f9

Please sign in to comment.