Skip to content

Commit 19191a8

Browse files
committed
Merge branch 'dev' into dev-feat-timesheets
2 parents 5b76230 + af1845c commit 19191a8

File tree

13 files changed

+465
-297
lines changed

13 files changed

+465
-297
lines changed

app/auth/view.py

Lines changed: 299 additions & 116 deletions
Large diffs are not rendered by default.

app/contracts/view.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ def on_save(self, e):
541541
self.show_snack(msg, isError)
542542
if not isError:
543543
# re route back
544-
self.on_navigate_back()
544+
self.navigate_back()
545545

546546
def build(self):
547547
"""Build the UI"""
@@ -630,7 +630,7 @@ def build(self):
630630
controls=[
631631
IconButton(
632632
icon=icons.CHEVRON_LEFT_ROUNDED,
633-
on_click=self.on_navigate_back,
633+
on_click=self.navigate_back,
634634
icon_size=dimens.ICON_SIZE,
635635
),
636636
self.form_title_ui_field,
@@ -965,7 +965,7 @@ def on_delete_confirmed(self, contract_id):
965965
self.show_snack(msg, is_err)
966966
if not is_err:
967967
# go back
968-
self.on_navigate_back()
968+
self.navigate_back()
969969

970970
def get_body_element(self, label, control):
971971
"""Returns a row with a label and a control."""
@@ -1060,7 +1060,7 @@ def build(self):
10601060
controls=[
10611061
IconButton(
10621062
icon=icons.KEYBOARD_ARROW_LEFT,
1063-
on_click=self.on_navigate_back,
1063+
on_click=self.navigate_back,
10641064
icon_size=dimens.ICON_SIZE,
10651065
),
10661066
TextButton(

app/core/abstractions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ def __init__(self, params: TuttleViewParams):
7474
self.vertical_alignment_in_parent = params.vertical_alignment_in_parent
7575
self.horizontal_alignment_in_parent = params.horizontal_alignment_in_parent
7676
self.keep_back_stack = params.keep_back_stack
77-
self.on_navigate_back = params.on_navigate_back
77+
self.navigate_back = params.on_navigate_back
7878
self.page_scroll_type = params.page_scroll_type
7979
self.upload_file_callback = params.upload_file_callback
8080
self.pick_file_callback = params.pick_file_callback

app/core/utils.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ def is_empty_str(txt: str) -> bool:
8787
return len(txt.strip()) == 0
8888

8989

90-
9190
def truncate_str(txt: str, max_chars: int = 25) -> str:
9291
if not txt:
9392
return ""
@@ -123,6 +122,12 @@ class TuttleComponentIcons(Enum):
123122
invoicing_selected_icon = icons.RECEIPT_ROUNDED
124123
datatable_icon = icons.TABLE_CHART
125124
datatable_selected_icon = icons.TABLE_CHART_ROUNDED
125+
profile_icon = icons.PERSON_OUTLINE
126+
profile_selected_icon = icons.PERSON_ROUNDED
127+
payment_icon = icons.PAYMENT
128+
payment_selected_icon = icons.PAYMENT_ROUNDED
129+
profile_photo_icon = icons.PHOTO_OUTLINED
130+
profile_photo_selected_icon = icons.PHOTO_ROUNDED
126131

127132
def __str__(self) -> str:
128133
return str(self.value)

app/core/views.py

Lines changed: 107 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,38 @@
11
import typing
22
from typing import Callable, List, Optional, Union
3-
3+
from dataclasses import dataclass
44
import datetime
55

6-
from flet import (AlertDialog,
7-
Column,
8-
Container,
9-
Dropdown,
10-
ElevatedButton,
11-
FilledButton,
12-
Icon,
13-
Image,
14-
PopupMenuButton,
15-
PopupMenuItem,
16-
ProgressBar,
17-
ResponsiveRow,
18-
Row,
19-
Text,
20-
TextField,
21-
TextStyle,
22-
UserControl,
23-
alignment,
24-
border_radius,
25-
dropdown,
26-
icons,
27-
padding,)
6+
from flet import (
7+
AlertDialog,
8+
Column,
9+
Container,
10+
Dropdown,
11+
ElevatedButton,
12+
FilledButton,
13+
Icon,
14+
Image,
15+
PopupMenuButton,
16+
PopupMenuItem,
17+
ProgressBar,
18+
margin,
19+
NavigationRail,
20+
Row,
21+
Text,
22+
TextField,
23+
TextStyle,
24+
UserControl,
25+
alignment,
26+
border_radius,
27+
dropdown,
28+
icons,
29+
padding,
30+
)
2831

2932
from res import colors, dimens, fonts, image_paths
3033

3134
from .abstractions import DialogHandler
32-
from .utils import (AUTO_SCROLL,
33-
CENTER_ALIGNMENT,
34-
CONTAIN,
35-
KEYBOARD_MULTILINE,
36-
KEYBOARD_NONE,
37-
KEYBOARD_PASSWORD,
38-
KEYBOARD_TEXT,
39-
SPACE_BETWEEN_ALIGNMENT,
40-
START_ALIGNMENT,
41-
TXT_ALIGN_CENTER,
42-
TXT_ALIGN_LEFT,
43-
AlertDialogControls,)
35+
from . import utils
4436

4537
lgSpace = Container(height=dimens.SPACE_LG, width=dimens.SPACE_STD, padding=0, margin=0)
4638
mdSpace = Container(height=dimens.SPACE_MD, width=dimens.SPACE_MD, padding=0, margin=0)
@@ -55,7 +47,7 @@ def get_heading(
5547
title: str = "",
5648
size: int = fonts.SUBTITLE_1_SIZE,
5749
color: Optional[str] = None,
58-
align: str = TXT_ALIGN_LEFT,
50+
align: str = utils.TXT_ALIGN_LEFT,
5951
show: bool = True,
6052
):
6153
"""Displays text formatted as a headline"""
@@ -74,7 +66,7 @@ def get_sub_heading_txt(
7466
subtitle: str = "",
7567
size: int = fonts.SUBTITLE_2_SIZE,
7668
color: Optional[str] = None,
77-
align: str = TXT_ALIGN_LEFT,
69+
align: str = utils.TXT_ALIGN_LEFT,
7870
show: bool = True,
7971
expand: bool = False,
8072
):
@@ -93,8 +85,8 @@ def get_sub_heading_txt(
9385
def get_heading_with_subheading(
9486
title: str,
9587
subtitle: str,
96-
alignment_in_container: str = START_ALIGNMENT,
97-
txt_alignment: str = TXT_ALIGN_LEFT,
88+
alignment_in_container: str = utils.START_ALIGNMENT,
89+
txt_alignment: str = utils.TXT_ALIGN_LEFT,
9890
title_size: int = fonts.SUBTITLE_1_SIZE,
9991
subtitle_size: int = fonts.SUBTITLE_2_SIZE,
10092
subtitle_color: Optional[str] = None,
@@ -125,7 +117,7 @@ def get_body_txt(
125117
color: Optional[str] = None,
126118
show: bool = True,
127119
col: Optional[dict] = None,
128-
align: str = TXT_ALIGN_LEFT,
120+
align: str = utils.TXT_ALIGN_LEFT,
129121
**kwargs,
130122
):
131123
"""Displays text standard-formatted for body"""
@@ -144,7 +136,7 @@ def get_std_txt_field(
144136
on_change: typing.Optional[Callable] = None,
145137
label: str = "",
146138
hint: str = "",
147-
keyboard_type: str = KEYBOARD_TEXT,
139+
keyboard_type: str = utils.KEYBOARD_TEXT,
148140
on_focus: typing.Optional[Callable] = None,
149141
initial_value: typing.Optional[str] = None,
150142
expand: typing.Optional[int] = None,
@@ -164,10 +156,10 @@ def get_std_txt_field(
164156
focused_border_width=1,
165157
on_focus=on_focus,
166158
on_change=on_change,
167-
password=keyboard_type == KEYBOARD_PASSWORD,
159+
password=keyboard_type == utils.KEYBOARD_PASSWORD,
168160
expand=expand,
169161
width=width,
170-
disabled=keyboard_type == KEYBOARD_NONE,
162+
disabled=keyboard_type == utils.KEYBOARD_NONE,
171163
text_size=fonts.BODY_1_SIZE,
172164
label_style=TextStyle(size=fonts.BODY_2_SIZE),
173165
error_style=TextStyle(size=fonts.BODY_2_SIZE, color=colors.ERROR_COLOR),
@@ -180,7 +172,7 @@ def get_std_multiline_field(
180172
label: str,
181173
hint: str,
182174
on_focus: typing.Optional[Callable] = None,
183-
keyboardType: str = KEYBOARD_MULTILINE,
175+
keyboardType: str = utils.KEYBOARD_MULTILINE,
184176
minLines: int = 3,
185177
maxLines: int = 5,
186178
):
@@ -244,29 +236,31 @@ def get_profile_photo_img(pic_src: str = image_paths.default_avatar):
244236
width=72,
245237
height=72,
246238
border_radius=border_radius.all(36),
247-
fit=CONTAIN,
239+
fit=utils.CONTAIN,
248240
)
249241

250242

251243
def get_image(path: str, semantic_label: str, width: int):
252244
return Container(
253245
width=width,
254-
content=Image(src=path, fit=CONTAIN, semantics_label=semantic_label),
246+
content=Image(src=path, fit=utils.CONTAIN, semantics_label=semantic_label),
255247
)
256248

257249

258250
def get_app_logo(width: int = 12):
259251
"""Returns app logo"""
260252
return Container(
261253
width=width,
262-
content=Image(src=image_paths.logoPath, fit=CONTAIN, semantics_label="logo"),
254+
content=Image(
255+
src=image_paths.logoPath, fit=utils.CONTAIN, semantics_label="logo"
256+
),
263257
)
264258

265259

266260
def get_labelled_logo():
267261
"""Returns app logo with app name next to it"""
268262
return Row(
269-
vertical_alignment=CENTER_ALIGNMENT,
263+
vertical_alignment=utils.CENTER_ALIGNMENT,
270264
controls=[
271265
get_app_logo(),
272266
get_heading(
@@ -494,7 +488,7 @@ class AlertDisplayPopUp(DialogHandler):
494488

495489
def __init__(
496490
self,
497-
dialog_controller: Callable[[any, AlertDialogControls], None],
491+
dialog_controller: Callable[[any, utils.AlertDialogControls], None],
498492
title: str,
499493
description: str,
500494
on_complete: Optional[Callable] = None,
@@ -507,7 +501,7 @@ def __init__(
507501
content=Container(
508502
height=pop_up_height,
509503
content=Column(
510-
scroll=AUTO_SCROLL,
504+
scroll=utils.AUTO_SCROLL,
511505
controls=[
512506
get_heading(
513507
title=title,
@@ -542,7 +536,7 @@ class ConfirmDisplayPopUp(DialogHandler):
542536

543537
def __init__(
544538
self,
545-
dialog_controller: Callable[[any, AlertDialogControls], None],
539+
dialog_controller: Callable[[any, utils.AlertDialogControls], None],
546540
title: str,
547541
description: str,
548542
data_on_confirmed: any,
@@ -557,7 +551,7 @@ def __init__(
557551
content=Container(
558552
height=pop_up_height,
559553
content=Column(
560-
scroll=AUTO_SCROLL,
554+
scroll=utils.AUTO_SCROLL,
561555
controls=[
562556
get_heading(
563557
title=title,
@@ -675,8 +669,10 @@ def get_or_txt(show_lines: Optional[bool] = True, show: bool = True):
675669
"""Returns a view representing ---- OR ----"""
676670
return Row(
677671
visible=show,
678-
alignment=SPACE_BETWEEN_ALIGNMENT if show_lines else CENTER_ALIGNMENT,
679-
vertical_alignment=CENTER_ALIGNMENT,
672+
alignment=utils.SPACE_BETWEEN_ALIGNMENT
673+
if show_lines
674+
else utils.CENTER_ALIGNMENT,
675+
vertical_alignment=utils.CENTER_ALIGNMENT,
680676
controls=[
681677
Container(
682678
height=2,
@@ -685,7 +681,7 @@ def get_or_txt(show_lines: Optional[bool] = True, show: bool = True):
685681
alignment=alignment.center,
686682
visible=show_lines,
687683
),
688-
get_body_txt("OR", align=TXT_ALIGN_CENTER, color=colors.GRAY_COLOR),
684+
get_body_txt("OR", align=utils.TXT_ALIGN_CENTER, color=colors.GRAY_COLOR),
689685
Container(
690686
height=2,
691687
bgcolor=colors.GRAY_COLOR,
@@ -695,3 +691,59 @@ def get_or_txt(show_lines: Optional[bool] = True, show: bool = True):
695691
),
696692
],
697693
)
694+
695+
696+
@dataclass
697+
class NavigationMenuItem:
698+
"""defines a menu item used in navigation rails"""
699+
700+
index: int
701+
label: str
702+
icon: str
703+
selected_icon: str
704+
destination: UserControl
705+
on_new_screen_route: Optional[str] = None
706+
on_new_intent: Optional[str] = None
707+
708+
709+
def get_std_navigation_menu(
710+
title: str,
711+
on_change,
712+
selected_index: Optional[int] = 0,
713+
destinations=[],
714+
menu_height: int = 300,
715+
width: int = int(dimens.MIN_WINDOW_WIDTH * 0.3),
716+
left_padding: int = dimens.SPACE_STD,
717+
top_margin: int = dimens.SPACE_STD,
718+
):
719+
"""
720+
Returns a navigation menu for the application.
721+
722+
:param title: Title of the navigation menu.
723+
:param on_change: Callable function to be called when the selected item in the menu changes.
724+
:param selected_index: The index of the selected item in the menu.
725+
:param destinations: List of destinations in the menu.
726+
:param menu_height: The height of the menu.
727+
:return: A NavigationRail widget containing the navigation menu.
728+
"""
729+
return NavigationRail(
730+
leading=Container(
731+
content=get_sub_heading_txt(
732+
subtitle=title,
733+
align=utils.START_ALIGNMENT,
734+
expand=True,
735+
color=colors.GRAY_DARK_COLOR,
736+
),
737+
expand=True,
738+
width=width,
739+
margin=margin.only(top=top_margin),
740+
padding=padding.only(left=left_padding),
741+
),
742+
selected_index=selected_index,
743+
min_width=utils.COMPACT_RAIL_WIDTH,
744+
extended=True,
745+
height=menu_height,
746+
min_extended_width=width,
747+
destinations=destinations,
748+
on_change=on_change,
749+
)

app/error_views/page_not_found_screen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def build(self):
2323
controls=[
2424
get_error_txt("OOps! Looks like you took a wrong turn"),
2525
get_primary_btn(
26-
label="Go Back".upper(), on_click=self.on_navigate_back
26+
label="Go Back".upper(), on_click=self.navigate_back
2727
),
2828
],
2929
),

app/home/intent.py

Lines changed: 0 additions & 20 deletions
This file was deleted.

0 commit comments

Comments
 (0)