Example #1
0
    def test_expire_tiles_without_data(self):
        rd1 = new_report_data('points')
        rd2 = new_report_data('points')

        tile_config_1 = {
            'tw_type':
            'Range',
            'series_spec_list': [
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['monique'])),
            ],
            'tile_options': {
                'seconds_back': 86400,
            }
        }
        tile1 = tiles.Tile.insert(rd1.owner_id, rd1.report.report_id,
                                  rd1.dashboard_id, tile_config_1)
        place_tile(tile1)
        self.assertTrue(tile1.get_tile_data()['series_data'][0]['data_points'])

        tile_config_2 = {
            'tw_type':
            'Range',
            'series_spec_list': [
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['john20'])),
            ],
            'tile_options': {
                'seconds_back': 86400,
            }
        }
        tile2 = tiles.Tile.insert(rd2.owner_id, rd2.report.report_id,
                                  rd2.dashboard_id, tile_config_2)
        place_tile(tile2)
        self.assertFalse(
            tile2.get_tile_data()['series_data'][0]['data_points'])
        res = tiles.expire_tiles_without_data([tile1, tile2],
                                              3600,
                                              Layout.select(
                                                  rd1.owner_id,
                                                  rd1.dashboard_id).layout_id,
                                              optimize_check=True)
        self.assertIsNone(res)

        time.sleep(0.5)
        rd2.report.process_input('0')

        res = tiles.expire_tiles_without_data([tile1, tile2],
                                              0.5,
                                              Layout.select(
                                                  rd1.owner_id,
                                                  rd1.dashboard_id).layout_id,
                                              optimize_check=True)
        self.assertTrue(res)
        self.assertFalse(Tile.select(rd1.dashboard_id, tile1.tile_id))
        self.assertTrue(Tile.select(rd2.dashboard_id, tile2.tile_id))
Example #2
0
    def test_deleting_layout_by_report_row(self):
        owner_id = uuid.uuid1()
        dashboard_id_1 = uuid.uuid1()
        r = reports.Report.insert(owner_id, 'r')
        tile_config = {
            'tw_type':
            'Single',
            'tags': ['p1:10'],
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {}
        }
        tile_config['tile_options'][
            'tpcreator_uispec'] = tpcreator.suggested_tpcreator_uispec(
                ['p1:10'])

        master_tile_1 = Tile.insert(owner_id, r.report_id, dashboard_id_1,
                                    tile_config)
        layouts.place_tile(master_tile_1)

        r.process_input('1', tags=['p1:11'])

        self.assertEqual(
            2,
            len(
                Layout.select(master_tile_1.owner_id,
                              master_tile_1.dashboard_id).layout_dict))

        rows = c.dao.LayoutDAO.select_layout_by_report_multi(
            master_tile_1.owner_id, master_tile_1.report_id, [], 'tpcreator',
            100)
        self.assertTrue(rows)

        layouts.detach_tile(master_tile_1)

        r.process_input('1', tags=['p1:12'])

        self.assertEqual(
            1,
            len(
                Layout.select(master_tile_1.owner_id,
                              master_tile_1.dashboard_id).layout_dict))

        rows = c.dao.LayoutDAO.select_layout_by_report_multi(
            master_tile_1.owner_id, master_tile_1.report_id, [], 'tpcreator',
            100)
        self.assertFalse(rows)
Example #3
0
def profile_dashboard(dashboard_id_str=None, dashboard_name=None):
    if not auth.access_profile():
        return redirect(url_for('bp_mqe.login', next='dashboard'))
    
    g.profile_page = 'dashboard'

    dbs = dashboards.OwnerDashboards(auth.logged_owner_id())
    if dashboard_id_str is None:
        active_db_id = dbs.dashboards[0].dashboard_id
    else:
        try:
            active_db_id = uuid.UUID(dashboard_id_str)
        except ValueError:
            abort(404)
        if active_db_id not in dbs.dashboard_by_id:
            abort(404)

    layout = Layout.select(auth.logged_owner_id(), active_db_id)

    if not reports.owner_has_reports(auth.logged_owner_id()):
        onboarding = True
    else:
        onboarding = False

    return render_template('profile_dashboard.html',
                   onboarding=onboarding,
                   dashboards=dbs,
                   active_db_id=active_db_id,
                   active_db_layout_id=layout.layout_id,
                   active_db_layout_dict=layout.layout_dict)
Example #4
0
    def test_sscreator_as_mod(self):
        owner_id = uuid.uuid4()
        dashboard_id = uuid.uuid4()

        tile_config = {
            'series_spec_list': [
                SeriesSpec(1, 0, dict(op='eq', args=['label1'])),
            ],
            'tile_options': {
                'sscs': SeriesSpec(1, 0, dict(op='eq', args=['label1']))
            }
        }
        r = Report.insert(owner_id, 'r')
        tile = Tile.insert(owner_id, r.report_id, dashboard_id, tile_config)
        layouts.place_tile(tile)
        ri1 = r.process_input('label1 1',
                              handle_sscreator=False).report_instance
        ri2 = r.process_input('label11 11\nlabel12 12',
                              handle_sscreator=False).report_instance
        ri3 = r.process_input('label21 21\nlabel22 22',
                              handle_sscreator=False).report_instance
        layout_rows = c.dao.LayoutDAO.select_layout_by_report_multi(owner_id, r.report_id,
                                                                    [], 'sscs', 100)
        mods = [sscreator.sscreator_mod(ri1, layout_rows[0]),
                sscreator.sscreator_mod(ri2, layout_rows[0]),
                sscreator.sscreator_mod(ri3, layout_rows[0])]
        layouts.apply_mods(mods, owner_id, dashboard_id, None)

        layout = Layout.select(owner_id, dashboard_id)
        tile = layout.tile_dict.keys()[0]
