def replace_tile(): dashboard_id = request.get_json()['dashboard_id'] tile_id = request.get_json()['tile_id'] report_id = request.get_json()['report_id'] tile_config = request.get_json()['tile_config'] for_layout_id = request.get_json()['for_layout_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) check_access(lambda: auth.access_report_instances(report_id)) tile = tiles.Tile.select(dashboard_id, tile_id) if not tile: return error(message='No tile found, please refresh the page') new_tile = tile.insert_similar(tile_config) repl_res = layouts.replace_tiles({tile: new_tile}, for_layout_id) if not repl_res: return error('A newer version of the dashboard is available, please refresh the page') log.info('Replaced tile %s with tile %s', tile_id, new_tile.tile_id) dataseries.update_default_options(new_tile) tpcreated_replacement = [[t1.tile_id, t2.tile_id] for (t1, t2) in repl_res.tile_replacement.items() if t2 != new_tile] return success(result=dict(new_tile=new_tile, new_layout_id=repl_res.new_layout.layout_id, tpcreated_replacement=tpcreated_replacement))
def move_tile(): dashboard_id = request.get_json()['dashboard_id'] tile_id = request.get_json()['tile_id'] target_dashboard_id = request.get_json()['target_dashboard_id'] for_layout_id = request.get_json()['for_layout_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) check_access(lambda: auth.access_dashboard(target_dashboard_id)) old_tile = tiles.Tile.select(dashboard_id, tile_id) if not old_tile: return error('Invalid source tile in move_tile %s %s' % (dashboard_id, tile_id)) new_tile = old_tile.copy(target_dashboard_id) if not layouts.place_tile(new_tile): return error('Cannot copy the source file') mres = layouts.detach_tile(old_tile, for_layout_id=for_layout_id) if not mres: return error(message='Deletion of the source tile unsuccessful due to old page data') log.info('Moved tile tile_id=%s dashboard_id=%s to tile tile_id=%s dashboard_id=%s', tile_id, dashboard_id, new_tile.tile_id, target_dashboard_id) return success(result=dict(new_layout_id=mres.new_layout.layout_id))
def fetch_tile_settings(): dashboard_id = request.get_json()['dashboard_id'] tile_id = request.get_json()['tile_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) tile = tiles.Tile.select(dashboard_id, tile_id) if not tile: return error(message='No tile found, please refresh the page') check_access(lambda: auth.access_report_instances(tile.report_id)) res = {} res['report_id'] = tile.report_id latest_instance_id = tile.report.fetch_latest_instance_id(tile.tile_options['tags']) if not latest_instance_id: return error(message='No report instances for report %s - at least one report instance is needed to display tile settings.' % tile.report.report_name) ri = tile.report.fetch_single_instance(latest_instance_id, tile.tile_options['tags']) res['latest_instance_id'] = latest_instance_id res['html_newest_table'] = get_template_attribute('m.html', 'table_as_html_table')(ri.table) if tile.tile_options['tags']: res['html_selected_tags'] = get_template_attribute('m.html', 'selected_tags')(tile.tile_options['tags']) tpcreator_uispec = tile.tile_options.get('tpcreator_uispec') if not tpcreator_uispec: tpcreator_uispec = tpcreator.suggested_tpcreator_uispec(tile.tile_options['tags']) res['html_tpcreator_content'] = get_template_attribute('m.html', 'tpcreator_content')(tpcreator_uispec) else: res['html_selected_tags'] = None res['html_tpcreator_content'] = None res['tile_options'] = tile.tile_options res['report_name'] = tile.report.report_name html_series_specs = [] for series_spec in tile.series_specs(): data_d = {} cell = series_spec.get_cell(ri) if cell: data_d['sampled-from'] = {'rowno': cell.rowno, 'colno': cell.colno} html_series_specs.append(get_template_attribute('m.html', 'series_spec')(series_spec, ri, data_d)) res['html_all_series_specs'] = '\n'.join(html_series_specs) if tile.tile_options.get('sscs'): res['html_sscs'] = get_template_attribute('m.html', 'series_spec_creator_spec')(tile.tile_options['sscs'], ri) else: res['html_sscs'] = None return success(result=res)
def create_tile(): dashboard_id = request.get_json()['dashboard_id'] report_id = request.get_json().get('report_id') report_instance_id = request.get_json().get('report_instance_id') tile_config = request.get_json()['tile_config'] moveresize = request.get_json()['moveresize'] for_layout_id = request.get_json()['for_layout_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) check_access(lambda: auth.access_report_instances(report_id)) if tile_config['tags']: tile_config['tile_options']['tpcreator_uispec'] = tpcreator.suggested_tpcreator_uispec( tile_config['tags']) tile = tiles.Tile.insert(auth.logged_owner_id(), report_id, dashboard_id, tile_config) mres = layouts.place_tile(tile, for_layout_id=for_layout_id) if not mres: return error(message='Could not place the new tile on the dashboard, a page refresh is needed') dataseries.update_default_options(tile) log.info('Created new tile report_id=%s dashboard_id=%s tile_id=%s', report_id, dashboard_id, tile.tile_id) tile_html = get_template_attribute('m.html', 'dashboard_tile')\ (tile.tile_id, mres.new_tiles[tile], moveresize) return success(result=dict( tile_html=tile_html, new_layout_id=mres.new_layout.layout_id, ))
def report_instance_for_viewer(): report_name = request.get_json()['report_name'] tags = request.get_json().get('tags') curr_report_instance_id = request.get_json()['curr_report_instance_id'] direction = request.get_json().get('direction') search_date = request.get_json().get('search_date') check_access(lambda: auth.access_profile()) report = Report.select_by_name(auth.logged_owner_id(), report_name) if not curr_report_instance_id: curr_report_instance_id = report.fetch_latest_instance_id(tags) if not curr_report_instance_id: return error() if not direction: if search_date is not None: ri = report.find_report_instance_by_dt(search_date, tags) else: ri = report.fetch_single_instance(curr_report_instance_id) elif direction == 'next': ri = report.fetch_next_instance(curr_report_instance_id, tags) elif direction == 'prev': ri = report.fetch_prev_instance(curr_report_instance_id, tags) else: return error('Wrong direction') res = {} res['report_id'] = report.report_id res['report_has_tags'] = report.has_tags() if ri: res['html_newest_table'] = get_template_attribute('m.html', 'table_as_html_table')(ri.table) res['created_raw'] = datetime_from_uuid1(ri.report_instance_id) res['created'] = format_datetime(datetime_from_uuid1(ri.report_instance_id)) res['tags'] = Markup(' '.join('<span class="selected-tag-name clickable">%s</span>' % tag for tag in ri.all_tags)) res['curr_report_instance_id'] = ri.report_instance_id res['has_next'] = report.fetch_next_instance(ri.report_instance_id, tags) is not None res['has_prev'] = report.fetch_prev_instance(ri.report_instance_id, tags) is not None else: res['html_newest_table'] = '' res['created_raw'] = '' res['created'] = '' res['tags'] = '' res['curr_report_instance_id'] = None res['has_next'] = False res['has_prev'] = False return success(result=res)
def delete_tile(): dashboard_id = request.get_json()['dashboard_id'] tile_id = request.get_json()['tile_id'] for_layout_id = request.get_json()['for_layout_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) tile = tiles.Tile.select(dashboard_id, tile_id) if not tile: return error('Invalid tile') mres = layouts.detach_tile(tile, for_layout_id=for_layout_id) if not mres: return error(message='Could not delete the tile, a page refresh is needed') log.info('Deleted tile dashboard_id=%s tile_id=%s', dashboard_id, tile_id) return success(result=dict(new_layout_id=mres.new_layout.layout_id))
def add_dashboard(): name = request.get_json()['name'].strip() check_access(lambda: auth.access_profile()) if not name: return error('Empty name') for invalid_char in ('/', '\\'): if invalid_char in name: return error('Invalid character "%s"' % invalid_char) dbs = dashboards.OwnerDashboards(auth.logged_owner_id()) if name in {db.dashboard_name for db in dbs.dashboards}: return error('A dashboard with this name is already created') new_db = dbs.insert_dashboard(name, {}) html = get_template_attribute('m.html', 'db_tab')(new_db, False, True) return success(result=dict(html=html))
def selected_tags_change(): report_id = request.get_json()['report_id'] tags = request.get_json()['tags'] check_access(lambda: auth.access_report_instances(report_id)) report = Report.select(report_id) latest_instance_id = report.fetch_latest_instance_id(tags) if not latest_instance_id: return error() ri = report.fetch_single_instance(latest_instance_id, tags) if not ri: return error('No report instance %s' % latest_instance_id) res = {} res['html_newest_table'] = get_template_attribute('m.html', 'table_as_html_table')(ri.table) res['latest_instance_id'] = latest_instance_id return success(result=res)
def delete_dashboard(): dashboard_id = request.get_json()['dashboard_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) dashboard = dashboards.Dashboard.select(auth.logged_owner_id(), dashboard_id) if not dashboard: return error('No such dashboard') dashboard.delete() return success()
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))
def add_report_name_entered(): report_name = request.get_json()['report_name'] check_access(lambda: auth.access_profile()) report = Report.select_by_name(auth.logged_owner_id(), report_name) if not report: return error(message='Incomplete report name') latest_instance_id = report.fetch_latest_instance_id() if not latest_instance_id: return error() ri = report.fetch_single_instance(latest_instance_id) tags = report.fetch_tags_sample('', TAGS_SAMPLE_LIMIT) res = {} res['has_tags'] = bool(tags) res['tag_sample'] = get_template_attribute('m.html', 'tag_sample')(tags) res['html_newest_table'] = get_template_attribute('m.html', 'table_as_html_table')(ri.table) res['report_id'] = report.report_id res['latest_instance_id'] = latest_instance_id res['latest_instance_tags'] = ri.all_tags return success(result=res)
def compute_series_spec(): report_id = request.get_json()['report_id'] report_instance_id = request.get_json()['report_instance_id'] sample = request.get_json()['sample'] check_access(lambda: auth.access_report_instances(report_id)) report = Report.select(report_id) report_instance = report.fetch_single_instance(report_instance_id) series_spec = dataseries.guess_series_spec(report, report_instance, sample['rowno'], sample['colno']) if series_spec is None: return error() series_spec_html = get_template_attribute('m.html', 'series_spec')(series_spec, report_instance) return success(result=dict(series_spec=series_spec, series_spec_html=series_spec_html))
def matching_cell_for_series_spec(): report_id = request.get_json()['report_id'] report_instance_id = request.get_json()['report_instance_id'] series_spec = request.get_json()['series_spec'] check_access(lambda: auth.access_report_instances(report_id)) report = Report.select(report_id) report_instance = report.fetch_single_instance(report_instance_id) if not report_instance: return error('No report instance') cell = series_spec.get_cell(report_instance) if not cell: return success() return success(result=dict(rowno=cell.rowno, colno=cell.colno))
def fetch_move_tile_data(): dashboard_id = request.get_json()['dashboard_id'] tile_id = request.get_json()['tile_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) dbs = dashboards.OwnerDashboards(auth.logged_owner_id()) options = [(serialize.mjson(db.dashboard_id), db.dashboard_name) for db in dbs.dashboards if db.dashboard_id != dashboard_id] tile = tiles.Tile.select(dashboard_id, tile_id) if not tile: return error('Invalid tile') result = dict( report_name=tile.report.report_name, has_options=bool(options), html_dashboard_select=get_template_attribute('m.html', 'select')('move-to-dashboard-select', options), ) return success(result=result)
def request_expire_tiles_without_data(): dashboard_id = request.get_json()['dashboard_id'] tile_id_list = request.get_json()['tile_id_list'] check_access(lambda: auth.access_dashboard(dashboard_id)) dashboard = dashboards.Dashboard.select(auth.logged_owner_id(), dashboard_id) if not dashboard: return error('No dashboard') max_seconds_without_data = nestedget(dashboard.dashboard_options, 'max_without_data', 'seconds_back') if not max_seconds_without_data: log.warn('request_expire_tiles_without_data called with empty max_seconds_without_data') return tile_list = tiles.Tile.select_multi(dashboard_id, tile_id_list).values() new_layout_id = tiles.expire_tiles_without_data(tile_list, max_seconds_without_data, None) return success(result=dict(tiles_expired=bool(new_layout_id)))
def update_dashboard(): dashboard_id = request.get_json()['dashboard_id'] new_dashboard_name = request.get_json()['new_dashboard_name'].strip() max_without_data = request.get_json().get('max_without_data') enable_synchronizing_tpcreated = request.get_json()['enable_synchronizing_tpcreated'] enable_synchronizing_tpcreated_x_axes = request.get_json()['enable_synchronizing_tpcreated_x_axes'] check_access(lambda: auth.access_dashboard(dashboard_id)) dashboard = dashboards.Dashboard.select(auth.logged_owner_id(), dashboard_id) if not dashboard: return error('Invalid dashboard') res = {} if dashboard.dashboard_name != new_dashboard_name: dashboard.update(dashboard_name=new_dashboard_name) res['new_dashboard_name'] = new_dashboard_name res['reloading_dashboard_required'] = \ dashboard.dashboard_options.get('enable_synchronizing_tpcreated', True) != \ enable_synchronizing_tpcreated or \ dashboard.dashboard_options.get('enable_synchronizing_tpcreated_x_axes', False) != \ enable_synchronizing_tpcreated_x_axes new_dashboard_options = copy.deepcopy(dashboard.dashboard_options) new_dashboard_options['max_without_data'] = max_without_data new_dashboard_options['enable_synchronizing_tpcreated'] = enable_synchronizing_tpcreated new_dashboard_options['enable_synchronizing_tpcreated_x_axes'] = \ enable_synchronizing_tpcreated_x_axes dashboard.update(dashboard_options=new_dashboard_options) res['new_dashboard_options'] = new_dashboard_options log.info('Updated dashboard %s with options %s', dashboard_id, new_dashboard_options) return success(result=res)
def fetch_tile_data(): dashboard_id = request.get_json()['dashboard_id'] tile_id = request.get_json()['tile_id'] check_access(lambda: auth.access_dashboard(dashboard_id)) tile = tiles.Tile.select(dashboard_id, tile_id) if not tile: return error(message='No tile found, please refresh the page', result='NO_TILE_FOUND') check_access(lambda: auth.access_report_instances(tile.report_id)) data = tile.get_tile_data() # Postprocess tile data - generate html if tile.tile_options['drawer_type'] == 'TextTableDrawer': data['drawer_html'] = get_template_attribute('m.html', 'tile_data_as_table')( data, data['series_data_as_rows']) del data['series_data_as_rows'] elif tile.tile_options['drawer_type'] == 'TextSingleDrawer': all_empty = not any(bool(d['data_points']) for d in data['series_data']) data['drawer_html'] = get_template_attribute('m.html', 'tile_data_as_single_text')(data, all_empty) return success(result=dict(tile_options=tile.tile_options, data=data))