Spaces:
Sleeping
Sleeping
- Format documents
Browse files- Reload polls list
- Fix poll exception on deleted poll
- Clear user votes after refresh
home.py
CHANGED
@@ -17,6 +17,7 @@ def is_valid_new_poll(poll_name):
|
|
17 |
return False
|
18 |
return True
|
19 |
|
|
|
20 |
def is_valid_join_poll(poll_name):
|
21 |
poll = utils.find_poll(poll_name)
|
22 |
if poll:
|
@@ -26,6 +27,8 @@ def is_valid_join_poll(poll_name):
|
|
26 |
else:
|
27 |
return True
|
28 |
return False
|
|
|
|
|
29 |
def is_valid_admin_password(poll_name, admin_password):
|
30 |
poll = utils.find_poll(poll_name)
|
31 |
if poll:
|
@@ -33,6 +36,7 @@ def is_valid_admin_password(poll_name, admin_password):
|
|
33 |
return True
|
34 |
return False
|
35 |
|
|
|
36 |
def join_poll(poll_name, admin_password=""):
|
37 |
if not is_valid_join_poll(poll_name):
|
38 |
st.error(f"Invalid poll name {poll_name}")
|
@@ -46,6 +50,7 @@ def join_poll(poll_name, admin_password=""):
|
|
46 |
if "poll" not in st.query_params:
|
47 |
st.query_params.from_dict({"poll": poll_name})
|
48 |
|
|
|
49 |
def new_poll(poll_name, admin_password):
|
50 |
if not is_valid_new_poll(poll_name):
|
51 |
return
|
@@ -56,7 +61,7 @@ def new_poll(poll_name, admin_password):
|
|
56 |
"name": poll_name,
|
57 |
"admin_password": admin_password,
|
58 |
"expiry": datetime.datetime.now() + datetime.timedelta(hours=3),
|
59 |
-
"votes"
|
60 |
}
|
61 |
|
62 |
utils.load_polls().append(poll)
|
@@ -64,8 +69,10 @@ def new_poll(poll_name, admin_password):
|
|
64 |
|
65 |
|
66 |
def show_polls():
|
|
|
67 |
with st.container(border=True):
|
68 |
st.header("Poll list:")
|
|
|
69 |
|
70 |
polls = utils.load_polls()
|
71 |
if len(polls) == 0:
|
@@ -103,14 +110,16 @@ def show_join_poll(column):
|
|
103 |
poll_name = st.text_input("Join Poll")
|
104 |
poll_admin_password = ""
|
105 |
if st.checkbox("Login as Admin", value=False):
|
106 |
-
poll_admin_password = st.text_input(
|
|
|
|
|
107 |
st.button(
|
108 |
"Join Poll",
|
109 |
type="primary",
|
110 |
key="btn_join",
|
111 |
use_container_width=True,
|
112 |
on_click=join_poll,
|
113 |
-
args=(poll_name,poll_admin_password),
|
114 |
)
|
115 |
|
116 |
|
@@ -125,7 +134,7 @@ def show_new_poll(column):
|
|
125 |
key="btn_new",
|
126 |
use_container_width=True,
|
127 |
on_click=new_poll,
|
128 |
-
args=(poll_name,poll_admin_password),
|
129 |
)
|
130 |
|
131 |
|
|
|
17 |
return False
|
18 |
return True
|
19 |
|
20 |
+
|
21 |
def is_valid_join_poll(poll_name):
|
22 |
poll = utils.find_poll(poll_name)
|
23 |
if poll:
|
|
|
27 |
else:
|
28 |
return True
|
29 |
return False
|
30 |
+
|
31 |
+
|
32 |
def is_valid_admin_password(poll_name, admin_password):
|
33 |
poll = utils.find_poll(poll_name)
|
34 |
if poll:
|
|
|
36 |
return True
|
37 |
return False
|
38 |
|
39 |
+
|
40 |
def join_poll(poll_name, admin_password=""):
|
41 |
if not is_valid_join_poll(poll_name):
|
42 |
st.error(f"Invalid poll name {poll_name}")
|
|
|
50 |
if "poll" not in st.query_params:
|
51 |
st.query_params.from_dict({"poll": poll_name})
|
52 |
|
53 |
+
|
54 |
def new_poll(poll_name, admin_password):
|
55 |
if not is_valid_new_poll(poll_name):
|
56 |
return
|
|
|
61 |
"name": poll_name,
|
62 |
"admin_password": admin_password,
|
63 |
"expiry": datetime.datetime.now() + datetime.timedelta(hours=3),
|
64 |
+
"votes": {},
|
65 |
}
|
66 |
|
67 |
utils.load_polls().append(poll)
|
|
|
69 |
|
70 |
|
71 |
def show_polls():
|
72 |
+
st.write("---")
|
73 |
with st.container(border=True):
|
74 |
st.header("Poll list:")
|
75 |
+
st.button("Reload Polls", use_container_width=True)
|
76 |
|
77 |
polls = utils.load_polls()
|
78 |
if len(polls) == 0:
|
|
|
110 |
poll_name = st.text_input("Join Poll")
|
111 |
poll_admin_password = ""
|
112 |
if st.checkbox("Login as Admin", value=False):
|
113 |
+
poll_admin_password = st.text_input(
|
114 |
+
"Admin Password", type="password", key="join_admin_password"
|
115 |
+
)
|
116 |
st.button(
|
117 |
"Join Poll",
|
118 |
type="primary",
|
119 |
key="btn_join",
|
120 |
use_container_width=True,
|
121 |
on_click=join_poll,
|
122 |
+
args=(poll_name, poll_admin_password),
|
123 |
)
|
124 |
|
125 |
|
|
|
134 |
key="btn_new",
|
135 |
use_container_width=True,
|
136 |
on_click=new_poll,
|
137 |
+
args=(poll_name, poll_admin_password),
|
138 |
)
|
139 |
|
140 |
|
poll.py
CHANGED
@@ -2,6 +2,8 @@ import utils
|
|
2 |
import streamlit as st
|
3 |
import plotly.express as px
|
4 |
import pandas as pd
|
|
|
|
|
5 |
|
6 |
def exit_poll():
|
7 |
set_votes([])
|
@@ -10,32 +12,64 @@ def exit_poll():
|
|
10 |
if "selected_poll_admin_password" in st.session_state:
|
11 |
del st.session_state["selected_poll_admin_password"]
|
12 |
|
|
|
13 |
def set_votes(votes=[]):
|
14 |
poll = utils.find_poll(st.session_state["selected_poll_name"])
|
|
|
|
|
|
|
15 |
uuid = st.session_state["UUID"]
|
16 |
-
|
|
|
|
|
|
|
|
|
|
|
17 |
|
18 |
def vote():
|
19 |
votes = st.session_state.get("vote_selected", [])
|
20 |
set_votes(votes)
|
21 |
|
|
|
22 |
def load_voting():
|
|
|
|
|
|
|
|
|
|
|
23 |
st.multiselect(
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
|
|
|
|
29 |
|
30 |
def is_admin():
|
31 |
password = st.session_state.get("selected_poll_admin_password", "")
|
32 |
poll = utils.find_poll(st.session_state["selected_poll_name"])
|
|
|
|
|
33 |
return poll["admin_password"] == password
|
34 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
def clear_votes_section():
|
36 |
poll = utils.find_poll(st.session_state["selected_poll_name"])
|
|
|
|
|
|
|
37 |
poll["votes"] = {}
|
38 |
|
|
|
39 |
def delete_poll():
|
40 |
utils.load_polls().remove(utils.find_poll(st.session_state["selected_poll_name"]))
|
41 |
st.query_params.pop("poll")
|
@@ -45,53 +79,73 @@ def delete_poll():
|
|
45 |
def load_votes():
|
46 |
selected_poll_name = st.session_state["selected_poll_name"]
|
47 |
poll = utils.find_poll(selected_poll_name)
|
|
|
|
|
|
|
48 |
votes = {x: 0 for x in utils.get_options()}
|
49 |
votes_count = 0
|
50 |
users_count = 0
|
51 |
-
for _,user_votes in poll["votes"].items():
|
52 |
-
users_count +=1
|
53 |
for vote in user_votes:
|
54 |
-
votes_count +=1
|
55 |
if vote in votes:
|
56 |
votes[vote] += 1
|
57 |
else:
|
58 |
votes[vote] = 1
|
59 |
|
60 |
-
|
61 |
-
|
62 |
-
df = pd.DataFrame(list(votes.items()), columns=['Status', 'Count'])
|
63 |
if df["Count"].sum() == 0:
|
64 |
st.warning("No votes yet!")
|
65 |
else:
|
66 |
st.success(f"Users:{users_count} | Votes:{votes_count}")
|
67 |
-
fig = px.pie(
|
|
|
|
|
|
|
|
|
|
|
68 |
st.plotly_chart(fig)
|
69 |
st.write(df)
|
70 |
st.button("Clear Votes", on_click=clear_votes_section, use_container_width=True)
|
71 |
st.button("Delete Poll", on_click=delete_poll, use_container_width=True)
|
72 |
|
|
|
73 |
def show_qrcode():
|
74 |
selected_poll_name = st.session_state["selected_poll_name"]
|
75 |
columns = st.columns(5)
|
76 |
with columns[2]:
|
77 |
st.image(utils.generate_qr_code_image_link(selected_poll_name))
|
78 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
79 |
def load():
|
|
|
80 |
selected_poll_name = st.session_state["selected_poll_name"]
|
81 |
st.write("")
|
82 |
columns = st.columns(3)
|
83 |
with columns[0]:
|
84 |
st.button("Exit", on_click=exit_poll, use_container_width=True)
|
85 |
with columns[1]:
|
86 |
-
st.button("Refresh", use_container_width=True)
|
87 |
with columns[2]:
|
88 |
-
st.link_button(
|
|
|
|
|
|
|
|
|
|
|
89 |
|
90 |
st.title(selected_poll_name)
|
91 |
if not is_admin():
|
92 |
load_voting()
|
93 |
else:
|
94 |
load_votes()
|
95 |
-
|
96 |
-
|
97 |
-
show_qrcode()
|
|
|
2 |
import streamlit as st
|
3 |
import plotly.express as px
|
4 |
import pandas as pd
|
5 |
+
import time
|
6 |
+
|
7 |
|
8 |
def exit_poll():
|
9 |
set_votes([])
|
|
|
12 |
if "selected_poll_admin_password" in st.session_state:
|
13 |
del st.session_state["selected_poll_admin_password"]
|
14 |
|
15 |
+
|
16 |
def set_votes(votes=[]):
|
17 |
poll = utils.find_poll(st.session_state["selected_poll_name"])
|
18 |
+
if poll is None:
|
19 |
+
on_poll_not_exists()
|
20 |
+
return
|
21 |
uuid = st.session_state["UUID"]
|
22 |
+
if votes == []:
|
23 |
+
if uuid in poll["votes"]:
|
24 |
+
del poll["votes"][uuid]
|
25 |
+
else:
|
26 |
+
poll["votes"][uuid] = votes
|
27 |
+
|
28 |
|
29 |
def vote():
|
30 |
votes = st.session_state.get("vote_selected", [])
|
31 |
set_votes(votes)
|
32 |
|
33 |
+
|
34 |
def load_voting():
|
35 |
+
poll = utils.find_poll(st.session_state["selected_poll_name"])
|
36 |
+
if poll is None:
|
37 |
+
on_poll_not_exists()
|
38 |
+
return
|
39 |
+
current_votes = poll["votes"].get(st.session_state["UUID"], [])
|
40 |
st.multiselect(
|
41 |
+
"How do you feel?",
|
42 |
+
utils.get_options(),
|
43 |
+
current_votes,
|
44 |
+
on_change=vote,
|
45 |
+
key="vote_selected",
|
46 |
+
)
|
47 |
+
|
48 |
|
49 |
def is_admin():
|
50 |
password = st.session_state.get("selected_poll_admin_password", "")
|
51 |
poll = utils.find_poll(st.session_state["selected_poll_name"])
|
52 |
+
if poll is None:
|
53 |
+
return False
|
54 |
return poll["admin_password"] == password
|
55 |
|
56 |
+
|
57 |
+
def on_poll_not_exists():
|
58 |
+
st.error(f"Poll {st.session_state['selected_poll_name']} does not exist")
|
59 |
+
st.query_params.pop("poll")
|
60 |
+
del st.session_state["selected_poll_name"]
|
61 |
+
if "selected_poll_admin_password" in st.session_state:
|
62 |
+
del st.session_state["selected_poll_admin_password"]
|
63 |
+
|
64 |
+
|
65 |
def clear_votes_section():
|
66 |
poll = utils.find_poll(st.session_state["selected_poll_name"])
|
67 |
+
if poll is None:
|
68 |
+
on_poll_not_exists()
|
69 |
+
return
|
70 |
poll["votes"] = {}
|
71 |
|
72 |
+
|
73 |
def delete_poll():
|
74 |
utils.load_polls().remove(utils.find_poll(st.session_state["selected_poll_name"]))
|
75 |
st.query_params.pop("poll")
|
|
|
79 |
def load_votes():
|
80 |
selected_poll_name = st.session_state["selected_poll_name"]
|
81 |
poll = utils.find_poll(selected_poll_name)
|
82 |
+
if poll is None:
|
83 |
+
on_poll_not_exists()
|
84 |
+
return
|
85 |
votes = {x: 0 for x in utils.get_options()}
|
86 |
votes_count = 0
|
87 |
users_count = 0
|
88 |
+
for _, user_votes in poll["votes"].items():
|
89 |
+
users_count += 1
|
90 |
for vote in user_votes:
|
91 |
+
votes_count += 1
|
92 |
if vote in votes:
|
93 |
votes[vote] += 1
|
94 |
else:
|
95 |
votes[vote] = 1
|
96 |
|
97 |
+
df = pd.DataFrame(list(votes.items()), columns=["Status", "Count"])
|
|
|
|
|
98 |
if df["Count"].sum() == 0:
|
99 |
st.warning("No votes yet!")
|
100 |
else:
|
101 |
st.success(f"Users:{users_count} | Votes:{votes_count}")
|
102 |
+
fig = px.pie(
|
103 |
+
df,
|
104 |
+
values="Count",
|
105 |
+
names="Status",
|
106 |
+
title="Audience Feedback",
|
107 |
+
)
|
108 |
st.plotly_chart(fig)
|
109 |
st.write(df)
|
110 |
st.button("Clear Votes", on_click=clear_votes_section, use_container_width=True)
|
111 |
st.button("Delete Poll", on_click=delete_poll, use_container_width=True)
|
112 |
|
113 |
+
|
114 |
def show_qrcode():
|
115 |
selected_poll_name = st.session_state["selected_poll_name"]
|
116 |
columns = st.columns(5)
|
117 |
with columns[2]:
|
118 |
st.image(utils.generate_qr_code_image_link(selected_poll_name))
|
119 |
|
120 |
+
|
121 |
+
def dummy_refresh():
|
122 |
+
selected_poll_name = st.session_state["selected_poll_name"]
|
123 |
+
poll = utils.find_poll(selected_poll_name)
|
124 |
+
if poll is None:
|
125 |
+
on_poll_not_exists()
|
126 |
+
return
|
127 |
+
|
128 |
+
|
129 |
def load():
|
130 |
+
dummy_refresh()
|
131 |
selected_poll_name = st.session_state["selected_poll_name"]
|
132 |
st.write("")
|
133 |
columns = st.columns(3)
|
134 |
with columns[0]:
|
135 |
st.button("Exit", on_click=exit_poll, use_container_width=True)
|
136 |
with columns[1]:
|
137 |
+
st.button("Refresh", use_container_width=True, on_click=dummy_refresh)
|
138 |
with columns[2]:
|
139 |
+
st.link_button(
|
140 |
+
"Link To Poll",
|
141 |
+
"?poll=" + selected_poll_name,
|
142 |
+
type="primary",
|
143 |
+
use_container_width=True,
|
144 |
+
)
|
145 |
|
146 |
st.title(selected_poll_name)
|
147 |
if not is_admin():
|
148 |
load_voting()
|
149 |
else:
|
150 |
load_votes()
|
151 |
+
show_qrcode()
|
|
|
|