Example #5
0
    def test_sscs_virtual_column(self):
        owner_id = uuid.uuid1()
        od = dashboards.OwnerDashboards(owner_id)
        dashboard_id = od.dashboards[0].dashboard_id

        r = Report.insert(owner_id, 'r')
        tile_config = {
            'tw_type': 'Single',
            'series_spec_list': [
                SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {}
        }
        tile_config['tile_options']['sscs'] = tile_config['series_spec_list'][
            0]

        tile = Tile.insert(owner_id, r.report_id, dashboard_id, tile_config)
        layouts.place_tile(tile)

        for inp in ['0', '1', '2\n3', '3\n4\n5\n']:
            res = r.process_input(inp)

        tile = Tile.select(
            dashboard_id,
            Layout.select(owner_id, dashboard_id).layout_dict.keys()[0])
        self.assertEqual(3, len(tile.series_specs()))
        return tile, r
Example #6
0
 def render_dashboard(owner_id, dashboard):
     print 'Rendering dashboard %r' % dashboard.dashboard_name
     layout = Layout.select(owner_id, dashboard.dashboard_id)
     for tile, visual_options in layout.tile_dict.items():
         tile_data = tile.get_tile_data()
         print 'Rendering tile %r at position %s/%s' % (
             tile_data['generated_tile_title'], visual_options['x'], visual_options['y'])
Example #7
0
 def test_detach_2_repack(self):
     tiles = self.test_place_multiple()
     detach_tile(tiles[0])
     repack(tiles[0].owner_id, tiles[0].dashboard_id)
     detach_tile(tiles[1])
     repack(tiles[0].owner_id, tiles[0].dashboard_id)
     del tiles[0]
     del tiles[0]
     layout = Layout.select(tiles[0].owner_id, tiles[0].dashboard_id)
     self.assertDictEqual(
         self.ld_from_vos(
             tiles,
             {
                 u'width': 4,
                 u'height': 4,
                 u'x': 0,
                 u'y': 0
             },
             {
                 u'width': 5,
                 u'height': 1,
                 u'x': 0,
                 u'y': 4
             },
             {
                 u'width': 4,
                 u'height': 4,
                 u'x': 4,
                 u'y': 0
             },
         ), layout.layout_dict)
Example #8
0
 def test_place(self):
     tile = call(tiles_test.TileTest.test_insert, dashboard_id=uuid.uuid1())
     res = place_tile(tile)
     self.assertIsNotNone(res)
     vo = {'width': 4, 'height': 4, 'x': 0, 'y': 0}
     self.assertEqual(vo, res.new_tiles[tile])
     layout = Layout.select(tile.owner_id, tile.dashboard_id)
     self.assertEqual(res.new_layout.layout_id, layout.layout_id)
     self.assertEqual({tile.tile_id: vo}, layout.layout_dict)
Example #9
0
    def test_place_wrong_id(self):
        dashboard_id = uuid.uuid1()
        tile = self.place(dashboard_id)
        layout = Layout.select(tile.owner_id, tile.dashboard_id)
        tile = self.place(dashboard_id)

        tile = call(tiles_test.TileTest.test_insert, dashboard_id=dashboard_id)
        res = place_tile(tile, for_layout_id=layout.layout_id)
        self.assertIsNone(res)
Example #10
0
    def test_synchronize_sizes_of_tpcreated(self):
        rd, master_tile = self.test_handle_tpcreator()

        layout = layouts.Layout.select(rd.owner_id, rd.dashboard_id)
        ld = layout.layout_dict
        ld[master_tile.tile_id]['width'] = 8
        ld[master_tile.tile_id]['height'] = 3
        ld = layouts.apply_mods_for_noninserted_layout(
            [layouts.repack_mod()], Layout(ld)).new_layout.layout_dict
        layout_id = layout.set(rd.owner_id, rd.dashboard_id)
        self.assertTrue(layout_id)

        self.assertTrue(
            tpcreator.synchronize_sizes_of_tpcreated(master_tile, layout_id))
        layout = Layout.select(rd.owner_id, rd.dashboard_id)
        ld = layout.layout_dict
        for tile_id in tpcreator.select_tpcreated_tile_ids(master_tile):
            self.assertEqual(8, ld[tile_id]['width'])
            self.assertEqual(3, ld[tile_id]['height'])
Example #11
0
def set_layout():
    dashboard_id = request.get_json()['dashboard_id']
    layout_id = request.get_json()['layout_id']
    data = request.get_json()['data']
    master_tile_id_resized = request.get_json().get('master_tile_id_resized')

    check_access(lambda: auth.access_dashboard(dashboard_id))

    new_layout = Layout(dict(data))
    new_layout_id = new_layout.set(auth.logged_owner_id(), dashboard_id, layout_id)

    reload_required = False
    if new_layout_id and master_tile_id_resized:
        master_tile = tiles.Tile.select(dashboard_id, master_tile_id_resized)
        if master_tile:
            synced_layout_id = tpcreator.synchronize_sizes_of_tpcreated(master_tile, new_layout_id)
            reload_required = bool(synced_layout_id)

    return success(result=dict(new_layout_id=new_layout_id,
                               reload_required=reload_required))
Example #12
0
    def test_set_new_layout(self):
        tiles = self.test_place_multiple()
        layout = Layout.select(tiles[0].owner_id, tiles[0].dashboard_id)
        layout.layout_dict = dict(layout.layout_dict.items()[:3])
        res = layout.set()
        self.assertIsNotNone(res)

        layout2 = Layout.select(tiles[0].owner_id, tiles[0].dashboard_id)
        layout.layout_dict = dict(layout.layout_dict.items()[:2])
        res = layout.set()
        self.assertIsNotNone(res)

        layout2_reselected = Layout.select(tiles[0].owner_id,
                                           tiles[0].dashboard_id)
        self.assertEqual(2, len(layout2_reselected.layout_dict))

        # wrong id
        res = layout2_reselected.set(tiles[0].owner_id, tiles[0].dashboard_id,
                                     layout2.layout_id)
        self.assertIsNone(res)
Example #13
0
    def test_select_multi(self):
        owner_id = uuid.uuid1()

        d_id1 = uuid.uuid1()
        d_id2 = uuid.uuid1()
        r = Report.insert(owner_id, 'r')

        res = Layout.select_multi(owner_id, [d_id1, d_id2])
        self.assertEqual([], res)

        tile_config = {
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
        }

        t1 = Tile.insert(owner_id, r.report_id, d_id1, tile_config)
        place_tile(t1)

        res = Layout.select_multi(owner_id, [d_id1, d_id2])
        self.assertEqual(1, len(res))
        self.assertEqual(
            Layout.select(owner_id, d_id1).layout_id, res[0].layout_id)

        t2 = Tile.insert(owner_id, r.report_id, d_id2, tile_config)
        place_tile(t2)
        res = Layout.select_multi(owner_id, [d_id1, d_id2])
        self.assertEqual(2, len(res))
        self.assertEqual(
            Layout.select(owner_id, d_id1).layout_id, res[0].layout_id)
        self.assertEqual(
            Layout.select(owner_id, d_id2).layout_id, res[1].layout_id)
Example #14
0
    def test_place_multiple(self):
        dashboard_id = uuid.uuid1()
        tiles = []
        for kwargs in ({}, {
                'initial_visual_options': {
                    'width': 12,
                    'height': 10
                }
        }, {}, {
                'initial_visual_options': {
                    'width': 5,
                    'height': 1
                }
        }, {}):
            tiles.append(self.place(dashboard_id, **kwargs))

        layout = Layout.select(tiles[0].owner_id, dashboard_id)
        self.assertEqual(
            self.ld_from_vos(
                tiles,
                {
                    u'width': 4,
                    u'height': 4,
                    u'x': 0,
                    u'y': 0
                },
                {
                    u'width': 12,
                    u'height': 10,
                    u'x': 0,
                    u'y': 4
                },
                {
                    u'width': 4,
                    u'height': 4,
                    u'x': 4,
                    u'y': 0
                },
                {
                    u'width': 5,
                    u'height': 1,
                    u'x': 0,
                    u'y': 14
                },
                {
                    u'width': 4,
                    u'height': 4,
                    u'x': 8,
                    u'y': 0
                },
            ), layout.layout_dict)
        return tiles
Example #15
0
def render_dashboard():
    dashboard_id = request.get_json()['dashboard_id']

    check_access(lambda: auth.access_dashboard(dashboard_id))

    db = dashboards.Dashboard.select(auth.logged_owner_id(), dashboard_id)
    if not db:
        return error('Invalid dashboard')
    layout = Layout.select(auth.logged_owner_id(), dashboard_id)
    html = get_template_attribute('m.html', 'dashboard')(db,
             layout.layout_id if layout else None,
             layout.layout_dict if layout else None)
    return success(result=dict(html=html))
Example #16
0
    def test_detach_all_and_attach(self):
        tiles = self.test_place_multiple()
        dashboard_id = tiles[0].dashboard_id
        for t in tiles:
            detach_tile(t)

        tile = call(tiles_test.TileTest.test_insert, dashboard_id=dashboard_id)
        res = place_tile(tile)
        vo = {'width': 4, 'height': 4, 'x': 0, 'y': 0}
        self.assertEqual(vo, res.new_tiles[tile])

        layout = Layout.select(tile.owner_id, tile.dashboard_id)
        self.assertEqual(res.new_layout.layout_id, layout.layout_id)
        self.assertEqual({tile.tile_id: vo}, layout.layout_dict)
Example #17
0
    def test_deleting_layout_by_report_row(self):
        tile, report = self.test_sscs_virtual_column()
        report.process_input('3\n4\n5\n6')

        tile = Tile.select(tile.dashboard_id, Layout.select(tile.owner_id, tile.dashboard_id).layout_dict.keys()[0])
        self.assertEqual(4, len(tile.series_specs()))

        layouts.detach_tile(tile)

        rows = c.dao.LayoutDAO.select_layout_by_report_multi(tile.owner_id,
                                                             tile.report_id, [], 'sscs', 100)
        self.assertTrue(rows)

        report.process_input('3\n4\n5\n6')

        rows = c.dao.LayoutDAO.select_layout_by_report_multi(tile.owner_id,
                                                             tile.report_id, [], 'sscs', 100)
        self.assertFalse(rows)
Example #18
0
    def test_tpcreator_as_mod_performance(self):
        owner_id = uuid.uuid4()
        dashboard_id = uuid.uuid4()
        tile_config = {
            'tags': ['str:sample_string'],
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {
                'tpcreator_uispec': [{
                    'tag': 'str:sample_string',
                    'prefix': 'str:'
                }],
            }
        }
        r = reports.Report.insert(owner_id, 'r')
        master_tile = Tile.insert(owner_id, r.report_id, dashboard_id,
                                  tile_config)
        layouts.place_tile(master_tile)

        strs = [random_string() for _ in xrange(199)]
        mods = []
        layout_rows = c.dao.LayoutDAO.select_layout_by_report_multi(
            owner_id, r.report_id, [], 'tpcreator', 100)
        start = time()
        for str in strs:
            res = r.process_input('1',
                                  tags=['str:%s' % str],
                                  handle_tpcreator=False)
            mods.append(
                tpcreator.tpcreator_mod(res.report_instance, layout_rows[0],
                                        200))
        print 'Creating report instances took %.1f' % ((time() - start) * 1000)

        start = time()
        layouts.apply_mods(mods, owner_id, dashboard_id, None)
        print 'Applying tpcreator_mods took %.1f' % ((time() - start) * 1000)

        layout = Layout.select(owner_id, dashboard_id)
        self.assertEqual(200, len(layout.layout_dict))
        tags_set = {tile.tags[0].split(':')[1] for tile in layout.tile_dict}
        self.assertEqual(200, len(tags_set))
        self.assertEqual(tags_set, set(strs + ['sample_string']))
Example #19
0
    def test_tpcreator_as_mod(self):
        owner_id = uuid.uuid4()
        dashboard_id = uuid.uuid4()

        tile_config = {
            'tags': ['p1:10'],
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {
                'tpcreator_uispec': [{
                    'tag': 'p1:10',
                    'prefix': 'p1:'
                }],
            }
        }
        r = reports.Report.insert(owner_id, 'r')
        master_tile = Tile.insert(owner_id, r.report_id, dashboard_id,
                                  tile_config)
        layouts.place_tile(master_tile)

        ri1 = r.process_input('0', tags=['p1:11'],
                              handle_tpcreator=False).report_instance
        ri2 = r.process_input('0', tags=['p1:12'],
                              handle_tpcreator=False).report_instance
        ri3 = r.process_input('0', tags=['p1:12'],
                              handle_tpcreator=False).report_instance
        layout_rows = c.dao.LayoutDAO.select_layout_by_report_multi(
            owner_id, r.report_id, [], 'tpcreator', 100)
        mods = [
            tpcreator.tpcreator_mod(ri1, layout_rows[0]),
            tpcreator.tpcreator_mod(ri2, layout_rows[0]),
            tpcreator.tpcreator_mod(ri3, layout_rows[0])
        ]
        layouts.apply_mods(mods, owner_id, dashboard_id, None)

        layout = Layout.select(owner_id, dashboard_id)
        self.assertEqual(3, len(layout.layout_dict))
        self.assertEqual([['p1:10'], ['p1:11'], ['p1:12']],
                         sorted(tile.tags for tile in layout.tile_dict))
Example #20
0
    def test_deleting_layout_by_report_row_after_deleting_dashboard(self):
        tile, report = self.test_sscs_virtual_column()
        report.process_input('3\n4\n5\n6')

        tile = Tile.select(
            tile.dashboard_id,
            Layout.select(tile.owner_id,
                          tile.dashboard_id).layout_dict.keys()[0])
        self.assertEqual(4, len(tile.series_specs()))

        od = dashboards.OwnerDashboards(tile.owner_id)
        for db in od.dashboards:
            db.delete()

        rows = c.dao.LayoutDAO.select_layout_by_report_multi(
            tile.owner_id, tile.report_id, [], 'sscs', 100)
        self.assertTrue(rows)

        report.process_input('3\n4\n5\n6\n7\n8')

        rows = c.dao.LayoutDAO.select_layout_by_report_multi(
            tile.owner_id, tile.report_id, [], 'sscs', 100)
        self.assertFalse(rows)
Example #21
0
def main():
    vars = tutorial.main()
    points_report = vars['points_report']
    owner_id = vars['owner_id']
    owner_dashboards = vars['owner_dashboards']
    dashboard = vars['dashboard']

    SECTION('Tile_config and tile_options')

    from mqe.dataseries import SeriesSpec
    from mqe.tiles import Tile

    tile_config = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'tile_title': 'Points by user',
        }
    }
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    pprint(tile.tile_options)

    tile_options2 = tile.tile_options.copy()
    tile_options2['owner_id'] = uuid.uuid4()
    tile2 = Tile.insert_with_tile_options(dashboard.dashboard_id,
                                          tile_options2)

    SECTION('Updating tile\'s config')

    from mqe.layouts import Layout, replace_tiles

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    tile = layout.tile_dict.keys()[0]

    tile_config = tile.get_tile_config()
    tile_config['tile_options']['seconds_back'] = 3600

    repl_tile = tile.insert_similar(tile_config)
    replace_tiles({tile: repl_tile}, for_layout_id=layout.layout_id)

    SECTION('Formatting tile data - tilewidgets and drawers')

    tile_config = {
        'tw_type':
        'Range',
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'tile_title': 'Points by user',
            'drawer_type': 'ChartRangeDrawer',
            'colors': ['red', 'blue'],
            'seconds_back': 3600,
        }
    }

    SECTION('Updating tile data')

    tile_data = tile.get_tile_data()

    input = """\
    user_name is_active points
    john      true      144
    monique   true      241
    """
    res = points_report.process_input(input)

    last_report_instance_id = tile_data['series_data'][0]['data_points'][
        -1].rid
    new_tile_data = tile.get_new_tile_data(last_report_instance_id)

    SECTION('Managing colors')

    from mqe.dataseries import update_default_options

    tile_config = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'colors': ['blue', 'red'],
        }
    }
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    print tile.get_tile_data()['combined_colors']

    update_default_options(tile)

    tile_config_2 = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
    }
    tile_2 = Tile.insert(owner_id, points_report.report_id,
                         dashboard.dashboard_id, tile_config_2)
    print tile_2.get_tile_data()['combined_colors']

    SECTION('Data series names')

    series_spec = SeriesSpec(2, 0, {'op': 'eq', 'args': ['monique']})
    series_spec.set_name("monique's points")
    tile_config = {'series_spec_list': [series_spec]}
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    print tile.get_tile_data()['series_data'][0]['name']

    SECTION('Creating custom tilewidgets and drawers')

    from mqe.tilewidgets import register_drawer_class, Drawer

    @register_drawer_class
    class MaxNumberDrawer(Drawer):

        drawer_type = 'MaxNumberDrawer'

        def process_tile_data(self, tile_data):
            max_number = 0
            for series_data in tile_data['series_data']:
                for point in series_data['data_points']:
                    if int(point.value) > max_number:
                        max_number = int(point.value)

            tile_data['max_number'] = max_number

    tile_config = {
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'drawer_type': 'MaxNumberDrawer',
        }
    }
    tile = Tile.insert(owner_id, points_report.report_id,
                       dashboard.dashboard_id, tile_config)
    print tile.get_tile_data()['max_number']
