Add on-screen keyboard for feedback dialog

This commit is contained in:
Lance Edgar 2023-09-25 23:12:19 -05:00
parent 0767b81d0b
commit 78e6704639
2 changed files with 183 additions and 119 deletions

View file

@ -0,0 +1,153 @@
# -*- coding: utf-8; -*-
################################################################################
#
# WuttaPOS -- Pythonic Point of Sale System
# Copyright © 2023 Lance Edgar
#
# This file is part of WuttaPOS.
#
# WuttaPOS is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# WuttaPOS is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# WuttaPOS. If not, see <http://www.gnu.org/licenses/>.
#
################################################################################
"""
WuttaPOS - feedback control
"""
import flet as ft
from .base import WuttaControl
from .keyboard import WuttaKeyboard
class WuttaFeedback(WuttaControl):
default_font_size = 20
default_button_height = 60
def __init__(self, *args, **kwargs):
self.on_send = kwargs.pop('on_send', None)
self.on_cancel = kwargs.pop('on_cancel', None)
super().__init__(*args, **kwargs)
def build(self):
self.button = ft.Container(content=ft.Text("Feedback", size=self.default_font_size,
weight=ft.FontWeight.BOLD),
height=self.default_button_height,
width=self.default_button_height * 3,
on_click=self.initial_click,
alignment=ft.alignment.center,
border=ft.border.all(1, 'black'),
border_radius=ft.border_radius.all(5),
bgcolor='blue')
return self.button
def initial_click(self, e):
self.message = ft.TextField(label="Message",
multiline=True, min_lines=5,
autofocus=True)
self.dlg = ft.AlertDialog(
modal=True,
title=ft.Text("User Feedback"),
content=ft.Container(
content=ft.Column(
[
ft.Text("Questions, suggestions, comments, complaints, etc. "
"are welcome and may be submitted below. "),
ft.Divider(),
self.message,
ft.Divider(),
WuttaKeyboard(self.config, on_keypress=self.keypress),
],
expand=True,
),
height=800,
),
actions=[
ft.Row(
[
ft.Container(content=ft.Text("Send Message",
size=self.default_font_size,
color='black',
weight=ft.FontWeight.BOLD),
height=self.default_button_height,
width=self.default_button_height * 3,
alignment=ft.alignment.center,
bgcolor='blue',
border=ft.border.all(1, 'black'),
border_radius=ft.border_radius.all(5),
on_click=self.send_feedback),
ft.Container(content=ft.Text("Cancel",
size=self.default_font_size,
weight=ft.FontWeight.BOLD),
height=self.default_button_height,
width=self.default_button_height * 2.5,
alignment=ft.alignment.center,
border=ft.border.all(1, 'black'),
border_radius=ft.border_radius.all(5),
on_click=self.cancel),
],
alignment=ft.MainAxisAlignment.CENTER,
),
],
)
self.page.dialog = self.dlg
self.dlg.open = True
self.page.update()
def keypress(self, key):
if key == '':
self.message.value += '\n'
elif key == '':
self.message.value = self.message.value[:-1]
else:
self.message.value += key
self.message.focus()
self.update()
def cancel(self, e):
self.dlg.open = False
self.page.update()
if self.on_cancel:
self.on_cancel(e)
def send_feedback(self, e):
if self.message.value:
self.app.send_email('pos_feedback', data={
'user_name': self.page.session.get('user_display'),
'message': self.message.value,
})
self.dlg.open = False
self.page.snack_bar = ft.SnackBar(ft.Text(f"MESSAGE WAS SENT",
color='black',
weight=ft.FontWeight.BOLD),
bgcolor='green',
duration=1500)
self.page.snack_bar.open = True
self.page.update()
if self.on_send:
self.on_send()
else:
self.message.focus()
self.page.update()

View file

