def column_clearfix(fixture): """If a logical row spans more than one visual row for a device size, bootstrap clearfixes are automatically inserted to ensure cells in resultant visual rows are neatly arranged. """ # Case: Adding a correct clearfix in the right place wrapping_layout = ColumnLayout(('column_a', ResponsiveSize(xs=8).offset(xs=2)), ('column_b', ResponsiveSize(xs=2).offset(xs=2)) ) widget = Div(fixture.view).use_layout(wrapping_layout) [column_a, clearfix, column_b] = widget.children vassert( [column_a, column_b] == [i for i in wrapping_layout.columns.values()] ) vassert( 'clearfix' in clearfix.get_attribute('class') ) vassert( 'visible-xs-block' in clearfix.get_attribute('class') ) # Case: When clearfix needs to take "implicit" sizes of smaller device classes into account wrapping_layout = ColumnLayout(('column_a', ResponsiveSize(xs=8).offset(xs=2)), ('column_b', ResponsiveSize(lg=2).offset(lg=2)) ) widget = Div(fixture.view).use_layout(wrapping_layout) [column_a, clearfix, column_b] = widget.children vassert( [column_a, column_b] == [i for i in wrapping_layout.columns.values()] ) vassert( 'clearfix' in clearfix.get_attribute('class') ) vassert( 'visible-lg-block' in clearfix.get_attribute('class') ) # Case: When no clearfix must be added non_wrapping_layout = ColumnLayout(('column_a', ResponsiveSize(xs=2).offset(xs=2)), ('column_b', ResponsiveSize(xs=2)) ) widget = Div(fixture.view).use_layout(non_wrapping_layout) [column_a, column_b] = widget.children vassert( [column_a, column_b] == [i for i in non_wrapping_layout.columns.values()] )
def test_column_clearfix(web_fixture): """If a logical row spans more than one visual row for a device size, bootstrap clearfixes are automatically inserted to ensure cells in resultant visual rows are neatly arranged. """ # Case: Adding a correct clearfix in the right place wrapping_layout = ColumnLayout(ColumnOptions('column_a', size=ResponsiveSize(md=8), offsets=ResponsiveSize(md=2)), ColumnOptions('column_b', size=ResponsiveSize(md=2), offsets=ResponsiveSize(md=2)) ) widget = Div(web_fixture.view).use_layout(wrapping_layout) [column_a, clearfix, column_b] = widget.children assert [column_a, column_b] == [i for i in wrapping_layout.columns.values()] assert 'clearfix' in clearfix.get_attribute('class') assert 'hidden-sm' in clearfix.get_attribute('class') # Case: When clearfix needs to take "implicit" sizes of smaller device classes into account wrapping_layout = ColumnLayout(ColumnOptions('column_a', size=ResponsiveSize(xs=8), offsets=ResponsiveSize(xs=2)), ColumnOptions('column_b', size=ResponsiveSize(lg=2), offsets=ResponsiveSize(lg=2)) ) widget = Div(web_fixture.view).use_layout(wrapping_layout) [column_a, clearfix, column_b] = widget.children assert [column_a, column_b] == [i for i in wrapping_layout.columns.values()] assert 'clearfix' in clearfix.get_attribute('class') assert 'hidden-md' in clearfix.get_attribute('class') # Case: When no clearfix must be added non_wrapping_layout = ColumnLayout(ColumnOptions('column_a', size=ResponsiveSize(xs=2), offsets=ResponsiveSize(xs=2)), ColumnOptions('column_b', size=ResponsiveSize(xs=2)) ) widget = Div(web_fixture.view).use_layout(non_wrapping_layout) [column_a, column_b] = widget.children assert [column_a, column_b] == [i for i in non_wrapping_layout.columns.values()]
def customise_widget(self): self.container = self.widget.add_child(Div(self.view)) self.container.use_layout(Container(fluid=False)) self.centre = self.container.add_child(Div(self.view)) column_layout = ColumnLayout(('left', ResponsiveSize(md=4)), ('right', ResponsiveSize(md=8))) self.centre.use_layout(column_layout)
def assemble(self): self.define_page(HTML5Page).use_layout( PageLayout(document_layout=Container(), contents_layout=ColumnLayout( ('main', ResponsiveSize(lg=6))).with_slots())) home = self.define_view('/', title='File upload demo') home.set_slot('main', CommentPostPanel.factory())
def __init__(self, view): super(CommentForm, self).__init__(view, 'myform') comment = Comment() layout = ColumnLayout( ColumnOptions('left', size=ResponsiveSize(lg=6)), ColumnOptions('right', size=ResponsiveSize(lg=6))) # .add_child() returns the added child here: row = self.add_child(Div(view).use_layout(layout)) left_column = row.layout.columns['left'] # ... and .use_layout() returns the Widget it is called on section = Div(view).use_layout(FormLayout()) left_column.add_child(section) email_input = TextInput(self, comment.fields.email_address) section.layout.add_input(email_input) inline_section = Div(view).use_layout(InlineFormLayout()) left_column.add_child(inline_section) text_input = TextInput(self, comment.fields.text) inline_section.layout.add_input(text_input) right_column = row.layout.columns['right'] right_column.add_child( LiteralHTML.from_restructured_text( view, ''' This form has two columns. Inputs go into the left one and this text into the right one. Some inputs are stacked and others are inlined. Arbitrarily complicated layouts can be created like this.'''))
def __init__(self, view, main_bookmarks): super().__init__(view) self.use_layout(PageLayout(document_layout=Container())) contents_layout = ColumnLayout(ColumnOptions('main', ResponsiveSize(lg=6))).with_slots() self.layout.contents.use_layout(contents_layout) menu = Nav(view).use_layout(TabLayout()).with_bookmarks(main_bookmarks) self.layout.header.add_child(menu)
def add_twelve(self): div = Div(self.view).use_layout(ColumnLayout()) self.body.add_child(div) for i in range(1, 13): column = div.layout.add_column(str(i), size=ResponsiveSize(md=1)) column.add_child(P(self.view, text='1/12th on md and larger'))
def assemble(self): self.define_page(HTML5Page).use_layout( PageLayout(document_layout=Container(), contents_layout=ColumnLayout( ('main', ResponsiveSize(lg=6))).with_slots())) home = self.define_view('/', title='Basic HTML Inputs demo') home.set_slot('main', ExampleForm.factory('myform'))
def assemble(self): page_layout = PageLayout(document_layout=Container(), contents_layout=ColumnLayout(('main', ResponsiveSize(lg=6))).with_slots()) self.define_page(HTML5Page).use_layout(page_layout) account_user_interface_factory = self.define_user_interface('/a_ui', AccountUI, {'main_slot': 'main'}, name='test_ui', bookmarks=fixture.bookmarks) fixture.account_user_interface_factory = account_user_interface_factory
def assemble(self): contents_layout = ColumnLayout( ('main', ResponsiveSize(lg=6))).with_slots() page_layout = PageLayout(contents_layout=contents_layout, document_layout=Container()) self.define_page(HTML5Page).use_layout(page_layout) comment = Comment() home = self.define_view('/', title='Page flow demo') home.set_slot('main', CommentForm.factory(comment)) thanks = self.define_view('/thanks', title='Thank you!') thanks_text = 'Thanks for submitting your comment' thanks.set_slot('main', P.factory(text=thanks_text)) none_submitted = self.define_view('/none', title='Nothing to say?') none_text = 'Mmm, you submitted an empty comment??' none_submitted.set_slot('main', P.factory(text=none_text)) self.define_transition(comment.events.submit, home, thanks, guard=Action(comment.contains_text)) self.define_transition(comment.events.submit, home, none_submitted, guard=Not(Action(comment.contains_text)))
def __init__(self, view, main_bookmarks): super(MenuPage, self).__init__(view) self.use_layout(PageLayout(document_layout=Container())) contents_layout = ColumnLayout( ('main', ResponsiveSize(md=4))).with_slots() self.layout.contents.use_layout(contents_layout) self.layout.header.add_child( Nav(view).use_layout(TabLayout()).with_bookmarks(main_bookmarks))
def assemble(self): page_layout = PageLayout(document_layout=Container(), contents_layout=ColumnLayout( ('main', ResponsiveSize(lg=6))).with_slots()) self.define_page(HTML5Page).use_layout(page_layout) find = self.define_view('/', title='Refreshing widget') find.set_slot('main', HomePanel.factory())
def test_column_gutters(web_fixture): """A ColumnLayout can be made that does not include gutters in the layout.""" fixture = web_fixture widget = Div(fixture.view).use_layout(ColumnLayout('column_name_a', 'column_name_b').without_gutters()) assert 'no-gutters' in widget.get_attribute('class').split()
def test_horizontal_alignment(web_fixture): """You can specify how columns are aligned horizontally.""" widget = Div( web_fixture.view).use_layout(ColumnLayout().with_justified_content( ContentJustification(md='around'))) assert 'justify-content-md-around' in widget.get_attribute('class').split()
def test_columns_classes(web_fixture): """The Div added for each column specified to ColumnLayout is given a CSS class derived from the column name.""" fixture = web_fixture widget = Div(fixture.view).use_layout(ColumnLayout('column_name_a')) column_a = widget.layout.columns['column_name_a'] assert 'column-column_name_a' in column_a.get_attribute('class')
def assemble(self): page_layout = PageLayout( document_layout=Container(), contents_layout=ColumnLayout( ColumnOptions('main', size=ResponsiveSize(lg=6))).with_slots()) self.define_page(HTML5Page).use_layout(page_layout) find = self.define_view('/', title='Addresses') find.set_slot('main', AddressBookPanel.factory())
def __init__(self, view): super(AddressBookPage, self).__init__(view) self.use_layout(PageLayout(document_layout=Container())) contents_layout = ColumnLayout(('secondary', ResponsiveSize(md=3)), ('main', ResponsiveSize(md=9))).with_slots() self.layout.contents.use_layout(contents_layout) nav = Nav(view).use_layout(PillLayout(stacked=True)) contents_layout.columns['secondary'].add_child(nav.with_languages())
def assemble(self): self.define_page(HTML5Page).use_layout(PageLayout(document_layout=Container(), contents_layout=ColumnLayout(ColumnOptions('main', size=ResponsiveSize(lg=6))).with_slots())) accounts = self.define_user_interface('/accounts', AccountUI, {'main_slot': 'main'}, name='test_ui', bookmarks=fixture.account_bookmarks) login_bookmark = accounts.get_bookmark(relative_path='/login') self.define_user_interface('/inbox', InboxUI, {'main_slot': 'main'}, name='test_ui', login_bookmark=login_bookmark, get_queues=get_queues)
def test_column_layout_default_options(web_fixture): """You can also pass only column names instead of ColumnOptions objects in which case the column will be configured with default ColumnOptions.""" widget = Div(web_fixture.view) widget.use_layout(ColumnLayout('column_a')) [column_a] = widget.children assert 'col' in column_a.get_attribute('class')
def assemble(self): self.define_page(HTML5Page).use_layout( PageLayout( document_layout=Container(), contents_layout=ColumnLayout( ColumnOptions('main', size=ResponsiveSize(lg=6))).with_slots())) home = self.define_view('/', title='Themed example') home.set_slot('main', SomeWidget.factory())
def assemble(self): self.define_page(HTML5Page).use_layout( PageLayout( document_layout=Container(), contents_layout=ColumnLayout( ColumnOptions('main', size=ResponsiveSize(lg=6))).with_slots())) home = self.define_view('/', title='Dynamic content demo') home.set_slot('main', AllocationDetailForm.factory())
def assemble(self): self.define_page(HTML5Page).use_layout( PageLayout( document_layout=Container(), contents_layout=ColumnLayout( ColumnOptions('main', size=ResponsiveSize(lg=6))).with_slots())) home = self.define_view('/', title='Responsive disclosure demo') home.set_slot('main', NewInvestmentForm.factory())
def __init__(self, view, bookmarks): super(MyCustomPage, self).__init__(view) self.use_layout(PageLayout(document_layout=Container())) contents_layout = ColumnLayout(ColumnOptions('secondary', size=ResponsiveSize(md=3)), ColumnOptions('main', size=ResponsiveSize(md=9))).with_slots() self.layout.contents.use_layout(contents_layout) menu = Nav(view).use_layout(TabLayout()).with_bookmarks(bookmarks) self.layout.header.add_child(menu)
def test_column_slots(web_fixture): """A ColumnLayout can be made that adds a Slot to each added column, named after the column it is added to.""" fixture = web_fixture widget = Div(fixture.view).use_layout(ColumnLayout('column_name_a', 'column_name_b').with_slots()) column_a, column_b = widget.layout.columns.values() assert 'column_name_a' in column_a.available_slots assert 'column_name_b' in column_b.available_slots
def assemble(self): contents_layout = ColumnLayout( ColumnOptions('main', ResponsiveSize(lg=6))).with_slots() page_layout = PageLayout(contents_layout=contents_layout, document_layout=Container()) self.define_page(HTML5Page).use_layout(page_layout) self.define_user_interface('/', PageFlowExampleUI, name='pageflow', slot_map={'main': 'main'})
def test_adding_columns_later_specifying_the_widget_to_use(web_fixture): """Specify the widget to use as a wrapper for the column. By default it is a Div""" widget = Div(web_fixture.view).use_layout(ColumnLayout()) column_widget_to_use = P(web_fixture.view) widget.layout.add_column('a_column', column_widget=column_widget_to_use) [added_column] = widget.children assert added_column is column_widget_to_use
def add_two(self): layout = ColumnLayout(('left', ResponsiveSize(md=4)), ('right', ResponsiveSize(md=8))) div = Div(self.view).use_layout(layout) self.body.add_child(div) div.layout.columns['left'].add_child( P(self.view, text='4/12ths on md and larger')) div.layout.columns['right'].add_child( P(self.view, text='8/12ths on md and larger'))
def adding_columns(fixture): """You can add additional columns after construction.""" widget = Div(fixture.view).use_layout(ColumnLayout()) vassert( not widget.children ) widget.layout.add_column(ResponsiveSize(lg=4)) [added_column] = widget.children vassert( added_column.get_attribute('class') == 'col-lg-4' )
def __init__(self, view): super().__init__(view) self.use_layout( PageLayout( document_layout=Container(), contents_layout=ColumnLayout( ColumnOptions('main', size=ResponsiveSize(lg=6))).with_slots())) navbar = Navbar(view).use_layout(NavbarLayout()) navbar.layout.set_brand_text('My Site') self.layout.header.add_child(navbar)
def test_vertical_alignment(web_fixture): """You can specify how columns are aligned vertically and override the alignment of a specific column.""" widget = Div(web_fixture.view).use_layout(ColumnLayout().with_vertical_alignment(Alignment(md='center'))) defaulted_column = widget.layout.add_column('default_column') specifically_overridden_column = widget.layout.add_column('overridden_column', vertical_align=Alignment(md='end')) assert 'align-items-md-center' in widget.get_attribute('class').split() assert 'align-self-md-end' in specifically_overridden_column.get_attribute('class').split() assert 'align' not in defaulted_column.get_attribute('class')