Example #22
0
def main():
    SECTION('Creating a report and report instances')


    import uuid
    from mqe.reports import Report

    owner_id = uuid.uuid4()

    simple_report = Report.insert(owner_id, 'simple')
    res = simple_report.process_input('10 20')
    print res.report_instance.table

    points_report = Report.insert(owner_id, 'points')
    input = """\
    user_name is_active points
    john      true      128
    monique   true      210
    """
    res = points_report.process_input(input)
    print res.report_instance.table


    SECTION('Creating a dashboard and a tile')


    from mqe.dashboards import OwnerDashboards

    owner_dashboards = OwnerDashboards(owner_id)
    dashboard = owner_dashboards.insert_dashboard('My Dashboard')

    from mqe.dataseries import SeriesSpec
    tile_config = {
        'tw_type': 'Range',
        'series_spec_list': [
            SeriesSpec(2, 0, {'op': 'eq', 'args': ['john']}),
            SeriesSpec(2, 0, {'op': 'eq', 'args': ['monique']}),
        ],
        'tile_options': {
            'seconds_back': 86400,
            'tile_title': 'Points by user',
        }
    }

    from mqe.tiles import Tile
    tile = Tile.insert(owner_id, points_report.report_id, dashboard.dashboard_id, tile_config)
    pprint(tile.get_tile_data())


    SECTION('Placing a tile in a dashboard layout')


    from mqe.layouts import place_tile

    res = place_tile(tile)
    if not res:
        raise ValueError('Placing the tile unsuccessful')

    from mqe.layouts import Layout

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    pprint(layout.layout_dict)


    def render_dashboard(owner_id, dashboard):
        print 'Rendering dashboard %r' % dashboard.dashboard_name
        layout = Layout.select(owner_id, dashboard.dashboard_id)
        for tile, visual_options in layout.tile_dict.items():
            tile_data = tile.get_tile_data()
            print 'Rendering tile %r at position %s/%s' % (
                tile_data['generated_tile_title'], visual_options['x'], visual_options['y'])
            # render tile_data['series_data']

    render_dashboard(owner_id, dashboard)

    return locals()
