Skip to content

Commit

Permalink
Updated news section on landing page
Browse files Browse the repository at this point in the history
Added modal pop up to show all covigator news if the user requests them
Formatting of news text changed to Markdown to support links and other fancy stuff in news messages
  • Loading branch information
johausmann committed Sep 29, 2023
1 parent 8ab6acc commit 2fe0a87
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 52 deletions.
5 changes: 3 additions & 2 deletions covigator/dashboard/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from covigator.dashboard.tabs.footer import get_footer
from covigator.dashboard.tabs.lineages import set_callbacks_lineages_tab, get_tab_lineages
from covigator.dashboard.tabs.mutation_stats import get_tab_mutation_stats, set_callbacks_mutation_stats_tab
from covigator.dashboard.tabs.overview import get_tab_overview
from covigator.dashboard.tabs.overview import get_tab_overview, set_callbacks_news_section
from covigator.dashboard.tabs.samples import get_tab_samples, set_callbacks_samples_tab
from covigator.dashboard.tabs.intrahost_mutations import get_tab_subclonal_variants, set_callbacks_subclonal_variants_tab
from covigator.dashboard.tabs.recurrent_mutations import get_tab_variants, set_callbacks_variants_tab
Expand Down Expand Up @@ -214,6 +214,7 @@ def get_application(self) -> dash.Dash:
set_callbacks_mutation_stats_tab(app=app, session=session)
set_callbacks_subclonal_variants_tab(app=app, session=session)
set_callbacks_download_tab(app=app, content_folder=self.config.content_folder)
set_callbacks_news_section(app=app)
return app


Expand Down Expand Up @@ -311,7 +312,7 @@ def switch_tab_callback(at, url, session, content_folder):
page = _get_page(url)
try:
if page == MAIN_PAGE:
return get_tab_overview()
return get_tab_overview(queries=queries)
elif at == ENA_DATASET_TAB_ID:
return get_tab_dataset_ena(queries=queries)
elif at == COVID19_PORTAL_DATASET_TAB_ID:
Expand Down
8 changes: 8 additions & 0 deletions covigator/dashboard/tabs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import dash_bootstrap_components as dbc

MONTH_PATTERN = "%Y-%m"
NEWS_PATTERN = "%Y-%m-%d"
MISSING_VALUE = "-"

APPLY_STYLE = {"height": "38px", "padding": "0 30px"}
Expand All @@ -21,3 +22,10 @@ def get_mini_container(title, value):
color="dark",
className="me-1",
style={"margin-right": "30px", "margin-left": "30px", 'font-size': '110%'})


COLOR_STATUS = {
"RELEASE": "success",
"WARNINGS": "warning",
"BUGS": "danger"
}
135 changes: 89 additions & 46 deletions covigator/dashboard/tabs/overview.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import dash_bootstrap_components as dbc
from dash import dcc
from dash import html
from sqlalchemy.orm import Session
from dash import Input, Output, State, html
from covigator.database.queries import Queries
from dash.dependencies import Output, Input, State
from covigator.dashboard.tabs import COLOR_STATUS, NEWS_PATTERN

def get_tab_overview():

def get_tab_overview(queries: Queries):

