Skip to content

Commit

Permalink
feat: add a description to reports and projects (#239)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Cabrera <[email protected]>
  • Loading branch information
Sparkier and cabreraalex authored Sep 29, 2023
1 parent 949204e commit ec64eea
Show file tree
Hide file tree
Showing 17 changed files with 473 additions and 273 deletions.
6 changes: 4 additions & 2 deletions backend/init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ CREATE TABLE projects (
data_url text,
calculate_histogram_metrics boolean NOT NULL DEFAULT false,
samples_per_page integer NOT NULL DEFAULT 10,
public boolean NOT NULL DEFAULT false
public boolean NOT NULL DEFAULT false,
description text NOT NULL DEFAULT ''
);

CREATE TABLE charts (
Expand All @@ -27,7 +28,8 @@ CREATE TABLE reports (
id integer GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name text NOT NULL,
owner_id integer NOT NULL REFERENCES users(id) ON DELETE CASCADE ON UPDATE CASCADE,
public boolean NOT NULL DEFAULT false
public boolean NOT NULL DEFAULT false,
description text NOT NULL DEFAULT ''
);

CREATE TABLE report_elements (
Expand Down
2 changes: 2 additions & 0 deletions backend/zeno_backend/classes/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class Project(CamelModel):
Default True.
samples_per_page (int): number of datapoints to show per page. Default 10.
public (bool): whether the task is public. Default False.
description (str): description of the project. Default "".
"""

uuid: str
Expand All @@ -34,6 +35,7 @@ class Project(CamelModel):
calculate_histogram_metrics: bool = True
samples_per_page: int = 10
public: bool = False
description: str = ""


class ProjectStats(CamelModel):
Expand Down
14 changes: 14 additions & 0 deletions backend/zeno_backend/classes/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ class Report(CamelModel):
linked_projects (list[str]): all projects that can be used with the report.
editor (bool): whether the current user can edit the report.
public (bool): whether the report is publically visible.
description (str): description of the report. Default "".
"""

id: int
Expand All @@ -34,6 +35,7 @@ class Report(CamelModel):
linked_projects: list[str]
editor: bool
public: bool = False
description: str = ""


class ReportElement(CamelModel):
Expand Down Expand Up @@ -62,3 +64,15 @@ class ReportResponse(CamelModel):

report: Report
report_elements: list[ReportElement]


class ReportStats(CamelModel):
"""Statistical numbers of a Zeno report.
Attributes:
num_projects (int): number of projects that are linked to the report.
num_elements (int): number of elements in the report.
"""

num_projects: int
num_elements: int
5 changes: 3 additions & 2 deletions backend/zeno_backend/database/insert.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ def project(project_config: Project, owner_id: int):
with Database() as db:
db.execute(
"INSERT INTO projects (uuid, name, owner_id, view, data_url, "
+ "calculate_histogram_metrics, samples_per_page, public) "
+ "VALUES (%s,%s,%s,%s,%s,%s,%s,%s);",
+ "calculate_histogram_metrics, samples_per_page, public, description) "
+ "VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s);",
[
project_config.uuid,
project_config.name,
Expand All @@ -73,6 +73,7 @@ def project(project_config: Project, owner_id: int):
project_config.calculate_histogram_metrics,
project_config.samples_per_page,
project_config.public,
project_config.description,
],
)
db.execute(
Expand Down
86 changes: 67 additions & 19 deletions backend/zeno_backend/database/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@
from zeno_backend.classes.metadata import StringFilterRequest
from zeno_backend.classes.metric import Metric
from zeno_backend.classes.project import Project, ProjectState, ProjectStats
from zeno_backend.classes.report import Report, ReportElement, ReportResponse
from zeno_backend.classes.report import (
Report,
ReportElement,
ReportResponse,
ReportStats,
)
from zeno_backend.classes.slice import Slice
from zeno_backend.classes.slice_finder import SQLTable
from zeno_backend.classes.table import TableRequest
Expand Down Expand Up @@ -50,7 +55,7 @@ def projects(user: User) -> list[Project]:
with Database() as db:
own_projects_result = db.execute_return(
"SELECT uuid, name, view, data_url, calculate_histogram_metrics, "
"samples_per_page, public FROM projects WHERE owner_id = %s;",
"samples_per_page, public, description FROM projects WHERE owner_id = %s;",
[user.id],
)
own_projects = list(
Expand All @@ -65,16 +70,17 @@ def projects(user: User) -> list[Project]:
samples_per_page=project[5],
editor=True,
public=project[6],
description=project[7],
),
own_projects_result,
)
)

user_projects_result = db.execute_return(
"SELECT p.uuid, p.name, p.owner_id, p.view, p.data_url, "
"p.calculate_histogram_metrics, p.samples_per_page, up.editor, p.public "
"FROM projects AS p JOIN user_project AS up ON p.uuid = up.project_uuid "
"WHERE up.user_id = %s;",
"p.calculate_histogram_metrics, p.samples_per_page, up.editor, p.public, "
"p.description FROM projects AS p JOIN user_project AS up "
"ON p.uuid = up.project_uuid WHERE up.user_id = %s;",
[user.id],
)
user_projects = []
Expand All @@ -95,14 +101,15 @@ def projects(user: User) -> list[Project]:
samples_per_page=res[6],
editor=res[7],
public=res[8],
description=res[9],
)
)