Example #23
0
    def test_expire_tiles_without_data_optimize_check(self):
        owner_id = report_data('points').report.owner_id
        report_id = report_data('points').report.report_id
        dashboard_id = report_data('points').dashboard_id

        report_data('points').report.process_input(
            json.dumps([
                OrderedDict([('user_name', 'xxx'), ('is_active', True),
                             ('points', 1000)]),
                OrderedDict([('user_name', 'yy'), ('is_active', True),
                             ('points', 2000)]),
            ]),
            created=datetime.datetime.utcnow() - datetime.timedelta(hours=8))

        tile_config_1 = {
            'tw_type':
            'Range',
            'series_spec_list': [
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['monique'])),
            ],
            'tile_options': {
                'seconds_back': 86400,
            }
        }
        tile1 = tiles.Tile.insert(owner_id, report_id, dashboard_id,
                                  tile_config_1)
        self.assertTrue(tile1.get_tile_data()['series_data'][0]['data_points'])

        tile_config_2 = {
            'tw_type':
            'Range',
            'series_spec_list': [
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['john'])),
            ],
            'tile_options': {
                'seconds_back': 86400,
            }
        }
        tile2 = tiles.Tile.insert(owner_id, report_id, dashboard_id,
                                  tile_config_2)
        self.assertTrue(tile2.get_tile_data()['series_data'][0]['data_points'])

        tile_config_3 = {
            'tw_type':
            'Range',
            'series_spec_list': [
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['xxx'])),
            ],
            'tile_options': {
                'seconds_back': 86400,
            }
        }
        tile3 = tiles.Tile.insert(owner_id, report_id, dashboard_id,
                                  tile_config_3)
        self.assertTrue(tile3.get_tile_data()['series_data'][0]['data_points'])

        place_tile(tile1)
        place_tile(tile2)
        place_tile(tile3)

        res = tiles.expire_tiles_without_data([tile1, tile2, tile3], 3600,
                                              Layout.select(
                                                  owner_id,
                                                  dashboard_id).layout_id)
        self.assertTrue(res)

        tile1 = tiles.Tile.select(tile1.dashboard_id, tile1.tile_id)
        self.assertIsNotNone(tile1)
        tile2 = tiles.Tile.select(tile2.dashboard_id, tile2.tile_id)
        self.assertIsNotNone(tile2)
        tile3 = tiles.Tile.select(tile3.dashboard_id, tile3.tile_id)
        self.assertIsNone(tile3)

        res = tiles.expire_tiles_without_data([tile1, tile2], 3600,
                                              Layout.select(
                                                  owner_id,
                                                  dashboard_id).layout_id)
        self.assertFalse(res)
