feat(api): dashboard re-think 1/5

This commit is contained in:
Taha Yassine Kraiem 2022-03-28 19:55:06 +02:00
parent cc08060e30
commit 8e1f93630c
8 changed files with 119 additions and 51 deletions

View file

@ -9,10 +9,9 @@ from starlette.responses import StreamingResponse
from chalicelib.utils import helper
from chalicelib.utils import pg_client
from routers import core, core_dynamic
from routers.app import v1_api
from routers.crons import core_crons
from routers.crons import core_dynamic_crons
from routers.subs import dashboard, insights, metrics
from routers.subs import dashboard, insights, metrics, v1_api
app = FastAPI()

View file

@ -77,13 +77,17 @@ def add_widget(project_id, user_id, dashboard_id, data: schemas.AddWidgetToDashb
row = cur.fetchone()
return helper.dict_to_camel_case(row)
# def get_widgets(project_id):
# with pg_client.PostgresClient() as cur:
# pg_query = f"""SELECT *
# FROM widgets
# WHERE deleted_at ISNULL
# AND project_id = %(projectId)s;"""
# params = {"projectId": project_id}
# cur.execute(cur.mogrify(pg_query, params))
# rows = cur.fetchall()
# return helper.list_to_camel_case(rows)
def remove_widget(project_id, user_id, dashboard_id,widget_id):
ref_key = "metric_id"
if data.template_id is not None:
ref_key = "template_id"
with pg_client.PostgresClient() as cur:
pg_query = f"""INSERT INTO dashboard_widgets(dashboard_id, {ref_key}, user_id, configuration, name)
VALUES (%(dashboard_id)s, %({ref_key})s, %(userId)s, %(configuration)s::jsonb, %(name)s)
RETURNING *;"""
params = {"userId": user_id, "projectId": project_id, "dashboard_id": dashboard_id, **data.dict()}
params["configuration"] = json.dumps(params.get("configuration", {}))
cur.execute(cur.mogrify(pg_query, params))
row = cur.fetchone()
return helper.dict_to_camel_case(row)

View file

@ -6,12 +6,13 @@ CATEGORY_DESCRIPTION = {
}
def get_templates():
def get_templates(project_id, user_id):
with pg_client.PostgresClient() as cur:
pg_query = f"""SELECT category, jsonb_agg(templates ORDER BY name) AS widgets
FROM templates
pg_query = cur.mogrify(f"""SELECT category, jsonb_agg(metrics ORDER BY name) AS widgets
FROM metrics
WHERE project_id ISNULL OR (project_id = %(project_id)s AND (is_public OR user_id= %(userId)s))
GROUP BY category
ORDER BY category;"""
ORDER BY category;""", {"project_id": project_id, "userId": user_id})
cur.execute(pg_query)
rows = cur.fetchall()
for r in rows:

View file

