Skip to content

Commit

Permalink
Merge pull request #131 from Michele-Alberti/development
Browse files Browse the repository at this point in the history
👻 Hide details in Excel file
  • Loading branch information
Michele-Alberti authored Mar 11, 2024
2 parents 3aced2f + e9f0f04 commit b065dd2
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 43 deletions.
105 changes: 71 additions & 34 deletions dlunch/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from . import __version__
from . import models
from omegaconf import DictConfig, OmegaConf
from openpyxl.utils import get_column_interval
from bokeh.models.widgets.tables import CheckboxEditor
from io import BytesIO
from PIL import Image
Expand Down Expand Up @@ -563,6 +564,10 @@ def send_order(
person: gui.Person,
gi: gui.GraphicInterface,
) -> None:
# Get username and note, updated at each key press
username_key_press = gi.person_widget._widgets["username"].value_input
note_key_press = gi.person_widget._widgets["note"].value_input

# Hide messages
gi.error_message.visible = False
gi.confirm_message.visible = False
Expand Down Expand Up @@ -591,11 +596,11 @@ def send_order(
# privileged user
if (
auth.is_guest(user=pn_user(config), config=config)
and (person.username in auth.list_users(config=config))
and (username_key_press in auth.list_users(config=config))
and (auth.is_auth_active(config=config))
):
pn.state.notifications.error(
f"{person.username} is a reserved name<br>Please choose a different one",
f"{username_key_press} is a reserved name<br>Please choose a different one",
duration=config.panel.notifications.duration,
)

Expand All @@ -612,7 +617,7 @@ def send_order(
if (
not auth.is_guest(user=pn_user(config), config=config)
and (
person.username
username_key_press
not in (
name
for name in auth.list_users(config=config)
Expand All @@ -622,7 +627,7 @@ def send_order(
and (auth.is_auth_active(config=config))
):
pn.state.notifications.error(
f"{person.username} is not a valid name<br>for a privileged user<br>Please choose a different one",
f"{username_key_press} is not a valid name<br>for a privileged user<br>Please choose a different one",
duration=config.panel.notifications.duration,
)

Expand All @@ -640,38 +645,38 @@ def send_order(
df_order = df[df.order]

# If username is missing or the order is empty return an error message
if person.username and not df_order.empty:
if username_key_press and not df_order.empty:
# Check if the user already placed an order
if session.get(models.Users, person.username):
if session.get(models.Users, username_key_press):
pn.state.notifications.warning(
f"Cannot overwrite an order<br>Delete {person.username}'s order first and retry",
f"Cannot overwrite an order<br>Delete {username_key_press}'s order first and retry",
duration=config.panel.notifications.duration,
)
log.warning(f"an order already exist for {person.username}")
log.warning(f"an order already exist for {username_key_press}")
else:
# Place order
try:
# Add User (note is empty by default)
# Do not pass guest for privileged users (default to NotAGuest)
if auth.is_guest(user=pn_user(config), config=config):
new_user = models.Users(
id=person.username,
id=username_key_press,
guest=person.guest,
takeaway=person.takeaway,
note=person.note,
note=note_key_press,
)
else:
new_user = models.Users(
id=person.username,
id=username_key_press,
takeaway=person.takeaway,
note=person.note,
note=note_key_press,
)
session.add(new_user)
# Add orders as long table (one row for each item selected by a user)
for index, row in df_order.iterrows():
# Order
new_order = models.Orders(
user=person.username,
user=username_key_press,
lunch_time=person.lunch_time,
menu_item_id=index,
)
Expand All @@ -689,7 +694,7 @@ def send_order(
"Order sent",
duration=config.panel.notifications.duration,
)
log.info(f"{person.username}'s order saved")
log.info(f"{username_key_press}'s order saved")
except Exception as e:
# Any exception here is a database fault
pn.state.notifications.error(
Expand All @@ -704,7 +709,7 @@ def send_order(
# Open modal window
app.open_modal()
else:
if not person.username:
if not username_key_press:
pn.state.notifications.warning(
"Please insert user name",
duration=config.panel.notifications.duration,
Expand All @@ -725,6 +730,9 @@ def delete_order(
person: gui.Person,
gi: gui.GraphicInterface,
) -> None:
# Get username, updated on every keypress
username_key_press = gi.person_widget._widgets["username"].value_input

# Hide messages
gi.error_message.visible = False
gi.confirm_message.visible = False
Expand All @@ -749,16 +757,16 @@ def delete_order(

return

if person.username:
if username_key_press:
# If auth is active, check if a guests is deleting an order of a
# privileged user
if (
auth.is_guest(user=pn_user(config), config=config)
and (person.username in auth.list_users(config=config))
and (username_key_press in auth.list_users(config=config))
and (auth.is_auth_active(config=config))
):
pn.state.notifications.error(
f"You do not have enough privileges<br>to delete<br>{person.username}'s order",
f"You do not have enough privileges<br>to delete<br>{username_key_press}'s order",
duration=config.panel.notifications.duration,
)

Expand All @@ -773,12 +781,14 @@ def delete_order(

# Delete user
num_rows_deleted_users = session.execute(
delete(models.Users).where(models.Users.id == person.username)
delete(models.Users).where(
models.Users.id == username_key_press
)
)
# Delete also orders (hotfix for Debian)
num_rows_deleted_orders = session.execute(
delete(models.Orders).where(
models.Orders.user == person.username
models.Orders.user == username_key_press
)
)
session.commit()
Expand All @@ -796,13 +806,13 @@ def delete_order(
"Order canceled",
duration=config.panel.notifications.duration,
)
log.info(f"{person.username}'s order canceled")
log.info(f"{username_key_press}'s order canceled")
else:
pn.state.notifications.warning(
f'No order for user named<br>"{person.username}"',
f'No order for user named<br>"{username_key_press}"',
duration=config.panel.notifications.duration,
)
log.info(f"no order for user named {person.username}")
log.info(f"no order for user named {username_key_press}")
else:
pn.state.notifications.warning(
"Please insert user name",
Expand Down Expand Up @@ -920,12 +930,31 @@ def download_dataframe(
if df_dict:
for time, df in df_dict.items():
log.info(f"writing sheet {time}")
df.to_excel(writer, sheet_name=time.replace(":", "."), startrow=1)
writer.sheets[time.replace(":", ".")].cell(
# users that placed an order for a given time
users_n = len(
[
c
for c in df.columns
if c != config.panel.gui.total_column_name
]
)
# Export dataframe to new sheet
worksheet_name = time.replace(":", ".")
df.to_excel(writer, sheet_name=worksheet_name, startrow=1)
# Add title
worksheet = writer.sheets[worksheet_name]
worksheet.cell(
1,
1,
f"Time - {time} | # {len([c for c in df.columns if c != config.panel.gui.total_column_name])}",
f"Time - {time} | # {users_n}",
)
# Group and hide columns, leave only ID and total
column_letters = get_column_interval(start=2, end=users_n + 1)
worksheet.column_dimensions.group(
column_letters[0], column_letters[-1], hidden=True
)

# Close and reset bytes_io for the next dataframe
writer.close() # Important!
bytes_io.seek(0) # Important!

Expand Down Expand Up @@ -958,8 +987,12 @@ def submit_password(gi: gui.GraphicInterface, config: DictConfig) -> bool:
password"""
# Get user's password hash
password_hash = auth.get_hash_from_user(pn_user(config), config=config)
# Get username, updated updated at each key press
old_password_key_press = gi.password_widget._widgets[
"old_password"
].value_input
# Check if old password is correct
if password_hash == gi.password_widget.object.old_password:
if password_hash == old_password_key_press:
# Check if new password match repeat password
return backend_submit_password(
gi=gi, config=config, user=pn_user(config), logout_on_success=True
Expand Down Expand Up @@ -990,19 +1023,23 @@ def backend_submit_password(
# Check if user is passed, otherwise check if backend widget
# (password_widget.object.user) is available
if not user:
username = gi.password_widget.object.user
username = gi.password_widget._widgets["user"].value_input
else:
username = user
# Get all passwords, updated at each key press
new_password_key_press = gi.password_widget._widgets[
"new_password"
].value_input
repeat_new_password_key_press = gi.password_widget._widgets[
"repeat_new_password"
].value_input
# Check if new password match repeat password
if username:
if (
gi.password_widget.object.new_password
== gi.password_widget.object.repeat_new_password
):
if new_password_key_press == repeat_new_password_key_press:
# Check if new password is valid with regex
if re.fullmatch(
config.basic_auth.psw_regex,
gi.password_widget.object.new_password,
new_password_key_press,
):
# If is_guest and is_admin are None (not passed) use the ones
# already set for the user
Expand All @@ -1020,7 +1057,7 @@ def backend_submit_password(
# Green light: update the password!
auth.add_user_hashed_password(
user=username,
password=gi.password_widget.object.new_password,
password=new_password_key_press,
config=config,
)

Expand Down
31 changes: 22 additions & 9 deletions dlunch/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,9 @@ def __init__(self, config, **params):
self.guest = config.panel.guest_types[0]
# Check user (a username is already set for privileged users)
username = pn_user(config)
if not auth.is_guest(user=username, config=config) and (
username is not None
):
if not auth.is_guest(
user=username, config=config, allow_override=False
) and (username is not None):
self.username = username

def __str__(self):
Expand Down Expand Up @@ -520,13 +520,18 @@ def reload_on_no_more_order_callback(
self.person_widget = pn.Param(
person.param,
widgets={
"guest": pn.widgets.RadioButtonGroup(
"guest": pnw.RadioButtonGroup(
options=OmegaConf.to_container(
config.panel.guest_types, resolve=True
),
button_type="primary",
button_style="outline",
)
),
"username": pnw.TextInput(
value=person.username,
value_input=person.username,
description=person.param.username.doc,
),
},
width=sidebar_content_width,
)
Expand Down Expand Up @@ -1111,15 +1116,20 @@ def submit_password_button_callback(self, config):

# Add privileged user callback
def add_privileged_user_button_callback(self):
# Get username, updated at each key press
username_key_press = self.add_privileged_user_widget._widgets[
"user"
].value_input
# Add user
auth.add_privileged_user(
self.add_privileged_user_widget.object.user,
username_key_press,
is_admin=self.add_privileged_user_widget.object.admin,
config=config,
)

self.reload_backend(config)
pn.state.notifications.success(
f"User '{self.add_privileged_user_widget.object.user}' added",
f"User '{username_key_press}' added",
duration=config.panel.notifications.duration,
)

Expand All @@ -1129,8 +1139,11 @@ def add_privileged_user_button_callback(self):

# Delete user callback
def delete_user_button_callback(self):
# Get username, updated at each key press
username_key_press = self.user_eraser._widgets["user"].value_input
# Delete user
deleted_data = auth.remove_user(
user=self.user_eraser.object.user, config=config
user=username_key_press, config=config
)
if (deleted_data["privileged_users_deleted"] > 0) or (
deleted_data["credentials_deleted"] > 0
Expand All @@ -1142,7 +1155,7 @@ def delete_user_button_callback(self):
)
else:
pn.state.notifications.error(
f"User '{self.user_eraser.object.user}' does not exist",
f"User '{username_key_press}' does not exist",
duration=config.panel.notifications.duration,
)

Expand Down

0 comments on commit b065dd2

Please sign in to comment.