Example #24
0
    def test_sscs_set_layout_fails(self):
        tile, report = self.test_sscs_virtual_column()
        dashboard_id_1 = tile.dashboard_id

        dashboard_id_2 = uuid.uuid1()
        tile2 = tile.copy(dashboard_id_2)
        self.assertEqual(3, len(tile.series_specs()))
        self.assertTrue(layouts.place_tile(tile2))

        report.process_input('3\n4\n5\n6')

        layout2 = Layout.select(tile.owner_id, dashboard_id_2)
        self.assertEqual(1, len(layout2.layout_dict))
        self.assertEqual(4, len(layout2.tile_dict.keys()[0].series_specs()))

        layout1 = Layout.select(tile.owner_id, dashboard_id_1)
        self.assertEqual(1, len(layout1.layout_dict))
        self.assertEqual(4, len(layout1.tile_dict.keys()[0].series_specs()))

        dashboard_id_3 = uuid.uuid1()
        tile3 = tile.copy(dashboard_id_3)
        self.assertEqual(3, len(tile.series_specs()))
        self.assertTrue(layouts.place_tile(tile3))

        report.process_input('3\n4\n5\n6\n7')

        layout3 = Layout.select(tile.owner_id, dashboard_id_3)
        self.assertEqual(1, len(layout3.layout_dict))
        self.assertEqual(5, len(layout3.tile_dict.keys()[0].series_specs()))

        layout2 = Layout.select(tile.owner_id, dashboard_id_2)
        self.assertEqual(1, len(layout2.layout_dict))
        self.assertEqual(5, len(layout2.tile_dict.keys()[0].series_specs()))

        layout1 = Layout.select(tile.owner_id, dashboard_id_1)
        self.assertEqual(1, len(layout1.layout_dict))
        self.assertEqual(5, len(layout1.tile_dict.keys()[0].series_specs()))

        mock_data = {'call': 0}
        def mock__set_new_layout(*args, **kwargs):
            mock_data['call'] += 1
            if mock_data['call'] >= 2:
                return None
            return mock__set_new_layout.old_fun(*args, **kwargs)

        with patch(layouts.Layout, layouts.Layout.set, mock__set_new_layout):
            report.process_input('3\n4\n5\n6\n7\n8')

        layout3 = Layout.select(tile.owner_id, dashboard_id_3)
        self.assertEqual(1, len(layout3.layout_dict))
        self.assertEqual(5, len(layout3.tile_dict.keys()[0].series_specs()))

        layout2 = Layout.select(tile.owner_id, dashboard_id_2)
        self.assertEqual(1, len(layout2.layout_dict))
        self.assertEqual(5, len(layout2.tile_dict.keys()[0].series_specs()))

        layout1 = Layout.select(tile.owner_id, dashboard_id_1)
        self.assertEqual(1, len(layout1.layout_dict))
        self.assertEqual(6, len(layout1.tile_dict.keys()[0].series_specs()))

        mock_data = {'call': 0}
        def mock__set_new_layout(*args, **kwargs):
            mock_data['call'] += 1
            if mock_data['call'] in (2, 3, 4):
                return None
            mock_data['call'] = mock_data['call'] + 1
            return mock__set_new_layout.old_fun(*args, **kwargs)

        with patch(layouts.Layout, layouts.Layout.set, mock__set_new_layout):
            report.process_input('3\n4\n5\n6\n7\n8\n9')

        layout3 = Layout.select(tile.owner_id, dashboard_id_3)
        self.assertEqual(1, len(layout3.layout_dict))
        self.assertEqual(7, len(layout3.tile_dict.keys()[0].series_specs()))

        layout2 = Layout.select(tile.owner_id, dashboard_id_2)
        self.assertEqual(1, len(layout2.layout_dict))
        self.assertEqual(7, len(layout2.tile_dict.keys()[0].series_specs()))

        layout1 = Layout.select(tile.owner_id, dashboard_id_1)
        self.assertEqual(1, len(layout1.layout_dict))
        self.assertEqual(7, len(layout1.tile_dict.keys()[0].series_specs()))
