diff --git a/covigator/__init__.py b/covigator/__init__.py index ed7cb5f..178263f 100644 --- a/covigator/__init__.py +++ b/covigator/__init__.py @@ -1,4 +1,4 @@ -VERSION = "v2.2.2" +VERSION = "v2.2.3" ANALYSIS_PIPELINE_VERSION = "v0.15.0" MISSENSE_VARIANT = "missense_variant" diff --git a/covigator/dashboard/tabs/overview.py b/covigator/dashboard/tabs/overview.py index fe1fcdb..5a30a9a 100644 --- a/covigator/dashboard/tabs/overview.py +++ b/covigator/dashboard/tabs/overview.py @@ -1,6 +1,8 @@ import dash_bootstrap_components as dbc from dash import html - +from sqlalchemy.orm import Session +from covigator.database.queries import Queries +from dash.dependencies import Output, Input, State def get_tab_overview(): @@ -110,8 +112,38 @@ def get_tab_overview(): ], outline=False, style={"width": "40rem", "height": "15rem", "margin-left": "40px"}, - )] - ), + ), + html.Br(), + dbc.Card( + [ + 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) + ) + ] + ) + ]) + ]) + ) + + ], + outline=False, + style={"width": "40rem", "height": "15rem", "margin-left": "40px"}, + ) + ]), ])), html.Br(), html.Br(), @@ -132,4 +164,16 @@ def get_header(): [html.Div([html.H1("Welcome to CoVigator Dashboard")], style={"text-align": "left"})], id="title")], width=4), dbc.Col([None], width=2) - ], id="header", className="row flex-display",) \ No newline at end of file + ], id="header", className="row flex-display",) + + +def get_news(session: Session): + queries = Queries(session=session) + newest_news = queries.get_top_news(n=3) + 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) + return children diff --git a/covigator/database/model.py b/covigator/database/model.py index 8a77985..1e9017f 100755 --- a/covigator/database/model.py +++ b/covigator/database/model.py @@ -52,6 +52,8 @@ def get_table_versioned_name(basename, config: Configuration): CONSTELLATION_SITES_TABLE_NAME = get_table_versioned_name('lineage_defining_variant', config=config) LINEAGE_SITES_JUNCTION_TABLE_NAME = get_table_versioned_name('lineage_variant', config=config) VARIANT_LEVEL_CONSTRAINT_NAME = get_table_versioned_name('variant_level', config=config) +NEWS_SECTION_TABLE_NAME = get_table_versioned_name('news_section', config=config) +NEWS_TYPE_CONSTRAINT_NAME = get_table_versioned_name('news_type', config=config) SEPARATOR = ";" Base = declarative_base() @@ -1208,3 +1210,21 @@ class LineageVariant(Base): pango_lineage_id = Column(ForeignKey(Lineages.pango_lineage_id), primary_key=True) variant_id = Column(ForeignKey(LineageDefiningVariants.variant_id), primary_key=True) + +class NewsType(enum.Enum): + __constraint_name__ = NEWS_TYPE_CONSTRAINT_NAME + + RELEASE = 1 + 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()) + message_type = Column(Enum(NewsType, name=NewsType.__constraint_name__)) + diff --git a/covigator/database/queries.py b/covigator/database/queries.py index c96629f..bffc3f7 100644 --- a/covigator/database/queries.py +++ b/covigator/database/queries.py @@ -15,7 +15,7 @@ VariantType, PrecomputedAnnotation, PrecomputedOccurrence, PrecomputedTableCounts, \ PrecomputedVariantAbundanceHistogram, PrecomputedSynonymousNonSynonymousCounts, RegionType, Domain, \ LastUpdate, SampleCovid19Portal, VariantObservationCovid19Portal, VariantCovid19Portal, Lineages, LineageVariant, \ - LineageDefiningVariants + LineageDefiningVariants, NewsSection from covigator.exceptions import CovigatorQueryException, CovigatorDashboardMissingPrecomputedData @@ -160,8 +160,8 @@ def get_lineage_defining_variants(self) -> pd.DataFrame: # Rename columns to match columns used in recurrent/intrahost mutations tab lineage_variants["dna_mutation"] = lineage_variants.apply(lambda x: x.variant_id if pd.isnull(x.hgvs) else None, axis=1) - lineage_variants = lineage_variants.rename(columns={"hgvs":"hgvs_p"}) - aa_level_mutations = lineage_variants[~pd.isnull(lineage_variants.hgvs_p)].loc[:, ['pangolin_lineage','hgvs_p']] + lineage_variants = lineage_variants.rename(columns={"hgvs": "hgvs_p"}) + aa_level_mutations = lineage_variants[~pd.isnull(lineage_variants.hgvs_p)].loc[:, ['pangolin_lineage', 'hgvs_p']] aa_level_mutations = aa_level_mutations.sort_values(['hgvs_p', 'pangolin_lineage']).groupby('hgvs_p')['pangolin_lineage'].agg(','.join) aa_level_mutations = aa_level_mutations.reset_index() @@ -844,3 +844,8 @@ def windowed_query(self, query, column, windowsize): for whereclause in self.column_windows(query.session, 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) + return news