Spaces:
Sleeping
Sleeping
Commit
·
ebaa573
1
Parent(s):
e338642
now it is possible to add details via the UI
Browse files- app.py +87 -22
- enums.py +14 -11
- local_storage/entities.py +27 -12
- local_storage/ls_manager.py +12 -5
- requirements-base.txt +2 -1
app.py
CHANGED
@@ -2,15 +2,17 @@ import re
|
|
2 |
from enum import Enum
|
3 |
|
4 |
import streamlit as st
|
|
|
5 |
from streamlit import session_state as ss
|
|
|
6 |
from streamlit.runtime.scriptrunner_utils.exceptions import StopException
|
7 |
|
8 |
from form.form import build_form_data_from_answers, write_pdf_form, work_categories
|
9 |
from llm_manager.llm_parser import LlmParser
|
10 |
-
from local_storage.entities import PersonalDetails, LocationDetails, ContractorDetails
|
11 |
from local_storage.ls_manager import LocalStorageManager
|
12 |
from prompts.prompts_manager import PromptsManager
|
13 |
-
from enums import Questions as Q
|
14 |
from repository.repository import build_repo_from_environment, get_repository
|
15 |
from repository import ModelRoles, Model
|
16 |
from utils.parsing_utils import check_for_missing_answers
|
@@ -19,6 +21,7 @@ user_msg = "Please describe what you need to do. To get the best results try to
|
|
19 |
|
20 |
find_tags_regex = re.compile(r"@(\S*)")
|
21 |
|
|
|
22 |
class Steps(Enum):
|
23 |
INITIAL_STATE = 1
|
24 |
PARSING_ANSWERS = 2
|
@@ -44,7 +47,9 @@ class UIManager:
|
|
44 |
get_repository("testing",
|
45 |
Model("fakeModel",
|
46 |
ModelRoles("a", "b", "c"))))
|
|
|
47 |
self.lsm = None
|
|
|
48 |
@staticmethod
|
49 |
def get_current_step() -> int:
|
50 |
try:
|
@@ -56,28 +61,33 @@ class UIManager:
|
|
56 |
def set_current_step(step: Steps):
|
57 |
ss["step"] = step.value
|
58 |
|
59 |
-
|
60 |
-
def _build_base_ui():
|
61 |
st.markdown("## Dubai Asset Management red tape cutter")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
62 |
|
63 |
def build_ui_for_initial_state(self, user_message):
|
64 |
help_ = user_message + "\n".join(self.pm.questions)
|
65 |
self._build_base_ui()
|
66 |
with st.form("Please describe your request"):
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
st.rerun()
|
76 |
|
77 |
def build_ui_for_parsing_answers(self):
|
78 |
self._build_base_ui()
|
79 |
with st.status("parsing user input for tags"):
|
80 |
-
self.lsm = LocalStorageManager() if not self.lsm else self.lsm
|
81 |
tags = find_tags_regex.findall(ss["user_input"])
|
82 |
details = [self.lsm.get_detail(t) for t in tags]
|
83 |
with st.status("initialising LLM"):
|
@@ -165,12 +175,12 @@ class UIManager:
|
|
165 |
self._build_validation_form(True, self._create_pdf_form,
|
166 |
"Create work permit request")
|
167 |
|
168 |
-
|
169 |
@staticmethod
|
170 |
def _get_personal_details(personal_details_key) -> PersonalDetails | None:
|
171 |
key_ = ss.get(personal_details_key)
|
172 |
if key_:
|
173 |
-
details = PersonalDetails(ss[f"fq_{Q.FULL_NAME.name}"], ss[f"fq_{Q.YOUR_EMAIL.name}"],
|
|
|
174 |
return details
|
175 |
return None
|
176 |
|
@@ -188,9 +198,7 @@ class UIManager:
|
|
188 |
ss[f"fq_{Q.COMPANY_EMAIL.name}"])
|
189 |
return None
|
190 |
|
191 |
-
|
192 |
-
|
193 |
-
def _build_validation_form(self, show_categories:bool, onsubmit, submit_button_label):
|
194 |
def build_form_fragment(form_, col, title, add_save, *questions):
|
195 |
form_.text(title)
|
196 |
for user_data in questions:
|
@@ -206,7 +214,7 @@ class UIManager:
|
|
206 |
col1, col2 = f.columns(2)
|
207 |
build_form_fragment(f, col1, "your details", True, Q.FULL_NAME, Q.CONTACT_NUMBER, Q.YOUR_EMAIL)
|
208 |
build_form_fragment(f, col2, "work details", False, Q.WORK_TO_DO, Q.START_DATE, Q.END_DATE)
|
209 |
-
build_form_fragment(f, col1, "location details",
|
210 |
Q.OWNER_OR_TENANT)
|
211 |
build_form_fragment(f, col2, "contractor details", True, Q.COMPANY_NAME, Q.COMPANY_NUMBER, Q.COMPANY_EMAIL)
|
212 |
if show_categories:
|
@@ -217,12 +225,69 @@ class UIManager:
|
|
217 |
if submit_data:
|
218 |
onsubmit()
|
219 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
220 |
|
221 |
um = UIManager()
|
222 |
|
223 |
-
def use_streamlit():
|
224 |
|
225 |
-
|
|
|
226 |
um.build_ui_for_initial_state(user_msg)
|
227 |
elif um.get_current_step() == Steps.PARSING_ANSWERS.value:
|
228 |
um.build_ui_for_parsing_answers()
|
|
|
2 |
from enum import Enum
|
3 |
|
4 |
import streamlit as st
|
5 |
+
import streamlit_tags as st_tags
|
6 |
from streamlit import session_state as ss
|
7 |
+
from streamlit.delta_generator import DeltaGenerator
|
8 |
from streamlit.runtime.scriptrunner_utils.exceptions import StopException
|
9 |
|
10 |
from form.form import build_form_data_from_answers, write_pdf_form, work_categories
|
11 |
from llm_manager.llm_parser import LlmParser
|
12 |
+
from local_storage.entities import PersonalDetails, LocationDetails, ContractorDetails, SavedDetails
|
13 |
from local_storage.ls_manager import LocalStorageManager
|
14 |
from prompts.prompts_manager import PromptsManager
|
15 |
+
from enums import Questions as Q, DetailsType
|
16 |
from repository.repository import build_repo_from_environment, get_repository
|
17 |
from repository import ModelRoles, Model
|
18 |
from utils.parsing_utils import check_for_missing_answers
|
|
|
21 |
|
22 |
find_tags_regex = re.compile(r"@(\S*)")
|
23 |
|
24 |
+
|
25 |
class Steps(Enum):
|
26 |
INITIAL_STATE = 1
|
27 |
PARSING_ANSWERS = 2
|
|
|
47 |
get_repository("testing",
|
48 |
Model("fakeModel",
|
49 |
ModelRoles("a", "b", "c"))))
|
50 |
+
self.update_in_progress = False
|
51 |
self.lsm = None
|
52 |
+
|
53 |
@staticmethod
|
54 |
def get_current_step() -> int:
|
55 |
try:
|
|
|
61 |
def set_current_step(step: Steps):
|
62 |
ss["step"] = step.value
|
63 |
|
64 |
+
def _build_base_ui(self):
|
|
|
65 |
st.markdown("## Dubai Asset Management red tape cutter")
|
66 |
+
self.lsm = LocalStorageManager() if not self.lsm else self.lsm
|
67 |
+
with st.sidebar:
|
68 |
+
st.markdown("### Personal details")
|
69 |
+
self.build_details_checkboxes(DetailsType.PERSONAL_DETAILS)
|
70 |
+
st.markdown("### Locations details")
|
71 |
+
self.build_details_checkboxes(DetailsType.LOCATION_DETAILS)
|
72 |
+
st.markdown("### Contractors details")
|
73 |
+
self.build_details_checkboxes(DetailsType.CONTRACTOR_DETAILS)
|
74 |
|
75 |
def build_ui_for_initial_state(self, user_message):
|
76 |
help_ = user_message + "\n".join(self.pm.questions)
|
77 |
self._build_base_ui()
|
78 |
with st.form("Please describe your request"):
|
79 |
+
st.text_area("Your input", height=700, label_visibility="hidden", placeholder=help_,
|
80 |
+
help=help_, key="user_input")
|
81 |
+
signature = st.file_uploader("Your signature", key="file_upload")
|
82 |
+
ss["signature"] = signature
|
83 |
+
submit_button = st.form_submit_button()
|
84 |
+
if submit_button:
|
85 |
+
self.set_current_step(Steps.PARSING_ANSWERS)
|
86 |
+
st.rerun()
|
|
|
87 |
|
88 |
def build_ui_for_parsing_answers(self):
|
89 |
self._build_base_ui()
|
90 |
with st.status("parsing user input for tags"):
|
|
|
91 |
tags = find_tags_regex.findall(ss["user_input"])
|
92 |
details = [self.lsm.get_detail(t) for t in tags]
|
93 |
with st.status("initialising LLM"):
|
|
|
175 |
self._build_validation_form(True, self._create_pdf_form,
|
176 |
"Create work permit request")
|
177 |
|
|
|
178 |
@staticmethod
|
179 |
def _get_personal_details(personal_details_key) -> PersonalDetails | None:
|
180 |
key_ = ss.get(personal_details_key)
|
181 |
if key_:
|
182 |
+
details = PersonalDetails(ss[f"fq_{Q.FULL_NAME.name}"], ss[f"fq_{Q.YOUR_EMAIL.name}"],
|
183 |
+
ss[f"fq_{Q.CONTACT_NUMBER.name}"])
|
184 |
return details
|
185 |
return None
|
186 |
|
|
|
198 |
ss[f"fq_{Q.COMPANY_EMAIL.name}"])
|
199 |
return None
|
200 |
|
201 |
+
def _build_validation_form(self, show_categories: bool, onsubmit, submit_button_label):
|
|
|
|
|
202 |
def build_form_fragment(form_, col, title, add_save, *questions):
|
203 |
form_.text(title)
|
204 |
for user_data in questions:
|
|
|
214 |
col1, col2 = f.columns(2)
|
215 |
build_form_fragment(f, col1, "your details", True, Q.FULL_NAME, Q.CONTACT_NUMBER, Q.YOUR_EMAIL)
|
216 |
build_form_fragment(f, col2, "work details", False, Q.WORK_TO_DO, Q.START_DATE, Q.END_DATE)
|
217 |
+
build_form_fragment(f, col1, "location details", True, Q.COMMUNITY, Q.BUILDING, Q.UNIT_APT_NUMBER,
|
218 |
Q.OWNER_OR_TENANT)
|
219 |
build_form_fragment(f, col2, "contractor details", True, Q.COMPANY_NAME, Q.COMPANY_NUMBER, Q.COMPANY_EMAIL)
|
220 |
if show_categories:
|
|
|
225 |
if submit_data:
|
226 |
onsubmit()
|
227 |
|
228 |
+
def build_details_checkboxes(self, dt: DetailsType):
|
229 |
+
details = self.lsm.get_details(dt)
|
230 |
+
with st.container(border=True):
|
231 |
+
col1, col2 = st.columns(2)
|
232 |
+
with col1:
|
233 |
+
st.markdown(f"#### {dt.title()}")
|
234 |
+
with col2:
|
235 |
+
st.markdown("#### Default")
|
236 |
+
for d in details:
|
237 |
+
with col1:
|
238 |
+
st.checkbox(label=d.short_description(), key=f"{dt.name}_{d.key}",
|
239 |
+
on_change=self._update_user_prompt, args=[dt, d.key])
|
240 |
+
with col2:
|
241 |
+
st.toggle(f"favourite_{d.key}", label_visibility="hidden", value=ss.get(f"DEFAULT_{dt.name}"))
|
242 |
+
add_new = st.button(f"Add {dt.title()}")
|
243 |
+
if add_new:
|
244 |
+
self.add_new_detail_dialog(dt)
|
245 |
+
|
246 |
+
@st.dialog("Add new")
|
247 |
+
def add_new_detail_dialog(self, type_: DetailsType):
|
248 |
+
if type_.name == DetailsType.CONTRACTOR_DETAILS.name:
|
249 |
+
new_item = ContractorDetails()
|
250 |
+
elif type_.name == DetailsType.PERSONAL_DETAILS.name:
|
251 |
+
new_item = PersonalDetails()
|
252 |
+
else:
|
253 |
+
new_item = LocationDetails()
|
254 |
+
with st.form("new item", border=False):
|
255 |
+
fields_labels = new_item.widget_labels()
|
256 |
+
for k,v in fields_labels.items():
|
257 |
+
st.text_input(label=v, key=k)
|
258 |
+
btn_save = st.form_submit_button("Save")
|
259 |
+
if btn_save:
|
260 |
+
for k in fields_labels:
|
261 |
+
setattr(new_item, k, ss[k])
|
262 |
+
self.lsm.save_details(new_item)
|
263 |
+
st.rerun()
|
264 |
+
def _update_user_prompt(self, type_: DetailsType, key: str):
|
265 |
+
if not self.update_in_progress:
|
266 |
+
self.update_in_progress = True
|
267 |
+
checkbox_key = f"{type_.name}_{key}"
|
268 |
+
if ss.get(checkbox_key) is True:
|
269 |
+
# if the checkbox is _selected_
|
270 |
+
to_deselect = [d for d in self.lsm.get_details(type_) if d.key != key]
|
271 |
+
for td in to_deselect:
|
272 |
+
# deselect other checkbox in the same type
|
273 |
+
ss[f"{type_.name}_{td}"] = False
|
274 |
+
if f"@{td}" in ss.get("user_input"):
|
275 |
+
# remove the key associated with this checkbox from the user input textarea
|
276 |
+
ss["user_input"] = ss.get["user_input"].replace(f"@{td}", "")
|
277 |
+
# add the key associated to the newly selected checkbox in the user input textarea
|
278 |
+
ss["user_input"] = f"{ss.get('user_input', '')} @{key}".strip()
|
279 |
+
else:
|
280 |
+
# remove the key associated to the newly deselected checkbox in the user input textarea
|
281 |
+
if f"@{key}" in ss.get("user_input"):
|
282 |
+
ss["user_input"] = ss.get("user_input", "").replace(f"@{key}", "").strip()
|
283 |
+
self.update_in_progress = False
|
284 |
+
|
285 |
|
286 |
um = UIManager()
|
287 |
|
|
|
288 |
|
289 |
+
def use_streamlit():
|
290 |
+
if um.get_current_step() == Steps.INITIAL_STATE.value:
|
291 |
um.build_ui_for_initial_state(user_msg)
|
292 |
elif um.get_current_step() == Steps.PARSING_ANSWERS.value:
|
293 |
um.build_ui_for_parsing_answers()
|
enums.py
CHANGED
@@ -1,16 +1,6 @@
|
|
1 |
from enum import Enum
|
2 |
|
3 |
|
4 |
-
class DetailsType(Enum):
|
5 |
-
PERSONAL_DETAILS = 1
|
6 |
-
LOCATION_DETAILS = 2
|
7 |
-
CONTRACTOR_DETAILS = 3
|
8 |
-
|
9 |
-
@classmethod
|
10 |
-
def values(cls):
|
11 |
-
return [cls.PERSONAL_DETAILS, cls.LOCATION_DETAILS, cls.CONTRACTOR_DETAILS]
|
12 |
-
|
13 |
-
|
14 |
class Questions(Enum):
|
15 |
FULL_NAME = 0
|
16 |
WORK_TO_DO = 1
|
@@ -30,4 +20,17 @@ class Questions(Enum):
|
|
30 |
def values(cls):
|
31 |
return [Questions.FULL_NAME, Questions.WORK_TO_DO, Questions.BUILDING, Questions.UNIT_APT_NUMBER,
|
32 |
Questions.OWNER_OR_TENANT, Questions.START_DATE, Questions.END_DATE, Questions.CONTACT_NUMBER,
|
33 |
-
Questions.COMPANY_NAME, Questions.COMPANY_EMAIL, Questions.COMPANY_NUMBER, Questions.YOUR_EMAIL]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
from enum import Enum
|
2 |
|
3 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4 |
class Questions(Enum):
|
5 |
FULL_NAME = 0
|
6 |
WORK_TO_DO = 1
|
|
|
20 |
def values(cls):
|
21 |
return [Questions.FULL_NAME, Questions.WORK_TO_DO, Questions.BUILDING, Questions.UNIT_APT_NUMBER,
|
22 |
Questions.OWNER_OR_TENANT, Questions.START_DATE, Questions.END_DATE, Questions.CONTACT_NUMBER,
|
23 |
+
Questions.COMPANY_NAME, Questions.COMPANY_EMAIL, Questions.COMPANY_NUMBER, Questions.YOUR_EMAIL]
|
24 |
+
|
25 |
+
|
26 |
+
class DetailsType(Enum):
|
27 |
+
PERSONAL_DETAILS = 1
|
28 |
+
LOCATION_DETAILS = 2
|
29 |
+
CONTRACTOR_DETAILS = 3
|
30 |
+
|
31 |
+
def title(self):
|
32 |
+
return self.name.replace("_", " ").lower()
|
33 |
+
|
34 |
+
@classmethod
|
35 |
+
def values(cls):
|
36 |
+
return [cls.PERSONAL_DETAILS, cls.LOCATION_DETAILS, cls.CONTRACTOR_DETAILS]
|
local_storage/entities.py
CHANGED
@@ -1,13 +1,14 @@
|
|
1 |
import abc
|
2 |
|
3 |
-
from enums import
|
4 |
|
5 |
|
6 |
class SavedDetails(abc.ABC):
|
7 |
-
|
8 |
excluded_fields = ["type_"]
|
9 |
-
|
|
|
10 |
self.type_ = type_
|
|
|
11 |
|
12 |
@classmethod
|
13 |
def load(cls, data: dict):
|
@@ -17,16 +18,26 @@ class SavedDetails(abc.ABC):
|
|
17 |
return cls.__init__(**{k: v for k, v in data if k != "type"})
|
18 |
|
19 |
def to_json(self):
|
20 |
-
|
|
|
21 |
|
22 |
def to_answers(self):
|
23 |
pass
|
24 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
class PersonalDetails(SavedDetails):
|
26 |
-
type_ = DetailsType.PERSONAL_DETAILS
|
27 |
|
28 |
-
def __init__(self, full_name, email, contact_number, *_):
|
29 |
-
super().__init__(
|
30 |
self.full_name = full_name
|
31 |
self.email = email
|
32 |
self.contact_number = contact_number
|
@@ -41,11 +52,13 @@ class PersonalDetails(SavedDetails):
|
|
41 |
answers[Questions.CONTACT_NUMBER] = self.contact_number
|
42 |
return answers
|
43 |
|
|
|
44 |
class LocationDetails(SavedDetails):
|
45 |
type_ = DetailsType.LOCATION_DETAILS
|
46 |
|
47 |
-
def __init__(self, owner_or_tenant: str, community: str, building: str
|
48 |
-
|
|
|
49 |
self.owner_or_tenant = owner_or_tenant
|
50 |
self.community = community
|
51 |
self.building = building
|
@@ -63,11 +76,13 @@ class LocationDetails(SavedDetails):
|
|
63 |
answers[Questions.UNIT_APT_NUMBER] = self.unit_number
|
64 |
return answers
|
65 |
|
|
|
66 |
class ContractorDetails(SavedDetails):
|
67 |
type_ = DetailsType.CONTRACTOR_DETAILS
|
68 |
|
69 |
-
def __init__(self, contractor_name: str, contractor_contact_number: str, contractor_email: str,
|
70 |
-
|
|
|
71 |
self.contractor_name = contractor_name
|
72 |
self.contractor_contact_number = contractor_contact_number
|
73 |
self.contractor_email = contractor_email
|
@@ -80,4 +95,4 @@ class ContractorDetails(SavedDetails):
|
|
80 |
answers[Questions.COMPANY_NUMBER] = self.contractor_contact_number
|
81 |
if self.contractor_name is not None:
|
82 |
answers[Questions.COMPANY_NAME] = self.contractor_name
|
83 |
-
return answers
|
|
|
1 |
import abc
|
2 |
|
3 |
+
from enums import Questions, DetailsType
|
4 |
|
5 |
|
6 |
class SavedDetails(abc.ABC):
|
|
|
7 |
excluded_fields = ["type_"]
|
8 |
+
|
9 |
+
def __init__(self, type_: DetailsType, key: str = None):
|
10 |
self.type_ = type_
|
11 |
+
self.key = key
|
12 |
|
13 |
@classmethod
|
14 |
def load(cls, data: dict):
|
|
|
18 |
return cls.__init__(**{k: v for k, v in data if k != "type"})
|
19 |
|
20 |
def to_json(self):
|
21 |
+
self.key = self.key.replace(" ", "_")
|
22 |
+
return {k: v for k, v in self.__dict__.items() if k not in self.excluded_fields}
|
23 |
|
24 |
def to_answers(self):
|
25 |
pass
|
26 |
|
27 |
+
def short_description(self):
|
28 |
+
return ", ".join([v for k, v in self.__dict__.items() if k not in self.excluded_fields])
|
29 |
+
|
30 |
+
def widget_labels(self) -> dict[str, str]:
|
31 |
+
fields = {k: " ".join(k.title().split("_")) for k in self.__dict__
|
32 |
+
if k not in self.excluded_fields and k != "key"}
|
33 |
+
fields["key"] = "Save as"
|
34 |
+
return fields
|
35 |
+
|
36 |
+
|
37 |
class PersonalDetails(SavedDetails):
|
|
|
38 |
|
39 |
+
def __init__(self, key: str = None, full_name: str = None, email: str = None, contact_number: str = None, *_):
|
40 |
+
super().__init__(DetailsType.PERSONAL_DETAILS, key)
|
41 |
self.full_name = full_name
|
42 |
self.email = email
|
43 |
self.contact_number = contact_number
|
|
|
52 |
answers[Questions.CONTACT_NUMBER] = self.contact_number
|
53 |
return answers
|
54 |
|
55 |
+
|
56 |
class LocationDetails(SavedDetails):
|
57 |
type_ = DetailsType.LOCATION_DETAILS
|
58 |
|
59 |
+
def __init__(self, owner_or_tenant: str = None, community: str = None, building: str = None,
|
60 |
+
unit_number: str = None, key: str = None, *_):
|
61 |
+
super().__init__(self.type_, key)
|
62 |
self.owner_or_tenant = owner_or_tenant
|
63 |
self.community = community
|
64 |
self.building = building
|
|
|
76 |
answers[Questions.UNIT_APT_NUMBER] = self.unit_number
|
77 |
return answers
|
78 |
|
79 |
+
|
80 |
class ContractorDetails(SavedDetails):
|
81 |
type_ = DetailsType.CONTRACTOR_DETAILS
|
82 |
|
83 |
+
def __init__(self, contractor_name: str = None, contractor_contact_number: str = None, contractor_email: str = None,
|
84 |
+
key: str = None, *_):
|
85 |
+
super().__init__(self.type_, key)
|
86 |
self.contractor_name = contractor_name
|
87 |
self.contractor_contact_number = contractor_contact_number
|
88 |
self.contractor_email = contractor_email
|
|
|
95 |
answers[Questions.COMPANY_NUMBER] = self.contractor_contact_number
|
96 |
if self.contractor_name is not None:
|
97 |
answers[Questions.COMPANY_NAME] = self.contractor_name
|
98 |
+
return answers
|
local_storage/ls_manager.py
CHANGED
@@ -8,7 +8,7 @@ class LocalStorageManager:
|
|
8 |
def __init__(self):
|
9 |
self.ls: LocalStorage = LocalStorage()
|
10 |
|
11 |
-
def get_detail(self, key: str):
|
12 |
for detail_type in DetailsType.values():
|
13 |
detail = self.ls.getItem(detail_type.name).get(key)
|
14 |
if detail:
|
@@ -21,7 +21,7 @@ class LocalStorageManager:
|
|
21 |
return None
|
22 |
return None
|
23 |
|
24 |
-
def save_details(self, details: SavedDetails
|
25 |
if isinstance(details, PersonalDetails):
|
26 |
type_ = DetailsType.PERSONAL_DETAILS
|
27 |
elif isinstance(details, LocationDetails):
|
@@ -31,8 +31,15 @@ class LocalStorageManager:
|
|
31 |
else:
|
32 |
raise ValueError("Unexpected type: {}", type(details))
|
33 |
existing_data = (self.ls.getItem(type_.name) or {})
|
34 |
-
existing_data[key] = details.to_json()
|
35 |
self.ls.setItem(type_.name, existing_data, type_.name)
|
36 |
|
37 |
-
def get_details(self, type_: DetailsType):
|
38 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
def __init__(self):
|
9 |
self.ls: LocalStorage = LocalStorage()
|
10 |
|
11 |
+
def get_detail(self, key: str = None):
|
12 |
for detail_type in DetailsType.values():
|
13 |
detail = self.ls.getItem(detail_type.name).get(key)
|
14 |
if detail:
|
|
|
21 |
return None
|
22 |
return None
|
23 |
|
24 |
+
def save_details(self, details: SavedDetails):
|
25 |
if isinstance(details, PersonalDetails):
|
26 |
type_ = DetailsType.PERSONAL_DETAILS
|
27 |
elif isinstance(details, LocationDetails):
|
|
|
31 |
else:
|
32 |
raise ValueError("Unexpected type: {}", type(details))
|
33 |
existing_data = (self.ls.getItem(type_.name) or {})
|
34 |
+
existing_data[details.key] = details.to_json()
|
35 |
self.ls.setItem(type_.name, existing_data, type_.name)
|
36 |
|
37 |
+
def get_details(self, type_: DetailsType) -> list[SavedDetails]:
|
38 |
+
if type_.value == DetailsType.PERSONAL_DETAILS.value:
|
39 |
+
cls = PersonalDetails
|
40 |
+
elif type_.value == DetailsType.LOCATION_DETAILS.value:
|
41 |
+
cls = LocationDetails
|
42 |
+
else:
|
43 |
+
cls = ContractorDetails
|
44 |
+
details = self.ls.getItem(type_.name) or {}
|
45 |
+
return [cls(**v) for k,v in details.items()]
|
requirements-base.txt
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
transformers
|
2 |
streamlit
|
3 |
PyPDFForm
|
4 |
-
streamlit-local-storage
|
|
|
|
1 |
transformers
|
2 |
streamlit
|
3 |
PyPDFForm
|
4 |
+
streamlit-local-storage
|
5 |
+
streamlit-tags
|