diff --git a/Dockerfile b/Dockerfile index 46e01450..372c8d12 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,12 +1,10 @@ - # Copyright (c) Microsoft Corporation. All rights reserved. -# Dockerfile # https://eng.ms/docs/more/containers-secure-supply-chain/approved-images FROM mcr.microsoft.com/oryx/python:3.10 RUN curl -fsSL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor -o /usr/share/keyrings/microsoft-prod.gpg RUN apt-get update -y -ENV IS_DOCKER True +RUN apt-get install wkhtmltopdf -y # Install dependencies WORKDIR ./ diff --git a/app/Home.py b/app/Home.py index f17a4c60..6ba8561c 100644 --- a/app/Home.py +++ b/app/Home.py @@ -1,36 +1,11 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. import streamlit as st +from components.app_loader import load_multipage_app import util.mermaid as mermaid -from streamlit_javascript import st_javascript -import util.session_variables - -def get_user(sv): - if sv.mode.value != 'cloud': - return - css=''' - [data-testid="stSidebarNavItems"] { - max-height: 100vh - } - ''' - st.markdown(f'', unsafe_allow_html=True) - js_code = """await fetch("/.auth/me") - .then(function(response) {return response.json();}) - """ - return_value = st_javascript(js_code) - - username = None - if return_value == 0: - pass # this is the result before the actual value is returned - elif isinstance(return_value, list) and len(return_value) > 0: - username = return_value[0]["user_id"] - sv.username.value = username - st.sidebar.write(f"Logged in as {username}") - else: - st.warning(f"Could not directly read username from azure active directory: {return_value}.") def main(): st.set_page_config(layout="wide", initial_sidebar_state="expanded", page_title='Intelligence Toolkit | Home') - sv = util.session_variables.SessionVariables('home') - get_user(sv) + load_multipage_app() transparency_faq = open('./app/TransparencyFAQ.md', 'r').read() st.markdown(transparency_faq + '\n\n' + f"""\ diff --git a/app/workflows/group_narratives/classes.py b/app/components/__init__.py similarity index 100% rename from app/workflows/group_narratives/classes.py rename to app/components/__init__.py diff --git a/app/components/app_loader.py b/app/components/app_loader.py new file mode 100644 index 00000000..54192886 --- /dev/null +++ b/app/components/app_loader.py @@ -0,0 +1,13 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. +from javascript.styles import add_styles +import components.app_user as au +import streamlit as st + +def load_multipage_app(): + #Load user if logged in + user = au.app_user() + user.view_get_info() + + #load css + add_styles() + diff --git a/app/components/app_user.py b/app/components/app_user.py new file mode 100644 index 00000000..60f29b22 --- /dev/null +++ b/app/components/app_user.py @@ -0,0 +1,41 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. +import streamlit as st +from javascript.scripts import get_auth_user +from util.session_variables import SessionVariables + +class app_user: + + sv = None + + def __init__(self, sv = None): + if sv is not None: + self.sv = sv + else: + self.sv = SessionVariables('home') + self.login() + + def _get_info(self): + return self.sv.username.value + + def _set_user(self, username): + self.sv.username.value = username + + def view_get_info(self): + if self.sv.username.value: + st.sidebar.write(f"Logged in as {self.sv.username.value}") + + def _view_error_info(self, return_value): + st.warning(f"Could not directly read username from azure active directory: {return_value}.") + + def login(self): + if self.sv.mode.value != 'cloud': + return + return_value = get_auth_user() + username = None + if return_value == 0: + pass # this is the result before the actual value is returned + elif isinstance(return_value, list) and len(return_value) > 0: + username = return_value[0]["user_id"] + self._set_user(username) + else: + self._view_error_info(return_value) \ No newline at end of file diff --git a/app/workflows/group_narratives/functions.py b/app/javascript/__init__.py similarity index 100% rename from app/workflows/group_narratives/functions.py rename to app/javascript/__init__.py diff --git a/app/javascript/scripts.py b/app/javascript/scripts.py new file mode 100644 index 00000000..85a9fecf --- /dev/null +++ b/app/javascript/scripts.py @@ -0,0 +1,9 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. +from streamlit_javascript import st_javascript +import streamlit as st + +def get_auth_user(): + js_code = """await fetch("/.auth/me") + .then(function(response) {return response.json();}) + """ + return st_javascript(js_code) \ No newline at end of file diff --git a/app/javascript/styles.py b/app/javascript/styles.py new file mode 100644 index 00000000..459a6822 --- /dev/null +++ b/app/javascript/styles.py @@ -0,0 +1,25 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. +import streamlit as st + +style_sidebar = ''' + [data-testid="stSidebarNavItems"] { + max-height: 100vh + } +''' + +style_pdf = '''body { + font-family: 'helvetica'; +} +''' + +style_iframes = ''' + iframe { + display: none; + } +''' + +def add_styles(): + st.markdown(f'''''', unsafe_allow_html=True) diff --git a/app/pages/Attribute_Patterns.py b/app/pages/Attribute_Patterns.py index e66b86c3..ed3be0ec 100644 --- a/app/pages/Attribute_Patterns.py +++ b/app/pages/Attribute_Patterns.py @@ -1,6 +1,11 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. import workflows.attribute_patterns.workflow +from components.app_loader import load_multipage_app +import streamlit as st def main(): + st.set_page_config(layout="wide", initial_sidebar_state="collapsed", page_title='Intelligence Toolkit | Attribute Patterns') + load_multipage_app() workflows.attribute_patterns.workflow.create() if __name__ == '__main__': diff --git a/app/pages/Data_Synthesis.py b/app/pages/Data_Synthesis.py index a03dc469..8b34d465 100644 --- a/app/pages/Data_Synthesis.py +++ b/app/pages/Data_Synthesis.py @@ -1,6 +1,11 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. import workflows.data_synthesis.workflow +from components.app_loader import load_multipage_app +import streamlit as st def main(): + st.set_page_config(layout="wide", initial_sidebar_state="collapsed", page_title='Intelligence Toolkit | Data Synthesis') + load_multipage_app() workflows.data_synthesis.workflow.create() if __name__ == '__main__': diff --git a/app/pages/Group_Narratives.py b/app/pages/Group_Narratives.py index fb6685e8..8e7b41b9 100644 --- a/app/pages/Group_Narratives.py +++ b/app/pages/Group_Narratives.py @@ -1,6 +1,11 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. import workflows.group_narratives.workflow +import streamlit as st +from components.app_loader import load_multipage_app def main(): + st.set_page_config(layout="wide", initial_sidebar_state="collapsed", page_title='Intelligence Toolkit | Group Narratives') + load_multipage_app() workflows.group_narratives.workflow.create() if __name__ == '__main__': diff --git a/app/pages/Question_Answering.py b/app/pages/Question_Answering.py index 5693255c..fac3dd33 100644 --- a/app/pages/Question_Answering.py +++ b/app/pages/Question_Answering.py @@ -1,6 +1,12 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. import workflows.question_answering.workflow +from components.app_loader import load_multipage_app +import streamlit as st + def main(): + st.set_page_config(layout="wide", initial_sidebar_state="collapsed", page_title='Intelligence Toolkit | Question Answering') + load_multipage_app() workflows.question_answering.workflow.create() if __name__ == '__main__': diff --git a/app/pages/Record_Matching.py b/app/pages/Record_Matching.py index c576a645..c3b77acc 100644 --- a/app/pages/Record_Matching.py +++ b/app/pages/Record_Matching.py @@ -1,6 +1,11 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. import workflows.record_matching.workflow +from components.app_loader import load_multipage_app +import streamlit as st def main(): + st.set_page_config(layout="wide", initial_sidebar_state="collapsed", page_title='Intelligence Toolkit | Record Matching') + load_multipage_app() workflows.record_matching.workflow.create() if __name__ == '__main__': diff --git a/app/pages/Risk_Networks.py b/app/pages/Risk_Networks.py index 158cc468..432ddb44 100644 --- a/app/pages/Risk_Networks.py +++ b/app/pages/Risk_Networks.py @@ -1,6 +1,11 @@ +# Copyright (c) 2024 Microsoft Corporation. All rights reserved. import workflows.risk_networks.workflow +from components.app_loader import load_multipage_app +import streamlit as st def main(): + st.set_page_config(layout="wide", initial_sidebar_state="collapsed", page_title='Intelligence Toolkit | Risk Networks') + load_multipage_app() workflows.risk_networks.workflow.create() if __name__ == '__main__': diff --git a/app/util/download_pdf.py b/app/util/download_pdf.py index 40edee1e..2493a914 100644 --- a/app/util/download_pdf.py +++ b/app/util/download_pdf.py @@ -3,20 +3,17 @@ import pdfkit from util.wkhtmltopdf import config_pdfkit, pdfkit_options import streamlit as st +from javascript.styles import style_pdf -css = '''body { - font-family: 'helvetica'; -} -''' #itk-label text_label = 'Report generated using Intelligence Toolkit (https://aka.ms/itk)' def add_download_pdf(name, text, button_text='Download PDF', is_markdown=True, disabled=False): if not name.endswith('.pdf'): name += '.pdf' - text = f'{text}