Add on-screen keyboard for feedback dialog
This commit is contained in:
		
							parent
							
								
									0767b81d0b
								
							
						
					
					
						commit
						78e6704639
					
				
					 2 changed files with 183 additions and 119 deletions
				
			
		
							
								
								
									
										153
									
								
								wuttapos/controls/feedback.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								wuttapos/controls/feedback.py
									
										
									
									
									
										Normal 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() | ||||
|  | @ -32,6 +32,7 @@ import flet as ft | |||
| 
 | ||||
| from .base import WuttaView | ||||
| from wuttapos.controls.custlookup import WuttaCustomerLookup | ||||
| from wuttapos.controls.feedback import WuttaFeedback | ||||
| from wuttapos.util import get_pos_batch_handler | ||||
| 
 | ||||
| 
 | ||||
|  | @ -66,6 +67,22 @@ class POSView(WuttaView): | |||
|     def get_batch_handler(self): | ||||
|         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): | ||||
|         session = self.app.get_session(customer) | ||||
|         if not batch: | ||||
|  | @ -96,13 +113,11 @@ class POSView(WuttaView): | |||
|             session.close() | ||||
| 
 | ||||
|             dlg.open = False | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         def cancel(e): | ||||
|             dlg.open = False | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         dlg = ft.AlertDialog( | ||||
|             modal=True, | ||||
|  | @ -144,9 +159,7 @@ class POSView(WuttaView): | |||
| 
 | ||||
|         def close(e): | ||||
|             dlg.open = False | ||||
|             self.main_input.value = '' | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         font_size = self.default_font_size * 0.8 | ||||
|         dlg = ft.AlertDialog( | ||||
|  | @ -219,9 +232,7 @@ class POSView(WuttaView): | |||
| 
 | ||||
|         def cancel(e): | ||||
|             dlg.open = False | ||||
|             self.main_input.value = '' | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         font_size = self.default_font_size * 0.8 | ||||
|         dlg = ft.AlertDialog( | ||||
|  | @ -291,21 +302,17 @@ class POSView(WuttaView): | |||
|             self.informed_refresh() | ||||
| 
 | ||||
|             dlg.open = False | ||||
|             self.main_input.value = '' | ||||
|             self.main_input.focus() | ||||
|             self.page.snack_bar = ft.SnackBar(ft.Text("CUSTOMER REMOVED", | ||||
|                                                       color='black', | ||||
|                                                       weight=ft.FontWeight.BOLD), | ||||
|                                               bgcolor='yellow', | ||||
|                                               duration=1500) | ||||
|             self.page.snack_bar.open = True | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         def cancel(e): | ||||
|             dlg.open = False | ||||
|             self.main_input.value = '' | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         font_size = self.default_font_size * 0.8 | ||||
|         dlg = ft.AlertDialog( | ||||
|  | @ -344,9 +351,7 @@ class POSView(WuttaView): | |||
|         if customer: | ||||
| 
 | ||||
|             self.set_customer(customer) | ||||
|             self.main_input.value = '' | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         else: # customer not found | ||||
|             self.page.snack_bar = ft.SnackBar(ft.Text(f"CUSTOMER NOT FOUND: {entry}", | ||||
|  | @ -355,6 +360,7 @@ class POSView(WuttaView): | |||
|                                               bgcolor='yellow', | ||||
|                                               duration=1500) | ||||
|             self.page.snack_bar.open = True | ||||
|             # TODO: should use reset() here? | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
| 
 | ||||
|  | @ -403,91 +409,6 @@ class POSView(WuttaView): | |||
|             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): | ||||
|             value = e.control.content.value | ||||
| 
 | ||||
|  | @ -720,8 +641,7 @@ class POSView(WuttaView): | |||
| 
 | ||||
|             ft.Row( | ||||
|                 [ | ||||
|                     tenkey_button("Feedback", height=70, width=200, | ||||
|                                   bgcolor='blue', on_click=feedback_click), | ||||
|                     WuttaFeedback(self.config, on_send=self.reset, on_cancel=self.reset), | ||||
|                     ft.Row( | ||||
|                         [ | ||||
|                             self.set_quantity, | ||||
|  | @ -848,14 +768,11 @@ class POSView(WuttaView): | |||
|             session.close() | ||||
| 
 | ||||
|             self.clear_all() | ||||
|             self.main_input.value = '' | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         def cancel(e): | ||||
|             dlg.open = False | ||||
|             self.main_input.focus() | ||||
|             self.page.update() | ||||
|             self.reset() | ||||
| 
 | ||||
|         session = self.app.make_session() | ||||
|         batch = self.get_current_batch(session, create=False) | ||||
|  | @ -924,8 +841,7 @@ class POSView(WuttaView): | |||
|         session.close() | ||||
| 
 | ||||
|         self.clear_all() | ||||
|         self.main_input.focus() | ||||
|         self.page.update() | ||||
|         self.reset() | ||||
| 
 | ||||
|     def clear_all(self): | ||||
|         self.items.controls.clear() | ||||
|  | @ -972,9 +888,4 @@ class POSView(WuttaView): | |||
| 
 | ||||
|         session.commit() | ||||
|         session.close() | ||||
| 
 | ||||
|         self.main_input.value = "" | ||||
|         self.main_input.focus() | ||||
|         self.set_quantity.data = None | ||||
|         self.set_quantity.value = None | ||||
|         self.page.update() | ||||
|         self.reset() | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Lance Edgar
						Lance Edgar