@ -21,15 +21,23 @@ def get_dashboards(projectId: int, context: schemas.CurrentContext = Depends(OR_
@app.get('/{projectId}/dashboards/{dashboardId}', tags=["dashboard", "metrics"])
def get_dashboards(projectId: int, dashboardId: int, context: schemas.CurrentContext = Depends(OR_context)):
def get_dashboard(projectId: int, dashboardId: int, context: schemas.CurrentContext = Depends(OR_context)):
return {"data": dashboards2.get_dashboard(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId)}
@app.post('/{projectId}/dashboards/{dashboardId}/metrics', tags=["dashboard", "metrics"])
@app.put('/{projectId}/dashboards/{dashboardId}/metrics', tags=["dashboard", "metrics"])
def add_widget_to_dashboards(projectId: int, dashboardId: int,
data: schemas.AddWidgetToDashboardPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
def add_widget_to_dashboard(projectId: int, dashboardId: int,
data: schemas.AddWidgetToDashboardPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": dashboards2.add_widget(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId,
data=data)}
@app.delete('/{projectId}/dashboards/{dashboardId}/metrics/{metricId}', tags=["dashboard", "metrics"])
def remove_widget_from_dashboard(projectId: int, dashboardId: int, metricId: int,
data: schemas.AddWidgetToDashboardPayloadSchema = Body(...),
context: schemas.CurrentContext = Depends(OR_context)):
return {"data": dashboards2.add_widget(project_id=projectId, user_id=context.user_id, dashboard_id=dashboardId,
data=data)}
@ -41,7 +49,7 @@ def add_widget_to_dashboards(projectId: int, dashboardId: int,
@app.get('/{projectId}/metrics/templates', tags=["dashboard", "metrics"])
def get_templates(projectId: int, context: schemas.CurrentContext = Depends(OR_context)):
return {"data": templates.get_templates()}
return {"data": templates.get_templates(project_id=projectId, user_id=context.user_id)}
@app.post('/{projectId}/metrics/try', tags=["dashboard"])

View file

@ -6,38 +6,86 @@ SELECT 'v1.5.5'
$$ LANGUAGE sql IMMUTABLE;
CREATE TABLE dashboards
-- CREATE TABLE dashboards
-- (
-- dashboard_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY,
-- project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE,
-- user_id integer NOT NULL REFERENCES users (user_id) ON DELETE SET NULL,
-- name text NOT NULL,
-- is_public boolean NOT NULL DEFAULT TRUE,
-- is_pinned boolean NOT NULL DEFAULT FALSE,
-- created_at timestamp NOT NULL DEFAULT timezone('utc'::text, now()),
-- deleted_at timestamp NULL DEFAULT NULL
-- );
-- CREATE TABLE templates
-- (
-- template_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY,
-- template_key text,
-- name text NOT NULL,
-- category text NOT NULL,
-- series jsonb NOT NULL,
-- config jsonb NOT NULL,
-- predefined boolean DEFAULT TRUE
-- );
-- CREATE TABLE dashboard_widgets
-- (
-- widget_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY,
-- dashboard_id integer NOT NULL REFERENCES dashboards (dashboard_id) ON DELETE CASCADE,
-- metric_id integer NOT NULL REFERENCES metrics (metric_id) ON DELETE CASCADE,
-- -- template_id integer NOT NULL REFERENCES templates (template_id) ON DELETE CASCADE,
-- user_id integer NOT NULL REFERENCES users (user_id) ON DELETE SET NULL,
-- created_at timestamp NOT NULL DEFAULT timezone('utc'::text, now()),
-- configuration jsonb NOT NULL DEFAULT '{}'::jsonb,
-- name text
-- );
-- INSERT INTO public.templates (name, category, series, config, predefined, template_key)
-- VALUES ('captured sessions', 'overview', '[]', '{}', true, 'count_sessions'),
-- ('request load time', 'overview', '[]', '{}', true, 'avg_request_load_time'),
-- ('page load time', 'overview', '[]', '{}', true, 'avg_page_load_time'),
-- ('image load time', 'overview', '[]', '{}', true, 'avg_image_load_time');
ALTER TYPE metric_view_type ADD VALUE IF NOT EXISTS 'areaChart';
ALTER TABLE IF EXISTS metrics
DROP CONSTRAINT IF EXISTS null_project_id_for_template_only;
ALTER TABLE IF EXISTS metrics
ADD COLUMN IF NOT EXISTS category text NULL DEFAULT 'custom',
ADD COLUMN IF NOT EXISTS is_predefined boolean NOT NULL DEFAULT FALSE,
ADD COLUMN IF NOT EXISTS is_template boolean NOT NULL DEFAULT FALSE,
ADD COLUMN IF NOT EXISTS key text NULL DEFAULT NULL,
ADD COLUMN IF NOT EXISTS config jsonb NOT NULL DEFAULT '{}'::jsonb,
ALTER COLUMN project_id DROP NOT NULL,
ADD CONSTRAINT null_project_id_for_template_only
CHECK ( (metrics.category != 'custom') != (metrics.project_id IS NOT NULL) );
CREATE TABLE IF NOT EXISTS dashboard_widgets
(
dashboard_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY,
project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE,
widget_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY,
dashboard_id integer NOT NULL REFERENCES dashboards (dashboard_id) ON DELETE CASCADE,
metric_id integer NOT NULL REFERENCES metrics (metric_id) ON DELETE CASCADE,
user_id integer NOT NULL REFERENCES users (user_id) ON DELETE SET NULL,
name text NOT NULL,
is_public boolean NOT NULL DEFAULT TRUE,
is_pinned boolean NOT NULL DEFAULT FALSE,
created_at timestamp NOT NULL DEFAULT timezone('utc'::text, now()),
deleted_at timestamp NULL DEFAULT NULL
config jsonb NOT NULL DEFAULT '{}'::jsonb,
name text
);
-- INSERT INTO public.templates (name, category, series, config, predefined, template_key)
-- VALUES ('captured sessions', 'overview', '[]', '{}', true, 'count_sessions'),
-- ('request load time', 'overview', '[]', '{}', true, 'avg_request_load_time'),
-- ('page load time', 'overview', '[]', '{}', true, 'avg_page_load_time'),
-- ('image load time', 'overview', '[]', '{}', true, 'avg_image_load_time');
CREATE TABLE widgets
(
widget_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY,
project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE,
user_id integer NOT NULL REFERENCES users (user_id) ON DELETE SET NULL,
name text NOT NULL,
is_template boolean NOT NULL DEFAULT FALSE,
predefined boolean NOT NULL DEFAULT FALSE,
created_at timestamp NOT NULL DEFAULT timezone('utc'::text, now()),
deleted_at timestamp NULL DEFAULT NULL
);
INSERT INTO metrics (name, category, config, is_predefined, is_template, is_public, key)
VALUES ('captured sessions', 'overview', '{}', true, true, true, 'count_sessions'),
('request load time', 'overview', '{}', true, true, true, 'avg_request_load_time'),
('page load time', 'overview', '{}', true, true, true, 'avg_page_load_time'),
('image load time', 'overview', '{}', true, true, true, 'avg_image_load_time');
CREATE TABLE dashboard_widgets
(
dashboard_id integer NOT NULL REFERENCES dashboards (dashboard_id) ON DELETE CASCADE,
widget_id integer NOT NULL REFERENCES widgets (widget_id) ON DELETE CASCADE,
user_id integer NOT NULL REFERENCES users (user_id) ON DELETE SET NULL,
created_at timestamp NOT NULL DEFAULT timezone('utc'::text, now()),
configuration jsonb NOT NULL DEFAULT '{}'::jsonb
);
COMMIT;
COMMIT

View file

@ -936,11 +936,11 @@ $$
CREATE INDEX jobs_project_id_idx ON jobs (project_id);
CREATE TYPE metric_type AS ENUM ('timeseries','table');
CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart');
CREATE TYPE metric_view_type AS ENUM ('lineChart','progress','table','pieChart','areaChart');
CREATE TABLE metrics
(
metric_id integer generated BY DEFAULT AS IDENTITY PRIMARY KEY,
project_id integer NOT NULL REFERENCES projects (project_id) ON DELETE CASCADE,
project_id integer NULL REFERENCES projects (project_id) ON DELETE CASCADE,
user_id integer REFERENCES users (user_id) ON DELETE SET NULL,
name text NOT NULL,
is_public boolean NOT NULL DEFAULT FALSE,
@ -951,8 +951,16 @@ $$
view_type metric_view_type NOT NULL DEFAULT 'lineChart',
metric_of text NOT NULL DEFAULT 'sessionCount',
metric_value text[] NOT NULL DEFAULT '{}'::text[],
metric_format text
metric_format text,
category text NULL DEFAULT 'custom',
is_predefined boolean NOT NULL DEFAULT FALSE,
is_template boolean NOT NULL DEFAULT FALSE,
key text NULL DEFAULT NULL,
config jsonb NOT NULL DEFAULT '{}'::jsonb,
CONSTRAINT null_project_id_for_template_only
CHECK ( (metrics.category != 'custom') != (metrics.project_id IS NOT NULL) )
);
CREATE INDEX metrics_user_id_is_public_idx ON public.metrics (user_id, is_public);
CREATE TABLE metric_series
(