Example #25
0
def main():
    vars = tutorial.main()
    owner_id = vars['owner_id']
    owner_dashboards = vars['owner_dashboards']
    dashboard = vars['dashboard']

    SECTION('Using tags for identifying entities')

    from mqe.reports import Report

    cpu_report = Report.select_or_insert(owner_id, 'cpu_usage')
    metrics = [
        ('user', 42.3),
        ('system', 13.4),
        ('io', 8.4),
    ]
    cpu_report.process_input(json.dumps(metrics), tags=['ip:192.168.1.18'])

    SECTION('Creating a master tile')

    from mqe.dataseries import SeriesSpec
    from mqe.tiles import Tile
    from mqe.layouts import place_tile, Layout, replace_tiles

    dashboard = owner_dashboards.insert_dashboard('CPU')

    master_tile_config = {
        'tw_type':
        'Range',
        'tags': ['ip:192.168.1.18'],
        'series_spec_list': [
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['user']
            }),
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['system']
            }),
        ],
        'tile_options': {
            'tile_title': 'CPU usage',
            'tpcreator_uispec': [{
                'tag': 'ip:192.168.1.18',
                'prefix': 'ip:'
            }]
        }
    }
    master_tile = Tile.insert(owner_id, cpu_report.report_id,
                              dashboard.dashboard_id, master_tile_config)
    print place_tile(master_tile)

    SECTION('Creating tiles from a master tile')

    metrics = json.dumps(metrics)

    cpu_report.process_input(metrics, tags=['ip:192.168.1.30'])
    cpu_report.process_input(metrics, tags=['ip:192.168.2.51'])
    cpu_report.process_input(metrics, tags=['ip:192.168.2.51'])

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    for tile in layout.tile_dict:
        print tile.tags

    SECTION('Synchronizing options of tpcreated tiles')

    new_master_tile_config = {
        'tw_type':
        'Range',
        'tags': ['ip:192.168.1.18'],
        'series_spec_list': [
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['user']
            }),
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['system']
            }),
            SeriesSpec(1, 0, {
                'op': 'eq',
                'args': ['io']
            }),
        ],
        'tile_options': {
            'tile_title': 'CPU usage',
            'tpcreator_uispec': [{
                'tag': 'ip:192.168.1.18',
                'prefix': 'ip:'
            }]
        }
    }
    new_master_tile = Tile.insert(owner_id, cpu_report.report_id,
                                  dashboard.dashboard_id,
                                  new_master_tile_config)
    assert replace_tiles({master_tile: new_master_tile}, for_layout_id=None)

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    for tile in layout.tile_dict:
        print len(tile.get_tile_data()['series_data'])

    SECTION('Expiring tiles and promoting new masters')

    from mqe.tpcreator import make_master_from_tpcreated

    old_master = [tile for tile in layout.tile_dict
                  if tile.is_master_tile()][0]
    new_chosen_master = [
        tile for tile in layout.tile_dict if tile.tags == ['ip:192.168.2.51']
    ][0]
    assert not new_chosen_master.is_master_tile()

    new_master = make_master_from_tpcreated(old_master, new_chosen_master)
    res = replace_tiles({
        old_master: new_master,
        new_chosen_master: None
    },
                        for_layout_id=None)
    print 'replaced %d tiles' % len(res.tile_replacement)

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    tile = [
        tile for tile in layout.tile_dict if tile.tags == ['ip:192.168.2.51']
    ][0]
    print tile.is_master_tile()