return dbc.CardBody([
get_header(),
Expand All @@ -30,15 +32,15 @@ def get_tab_overview():
European Nucleotide Archive (ENA) and genome assemblies from the COVID-19 Data Portal.
CoVigator is open-data-friendly and allowing it to be adopted to other SARS-CoV-2 data sources.
"""),
html.Br(),
html.P("""
CoVigator provides high-resolution SARS-CoV-2 mutations from genome assemblies and raw
reads allowing confirmation of evolutionary trends. CoVigator pipeline puts a special
emphasis on identification of SARS-CoV-2 intrahost mutations, thus reporting potential
SARS-CoV-2 variants of concern (VoC). CoVigator project is open sourced and made
available under the MIT license. The knowledge base and dashboard source is
hosted at https://github.com/TRON-Bioinformatics/covigator
"""),
html.P([
"""
CoVigator provides high-resolution SARS-CoV-2 mutations from genome assemblies and raw
reads allowing confirmation of evolutionary trends. CoVigator pipeline puts a special
emphasis on identification of SARS-CoV-2 intrahost mutations, thus reporting potential
SARS-CoV-2 variants of concern (VoC). CoVigator project is open sourced and made
available under the MIT license. The knowledge base and dashboard source is
hosted at """,
html.A("github", href='https://github.com/TRON-Bioinformatics/covigator')]),
html.Br(),
html.P("""
If you are interested in our work, please also have a read of our most recent publication.
Expand Down Expand Up @@ -116,39 +118,37 @@ def get_tab_overview():
html.Br(),
dbc.Card(
[
dbc.CardHeader([
html.Div(
dbc.Row([
dbc.Col(html.H5("Covigator News"), width=6),
dbc.Col(
dbc.Button("see all covigator news",
id="open",
n_clicks=0,
style={"justify":"end", "margin-right": "1%"}),
width=6

),
]),
),
get_all_news(queries)
]),
dbc.CardBody(
dbc.Row([
dbc.Col([
html.Div(
children=[
html.H2("Covigator News Section"),
html.P(
"""
Here you can find information about new data
releases, updates to Coivgator NGS pipeline or
Covigator python package
"""),
html.Br(),
html.Div(
id="news_section",
children=get_news(Session)
)
]
)
])
])
html.Div(
children=get_news(queries)
)
)

],
outline=False,
style={"width": "40rem", "height": "15rem", "margin-left": "40px"},
outline=True,
style={"width": "40rem", "margin-left": "40px"},
)
]),
])),
html.Br(),
html.Br(),
html.Br(),
html.Br(),
#html.Br(),
#html.Br(),
#html.Br(),
],
style={"text-align": "left", "font-size": 16}),
], width=8),
Expand All @@ -167,13 +167,56 @@ def get_header():
], id="header", className="row flex-display",)


def get_news(session: Session):
queries = Queries(session=session)
newest_news = queries.get_top_news(n=3)
def get_all_news(queries: Queries):
news_items = get_news(queries, None)
modal = dbc.Modal(
[
dbc.ModalHeader(dbc.ModalTitle("All Covigator News"), close_button=False),
dbc.ModalBody(children=news_items),
dbc.ModalFooter(
dbc.Button(
"Close", id="close", className="ms-auto", n_clicks=0
)
),
],
id="modal",
is_open=False,
scrollable=True,
)
return modal


def get_news(queries: Queries, n=3):
"""
Get news from database when website is (re)loaded and create children for news section
cardboard.
"""
newest_news = queries.get_top_news(n=n)
children = []
#for this_news in newest_news.iterrows():
# news_item = []
# news_item.append(html.H3(this_news.message))
# news_item.append(html.P(this_news.publishing_date))
# children.extend(news_item)
for this_news in newest_news.itertuples():
children.append(
dbc.Alert(children=[
dbc.Badge(children=[
this_news.published_date.strftime(NEWS_PATTERN),
" ",
this_news.message_type.name],
className="me-1"
),
html.Br(),
dcc.Markdown(this_news.message_text)
],
color=COLOR_STATUS[this_news.message_type.name]
))
return children


def set_callbacks_news_section(app):
@app.callback(
Output("modal", "is_open"),
[Input("open", "n_clicks"), Input("close", "n_clicks")],
[State("modal", "is_open")],
)
def toggle_modal(n1, n2, is_open):
if n1 or n2:
return not is_open
return is_open
3 changes: 2 additions & 1 deletion covigator/database/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1218,13 +1218,14 @@ class NewsType(enum.Enum):
WARNINGS = 2
BUGS = 3


class NewsSection(Base):
"""
Table to hold information for news section
"""
__tablename__ = NEWS_SECTION_TABLE_NAME

message_text = Column(String, primary_key=True)
publishing_date = Column(DateTime(timezone=True), nullable=False, default=datetime.now())
published_date = Column(DateTime(timezone=True), nullable=False, default=datetime.now())
message_type = Column(Enum(NewsType, name=NewsType.__constraint_name__))

11 changes: 8 additions & 3 deletions covigator/database/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,12 @@ def windowed_query(self, query, column, windowsize):
for row in query.filter(whereclause).order_by(column):
yield row

def get_top_news(self, n=5):
query = self.session.query(NewsSection.message_text).order_by(NewsSection.publishing_date, desc)
news = pd.read_sql(query.statement, self.session.bind).head(n)
def get_top_news(self, n=3):
"""
Get news from database, sort by publishing date and return n news when specified.
"""
query = self.session.query(NewsSection).order_by(NewsSection.published_date.desc())
news = pd.read_sql(query.statement, self.session.bind)
if n is not None:
news = news.head(n)
return news

0 comments on commit 2fe0a87

Please sign in to comment.