@ -32,6 +32,7 @@ import flet as ft
from .base import WuttaView from .base import WuttaView
from wuttapos.controls.custlookup import WuttaCustomerLookup from wuttapos.controls.custlookup import WuttaCustomerLookup
from wuttapos.controls.feedback import WuttaFeedback
from wuttapos.util import get_pos_batch_handler from wuttapos.util import get_pos_batch_handler
@ -66,6 +67,22 @@ class POSView(WuttaView):
def get_batch_handler(self): def get_batch_handler(self):
return get_pos_batch_handler(self.config) return get_pos_batch_handler(self.config)
def reset(self, e=None, update=True):
"""
This is a convenience method, meant only to clear the main
input and set focus to it. Will also update() the page
by default.
The ``e`` arg is ignored and accepted only so this method may
be registered as an event handler, e.g. ``on_cancel``.
"""
self.set_quantity.data = None
self.set_quantity.value = None
self.main_input.value = ''
self.main_input.focus()
if update:
self.page.update()
def set_customer(self, customer, batch=None): def set_customer(self, customer, batch=None):
session = self.app.get_session(customer) session = self.app.get_session(customer)
if not batch: if not batch:
@ -96,13 +113,11 @@ class POSView(WuttaView):
session.close() session.close()
dlg.open = False dlg.open = False
self.main_input.focus() self.reset()
self.page.update()
def cancel(e): def cancel(e):
dlg.open = False dlg.open = False
self.main_input.focus() self.reset()
self.page.update()
dlg = ft.AlertDialog( dlg = ft.AlertDialog(
modal=True, modal=True,
@ -144,9 +159,7 @@ class POSView(WuttaView):
def close(e): def close(e):
dlg.open = False dlg.open = False
self.main_input.value = '' self.reset()
self.main_input.focus()
self.page.update()
font_size = self.default_font_size * 0.8 font_size = self.default_font_size * 0.8
dlg = ft.AlertDialog( dlg = ft.AlertDialog(
@ -219,9 +232,7 @@ class POSView(WuttaView):
def cancel(e): def cancel(e):
dlg.open = False dlg.open = False
self.main_input.value = '' self.reset()
self.main_input.focus()
self.page.update()
font_size = self.default_font_size * 0.8 font_size = self.default_font_size * 0.8
dlg = ft.AlertDialog( dlg = ft.AlertDialog(
@ -291,21 +302,17 @@ class POSView(WuttaView):
self.informed_refresh() self.informed_refresh()
dlg.open = False dlg.open = False
self.main_input.value = ''
self.main_input.focus()
self.page.snack_bar = ft.SnackBar(ft.Text("CUSTOMER REMOVED", self.page.snack_bar = ft.SnackBar(ft.Text("CUSTOMER REMOVED",
color='black', color='black',
weight=ft.FontWeight.BOLD), weight=ft.FontWeight.BOLD),
bgcolor='yellow', bgcolor='yellow',
duration=1500) duration=1500)
self.page.snack_bar.open = True self.page.snack_bar.open = True
self.page.update() self.reset()
def cancel(e): def cancel(e):
dlg.open = False dlg.open = False
self.main_input.value = '' self.reset()
self.main_input.focus()
self.page.update()
font_size = self.default_font_size * 0.8 font_size = self.default_font_size * 0.8
dlg = ft.AlertDialog( dlg = ft.AlertDialog(
@ -344,9 +351,7 @@ class POSView(WuttaView):
if customer: if customer:
self.set_customer(customer) self.set_customer(customer)
self.main_input.value = '' self.reset()
self.main_input.focus()
self.page.update()
else: # customer not found else: # customer not found
self.page.snack_bar = ft.SnackBar(ft.Text(f"CUSTOMER NOT FOUND: {entry}", self.page.snack_bar = ft.SnackBar(ft.Text(f"CUSTOMER NOT FOUND: {entry}",
@ -355,6 +360,7 @@ class POSView(WuttaView):
bgcolor='yellow', bgcolor='yellow',
duration=1500) duration=1500)
self.page.snack_bar.open = True self.page.snack_bar.open = True
# TODO: should use reset() here?
self.main_input.focus() self.main_input.focus()
self.page.update() self.page.update()
@ -403,91 +409,6 @@ class POSView(WuttaView):
expand=1, expand=1,
) )
def feedback_click(e):
message = ft.TextField(label="Message",
multiline=True, min_lines=5,
autofocus=True)
def send_feedback(e):
if message.value:
self.app.send_email('pos_feedback', data={
'user_name': self.page.session.get('user_display'),
'message': message.value,
})
dlg.open = False
self.page.snack_bar = ft.SnackBar(ft.Text(f"MESSAGE WAS SENT",
color='black',
weight=ft.FontWeight.BOLD),
bgcolor='green',
duration=1500)
self.page.snack_bar.open = True
self.main_input.focus()
else:
message.focus()
self.page.update()
def cancel(e):
dlg.open = False
self.main_input.focus()
self.page.update()
button_height = self.default_button_size * 0.8
dlg = ft.AlertDialog(
modal=True,
title=ft.Text("User Feedback"),
content=ft.Container(
content=ft.Column(
[
ft.Text("Questions, suggestions, comments, complaints, etc. "
"are welcome and may be submitted below. "),
ft.Divider(),
message,
],
expand=True,
),
height=500,
),
actions=[
ft.Row(
[
ft.Container(content=ft.Text("Send Message",
size=self.default_font_size,
color='black',
weight=ft.FontWeight.BOLD),
height=button_height,
width=self.default_button_size * 3,
alignment=ft.alignment.center,
bgcolor='blue',
border=ft.border.all(1, 'black'),
border_radius=ft.border_radius.all(5),
on_click=send_feedback),
ft.Container(content=ft.Text("Cancel",
size=self.default_font_size,
weight=ft.FontWeight.BOLD),
height=button_height,
width=self.default_button_size * 2.5,
alignment=ft.alignment.center,
border=ft.border.all(1, 'black'),
border_radius=ft.border_radius.all(5),
on_click=cancel),
],
alignment=ft.MainAxisAlignment.CENTER,
),
],
)
self.page.dialog = dlg
dlg.open = True
self.page.update()
def tenkey_click(e): def tenkey_click(e):
value = e.control.content.value value = e.control.content.value
@ -720,8 +641,7 @@ class POSView(WuttaView):
ft.Row( ft.Row(
[ [
tenkey_button("Feedback", height=70, width=200, WuttaFeedback(self.config, on_send=self.reset, on_cancel=self.reset),
bgcolor='blue', on_click=feedback_click),
ft.Row( ft.Row(
[ [
self.set_quantity, self.set_quantity,
@ -848,14 +768,11 @@ class POSView(WuttaView):
session.close() session.close()
self.clear_all() self.clear_all()
self.main_input.value = '' self.reset()
self.main_input.focus()
self.page.update()
def cancel(e): def cancel(e):
dlg.open = False dlg.open = False
self.main_input.focus() self.reset()
self.page.update()
session = self.app.make_session() session = self.app.make_session()
batch = self.get_current_batch(session, create=False) batch = self.get_current_batch(session, create=False)
@ -924,8 +841,7 @@ class POSView(WuttaView):
session.close() session.close()
self.clear_all() self.clear_all()
self.main_input.focus() self.reset()
self.page.update()
def clear_all(self): def clear_all(self):
self.items.controls.clear() self.items.controls.clear()
@ -972,9 +888,4 @@ class POSView(WuttaView):
session.commit() session.commit()
session.close() session.close()
self.reset()
self.main_input.value = ""
self.main_input.focus()
self.set_quantity.data = None
self.set_quantity.value = None
self.page.update()