This commit is contained in:
parent
9af30d582f
commit
a94d27db0c
1 changed files with 66 additions and 51 deletions
|
@ -4,6 +4,7 @@ from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import logging
|
import logging
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
# from typing import Any
|
# from typing import Any
|
||||||
|
|
||||||
from matplotlib.figure import Figure
|
from matplotlib.figure import Figure
|
||||||
|
@ -22,9 +23,8 @@ import matplotlib.pyplot as plt
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class DashboardPageSource(Model, table=True):
|
class DashboardPageSource(Model, table=True):
|
||||||
__tablename__ = 'dashboard_page_source' # type: ignore
|
__tablename__ = "dashboard_page_source" # type: ignore
|
||||||
__table_args__ = gisaf.table_args
|
__table_args__ = gisaf.table_args
|
||||||
|
|
||||||
id: str = Field(primary_key=True)
|
id: str = Field(primary_key=True)
|
||||||
|
@ -36,6 +36,7 @@ class DashboardPageCommon(Model):
|
||||||
Base class for DashboardPage and DashboardPageSection, where some methods
|
Base class for DashboardPage and DashboardPageSection, where some methods
|
||||||
are common, eg. attachments
|
are common, eg. attachments
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name: str
|
name: str
|
||||||
df: bytes | None = None
|
df: bytes | None = None
|
||||||
plot: bytes | None = None
|
plot: bytes | None = None
|
||||||
|
@ -70,11 +71,11 @@ class DashboardPageCommon(Model):
|
||||||
elif isinstance(plot, plt.Figure): # type: ignore
|
elif isinstance(plot, plt.Figure): # type: ignore
|
||||||
fig = plot
|
fig = plot
|
||||||
if fig:
|
if fig:
|
||||||
fig.savefig(self.get_plot_file_path(), bbox_inches='tight')
|
fig.savefig(self.get_plot_file_path(), bbox_inches="tight")
|
||||||
plt.close(fig)
|
plt.close(fig)
|
||||||
|
|
||||||
if plot and not fig:
|
if plot and not fig:
|
||||||
logger.warning('Cannot save dashboard attachment (unknown attachment type)')
|
logger.warning("Cannot save dashboard attachment (unknown attachment type)")
|
||||||
return
|
return
|
||||||
|
|
||||||
# logger.info(f'Saved attachment of dashboard page {self.group}/{self.name} '
|
# logger.info(f'Saved attachment of dashboard page {self.group}/{self.name} '
|
||||||
|
@ -89,7 +90,7 @@ class DashboardPageCommon(Model):
|
||||||
"""
|
"""
|
||||||
if not self.attachment:
|
if not self.attachment:
|
||||||
## Not set yet (creation)
|
## Not set yet (creation)
|
||||||
self.attachment = f'{self.name}.png'
|
self.attachment = f"{self.name}.png"
|
||||||
|
|
||||||
self.ensure_dir_exists()
|
self.ensure_dir_exists()
|
||||||
|
|
||||||
|
@ -101,11 +102,11 @@ class DashboardPageCommon(Model):
|
||||||
elif isinstance(attached, plt.Figure): # type: ignore
|
elif isinstance(attached, plt.Figure): # type: ignore
|
||||||
fig = attached
|
fig = attached
|
||||||
if fig:
|
if fig:
|
||||||
fig.savefig(self.get_attachment_file_name(), bbox_inches='tight')
|
fig.savefig(self.get_attachment_file_name(), bbox_inches="tight")
|
||||||
plt.close(fig)
|
plt.close(fig)
|
||||||
|
|
||||||
if attached and not fig:
|
if attached and not fig:
|
||||||
logger.warning('Cannot save dashboard attachment (unknown attachment type)')
|
logger.warning("Cannot save dashboard attachment (unknown attachment type)")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# logger.info(f'Saved attachment of dashboard page {self.group}/{self.name} '
|
# logger.info(f'Saved attachment of dashboard page {self.group}/{self.name} '
|
||||||
|
@ -140,25 +141,25 @@ class DashboardPageMetaData(BaseModel):
|
||||||
|
|
||||||
|
|
||||||
class DashboardPage(DashboardPageCommon, DashboardPageMetaData, table=True):
|
class DashboardPage(DashboardPageCommon, DashboardPageMetaData, table=True):
|
||||||
__tablename__ = 'dashboard_page' # type: ignore
|
__tablename__ = "dashboard_page" # type: ignore
|
||||||
__table_args__ = gisaf.table_args
|
__table_args__ = gisaf.table_args
|
||||||
|
|
||||||
class Admin:
|
class Admin:
|
||||||
menu = 'Dashboard'
|
menu = "Dashboard"
|
||||||
|
|
||||||
id: int = Field(primary_key=True)
|
id: int = Field(primary_key=True)
|
||||||
time: datetime | None = Field(default_factory=datetime.now)
|
time: datetime | None = Field(default_factory=datetime.now)
|
||||||
notebook: str | None = None
|
notebook: str | None = None
|
||||||
source_id: int | None = Field(foreign_key=gisaf.table('dashboard_page_source.id'))
|
source_id: str | None = Field(foreign_key=gisaf.table("dashboard_page_source.id"))
|
||||||
expanded_panes: str | None
|
expanded_panes: str | None
|
||||||
source: DashboardPageSource = Relationship()
|
source: DashboardPageSource = Relationship()
|
||||||
sections: list['DashboardPageSection'] = Relationship()
|
sections: list["DashboardPageSection"] = Relationship()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'{self.group:s}/{self.name:s}'
|
return f"{self.group:s}/{self.name:s}"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<models.DashboardPage {self.group:s}/{self.name:s}>'
|
return f"<models.DashboardPage {self.group:s}/{self.name:s}>"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def selectinload(cls):
|
def selectinload(cls):
|
||||||
|
@ -182,7 +183,9 @@ class DashboardPage(DashboardPageCommon, DashboardPageMetaData, table=True):
|
||||||
if base_dir:
|
if base_dir:
|
||||||
return base_dir / self.group / self.attachment
|
return base_dir / self.group / self.attachment
|
||||||
else:
|
else:
|
||||||
raise UserWarning('Cannot save attachment: no notebook/base_storage_dir in gisaf config')
|
raise UserWarning(
|
||||||
|
"Cannot save attachment: no notebook/base_storage_dir in gisaf config"
|
||||||
|
)
|
||||||
|
|
||||||
def get_attachment_url(self):
|
def get_attachment_url(self):
|
||||||
## Serve through web front-end (nginx static file)
|
## Serve through web front-end (nginx static file)
|
||||||
|
@ -190,37 +193,37 @@ class DashboardPage(DashboardPageCommon, DashboardPageMetaData, table=True):
|
||||||
return
|
return
|
||||||
base_storage_url = conf.dashboard.base_storage_url
|
base_storage_url = conf.dashboard.base_storage_url
|
||||||
if not base_storage_url:
|
if not base_storage_url:
|
||||||
base_storage_url = '/dashboard-attachment/'
|
base_storage_url = "/dashboard-attachment/"
|
||||||
return f'{base_storage_url}{self.group}/{self.attachment}'
|
return f"{base_storage_url}{self.group}/{self.attachment}"
|
||||||
|
|
||||||
def get_notebook_url(self):
|
def get_notebook_url(self):
|
||||||
if self.notebook:
|
if self.notebook:
|
||||||
base_url = conf.dashboard.base_source_url
|
base_url = conf.dashboard.base_source_url
|
||||||
if base_url:
|
if base_url:
|
||||||
return f'{base_url}{self.notebook}'
|
return f"{base_url}{self.notebook}"
|
||||||
else:
|
else:
|
||||||
logger.debug('Notebook: no base_url in gisaf config')
|
logger.debug("Notebook: no base_url in gisaf config")
|
||||||
|
|
||||||
|
|
||||||
class DashboardPageSection(DashboardPageCommon, table=True):
|
class DashboardPageSection(DashboardPageCommon, table=True):
|
||||||
__tablename__ = 'dashboard_page_section' # type: ignore
|
__tablename__ = "dashboard_page_section" # type: ignore
|
||||||
__table_args__ = gisaf.table_args
|
__table_args__ = gisaf.table_args
|
||||||
|
|
||||||
class Admin:
|
class Admin:
|
||||||
menu = 'Dashboard'
|
menu = "Dashboard"
|
||||||
|
|
||||||
id: str = Field(primary_key=True)
|
id: str = Field(primary_key=True)
|
||||||
name: str
|
name: str
|
||||||
dashboard_page_id: int = Field(foreign_key=gisaf.table('dashboard_page.id'))
|
dashboard_page_id: int = Field(foreign_key=gisaf.table("dashboard_page.id"))
|
||||||
dashboard_page: DashboardPage = Relationship(back_populates='sections')
|
dashboard_page: DashboardPage = Relationship(back_populates="sections")
|
||||||
|
|
||||||
description: str
|
description: str
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f'{self.name} for dashboard page #{self.dashboard_page_id}'
|
return f"{self.name} for dashboard page #{self.dashboard_page_id}"
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return f'<models.DashboardPageSection #{self.id}>'
|
return f"<models.DashboardPageSection #{self.id}>"
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def selectinload(cls):
|
def selectinload(cls):
|
||||||
|
@ -230,16 +233,23 @@ class DashboardPageSection(DashboardPageCommon, table=True):
|
||||||
## Serve through web front-end (nginx static file)
|
## Serve through web front-end (nginx static file)
|
||||||
if not self.plot:
|
if not self.plot:
|
||||||
return
|
return
|
||||||
return conf.dashboard.base_storage_url \
|
return (
|
||||||
+ self.dashboard_page.group + '/' \
|
conf.dashboard.base_storage_url
|
||||||
+ self.dashboard_page.name + '/' \
|
+ self.dashboard_page.group
|
||||||
+ self.name + '.png'
|
+ "/"
|
||||||
|
+ self.dashboard_page.name
|
||||||
|
+ "/"
|
||||||
|
+ self.name
|
||||||
|
+ ".png"
|
||||||
|
)
|
||||||
|
|
||||||
def ensure_dir_exists(self):
|
def ensure_dir_exists(self):
|
||||||
"""
|
"""
|
||||||
Make sure the directory exists, before saving the file
|
Make sure the directory exists, before saving the file
|
||||||
"""
|
"""
|
||||||
dir_name = Path(conf.dashboard.base_storage_dir) / self.page.group / self.page.name
|
dir_name = (
|
||||||
|
Path(conf.dashboard.base_storage_dir) / self.page.group / self.page.name
|
||||||
|
)
|
||||||
dir_name.mkdir(exist_ok=True)
|
dir_name.mkdir(exist_ok=True)
|
||||||
return dir_name
|
return dir_name
|
||||||
|
|
||||||
|
@ -252,11 +262,13 @@ class DashboardPageSection(DashboardPageCommon, table=True):
|
||||||
return
|
return
|
||||||
base_dir = Path(conf.dashboard.base_storage_dir)
|
base_dir = Path(conf.dashboard.base_storage_dir)
|
||||||
if not base_dir:
|
if not base_dir:
|
||||||
raise UserWarning('Cannot save attachment: no notebook/base_storage_dir in gisaf config')
|
raise UserWarning(
|
||||||
|
"Cannot save attachment: no notebook/base_storage_dir in gisaf config"
|
||||||
|
)
|
||||||
return base_dir / self.page.group / self.page.name / self.attachment
|
return base_dir / self.page.group / self.page.name / self.attachment
|
||||||
|
|
||||||
def get_plot_file_name(self):
|
def get_plot_file_name(self):
|
||||||
return f'{self.name}.png'
|
return f"{self.name}.png"
|
||||||
|
|
||||||
def get_plot_file_path(self):
|
def get_plot_file_path(self):
|
||||||
"""
|
"""
|
||||||
|
@ -267,12 +279,14 @@ class DashboardPageSection(DashboardPageCommon, table=True):
|
||||||
return
|
return
|
||||||
base_dir = Path(conf.dashboard.base_storage_dir)
|
base_dir = Path(conf.dashboard.base_storage_dir)
|
||||||
if not base_dir:
|
if not base_dir:
|
||||||
raise UserWarning('Cannot save attachment: no notebook/base_storage_dir in gisaf config')
|
raise UserWarning(
|
||||||
|
"Cannot save attachment: no notebook/base_storage_dir in gisaf config"
|
||||||
|
)
|
||||||
return base_dir / self.page.group / self.page.name / self.get_plot_file_name()
|
return base_dir / self.page.group / self.page.name / self.get_plot_file_name()
|
||||||
|
|
||||||
|
|
||||||
class Widget(Model, table=True):
|
class Widget(Model, table=True):
|
||||||
__tablename__ = 'widget' # type: ignore
|
__tablename__ = "widget" # type: ignore
|
||||||
__table_args__ = gisaf.table_args
|
__table_args__ = gisaf.table_args
|
||||||
## CREATE TABLE gisaf.widget (name char(50) not null PRIMARY KEY, title varchar, subtitle varchar, notebook varchar, content varchar, time timestamp);
|
## CREATE TABLE gisaf.widget (name char(50) not null PRIMARY KEY, title varchar, subtitle varchar, notebook varchar, content varchar, time timestamp);
|
||||||
name: str = Field(primary_key=True, sa_type=String(50)) # type: ignore
|
name: str = Field(primary_key=True, sa_type=String(50)) # type: ignore
|
||||||
|
@ -283,7 +297,7 @@ class Widget(Model, table=True):
|
||||||
notebook: str | None = None
|
notebook: str | None = None
|
||||||
|
|
||||||
class Admin:
|
class Admin:
|
||||||
menu = 'Dashboard'
|
menu = "Dashboard"
|
||||||
|
|
||||||
|
|
||||||
class DashboardSection(BaseModel):
|
class DashboardSection(BaseModel):
|
||||||
|
@ -315,3 +329,4 @@ class DashboardHome(BaseModel):
|
||||||
title: str
|
title: str
|
||||||
content: str
|
content: str
|
||||||
footer: str
|
footer: str
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue