示例#1
0
def iommi_debug_panel(part):
    source_url = source_url_from_part(part)
    script = r"""
        window.iommi_start_pick = function() {
            window.iommi_pick_stack = [];

            function create(html) {
                let r = document.createElement('div');
                r.innerHTML = html;
                return r.firstChild;
            }

            window.iommi_close_pick_toolbar = function() {
                window.iommi_pick_stack.forEach(function(el) {
                    el[3].style.backgroundColor = el[2];
                });
                document.getElementById('iommi-pick-toolbar').remove()
            };

            function update_toolbar() {
                let toolbar = document.getElementById('iommi-pick-toolbar');
                if (!toolbar) {
                    return;
                }

                while(toolbar.firstChild) {
                    toolbar.removeChild(toolbar.firstChild);
                }

                toolbar.append(create('<div style="float: right" onclick="iommi_close_pick_toolbar()">close</div>'));
                for (let i in window.iommi_pick_stack) {
                    let x = window.iommi_pick_stack[i];
                    toolbar.append(create('<div style="background-color: ' + getColor(i) + '">' + x[0] + ' <a href="https://docs.iommi.rocks/en/latest/' + x[1] + '.html">' + x[1] + '</a></div>'));
                }
            }

            let with_iommi_path = document.querySelectorAll('*[data-iommi-path]');

            let colors = [
                'rgb(255, 255, 191)',
                'rgb(254, 224, 139)',
                'rgb(253, 174,  97)',
                'rgb(244, 109,  67)',
                'rgb(213,  62,  79)',
                'rgb(158,   1,  66)',
                'rgb(230, 245, 152)',
                'rgb(171, 221, 164)',
                'rgb(102, 194, 165)',
                'rgb( 50, 136, 189)',
                'rgb( 94,  79, 162)',
            ];

            function getColor(index) {
                return colors[Math.min(index, colors.length - 1)]
            }

            function mouseenter() {
                window.iommi_pick_stack.push([this.getAttribute('data-iommi-path'), this.getAttribute('data-iommi-type'), this.style.backgroundColor, this])
                this.style.backgroundColor = getColor(window.iommi_pick_stack.length-1);
                update_toolbar();
            }

            function mouseleave() {
                if (window.iommi_pick_stack.length) {
                    this.style.backgroundColor = window.iommi_pick_stack.pop()[2];
                    update_toolbar();
                }
            }
            function click() {
                document.querySelectorAll('*[data-iommi-path]').forEach(function (e) {
                    e.removeEventListener('mouseenter', mouseenter)
                    e.removeEventListener('mouseleave', mouseleave)
                    e.removeEventListener('click', click)
                });
            }

            with_iommi_path.forEach(function (e) {
                e.addEventListener('mouseenter', mouseenter);
                e.addEventListener('mouseleave', mouseleave);
                setTimeout(function(){
                    e.addEventListener('click', click);
                });
            });

            let toolbar = create('<div id="iommi-pick-toolbar" style="position: fixed; left: 0; bottom: 0; width: 100%; background-color: white; color: black; padding: 4px; border-top: 2px solid #1084ff; z-index: 200">');

            document.getElementsByTagName('body')[0].append(toolbar);
        };
    """

    from iommi.menu import get_debug_menu

    return get_debug_menu(sub_menu__code__url=source_url).bind(
        request=part.get_request()).__html__() + mark_safe(
            f'<script>{script}</script>')
示例#2
0
def validate_styles(*,
                    additional_classes: List[Type] = None,
                    default_classes=None,
                    styles=None):
    """
    This function validates all registered styles against all standard
    classes. If you have more classes you need to have checked against,
    pass these as the `classes` argument.

    The `default_classes` parameter can be used to say which classes are
    checked for valid data. By default this is all the `Part`-derived
    classes in iommmi. This parameter is primarily used by tests.

    The `styles` parameter can be used to specify which exact styles to
    validate. By default it will validate all registered styles. This
    parameter is primarily used by tests.
    """
    if default_classes is None:
        from iommi import (
            Action,
            Column,
            Field,
            Form,
            Menu,
            MenuItem,
            Query,
            Table,
            Filter,
        )
        from iommi.table import Paginator
        from iommi.menu import (
            MenuBase,
            get_debug_menu,
        )
        from iommi.error import Errors
        from iommi.action import Actions
        from iommi.admin import Admin
        from iommi.fragment import Container
        from iommi.fragment import Header
        from iommi.live_edit import LiveEditPage

        default_classes = [
            Action,
            Actions,
            Column,
            get_debug_menu().__class__,
            Errors,
            Field,
            Form,
            Menu,
            MenuBase,
            MenuItem,
            Paginator,
            Query,
            Table,
            Filter,
            Admin,
            Container,
            Header,
            LiveEditPage,
        ]
    if additional_classes is None:
        additional_classes = []

    classes = default_classes + additional_classes

    if styles is None:
        styles = _styles

    # We can have multiple classes called Field. In fact that's the recommended way to use iommi!
    classes_by_name = defaultdict(list)
    for cls in classes:
        for cls_name in class_names_for(cls):
            classes_by_name[cls_name].append(cls)

    # This will functionally merge separate trees of class inheritance. So it produces a list of all shortcuts on all classes called something.Field.
    shortcuts_available_by_class_name = defaultdict(set)
    for cls_name, classes in items(classes_by_name):
        for cls in classes:
            shortcuts_available_by_class_name[cls_name].update(
                get_shortcuts_by_name(cls).keys())

    invalid_class_names = []
    non_existent_shortcut_names = []
    for style_name, style in items(styles):
        for cls_name, config in items(style.config):
            # First validate the top level classes
            if cls_name not in classes_by_name:
                invalid_class_names.append((style_name, cls_name))
                continue

            # Then validate the shortcuts
            for shortcut_name in keys(config.get('shortcuts', {})):
                if shortcut_name not in shortcuts_available_by_class_name[
                        cls_name]:
                    non_existent_shortcut_names.append(
                        (style_name, cls_name, shortcut_name))

    if invalid_class_names or non_existent_shortcut_names:
        invalid_class_names_str = '\n'.join(
            f'    Style: {style_name} - class: {cls_name}'
            for style_name, cls_name in invalid_class_names)
        if invalid_class_names_str:
            invalid_class_names_str = 'Invalid class names:\n' + invalid_class_names_str
        invalid_shortcut_names_str = '\n'.join(
            f'    Style: {style_name} - class: {cls_name} - shortcut: {shortcut_name}'
            for style_name, cls_name, shortcut_name in
            non_existent_shortcut_names)
        if invalid_shortcut_names_str:
            invalid_shortcut_names_str = 'Invalid shortcut names:\n' + invalid_shortcut_names_str
        raise InvalidStyleConfigurationException('\n\n'.join(
            [invalid_class_names_str, invalid_shortcut_names_str]))
示例#3
0
def test_debug_menu():
    assert get_debug_menu().bind(request=req('get')).__html__(
    ) == '<nav style="background: white; border: 1px solid black; bottom: -1px; position: fixed; right: -1px; z-index: 100"><ul style="list-style: none"><li><a class="link" href="/code/">Code</a></li><li><a class="link" href="?/debug_tree">Tree</a></li><li onclick="window.iommi_start_pick()"><a class="link" href="#">Pick</a></li><li><a class="link" href="?_iommi_live_edit">Edit</a></li><li><a class="link" href="?_iommi_prof">Profile</a></li><li><a class="link" href="?_iommi_sql_trace">SQL trace</a></li></ul></nav>'