diff --git a/src/justgetit/app.py b/src/justgetit/app.py index 99e1f93..da60c91 100644 --- a/src/justgetit/app.py +++ b/src/justgetit/app.py @@ -8,6 +8,7 @@ from justgetit.configuration import Configuration from justgetit.providekey import ProvideKey from justgetit.lists import Lists from justgetit.backend import BackEnd +from justgetit.localdata import LocalData class JustEatIt(toga.App): login_screen = toga.Box() @@ -34,6 +35,7 @@ class JustEatIt(toga.App): def startup(self): self.configuration = Configuration(self) + self.data = LocalData(self) self.login_screen = Login() self.register_screen = Register() @@ -58,10 +60,11 @@ class JustEatIt(toga.App): # Initial layout clamp self.on_resize(self.main_window) - def set_page(self, page): + def set_page(self, page): if self.last_screen_width > 0: page.set_screen_width(self.last_screen_width) self.main_window.content = page + page.on_show() def on_resize(self, widget, **kwargs): width = self.main_window.size.width diff --git a/src/justgetit/backend.py b/src/justgetit/backend.py index 12ef4ca..e8ba4b1 100644 --- a/src/justgetit/backend.py +++ b/src/justgetit/backend.py @@ -1,9 +1,7 @@ from justgetit.constants import * import httpx -import json import toga - class BackEnd(): """ This is the interface for the backend. @@ -32,7 +30,6 @@ class BackEnd(): response = await client.post(f"{API}/{endpoint}", data=parameters) self.payload = response.json() self.status = int(self.payload['status']) - print(f" payload {self.payload}") except httpx.RequestError as exc: self.status = -2 @@ -50,3 +47,24 @@ class BackEnd(): callback(parameters, self.payload) + def postwait(self, endpoint, parameters): + """ + Call the server, always with a POST, for a specific endpoint and the parameters + in the body + + :param endpoint: the endpoint without /api/ (no slashes) + :param parameters: A dict with the parameters for the call + :param callback: def in the calling function to return to + """ + self.status = 0 + self.payload = None + if len(endpoint)>2: + try: + response = httpx.post(f"{API}/{endpoint}", data=parameters) + self.payload = response.json() + self.status = int(self.payload['status']) + except httpx.RequestError as exc: + self.status = -2 + + return self.payload + \ No newline at end of file diff --git a/src/justgetit/basepage.py b/src/justgetit/basepage.py index 5721041..5487c34 100644 --- a/src/justgetit/basepage.py +++ b/src/justgetit/basepage.py @@ -65,7 +65,7 @@ class BasePage(toga.Box): justify_content=START, margin=24, flex=1, - background_color="yellow" + # background_color="yellow" ) ) @@ -136,6 +136,9 @@ class BasePage(toga.Box): if w>0: self.content_box.style.width = w + def on_show(self): + print("new page shown") + async def display_warning(self, message): self.warningtext.text = message self.warning_box = self.warningline_outer diff --git a/src/justgetit/configuration.py b/src/justgetit/configuration.py index 6e88dd7..f08479d 100644 --- a/src/justgetit/configuration.py +++ b/src/justgetit/configuration.py @@ -8,8 +8,7 @@ class Configuration(): This class holds persistent configuration: - appkey: the app key, alowing traffic with the backend - last_key_validation_date: last date the appkey was validated, should be no more than a week ago otherwise the app will not run - - username: the user name - - userpwd: the users pwd + - user: the user as a dict - userlang: the users language - lastlogin_date: date of last sucessful login """ @@ -39,7 +38,6 @@ class Configuration(): def has_valid_app_key(self): return True if 'appkey' in self.data: - print("found app key {self.data['appkey']}") today = datetime.date.today() last_month = today - datetime.timedelta(days=30) if self.data['last_key_validation_date'] > last_month: @@ -53,9 +51,9 @@ class Configuration(): self.save() def user_is_logged_in(self): - return True - if 'username' in self.data: - print("found user {self.data['username']}") + # return True + if 'user' in self.data: + print(f"found user {self.data['user']['name']}") today = datetime.date.today() last_week = today - datetime.timedelta(days=7) if self.data['lastlogin_date'] > last_week: @@ -63,9 +61,8 @@ class Configuration(): return True return False - def store_login(self, user, pwd): - self.data['username'] = user - self.data['userpwd'] = pwd + def store_login(self, user_dict): + self.data['user'] = user_dict self.data['lastlogin_date'] = datetime.date.today() self.save() @@ -75,7 +72,13 @@ class Configuration(): self.data['lastlogin_date'] = today def logout_user(self): - self.data.pop('username', None) - self.data.pop('userpwd', None) + self.data.pop('user', None) self.data.pop('lastlogin_date', None) - self.save() \ No newline at end of file + self.save() + + def get_userid(self): + result = 0 + if 'user' in self.data: + print() + result = self.data['user']['id'] + return result \ No newline at end of file diff --git a/src/justgetit/images/logo.png b/src/justgetit/images/logo.png new file mode 100644 index 0000000..6d3ca32 Binary files /dev/null and b/src/justgetit/images/logo.png differ diff --git a/src/justgetit/lists.py b/src/justgetit/lists.py index 9fd1955..4e9e486 100644 --- a/src/justgetit/lists.py +++ b/src/justgetit/lists.py @@ -1,11 +1,90 @@ import toga from toga.style import Pack from toga.style.pack import COLUMN, ROW, END, START, CENTER, HIDDEN, JUSTIFY -# from justgetit.constants import SCREENHEIGHT, SCREENWIDTH -import asyncio +from toga.sources import ListSource, Listener +import datetime from justgetit.constants import * from justgetit.basepage import BasePage +class DatabaseList(toga.Box): + def __init__(self, id=None, style=None, children=None, **kwargs): + style.direction = COLUMN + super().__init__(id, style, children, **kwargs) + self.data = ListSource( + accessors=["id", "owner_user_id", "name", "is_active"] + ) + self.data.add_listener(DatabaseList.DataListener(self)) + + class DataListener(Listener): + # listen to the database + def __init__(self, parent_widget): + print("widget: data-item init") + self.parent_widget = parent_widget + super().__init__() + + def change(self, item): + print("widget: data-item change") + return super().change(item) + + def clear(self): + print("widget: data-item clear") + return super().clear() + + def insert(self, index, item): + print("widget: data-item insert") + self.parent_widget.add(self.create_row(item.name,"3", "20")) + return super().insert(index, item) + + def remove(self, index, item): + print("widget: data-item remove") + return super().remove(index, item) + + def create_row(self, text, openitems, totalitems): + label = toga.Button( + text=text, + margin_bottom=2, + style = Pack( + # margin_bottom=2, # scrollig doesnt work, bug?, replaced by margin_bottom in Button + # width=250, + flex=15, + background_color="white", #white + font_size=15 + ) + ) + spacer = toga.Box( + style = Pack( + flex=1 + ) + ) + indicator = toga.Label( + text = f"{openitems} / {totalitems}", + style = Pack( + color="blue", + margin=8, + flex=2 + ) + ) + listrow_inner = toga.Box( + style = Pack( + margin_bottom=1, + flex=1, + background_color="white", #white + ) + ) + listrow_inner.add(label) + listrow_inner.add(spacer) + listrow_inner.add(indicator) + + listrow_outer = toga.Box( + style = Pack( + # flex=1, + background_color="#ccc", # ccc + ) + ) + listrow_outer.add(listrow_inner) + + return(listrow_outer) + class Lists(BasePage): @@ -19,6 +98,7 @@ class Lists(BasePage): :param args: args for super :param kwargs: kwars for super """ + # set button and image self.first_menu_button_icon = 'edit3' self.first_menu_button_callback = self.edit_button_pressed @@ -28,14 +108,17 @@ class Lists(BasePage): super().__init__(*args, **kwargs) # here the list of lists - listholder = toga.Column( + self.listholder = DatabaseList( style=Pack( margin_bottom=10, - background_color="#aaa", + # background_color="white", ) ) + + + scrollarea = toga.ScrollContainer( - content=listholder, + content=self.listholder, style=Pack( flex=1, margin=10, @@ -45,8 +128,8 @@ class Lists(BasePage): - for i in range(30): - listholder.add(self.create_row("Supermarkt",f"{i}","30")) + # for i in range(30): + # listholder.add(self.create_row("Supermarkt",f"{i}","30")) @@ -75,6 +158,15 @@ class Lists(BasePage): self.content_box.add(scrollarea) # self.content_box.add(save_button_box) + def on_show(self): + super().on_show() + self.listholder.data.clear() + for l in self.app.data.reload_list(): + print(type(l)) + self.listholder.data.append(l) + + # self.listholder.data.data = self.app.data.reload_list() + def edit_button_pressed(self): self.app.goto_next_page_by_name(PAGE_EDITLISTS) diff --git a/src/justgetit/localdata.py b/src/justgetit/localdata.py new file mode 100644 index 0000000..bc544f2 --- /dev/null +++ b/src/justgetit/localdata.py @@ -0,0 +1,66 @@ +import datetime +import asyncio + +class ListOfLists(): + def __init__(self, app): + self.app = app + # self.listento = widget_to_listen_to + self.data = [] + # self.widget_data = list_source_object + # self.reload() + + # self.widget_data.append({"name": "ToDo", "id": 3, "owner_user_id": 3, "is_active": True, "updated_at": datetime.datetime.now() }) + + def reload(self, userid): + parameters = {} + parameters['userid'] = userid + result = self.app.backend.postwait('load_lists', parameters) + return result['data'] + + + def on_reloaded(self, bla): + print("reloaded") + + def clear(self): + self.data = [] + + + +class List(): + id = 0 + updated_at = None + owner_user_id = 0 + name = '' + is_active = True + + +class Item(): + id = 0 + updated_at = None + listofitems_id = 0 + label = '' + quantity = 0 + unit = '' + label_alt1 = '' + label_alt2 = '' + is_checked = False + is_suggestion = False + category = '' + +class LocalData(): + def __init__(self, app): + self.app = app + self.curent_userid = 0 + self.current_listid = 0 + self.lists = ListOfLists(app) + + def set_user(self, userid): + if userid != self.curent_userid: + self.lists.clear() + self.curent_userid = userid + + def reload_list(self): + self.curent_userid = self.app.configuration.get_userid() + if self.curent_userid > 0: + return self.lists.reload(self.curent_userid) + \ No newline at end of file diff --git a/src/justgetit/localmodel.py b/src/justgetit/localmodel.py deleted file mode 100644 index 8294e7f..0000000 --- a/src/justgetit/localmodel.py +++ /dev/null @@ -1,22 +0,0 @@ - - -class ListItems(): - id = 0 - updated_at = None - owner_user_id = 0 - name = '' - is_active = True - - -class Item(): - id = 0 - updated_at = db.Column(db.TIMESTAMP, default=datetime.now(), onupdate=datetime.now(), nullable=False) - listofitems_id = db.Column(db.Integer, nullable=False) - label = db.Column(db.String(40), nullable=False) - quantity = db.Column(db.Integer, default=0) - unit = db.Column(db.String(10)) - label_alt1 = db.Column(db.String(40)) - label_alt2 = db.Column(db.String(40)) - is_checked = db.Column(db.Boolean, default=False) - is_suggestion = db.Column(db.Boolean, default=False) - category = db.Column(db.String(20)) \ No newline at end of file diff --git a/src/justgetit/login.py b/src/justgetit/login.py index 7422c7e..fa6422b 100644 --- a/src/justgetit/login.py +++ b/src/justgetit/login.py @@ -60,7 +60,6 @@ class Login(BasePage): ) ) - # wrapping up the windows elements self.content_box.add(self.name_input) self.content_box.add(self.password_input) @@ -82,7 +81,8 @@ class Login(BasePage): def after_backend_login(self, parameters, return_data): if return_data['status'] > 0: # store login etc in config - self.app.configuration.store_login(parameters['user'], parameters['password']) + self.app.configuration.store_login(return_data['data']) + print(return_data) # goto lists screen self.app.goto_next_page_by_name(PAGE_LISTS) diff --git a/src/justgetit/test_source.py b/src/justgetit/test_source.py new file mode 100644 index 0000000..3119735 --- /dev/null +++ b/src/justgetit/test_source.py @@ -0,0 +1,59 @@ +from toga.sources import ListSource, Listener +import datetime + + +class Ear(Listener): + + def __init__(self): + print("ear init") + super().__init__() + + def change(self, item): + print("ear change") + return super().change(item) + + def clear(self): + print("ear clear") + return super().clear(item) + + def insert(self, index, item): + print("ear insert") + return super().insert(index, item) + + def remove(self, index, item): + print("ear remove") + return super().remove(index, item) + + + + + +source = ListSource( + accessors=["id", "updated_at", "owner_user_id", "name", "is_active"], + data=[ + {"name": "Super", "id": 2, "owner_user_id": 3, "is_active": True, "updated_at": datetime.datetime.now() }, + + ] +) + +e = Ear() +source.add_listener(e) + + +# Get the first item in the source +item = source[0] +print(f"Animal's name is {item.name}") +print(item) +item.name = "more super" +print(item) + +# Find an item with a name of "Thylacine" +# item = source.find({"name": "Super"}) + +# Remove that item from the data +source.remove(item) + +# Insert a new item at the start of the data +# source.insert(0, {"name": "Bettong", "weight": 1.2}) + +source.append({"name": "ToDo", "id": 3, "owner_user_id": 3, "is_active": True, "updated_at": datetime.datetime.now() })