project_org_result = db.execute_return(
"SELECT p.uuid, p.name, p.owner_id, p.view, p.calculate_histogram_metrics,"
" p.data_url, p.samples_per_page, op.editor, p.public FROM projects AS p "
"JOIN (SELECT op.project_uuid, uo.organization_id, editor "
"FROM user_organization as uo JOIN organization_project as op"
" p.data_url, p.samples_per_page, op.editor, p.public, p.description "
"FROM projects AS p JOIN (SELECT op.project_uuid, uo.organization_id, "
"editor FROM user_organization as uo JOIN organization_project as op"
" ON uo.organization_id = op.organization_id "
"WHERE user_id = %s) AS op ON p.uuid = op.project_uuid;",
[user.id],
Expand All @@ -125,6 +132,7 @@ def projects(user: User) -> list[Project]:
samples_per_page=res[6],
editor=res[7],
public=res[8],
description=res[9],
)
)
org_projects = list(
Expand All @@ -146,7 +154,7 @@ def public_projects() -> list[Project]:
with Database() as db:
project_result = db.execute_return(
"SELECT uuid, name, owner_id, view, data_url, calculate_histogram_metrics, "
"samples_per_page FROM projects WHERE public IS TRUE;",
"samples_per_page, description FROM projects WHERE public IS TRUE;",
)
projects = []
for res in project_result:
Expand All @@ -166,6 +174,7 @@ def public_projects() -> list[Project]:
samples_per_page=res[6],
editor=False,
public=True,
description=res[7],
)
)
return projects
Expand All @@ -182,7 +191,7 @@ def reports(user: User) -> list[Report]:
"""
with Database() as db:
own_reports_result = db.execute_return(
"SELECT id, name, public FROM reports WHERE owner_id = %s;",
"SELECT id, name, public, description FROM reports WHERE owner_id = %s;",
[user.id],
)
own_reports = []
Expand All @@ -202,11 +211,12 @@ def reports(user: User) -> list[Report]:
else list(map(lambda linked: str(linked[0]), linked_projects)),
editor=True,
public=report[2],
description=report[3],
)
)

user_reports_result = db.execute_return(
"SELECT r.id, r.name, r.owner_id, ur.editor, r.public "
"SELECT r.id, r.name, r.owner_id, ur.editor, r.public, r.description "
"FROM reports AS r JOIN user_report AS ur ON r.id = ur.report_id "
"WHERE ur.user_id = %s;",
[user.id],
Expand Down Expand Up @@ -235,13 +245,14 @@ def reports(user: User) -> list[Report]:
),
editor=res[4],
public=res[5],
description=res[6],
)
)

report_org_result = db.execute_return(
"SELECT r.id, r.name, r.owner_id, op.editor, r.public FROM reports AS r "
"JOIN (SELECT op.report_id, uo.organization_id, op.editor "
"FROM user_organization as uo JOIN organization_report as op"
"SELECT r.id, r.name, r.owner_id, op.editor, r.public, r.description "
"FROM reports AS r JOIN (SELECT op.report_id, uo.organization_id, "
"op.editor FROM user_organization as uo JOIN organization_report as op"
" ON uo.organization_id = op.organization_id "
"WHERE user_id = %s) AS op ON r.id = op.report_id;",
[user.id],
Expand Down Expand Up @@ -270,6 +281,7 @@ def reports(user: User) -> list[Report]:
),
editor=res[4],
public=res[5],
description=res[6],
)
)
org_reports = list(
Expand All @@ -290,7 +302,7 @@ def public_reports() -> list[Report]:
"""
with Database() as db:
report_result = db.execute_return(
"SELECT id, name, owner_id FROM reports WHERE public IS TRUE;",
"SELECT id, name, owner_id, description FROM reports WHERE public IS TRUE;",
)
reports = []
if report_result is not None:
Expand All @@ -316,6 +328,7 @@ def public_reports() -> list[Report]:
),
editor=False,
public=True,
description=res[3],
)
)
return reports
Expand Down Expand Up @@ -480,7 +493,7 @@ def report(
owner_id = owner_id[0][0]

report_result = db.execute_return(
"SELECT id, name, owner_id, public FROM reports "
"SELECT id, name, owner_id, public, description FROM reports "
"WHERE name = %s AND owner_id = %s;",
[report_name, owner_id],
)
Expand Down Expand Up @@ -537,6 +550,7 @@ def report(
else list(map(lambda linked: str(linked[0]), linked_projects)),
editor=editor,
public=bool(report_result[0][3]),
description=str(report_result[0][4]),
),
report_elements=list(
map(
Expand Down Expand Up @@ -599,8 +613,8 @@ def project_from_uuid(project_uuid: str) -> Project | None:
"""
with Database() as db:
project_result = db.execute_return(
"SELECT uuid, name, owner_id, view, "
"data_url, calculate_histogram_metrics, samples_per_page, public "
"SELECT uuid, name, owner_id, view, data_url, calculate_histogram_metrics, "
"samples_per_page, public, description "
"FROM projects WHERE uuid = %s;",
[project_uuid],
)
Expand All @@ -623,6 +637,7 @@ def project_from_uuid(project_uuid: str) -> Project | None:
if isinstance(project_result[6], int)
else 10,
public=bool(project_result[7]),
description=str(project_result[8]),
)


Expand All @@ -637,7 +652,8 @@ def report_from_id(report_id: int) -> Report | None:
"""
with Database() as db:
report_result = db.execute_return(
"SELECT id, name, owner_id, public FROM reports WHERE id = %s;",
"SELECT id, name, owner_id, public, description "
"FROM reports WHERE id = %s;",
[report_id],
)
if len(report_result) == 0:
Expand All @@ -663,6 +679,7 @@ def report_from_id(report_id: int) -> Report | None:
else list(map(lambda linked: str(linked[0]), linked_projects)),
editor=False,
public=bool(report_result[3]),
description=str(report_result[4]),
)


Expand Down Expand Up @@ -855,6 +872,37 @@ def project_stats(project: str) -> ProjectStats | None:
)


def report_stats(report_id: int) -> ReportStats | None:
"""Get statistics for a specified report.
Args:
report_id (int): id of the report to get statistics for.
Returns:
ReportStats | None: statistics of the specified report.
"""
with Database() as db:
num_projects = db.execute_return(
"SELECT COUNT(*) FROM report_project WHERE report_id = %s;",
[report_id],
)
num_elements = db.execute_return(
"SELECT COUNT(*) FROM report_elements " "WHERE report_id = %s;", [report_id]
)
return (
ReportStats(
num_projects=num_projects[0][0]
if isinstance(num_projects[0][0], int)
else 0,
num_elements=num_elements[0][0]
if isinstance(num_elements[0][0], int)
else 0,
)
if len(num_projects) > 0 and len(num_elements) > 0
else None
)


def metrics(project_uuid: str) -> list[Metric]:
"""Get all metrics for a specified project.
Expand Down
15 changes: 6 additions & 9 deletions backend/zeno_backend/database/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,16 @@ def project(project_config: Project):
with Database() as db:
db.execute(
"UPDATE projects SET name = %s, calculate_histogram_metrics = %s, "
"view = %s, data_url = %s, samples_per_page = %s, public = %s "
"WHERE uuid = %s;",
"view = %s, data_url = %s, samples_per_page = %s, public = %s, "
"description = %s WHERE uuid = %s;",
[
project_config.name,
project_config.calculate_histogram_metrics,
project_config.view,
project_config.data_url,
project_config.samples_per_page,
project_config.public,
project_config.description,
project_config.uuid,
],
)
Expand Down Expand Up @@ -251,13 +252,9 @@ def report(report: Report):
return
db = Database()
db.connect_execute(
"UPDATE reports SET name = %s, owner_id = %s, public = %s WHERE id = %s;",
[
report.name,
owner_id.id,
report.public,
report.id,
],
"UPDATE reports SET name = %s, owner_id = %s, public = %s, description = %s "
"WHERE id = %s;",
[report.name, owner_id.id, report.public, report.description, report.id],
)


Expand Down
17 changes: 16 additions & 1 deletion backend/zeno_backend/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,12 @@
from zeno_backend.classes.metadata import HistogramBucket, StringFilterRequest
from zeno_backend.classes.metric import Metric, MetricRequest
from zeno_backend.classes.project import Project, ProjectState, ProjectStats
from zeno_backend.classes.report import Report, ReportElement, ReportResponse
from zeno_backend.classes.report import (
Report,
ReportElement,
ReportResponse,
ReportStats,
)
from zeno_backend.classes.slice import Slice
from zeno_backend.classes.slice_finder import SliceFinderRequest, SliceFinderReturn
from zeno_backend.classes.table import TableRequest
Expand Down Expand Up @@ -150,6 +155,16 @@ def get_project_stats(project: str, request: Request):
return Response(status_code=401)
return select.project_stats(project)

@api_app.get(
"/report-stats/{report_id}",
response_model=ReportStats,
tags=["zeno"],
)
def get_report_stats(report_id: int, request: Request):
if not util.report_access_valid(report_id, request):
return Response(status_code=401)
return select.report_stats(report_id)

@api_app.get(
"/models/{project}",
response_model=list[str],
Expand Down
Loading

0 comments on commit ec64eea

Please sign in to comment.