Example #26
0
    def test_multiple_tags_order(self):
        tile_config = {
            'tags': ['p1:10', 'p2:10', 'zzz'],
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {
                'tpcreator_uispec': [{
                    'tag': 'p1:10',
                    'prefix': 'p1:'
                }, {
                    'tag': 'p1:20',
                    'prefix': 'p1:'
                }, {
                    'tag': 'zzz',
                    'prefix': 'z'
                }],
            }
        }
        owner_id = uuid.uuid1()
        dashboard_id_1 = uuid.uuid1()
        r = reports.Report.insert(owner_id, 'r')
        master_tile = Tile.insert(owner_id, r.report_id, dashboard_id_1,
                                  tile_config)
        layouts.place_tile(master_tile)

        r.process_input('1', tags=['p1:11', 'p1:12'])
        self.assertEqual(
            1, len(Layout.select(owner_id, dashboard_id_1).layout_dict))

        r.process_input('1', tags=['p1:11', 'p2:12', 'zz'])
        layout = Layout.select(owner_id, dashboard_id_1)
        self.assertEqual(2, len(layout.layout_dict))
        self.assertIn(['p1:11', 'zz'], [t.tags for t in layout.tile_dict])

        r.process_input('1', tags=[
            'p2:12',
            'aaa',
            'p1:11',
        ])
        layout = Layout.select(owner_id, dashboard_id_1)
        self.assertEqual(2, len(layout.layout_dict))

        tile_config_2 = {
            'tags': ['p1:10', 'p2:10'],
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {
                'tpcreator_uispec': [{
                    'tag': 'p1:10',
                    'prefix': 'p1:'
                }, {
                    'tag': 'p1:20',
                    'prefix': ''
                }]
            }
        }
        dashboard_id_2 = uuid.uuid1()
        master_tile_2 = Tile.insert(owner_id, r.report_id, dashboard_id_2,
                                    tile_config_2)
        layouts.place_tile(master_tile_2)

        r.process_input('1', tags=['p1:11', 'p2:12'])
        layout = Layout.select(owner_id, dashboard_id_2)
        self.assertEqual(2, len(layout.layout_dict))
        self.assertIn(['p1:11', 'p2:12'], [t.tags for t in layout.tile_dict])

        tile_config_3 = {
            'tags': ['p2:10', 'p1:10'],
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {
                'tpcreator_uispec': [{
                    'tag': 'p1:20',
                    'prefix': ''
                }, {
                    'tag': 'p1:10',
                    'prefix': 'p1:'
                }]
            }
        }
        dashboard_id_3 = uuid.uuid1()
        master_tile_3 = Tile.insert(owner_id, r.report_id, dashboard_id_3,
                                    tile_config_3)
        layouts.place_tile(master_tile_3)

        r.process_input('1', tags=['p1:10', 'p2:10'])
        layout = Layout.select(owner_id, dashboard_id_3)
        self.assertEqual(1, len(layout.layout_dict))

        r.process_input('1', tags=['p2:11', 'p1:12'])
        layout = Layout.select(owner_id, dashboard_id_3)
        self.assertEqual(2, len(layout.layout_dict))
        self.assertIn(['p1:12', 'p2:11'], [t.tags for t in layout.tile_dict])
Example #27
0
    def test_set_layout_fails(self):
        owner_id = uuid.uuid1()
        dashboard_id_1 = uuid.uuid1()
        r = reports.Report.insert(owner_id, 'r')
        tile_config = {
            'tw_type':
            'Single',
            'tags': ['p1:10'],
            'series_spec_list': [
                dataseries.SeriesSpec(0, -1, dict(op='eq', args=['0'])),
            ],
            'tile_options': {}
        }
        tile_config['tile_options'][
            'tpcreator_uispec'] = tpcreator.suggested_tpcreator_uispec(
                ['p1:10'])

        master_tile_1 = Tile.insert(owner_id, r.report_id, dashboard_id_1,
                                    tile_config)
        layouts.place_tile(master_tile_1)

        r.process_input('1', tags=['p1:10'])

        self.assertEqual(
            1,
            len(
                Layout.select(master_tile_1.owner_id,
                              master_tile_1.dashboard_id).layout_dict))

        master_tile_2 = master_tile_1.copy(dashboard_id_1)
        layouts.place_tile(master_tile_2)

        r.process_input('1', tags=['p1:11'])

        layout_1 = Layout.select(master_tile_1.owner_id,
                                 master_tile_1.dashboard_id)
        self.assertEqual(4, len(layout_1.layout_dict))
        self.assertEqual(
            1, len(layout_1.get_tpcreated_tile_ids(master_tile_1.tile_id)))
        self.assertEqual(
            1, len(layout_1.get_tpcreated_tile_ids(master_tile_2.tile_id)))
        self.assertNotEqual(
            layout_1.get_tpcreated_tile_ids(master_tile_1.tile_id),
            layout_1.get_tpcreated_tile_ids(master_tile_2.tile_id))

        dashboard_id_2 = uuid.uuid1()
        master_tile_3 = master_tile_1.copy(dashboard_id_2)
        layouts.place_tile(master_tile_3)

        dashboard_id_3 = uuid.uuid1()
        master_tile_4 = master_tile_1.copy(dashboard_id_3)
        layouts.place_tile(master_tile_4)

        r.process_input('1', tags=['p1:12'])

        layout_1 = Layout.select(master_tile_1.owner_id, dashboard_id_1)
        layout_2 = Layout.select(master_tile_1.owner_id, dashboard_id_2)
        layout_3 = Layout.select(master_tile_1.owner_id, dashboard_id_3)

        self.assertEqual(6, len(layout_1.layout_dict))
        self.assertEqual(2, len(layout_2.layout_dict))
        self.assertEqual(2, len(layout_3.layout_dict))

        mock_data = {'call': 0}

        def mock__set_new_layout(*args, **kwargs):
            mock_data['call'] += 1
            if mock_data['call'] >= 2:
                return None
            return mock__set_new_layout.old_fun(*args, **kwargs)

        with patch(layouts.Layout, layouts.Layout.set, mock__set_new_layout):
            r.process_input('1', tags=['p1:13'])

        layout_1 = Layout.select(master_tile_1.owner_id, dashboard_id_1)
        layout_2 = Layout.select(master_tile_1.owner_id, dashboard_id_2)
        layout_3 = Layout.select(master_tile_1.owner_id, dashboard_id_3)

        self.assertEqual(8, len(layout_1.layout_dict))
        self.assertEqual(2, len(layout_2.layout_dict))
        self.assertEqual(2, len(layout_3.layout_dict))

        mock_data = {'call': 0}

        def mock__set_new_layout(*args, **kwargs):
            mock_data['call'] += 1
            if mock_data['call'] % 5 != 0:
                return None
            return mock__set_new_layout.old_fun(*args, **kwargs)

        with patch(layouts.Layout, layouts.Layout.set, mock__set_new_layout):
            r.process_input('1', tags=['p1:14'])

        layout_1 = Layout.select(master_tile_1.owner_id, dashboard_id_1)
        layout_2 = Layout.select(master_tile_1.owner_id, dashboard_id_2)
        layout_3 = Layout.select(master_tile_1.owner_id, dashboard_id_3)

        self.assertEqual(10, len(layout_1.layout_dict))
        self.assertEqual(3, len(layout_2.layout_dict))
        self.assertEqual(3, len(layout_3.layout_dict))
