Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
Add village status selection and description to the markers, change marker color if village was visited but is in critical condition
#15
by
loubnabnl
HF staff
- opened
- app.py +106 -32
- src/map_utils.py +1 -0
app.py
CHANGED
@@ -7,7 +7,6 @@ import pandas as pd
|
|
7 |
import streamlit as st
|
8 |
from huggingface_hub import HfApi
|
9 |
from streamlit_folium import st_folium
|
10 |
-
from src.utils import add_latlng_col
|
11 |
|
12 |
from src.text_content import (
|
13 |
COLOR_MAPPING,
|
@@ -21,18 +20,21 @@ from src.text_content import (
|
|
21 |
REVIEW_TEXT,
|
22 |
SLOGAN,
|
23 |
)
|
24 |
-
from src.utils import init_map, parse_gg_sheet
|
25 |
|
26 |
TOKEN = os.environ.get("HF_TOKEN", None)
|
27 |
REQUESTS_URL = "https://docs.google.com/spreadsheets/d/1gYoBBiBo1L18IVakHkf3t1fOGvHWb23loadyFZUeHJs/edit#gid=966953708"
|
28 |
-
INTERVENTIONS_URL =
|
29 |
-
"https://docs.google.com/spreadsheets/d/1eXOTqunOWWP8FRdENPs4cU9ulISm4XZWYJJNR1-SrwY/edit#gid=2089222765"
|
30 |
-
)
|
31 |
api = HfApi(TOKEN)
|
32 |
|
33 |
|
34 |
# Initialize Streamlit Config
|
35 |
-
st.set_page_config(
|
|
|
|
|
|
|
|
|
|
|
36 |
|
37 |
# Initialize States
|
38 |
if "sleep_time" not in st.session_state:
|
@@ -42,7 +44,9 @@ if "auto_refresh" not in st.session_state:
|
|
42 |
|
43 |
auto_refresh = st.sidebar.checkbox("Auto Refresh?", st.session_state.auto_refresh)
|
44 |
if auto_refresh:
|
45 |
-
number = st.sidebar.number_input(
|
|
|
|
|
46 |
st.session_state.sleep_time = number
|
47 |
|
48 |
|
@@ -50,21 +54,34 @@ if auto_refresh:
|
|
50 |
def display_interventions(interventions_df, m):
|
51 |
"""Display NGO interventions on the map"""
|
52 |
for index, row in interventions_df.iterrows():
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
)
|
58 |
-
|
59 |
-
"
|
60 |
-
|
61 |
-
|
62 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
63 |
intervention_type = row[interventions_df.columns[6]].split("/")[0].strip()
|
64 |
org = row[interventions_df.columns[1]]
|
65 |
city = row[interventions_df.columns[9]]
|
66 |
date = row[interventions_df.columns[4]]
|
67 |
-
|
|
|
68 |
if row["latlng"] is None:
|
69 |
continue
|
70 |
folium.Marker(
|
@@ -94,7 +111,9 @@ def show_requests(filtered_df, m):
|
|
94 |
if not pd.isna(row[" لأي جماعة / قيادة / دوار تنتمون ؟"])
|
95 |
else None,
|
96 |
popup=folium.Popup(display_text, max_width=300),
|
97 |
-
icon=folium.Icon(
|
|
|
|
|
98 |
).add_to(m)
|
99 |
|
100 |
|
@@ -146,10 +165,14 @@ def display_dataframe(df, drop_cols, data_url, search_id=True, status=False):
|
|
146 |
if status:
|
147 |
target = "Pouvez-vous nous préciser si vous êtes déjà intervenus ou si vous prévoyez de le faire | Tell us if you already made the intervention, or if you're planning to do it"
|
148 |
if selected_status == "Done / تم":
|
149 |
-
display_df = display_df[
|
|
|
|
|
150 |
|
151 |
elif selected_status == "Planned / مخطط لها":
|
152 |
-
display_df = display_df[
|
|
|
|
|
153 |
|
154 |
st.dataframe(display_df, height=500)
|
155 |
st.markdown(
|
@@ -175,7 +198,9 @@ def id_review_submission():
|
|
175 |
st.subheader("🔍 Review of requests")
|
176 |
st.markdown(REVIEW_TEXT)
|
177 |
|
178 |
-
id_to_review = st.number_input(
|
|
|
|
|
179 |
reason_for_review = st.text_area("Explain why / أدخل سبب المراجعة")
|
180 |
if st.button("Submit / أرسل"):
|
181 |
if reason_for_review == "":
|
@@ -190,7 +215,9 @@ def id_review_submission():
|
|
190 |
repo_id="nt3awnou/review_requests",
|
191 |
repo_type="dataset",
|
192 |
)
|
193 |
-
st.success(
|
|
|
|
|
194 |
|
195 |
|
196 |
# Logo and Title
|
@@ -215,14 +242,10 @@ options = [
|
|
215 |
]
|
216 |
selected_options = []
|
217 |
|
218 |
-
# with tab_en:
|
219 |
-
# st.markdown("👉 **Choose request type**")
|
220 |
-
# with tab_ar:
|
221 |
-
# st.markdown("👉 **اختر نوع الطلب**")
|
222 |
-
# with tab_fr:
|
223 |
-
# st.markdown("👉 **Choisissez le type de demande**")
|
224 |
|
225 |
-
st.markdown(
|
|
|
|
|
226 |
col1, col2, col3, col4, col5 = st.columns([2, 3, 2, 3, 4])
|
227 |
cols = [col1, col2, col3, col4, col5]
|
228 |
|
@@ -241,8 +264,58 @@ show_interventions = st.checkbox(
|
|
241 |
value=True,
|
242 |
)
|
243 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
244 |
if show_interventions:
|
245 |
-
|
|
|
|
|
|
|
|
|
246 |
display_interventions(interventions_df, m)
|
247 |
|
248 |
# Show requests
|
@@ -269,6 +342,7 @@ drop_cols = [
|
|
269 |
"GeoCode",
|
270 |
"GeoAddress",
|
271 |
"Status",
|
|
|
272 |
]
|
273 |
display_dataframe(filtered_df, drop_cols, REQUESTS_URL, search_id=True)
|
274 |
|
@@ -277,7 +351,7 @@ st.divider()
|
|
277 |
st.subheader("📝 **Table of interventions / جدول التدخلات**")
|
278 |
display_dataframe(
|
279 |
interventions_df,
|
280 |
-
[],
|
281 |
INTERVENTIONS_URL,
|
282 |
search_id=False,
|
283 |
status=True,
|
|
|
7 |
import streamlit as st
|
8 |
from huggingface_hub import HfApi
|
9 |
from streamlit_folium import st_folium
|
|
|
10 |
|
11 |
from src.text_content import (
|
12 |
COLOR_MAPPING,
|
|
|
20 |
REVIEW_TEXT,
|
21 |
SLOGAN,
|
22 |
)
|
23 |
+
from src.utils import add_latlng_col, init_map, parse_gg_sheet
|
24 |
|
25 |
TOKEN = os.environ.get("HF_TOKEN", None)
|
26 |
REQUESTS_URL = "https://docs.google.com/spreadsheets/d/1gYoBBiBo1L18IVakHkf3t1fOGvHWb23loadyFZUeHJs/edit#gid=966953708"
|
27 |
+
INTERVENTIONS_URL = "https://docs.google.com/spreadsheets/d/1eXOTqunOWWP8FRdENPs4cU9ulISm4XZWYJJNR1-SrwY/edit#gid=2089222765"
|
|
|
|
|
28 |
api = HfApi(TOKEN)
|
29 |
|
30 |
|
31 |
# Initialize Streamlit Config
|
32 |
+
st.set_page_config(
|
33 |
+
layout="wide",
|
34 |
+
initial_sidebar_state="collapsed",
|
35 |
+
page_icon="🤝",
|
36 |
+
page_title="Nt3awnou نتعاونو",
|
37 |
+
)
|
38 |
|
39 |
# Initialize States
|
40 |
if "sleep_time" not in st.session_state:
|
|
|
44 |
|
45 |
auto_refresh = st.sidebar.checkbox("Auto Refresh?", st.session_state.auto_refresh)
|
46 |
if auto_refresh:
|
47 |
+
number = st.sidebar.number_input(
|
48 |
+
"Refresh rate in seconds", value=st.session_state.sleep_time
|
49 |
+
)
|
50 |
st.session_state.sleep_time = number
|
51 |
|
52 |
|
|
|
54 |
def display_interventions(interventions_df, m):
|
55 |
"""Display NGO interventions on the map"""
|
56 |
for index, row in interventions_df.iterrows():
|
57 |
+
village_status = row[interventions_df.columns[7]]
|
58 |
+
if (
|
59 |
+
row[interventions_df.columns[5]]
|
60 |
+
== "Intervention prévue dans le futur / Planned future intervention"
|
61 |
+
):
|
62 |
+
# future intervention
|
63 |
+
color_mk = "pink"
|
64 |
+
status = "Planned ⌛"
|
65 |
+
elif (
|
66 |
+
row[interventions_df.columns[5]]
|
67 |
+
!= "Intervention prévue dans le futur / Planned future intervention"
|
68 |
+
and village_status
|
69 |
+
!= "Critique, Besoin d'aide en urgence / Critical, in urgent need of help"
|
70 |
+
):
|
71 |
+
# past intervention and village not in a critical condition
|
72 |
+
color_mk = "green"
|
73 |
+
status = "Done ✅"
|
74 |
+
|
75 |
+
else:
|
76 |
+
color_mk = "darkgreen"
|
77 |
+
status = "Partial ⚠️"
|
78 |
+
|
79 |
intervention_type = row[interventions_df.columns[6]].split("/")[0].strip()
|
80 |
org = row[interventions_df.columns[1]]
|
81 |
city = row[interventions_df.columns[9]]
|
82 |
date = row[interventions_df.columns[4]]
|
83 |
+
population = row[interventions_df.columns[11]]
|
84 |
+
intervention_info = f"<b>Intervention Status:</b> {status}<br><b>Village Status:</b> {village_status.split('/')[0]}<br><b>Org:</b> {org}<br><b>Intervention:</b> {intervention_type}<br><b>Population:</b> {population}<br><b>📅 Date:</b> {date}"
|
85 |
if row["latlng"] is None:
|
86 |
continue
|
87 |
folium.Marker(
|
|
|
111 |
if not pd.isna(row[" لأي جماعة / قيادة / دوار تنتمون ؟"])
|
112 |
else None,
|
113 |
popup=folium.Popup(display_text, max_width=300),
|
114 |
+
icon=folium.Icon(
|
115 |
+
color=COLOR_MAPPING.get(request_type, "blue"), icon=icon_name
|
116 |
+
),
|
117 |
).add_to(m)
|
118 |
|
119 |
|
|
|
165 |
if status:
|
166 |
target = "Pouvez-vous nous préciser si vous êtes déjà intervenus ou si vous prévoyez de le faire | Tell us if you already made the intervention, or if you're planning to do it"
|
167 |
if selected_status == "Done / تم":
|
168 |
+
display_df = display_df[
|
169 |
+
display_df[target] == "Intervention déjà passée / Past intevention"
|
170 |
+
]
|
171 |
|
172 |
elif selected_status == "Planned / مخطط لها":
|
173 |
+
display_df = display_df[
|
174 |
+
display_df[target] != "Intervention déjà passée / Past intevention"
|
175 |
+
]
|
176 |
|
177 |
st.dataframe(display_df, height=500)
|
178 |
st.markdown(
|
|
|
198 |
st.subheader("🔍 Review of requests")
|
199 |
st.markdown(REVIEW_TEXT)
|
200 |
|
201 |
+
id_to_review = st.number_input(
|
202 |
+
"Enter id / أدخل الرقم", min_value=0, max_value=len(df), value=0, step=1
|
203 |
+
)
|
204 |
reason_for_review = st.text_area("Explain why / أدخل سبب المراجعة")
|
205 |
if st.button("Submit / أرسل"):
|
206 |
if reason_for_review == "":
|
|
|
215 |
repo_id="nt3awnou/review_requests",
|
216 |
repo_type="dataset",
|
217 |
)
|
218 |
+
st.success(
|
219 |
+
"Submitted at https://huggingface.co/datasets/nt3awnou/review_requests/ تم الإرسال"
|
220 |
+
)
|
221 |
|
222 |
|
223 |
# Logo and Title
|
|
|
242 |
]
|
243 |
selected_options = []
|
244 |
|
|
|
|
|
|
|
|
|
|
|
|
|
245 |
|
246 |
+
st.markdown(
|
247 |
+
"👉 **Choose request type | Choissisez le type de demande | اختر نوع الطلب**"
|
248 |
+
)
|
249 |
col1, col2, col3, col4, col5 = st.columns([2, 3, 2, 3, 4])
|
250 |
cols = [col1, col2, col3, col4, col5]
|
251 |
|
|
|
264 |
value=True,
|
265 |
)
|
266 |
|
267 |
+
# Categories of villages
|
268 |
+
|
269 |
+
st.markdown(
|
270 |
+
"👉 **State of villages visited by NGOs| Etat de villages visités par les ONGs | اختر نوع القرى التي زارتها الجمعيات**",
|
271 |
+
unsafe_allow_html=True,
|
272 |
+
)
|
273 |
+
|
274 |
+
|
275 |
+
# use checkboxes
|
276 |
+
col_1, col_2, col_3 = st.columns([1, 1, 1])
|
277 |
+
|
278 |
+
critical_villages = col_1.checkbox(
|
279 |
+
"🚨 Critical, in urgent need of help / وضع حرج، في حاجة عاجلة للمساعدة",
|
280 |
+
value=True,
|
281 |
+
)
|
282 |
+
partially_satisfied_villages = col_2.checkbox(
|
283 |
+
"⚠️ Partially served / مساعدة جزئية، بحاجة للمزيد من التدخلات",
|
284 |
+
value=True,
|
285 |
+
)
|
286 |
+
fully_satisfied_villages = col_3.checkbox(
|
287 |
+
"✅ Fully served / تمت المساعدة بشكل كامل",
|
288 |
+
value=True,
|
289 |
+
)
|
290 |
+
|
291 |
+
selected_village_types = []
|
292 |
+
|
293 |
+
if critical_villages:
|
294 |
+
selected_village_types.append(
|
295 |
+
"🚨 Critical, in urgent need of help / وضع حرج، في حاجة عاجلة للمساعدة"
|
296 |
+
)
|
297 |
+
|
298 |
+
if partially_satisfied_villages:
|
299 |
+
selected_village_types.append(
|
300 |
+
"⚠️ Partially served / مساعدة جزئية، بحاجة للمزيد من التدخلات"
|
301 |
+
)
|
302 |
+
|
303 |
+
if fully_satisfied_villages:
|
304 |
+
selected_village_types.append("✅ Fully served / تمت المساعدة بشكل كامل")
|
305 |
+
|
306 |
+
status_mapping = {
|
307 |
+
"🚨 Critical, in urgent need of help / وضع حرج، في حاجة عاجلة للمساعدة": "Critique, Besoin d'aide en urgence / Critical, in urgent need of help",
|
308 |
+
"⚠️ Partially served / مساعدة جزئية، بحاجة للمزيد من التدخلات": "Partiellement satisfait / Partially Served",
|
309 |
+
"✅ Fully served / تمت المساعدة بشكل كامل": "Entièrement satisfait / Fully served",
|
310 |
+
}
|
311 |
+
selected_statuses = [status_mapping[status] for status in selected_village_types]
|
312 |
+
|
313 |
if show_interventions:
|
314 |
+
interventions_df = interventions_df.loc[
|
315 |
+
interventions_df[
|
316 |
+
"Etat de la région actuel | Current situation of the area "
|
317 |
+
].isin(selected_statuses)
|
318 |
+
]
|
319 |
display_interventions(interventions_df, m)
|
320 |
|
321 |
# Show requests
|
|
|
342 |
"GeoCode",
|
343 |
"GeoAddress",
|
344 |
"Status",
|
345 |
+
"id",
|
346 |
]
|
347 |
display_dataframe(filtered_df, drop_cols, REQUESTS_URL, search_id=True)
|
348 |
|
|
|
351 |
st.subheader("📝 **Table of interventions / جدول التدخلات**")
|
352 |
display_dataframe(
|
353 |
interventions_df,
|
354 |
+
[], # We show NGOs contact information
|
355 |
INTERVENTIONS_URL,
|
356 |
search_id=False,
|
357 |
status=True,
|
src/map_utils.py
CHANGED
@@ -46,6 +46,7 @@ template = """
|
|
46 |
<li><span style='background:#37A8DA;opacity:0.7;'></span>Food & Water / طعام وماء</li>
|
47 |
<li><span style='background:#575757;opacity:0.7;'></span>Danger / مخاطر (تسرب الغاز، تلف في الخدمات العامة...)</li>
|
48 |
<li><span style='background:#6EAA25;opacity:0.7;'></span>Done / تم</li>
|
|
|
49 |
<li><span style='background:#FF91E8;opacity:0.7;'></span>Planned / مخطط لها</li>
|
50 |
</ul>
|
51 |
</div>
|
|
|
46 |
<li><span style='background:#37A8DA;opacity:0.7;'></span>Food & Water / طعام وماء</li>
|
47 |
<li><span style='background:#575757;opacity:0.7;'></span>Danger / مخاطر (تسرب الغاز، تلف في الخدمات العامة...)</li>
|
48 |
<li><span style='background:#6EAA25;opacity:0.7;'></span>Done / تم</li>
|
49 |
+
<li><span style='background:#023020;opacity:0.7;'></span>Partial / تم جزئيا</li>
|
50 |
<li><span style='background:#FF91E8;opacity:0.7;'></span>Planned / مخطط لها</li>
|
51 |
</ul>
|
52 |
</div>
|