You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
247 lines
10 KiB
247 lines
10 KiB
# _base_class.py |
|
import os |
|
import re |
|
import streamlit as st |
|
from _arango import ArangoDB |
|
from _chromadb import ChromaDB |
|
|
|
class BaseClass: |
|
def __init__(self, username: str, **kwargs) -> None: |
|
self.username: str = username |
|
self.project_name: str = kwargs.get('project_name', None) |
|
self.collection: str = kwargs.get('collection_name', None) |
|
self.user_arango: ArangoDB = self.get_arango() |
|
self.base_arango: ArangoDB = self.get_arango(admin=True) |
|
for key, value in kwargs.items(): |
|
setattr(self, key, value) |
|
|
|
|
|
def get_arango(self, admin: bool = False, db_name: str = None) -> ArangoDB: |
|
if db_name: |
|
return ArangoDB(db_name=db_name) |
|
elif admin: |
|
return ArangoDB() |
|
else: |
|
from colorprinter.print_color import print_yellow |
|
return ArangoDB(user=self.username, db_name=self.username) |
|
|
|
def get_article_collections(self) -> list: |
|
article_collections = self.user_arango.db.aql.execute( |
|
'FOR doc IN article_collections RETURN doc["name"]' |
|
) |
|
return list(article_collections) |
|
|
|
def get_projects(self) -> list: |
|
projects = self.user_arango.db.aql.execute( |
|
'FOR doc IN projects RETURN doc["name"]' |
|
) |
|
return list(projects) |
|
|
|
|
|
def get_chromadb(self): |
|
return ChromaDB() |
|
|
|
def get_project(self, project_name: str): |
|
doc = self.user_arango.db.aql.execute( |
|
f'FOR doc IN projects FILTER doc["name"] == "{project_name}" RETURN doc', |
|
count=True, |
|
) |
|
if doc: |
|
return doc.next() |
|
|
|
|
|
def set_filename(self, filename=None, folder="other_documents"): |
|
""" |
|
Checks if a file with the given filename already exists in the download folder. |
|
If it does, appends or increments a numerical suffix to the filename until a unique name is found. |
|
|
|
Args: |
|
filename (str): The base name of the file to check. |
|
|
|
Sets: |
|
self.file_path (str): The unique file path generated. |
|
""" |
|
|
|
download_folder = f"user_data/{self.username}/{self.document_type}" |
|
if self.is_sci and not self.document_type == "notes": |
|
self.file_path = f"sci_articles/{self.doi}.pdf".replace("/", "_") |
|
return os.path.exists(self.file_path) |
|
else: |
|
file_path = f"{download_folder}/{filename}" |
|
while os.path.exists(file_path + ".pdf"): |
|
if not re.search(r"(_\d+)$", file_path): |
|
file_path += "_1" |
|
else: |
|
file_path = re.sub( |
|
r"(\d+)$", lambda x: str(int(x.group()) + 1), file_path |
|
) |
|
self.file_path = file_path + ".pdf" |
|
return file_path |
|
|
|
|
|
class StreamlitBaseClass(BaseClass): |
|
""" |
|
StreamlitBaseClass is a base class for Streamlit applications that provides methods for managing user settings, session state, and user interactions with collections and projects. |
|
Methods: |
|
__init__(username: str, **kwargs) -> None: |
|
Initializes the StreamlitBaseClass with a username and additional keyword arguments. |
|
get_settings(field: str = None): |
|
Retrieves user settings from the database. If a specific field is provided, returns the value of that field. Otherwise, returns all settings. |
|
update_settings(key, value) -> None: |
|
Updates a specific setting in the database and the Streamlit session state. |
|
get_settings(): |
|
Retrieves user settings from the database. |
|
update_session_state(page_name=None): |
|
Updates the Streamlit session state with the attributes of the current instance. If a page name is provided, updates the session state for that page. |
|
update_current_page(page_name): |
|
Updates the current page in the Streamlit session state and the database. |
|
choose_collection(text="Select a collection of favorite articles") -> str: |
|
Displays a select box for choosing a collection of favorite articles. Updates the current collection in the session state and the database. |
|
choose_project(text="Select a project") -> str: |
|
Displays a select box for choosing a project. Updates the current project in the session state and the database. |
|
""" |
|
def __init__(self, username: str, **kwargs) -> None: |
|
super().__init__(username, **kwargs) |
|
|
|
def get_settings(self, field: str = None): |
|
""" |
|
Retrieve or initialize user settings from the database. |
|
|
|
This method fetches the user settings document from the "settings" collection |
|
in the ArangoDB database. If the settings document does not exist, it initializes |
|
it with default values for "current_collection" and "current_page". The settings |
|
are then stored in the Streamlit session state. |
|
|
|
Args: |
|
field (str, optional): The specific field to retrieve from the settings. |
|
If not provided, the entire settings document is returned. |
|
|
|
Returns: |
|
dict or any: The entire settings document if no field is specified, |
|
otherwise the value of the specified field. |
|
""" |
|
settings = self.user_arango.db.document("settings/settings") |
|
if not settings: |
|
self.user_arango.db.collection("settings").insert( |
|
{"_key": "settings", "current_collection": None, "current_page": None} |
|
) |
|
for i in ["current_collection", "current_page"]: |
|
if i not in settings: |
|
settings[i] = None |
|
st.session_state["settings"] = settings |
|
if field: |
|
return settings[field] |
|
return settings |
|
|
|
def update_settings(self, key, value) -> None: |
|
""" |
|
Update a specific setting in the database and session state. |
|
|
|
Args: |
|
key (str): The key of the setting to update. |
|
value (Any): The new value for the setting. |
|
|
|
Returns: |
|
None |
|
""" |
|
self.user_arango.db.collection("settings").update_match( |
|
filters={"_key": "settings"}, |
|
body={key: value}, |
|
merge=True, |
|
) |
|
st.session_state["settings"][key] = value |
|
|
|
def update_session_state(self, page_name=None): |
|
""" |
|
Updates the Streamlit session state with the attributes of the current instance. |
|
|
|
Parameters: |
|
page_name (str, optional): The name of the page to update in the session state. |
|
If not provided, it defaults to the current page stored in the session state. |
|
|
|
The method iterates over the instance's attributes and updates the session state |
|
for the given page name with those attributes that are of type str, int, float, list, dict, or bool. |
|
""" |
|
|
|
if not page_name: |
|
page_name = st.session_state.get("current_page") |
|
for attr, value in self.__dict__.items(): |
|
if any([isinstance(value, t) for t in [str, int, float, list, dict, bool]]): |
|
st.session_state[page_name][attr] = value |
|
# for k, v in st.session_state[page_name].items(): |
|
# if isinstance(v, list): |
|
# print(k.upper()) |
|
# for j in v: |
|
# print(j) |
|
# else: |
|
# print(k.upper(), v) |
|
|
|
def update_current_page(self, page_name): |
|
""" |
|
Updates the current page in the session state and settings. |
|
|
|
Args: |
|
page_name (str): The name of the page to set as the current page. |
|
|
|
Side Effects: |
|
Updates the "current_page" in the session state and settings if it is different from the current value. |
|
""" |
|
if st.session_state.get("current_page") != page_name: |
|
st.session_state["current_page"] = page_name |
|
self.update_settings("current_page", page_name) |
|
|
|
|
|
def choose_collection(self, text="Select a collection of favorite articles") -> str: |
|
""" |
|
Prompts the user to select a collection of favorite articles from a list. |
|
|
|
Args: |
|
text (str): The prompt text to display for the selection box. Defaults to "Select a collection of favorite articles". |
|
|
|
Returns: |
|
str: The name of the selected collection. |
|
|
|
Side Effects: |
|
- Sets the `project` attribute to None. |
|
- Sets the `collection` attribute to the selected collection. |
|
- Updates the settings with the key "current_collection" to the selected collection. |
|
- Updates the session state. |
|
""" |
|
collections = self.get_article_collections() |
|
collection = st.selectbox(text, collections, index=None) |
|
if collection: |
|
self.project = None |
|
self.collection = collection |
|
self.update_settings("current_collection", collection) |
|
self.update_session_state() |
|
return collection |
|
|
|
def choose_project(self, text="Select a project") -> str: |
|
""" |
|
Prompts the user to select a project from a list of available projects. |
|
|
|
Args: |
|
text (str): The prompt text to display for project selection. Defaults to "Select a project". |
|
|
|
Returns: |
|
str: The name of the selected project. |
|
|
|
Side Effects: |
|
- Updates the current project settings. |
|
- Updates the session state. |
|
- Prints the chosen project name to the console. |
|
""" |
|
projects = self.get_projects() |
|
print('projects', projects) |
|
print(self.project_name) |
|
|
|
project = st.selectbox(text, projects, index=projects.index(self.project_name) if self.project_name in projects else None) |
|
print('Choosing project...') |
|
if project: |
|
from projects_page import Project |
|
self.project = Project(self.username, project, self.user_arango) |
|
self.collection = None |
|
self.update_settings("current_project", self.project.name) |
|
self.update_session_state() |
|
print('CHOOSEN PROJECT:', self.project.name) |
|
return self.project
|
|
|