Example #1
0
    def set(self, owner_id=None, dashboard_id=None, old_layout_id=None):
        """Set a new layout definition for the dashboard (replacing the existing one), using
        the current content of the :attr:`layout_dict`. The parameters are optional - if not
        specified, the current values of :attr:`owner_id`, :attr:`dashboard_id` and
        :attr:`layout_id` are used.

        :param owner_id: the owner ID of the dashboard
        :param dashboard_id: the dashboard's ID
        :param old_layout_id: ``None`` if this should be a new layout definition
            for the dashboard, ``layout_id`` of the existing layout otherwise
        :return: a ``layout_id`` of a newly set layout if the operation was successful,
            ``None`` otherwise (ie. when the passed ``old_layout_id`` didn't match the
            version in the database)
        """
        owner_id = owner_id or self.owner_id
        if not owner_id:
            raise ValueError(
                'owner_id not set in Layout and not passed as an argument')
        dashboard_id = dashboard_id or self.dashboard_id
        if not dashboard_id:
            raise ValueError(
                'dashboard_id not set in Layout and not passed as an argument')
        old_layout_id = old_layout_id or self.layout_id

        # a layout def is a layout_dict serialized as a list of items. The list is
        # sorted by tile creation time (but this assumption should not be generally made).
        new_layout_def = serialize.mjson(
            sorted(self.layout_dict.items(),
                   key=lambda (tile_id, vo): tile_id.time))

        # Merge old layout_props with new data

        old_layout_props_row = c.dao.LayoutDAO.select(owner_id, dashboard_id,
                                                      ['layout_props'])

        if not old_layout_props_row and old_layout_id:
            return None

        if old_layout_props_row and old_layout_props_row['layout_props']:
            old_layout_props = serialize.json_loads(
                old_layout_props_row['layout_props'])
        else:
            old_layout_props = {'by_tile_id': []}

        by_tile_id = {}
        old_by_tile_id = dict(old_layout_props['by_tile_id'])

        tile_ids_to_fetch = []
        for tile_id in self.layout_dict:
            if tile_id in old_by_tile_id:
                by_tile_id[tile_id] = old_by_tile_id[tile_id]
            elif tile_id in self._included_tiles:
                by_tile_id[tile_id] = self.props_of_tile(
                    self._included_tiles[tile_id])
            else:
                tile_ids_to_fetch.append(tile_id)

        tile_dict = Tile.select_multi(dashboard_id, tile_ids_to_fetch)
        for tile_id, tile in tile_dict.items():
            by_tile_id[tile.tile_id] = self.props_of_tile(tile)

        # Compute data for sscreator and tpcreator

        sscs_data = set()
        master_data = set()
        for props in by_tile_id.values():
            if props.get('sscs'):
                #sscs_data.add((props['report_id'], tuple(props['tags'])))
                sscs_data.add(props['report_id'])
            if props.get('is_master'):
                master_data.add(props['report_id'])

        new_layout_props = serialize.mjson({'by_tile_id': by_tile_id.items()})

        # Set the new layout

        new_layout_id = gen_timeuuid()
        res = c.dao.LayoutDAO.set(owner_id, dashboard_id, old_layout_id,
                                  new_layout_id, new_layout_def,
                                  new_layout_props)
        if not res:
            log.info('Setting new layout failed')
            return None

        # Insert layout_by_report for sscs and tpcreator

        c.dao.LayoutDAO.insert_layout_by_report_multi(owner_id, sscs_data, [],
                                                      'sscs', dashboard_id,
                                                      new_layout_id)
        c.dao.LayoutDAO.insert_layout_by_report_multi(owner_id, master_data,
                                                      [], 'tpcreator',
                                                      dashboard_id,
                                                      new_layout_id)

        self.layout_id = new_layout_id

        return new_layout_id
Example #2
0
    def test_handle_tpcreator(self):
        rd = new_report_data('points')

        tile_config = {
            'tw_type':
            'Range',
            'tags': ['p1:10'],
            'series_spec_list': [
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['monique'])),
            ],
            'tile_options': {
                'seconds_back':
                600,
                'tile_title':
                'm0',
                'sscs':
                dataseries.SeriesSpec(2, 0, dict(op='eq', args=['monique'])),
            }
        }
        tile_config['tile_options'][
            'tpcreator_uispec'] = tpcreator.suggested_tpcreator_uispec(
                tile_config['tags'])

        master_tile = Tile.insert(rd.owner_id, rd.report.report_id,
                                  rd.dashboard_id, tile_config)
        layouts.place_tile(master_tile)

        d = [
            OrderedDict([('user_name', 'robert3'), ('is_active', True),
                         ('points', 128)])
        ]
        rd.report.process_input(json.dumps(d), tags=['p1:10'])
        master_tile = rd.only_tile_from_layout()
        self.assertEqual([], tpcreator.select_tpcreated_tile_ids(master_tile))
        self.assertEqual([master_tile.tile_id],
                         _select_tile_ids(rd.dashboard_id))

        d = [
            OrderedDict([('user_name', 'robert3'), ('is_active', True),
                         ('points', 128)])
        ]
        rd.report.process_input(json.dumps(d), tags=['p1:20'])
        self.assertEqual(2, len(_select_tile_ids(rd.dashboard_id)))
        tiles = Tile.select_multi(rd.dashboard_id,
                                  _select_tile_ids(rd.dashboard_id)).values()
        created_tile = util.first(tiles, key=lambda t: not t.is_master_tile())
        self.assertEqual(['p1:20'], created_tile.tile_options['tags'])
        self.assertEqual(600, created_tile.tile_options['seconds_back'])
        self.assertEqual(tile_config['tile_options']['sscs'],
                         created_tile.tile_options['sscs'])
        td = created_tile.get_tile_data()
        self.assertEqual('points (monique, robert3)',
                         td['generated_tile_title'])
        self.assertEqual('[p1:20]', td['generated_tile_title_postfix'])

        d = [
            OrderedDict([('user_name', 'robert3'), ('is_active', True),
                         ('points', 128)])
        ]
        rd.report.process_input(json.dumps(d), tags=['p1:30', 'p2:30'])
        self.assertEqual(3, len(_select_tile_ids(rd.dashboard_id)))

        del tile_config['tile_options']['tpcreator_uispec']
        tile_config['tile_options']['tile_title'] = 'ot0'
        other_tile = Tile.insert(rd.owner_id, rd.report.report_id,
                                 rd.dashboard_id, tile_config)
        layouts.place_tile(other_tile)
        self.assertEqual(4, len(_select_tile_ids(rd.dashboard_id)))

        self.assertEqual(2,
                         len(tpcreator.select_tpcreated_tile_ids(master_tile)))

        for i, tile_id in enumerate(
                tpcreator.select_tpcreated_tile_ids(master_tile)):
            tile = Tile.select(rd.dashboard_id, tile_id)
            tile_config = tile.get_tile_config()
            tile_config['tile_options']['tile_title'] = 'tpc%d' % i
            new_tile = tile.insert_similar(tile_config)
            layouts.replace_tiles({tile: new_tile}, None)

        return rd, Tile.select(master_tile.dashboard_id, master_tile.tile_id)