Example #28
0
def main():
    vars = tutorial.main()
    points_report = vars['points_report']
    tile = vars['tile']
    owner_id = vars['owner_id']
    owner_dashboards = vars['owner_dashboards']

    SECTION('Auto-creating new data series')

    input = """\
    user_name is_active points
    john      true      128
    monique   true      210
    alex      true      12
    """
    points_report.process_input(input)

    series_names = [
        series_data['name']
        for series_data in tile.get_tile_data()['series_data']
    ]
    print series_names

    new_dashboard = owner_dashboards.insert_dashboard('Points')

    tile_config = {
        'tw_type':
        'Range',
        'series_spec_list': [
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            }),
            SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['monique']
            }),
        ],
        'tile_options': {
            'seconds_back': 86400,
            'tile_title': 'Points by user',
            'sscs': SeriesSpec(2, 0, {
                'op': 'eq',
                'args': ['john']
            })
        }
    }
    new_tile = Tile.insert(owner_id, points_report.report_id,
                           new_dashboard.dashboard_id, tile_config)
    place_tile(new_tile)

    input = """\
    user_name is_active points
    john      true      133
    monique   true      220
    alex      true      18
    andrew    true      6
    """
    points_report.process_input(input)

    layout = Layout.select(owner_id, new_dashboard.dashboard_id)
    tile_id = layout.layout_dict.keys()[0]
    tile = Tile.select(new_dashboard.dashboard_id, tile_id)

    series_names = [
        series_data['name']
        for series_data in tile.get_tile_data()['series_data']
    ]
    print series_names
Example #29
0
def main():
    vars = tutorial.main()
    points_report = vars['points_report']
    tile = vars['tile']
    owner_id = vars['owner_id']
    owner_dashboards = vars['owner_dashboards']
    dashboard = vars['dashboard']

    SECTION('Placing, detaching, replacing tiles')

    from mqe.layouts import Layout, place_tile

    layout = Layout.select(owner_id, dashboard.dashboard_id)

    new_tile = tile.copy(dashboard.dashboard_id)
    # we decided that new_tile should be put in the current layout
    res = place_tile(new_tile, for_layout_id=layout.layout_id)
    if not res:
        raise ValueError('Placing the tile unsuccessful')
    else:
        print 'New tile placed with visual_options', res.new_tiles[new_tile]

    from mqe.layouts import replace_tiles
    from mqe.tiles import Tile

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    tile = Tile.select(dashboard.dashboard_id, layout.layout_dict.keys()[0])
    tile_config = tile.get_tile_config()
    tile_config['tile_options']['tile_title'] = 'New Title'
    repl_tile = tile.insert_similar(tile_config)
    res = replace_tiles({tile: repl_tile}, for_layout_id=layout.layout_id)
    if not res:
        raise ValueError('Replacement of tiles unsuccessful')
    else:
        print 'Tiles replaced:', res.tile_replacement

    SECTION('Setting a custom layout')

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    for visual_options in layout.layout_dict.values():
        visual_options['height'] += 1
    new_layout_id = layout.set()
    if not new_layout_id:
        raise ValueError('Updating the layout failed')

    SECTION('Layout mods')

    from mqe.layouts import replace_tiles_mod, place_tile_mod, apply_mods
    tile = repl_tile
    tile1 = tile.copy(dashboard.dashboard_id)
    tile2 = tile.copy(dashboard.dashboard_id)
    tile3 = tile.copy(dashboard.dashboard_id)

    layout = Layout.select(owner_id, dashboard.dashboard_id)
    mods = [
        replace_tiles_mod({tile: tile1}),
        place_tile_mod(tile2),
        place_tile_mod(tile3),
    ]
    res = apply_mods(mods,
                     owner_id,
                     dashboard.dashboard_id,
                     for_layout_id=layout.layout_id)
    if not res:
        raise ValueError('Operation failed')
    else:
        print res

    from mqe.layouts import LayoutModificationImpossible

    def detach_top_tiles_mod():
        def do(layout_mod):
            tile_ids = [
                tile_id for tile_id, visual_options in
                layout_mod.layout.layout_dict.items()
                if visual_options['y'] == 0
            ]
            if not tile_ids:
                raise LayoutModificationImpossible()
            for tile_id in tile_ids:
                del layout_mod.layout.layout_dict[tile_id]
                layout_mod.detached_tiles.append(
                    Tile.select(layout_mod.layout.dashboard_id, tile_id))

        return do

    res = apply_mods([detach_top_tiles_mod()], owner_id,
                     dashboard.dashboard_id, None)
    if not res:
        raise ValueError('Operation failed')
    else:
        print res

    def detach_top_tiles_using_replacement_mod():
        def do(layout_mod):
            tiles = [
                tile for tile, visual_options in
                layout_mod.layout.tile_dict.items() if visual_options['y'] == 0
            ]
            if not tiles:
                raise LayoutModificationImpossible()
            replace_tiles_mod({tile: None for tile in tiles})(layout_mod)

        return do