Пример #1
0
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()]
Пример #2
0
 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)
Пример #3
0
    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.'''))
Пример #4
0
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()] )  
Пример #5
0
 def add_upload_controls(self):
     controls_panel = self.upload_form.add_child(Div(self.view)).use_layout(FormLayout())
     file_input = controls_panel.layout.add_input(FileInput(self.upload_form.form, self.fields.uploaded_file), hide_label=True)
     
     button_addon = file_input.html_representation.add_child(Div(self.view))
     button_addon.append_class('input-group-append')
     button_addon.add_child(Button(self.upload_form.form, self.events.upload_file, style='secondary', outline=True))
     return controls_panel
Пример #6
0
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()
Пример #7
0
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()
Пример #8
0
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')
Пример #9
0
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')
Пример #10
0
def test_column_layout_unspecified_size(web_fixture):
    """Specifying a size of True for a device class means that the size is automatically computed by dividing available
       space equally amongst all the columns so specified."""

    layout = ColumnLayout(ColumnOptions('column_a', size=ResponsiveSize(lg=True)), ColumnOptions('column_b', size=ResponsiveSize(lg=True)))
    widget = Div(web_fixture.view)

    widget.use_layout(layout)

    column_a, column_b = widget.children

    assert 'col-lg' in column_a.get_attribute('class')
    assert 'col-lg' in column_b.get_attribute('class')
Пример #11
0
def test_containers(web_fixture):
    """There are two types of Bootstrap containers:  a full width container, and a responsive (fluid) container."""

    widget = Div(web_fixture.view).use_layout(Container())
    tester = WidgetTester(widget)

    css_class = tester.xpath('//div')[0].attrib['class']
    assert 'container' == css_class

    widget = Div(web_fixture.view).use_layout(Container(fluid=True))
    tester = WidgetTester(widget)

    css_class = tester.xpath('//div')[0].attrib['class']
    assert 'container-fluid' == css_class
Пример #12
0
    def __init__(self, form, bound_field):
        file_input = FileInputButton(form, bound_field)
        super().__init__(file_input)

        self.input_group = self.add_child(Div(self.view))
        self.input_group.append_class('input-group')
        self.input_group.append_class('reahl-bootstrapfileinput')
        self.set_html_representation(self.input_group)

        div = self.input_group.add_child(Div(form.view))
        div.append_class('input-group-prepend')
        div.add_child(file_input)

        filename_input = self.input_group.add_child(Span(self.view, text=_('No files chosen')))
        filename_input.append_class('form-control')
Пример #13
0
    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'))
Пример #14
0
    def customise_widget(self):
        super().customise_widget()
        if not self.widget.css_id_is_set:
            raise ProgrammerError('%s has no css_id set. A %s can only be used with a Widget that has a css_id' %
                                  (self.widget, self.__class__))

        collapsing_content = Div(self.view, css_id='%s_collapsable' % self.widget.css_id)
        collapsing_content.append_class('navbar-collapse')
        self.collapsing_content = collapsing_content
        self.contents_container.add_child(collapsing_content)
        self.contents_container = collapsing_content

        self.add_toggle(collapsing_content, text=self.text, left_aligned=self.align_toggle_left)

        toggle_size = self.collapse_below_device_class.one_smaller
        self.nav.append_class('navbar-expand-%s' % toggle_size.name)
Пример #15
0
def test_brand_may_be_collapsed_with_expandable_content(
        web_fixture, navbar_fixture, brand_collapse_fixture):
    """Brands may be collapse along with the other content."""

    responsive_navbar = navbar_fixture.navbar
    responsive_navbar.set_id('my_navbar_id')
    responsive_navbar.use_layout(
        ResponsiveLayout(
            'md',
            collapse_brand_with_content=brand_collapse_fixture.brand_collapse))
    responsive_navbar.layout.add(navbar_fixture.nav)

    brand_widget = Div(web_fixture.view)
    responsive_navbar.layout.set_brand(brand_widget)

    if brand_collapse_fixture.brand_collapse:
        [toggle, collapse_div] = responsive_navbar.children[0].children
        [brand, navbar_nav] = collapse_div.children
    else:
        [brand, toggle, collapse_div] = responsive_navbar.children[0].children
        [navbar_nav] = collapse_div.children

    assert brand is brand_widget
    assert 'navbar-collapse' in collapse_div.get_attribute('class')
    assert 'navbar-nav' in navbar_nav.html_representation.get_attribute(
        'class')
    assert 'navbar-toggler' in toggle.get_attribute('class')
Пример #16
0
    def __init__(self, view, css_id, show_indicators=True, interval=5000, pause='hover', wrap=True, keyboard=True, min_height=None):
        super(Carousel, self).__init__(view)
        self.carousel_panel = self.add_child(Div(view, css_id=css_id))
        self.carousel_panel.append_class('carousel')
        self.carousel_panel.append_class('slide')
        self.carousel_panel.set_attribute('data-ride', 'carousel')

        self.carousel_panel.set_attribute('data-interval', six.text_type(interval))
        pause_option = HTMLAttributeValueOption(pause or 'false', True, constrain_value_to=['hover', 'false'])
        self.carousel_panel.set_attribute('data-pause', pause_option.as_html_snippet())
        self.carousel_panel.set_attribute('data-wrap', 'true' if wrap else 'false')
        self.carousel_panel.set_attribute('data-keyboard', 'true' if keyboard else 'false')
        if min_height:
            style = self.carousel_panel.add_child(HTMLElement(self.view, 'style', children_allowed=True))
            css_id = self.carousel_panel.css_id
            style.add_child(TextNode(self.view, '#%s .carousel-item { min-height: %sem; }' % (css_id, min_height)))

        self.show_indicators = show_indicators
        if self.show_indicators:
            self.indicator_list = self.carousel_panel.add_child(self.create_indicator_list())
        self.inner = self.carousel_panel.add_child(self.create_inner())
        self.slides = []

        self.add_control(previous=True)
        self.add_control()
Пример #17
0
def test_adding_other_than_form_or_nav_is_not_allowed(web_fixture,
                                                      navbar_fixture):
    """Only Navs, Forms and Text may be added to a NavbarLayout."""

    navbar = navbar_fixture.navbar.use_layout(NavbarLayout())
    not_a_form_or_nav = Div(web_fixture.view)

    with expected(IsInstance):
        navbar.layout.add(not_a_form_or_nav)

    # Case: Form
    navbar = navbar_fixture.new_navbar().use_layout(NavbarLayout())
    navbar.layout.add(navbar_fixture.form)
    [added_widget] = navbar.children[0].children
    assert added_widget is navbar_fixture.form
    assert 'form-inline' in navbar_fixture.form.get_attribute('class')

    # Case: Nav
    navbar = navbar_fixture.new_navbar().use_layout(NavbarLayout())
    assert 'navbar-nav' not in navbar_fixture.nav.html_representation.get_attribute(
        'class').split(' ')
    navbar.layout.add(navbar_fixture.nav)
    [added_widget] = navbar.children[0].children
    assert added_widget is navbar_fixture.nav
    assert 'navbar-nav' in navbar_fixture.nav.html_representation.get_attribute(
        'class').split(' ')

    # Case: Text
    navbar = navbar_fixture.new_navbar().use_layout(NavbarLayout())
    navbar.layout.add(navbar_fixture.textnode)
    [added_widget] = navbar.children[0].children
    [textnode] = added_widget.children
    assert isinstance(added_widget, Span)
    assert textnode is navbar_fixture.textnode
    assert 'navbar-text' in added_widget.get_attribute('class').split(' ')
Пример #18
0
def test_checkbox_with_inline_layout(web_fixture, choices_fixture):
    """PrimitiveCheckboxInputs can be rendered inlined with each other by using the ChoicesLayout with the inline=True setting."""
    fixture = choices_fixture

    inlined_container = Div(web_fixture.view).use_layout(ChoicesLayout(inline=True))
    inlined_container.layout.add_choice(PrimitiveCheckboxInput(fixture.form, fixture.boolean_field))

    assert 'custom-control-inline' in inlined_container.children[0].get_attribute('class').split(' ')
Пример #19
0
    def add(self, widget, left=None, right=None):
        """Adds the given Form or Nav `widget` to the Navbar.

        :param widget: A :class:`~reahl.web.bootstrap.navs.Nav` or :class:`~reahl.web.bootstrap.ui.Form` to add.
        :keyword left: If True, `widget` is aligned to the left of the Navbar.
        :keyword right: If True, `widget` is aligned to the right of the Navbar.
        """
        if isinstance(widget, reahl.web.bootstrap.navs.Nav):
            widget.append_class('navbar-nav')
        if left or right:
            child = Div(self.view).use_layout(
                ResponsiveFloat(left=left, right=right))
            child.add_child(widget)
        else:
            child = widget
        self.contents_container.add_child(child)
        return widget
Пример #20
0
 def make_allocation_input(self, allocation, field):
     div = Div(self.view).use_layout(FormLayout())
     div.layout.add_input(TextInput(self,
                                    field,
                                    name_discriminator=allocation.fund_code,
                                    refresh_widget=self),
                          hide_label=True)
     return div
Пример #21
0
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')
Пример #22
0
 def __init__(self, view, caption_text=None, summary=None, css_id=None):
     super().__init__(view)
     self.main_div = self.add_child(Div(view, css_id=css_id))
     self.set_html_representation(self.main_div)
     self.table = self.main_div.add_child(
         reahl.web.ui.Table(view,
                            caption_text=caption_text,
                            summary=summary))
     self.table.append_class('table')
Пример #23
0
 def create_form_group(self, html_input):
     if isinstance(html_input, RadioButtonSelectInput):
         form_group = self.widget.add_child(FieldSet(self.view))
     else:
         form_group = self.widget.add_child(Div(self.view))
     form_group.append_class('form-group')
     html_input.add_attribute_source(reahl.web.ui.ValidationStateAttributes(html_input,
                                                          error_class='is-invalid',
                                                          success_class='is-valid'))
     return form_group
Пример #24
0
 def create_contents(self):
     div = self.add_child(Div(self.view))
     self.set_html_representation(div)
     div.add_child(P(self.view, text=self.task.title))
     form = div.add_child(Form(self.view, 'task_form'))
     form.use_layout(FormLayout())
     defer_btn = form.add_child(Button(form, self.user_interface.workflow_interface.events.defer_task))
     defer_btn.use_layout(ButtonLayout(style='primary'))
     release_btn = form.add_child(Button(form, self.user_interface.workflow_interface.events.release_task.with_arguments(task=self.task)))
     release_btn.use_layout(ButtonLayout(style='primary'))
Пример #25
0
def test_navbar_toggle_customised(web_fixture, navbar_fixture):
    """The text on a toggle that hides an element is customisable"""

    element_to_collapse = Div(web_fixture.view, css_id='my_id')
    toggle = navbar_fixture.navbar_with_layout.layout.add_toggle(
        element_to_collapse, text='≎')

    [toggle_text_node] = toggle.children

    assert ('≎' == toggle_text_node.value)
Пример #26
0
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
Пример #27
0
    def __init__(self, html_input, cue_widget):
        super(CueInput, self).__init__(html_input)
        div = self.add_child(Div(self.view))
        self.set_html_representation(div)

        div.append_class('reahl-bootstrapcueinput')
        cue_widget.append_class('reahl-bootstrapcue')

        div.add_child(html_input)
        self.cue_widget = div.add_child(cue_widget)
Пример #28
0
 def __init__(self, prepend, input_widget, append):
     super(InputGroup, self).__init__(input_widget)
     self.div = self.add_child(Div(self.view))
     self.div.append_class('input-group')
     if prepend:
         self.add_as_addon(prepend, 'prepend')
     self.input_widget = self.div.add_child(input_widget)
     if append:
         self.add_as_addon(append, 'append')
     self.set_html_representation(self.div)
Пример #29
0
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
Пример #30
0
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' )