-
Presently our web app is pretty much open to everyone. Even if you are not logged in, you can view the Home, Add and Calendar pages. Although these pages don't hold sensitive private information, the functionality of these pages depend up a user being logged in:
- HomeComponent → displays the user's assessment
- CalendarComponent → displays the user's assessment timeline
- AddComponent → adds the user's assessment details
This means that if there is no user logged in, then these components will not function correctly. In this tutorial, we will fix that problem.
For the AddComponent and the CalendarComponent we will add a second card with and error message. Then, when the component is loaded, either the default card or the error card will be displayed.
When it comes to home we will choose between loading the HomeComponent or the WelcomeComponent, depending upon the user login status.
Open the AddComponent in Design mode.
- Choose the current card
- Change it's name from self.card_1 to self.card_details
- Add a new card between self.card_details and self.label_message (pay close attention to the brown lines)
- Name the new card self.card_error
- Add a label to the self.card_error
- Change the text to
Please login to access this feature - Change foreground to
#ff0000 - Change role to your desired formatting
- Change icon to
fa:warning - Change align to
center
We haven't added anything to the CalendarComponent, so we will need to add two cards:
- call the first one self.card_details
- call the second one self.card_error
Leave self.card_details blank, and then change self.card_error to be the same as AddComponent.
We don't have to change the layout of the HomeComponent as we will simply load the WelcomeComponent instead. We will worry about the welcomeComponent layout later on.
The AddComponent code will simply check if someone is logged in and adjust the visibility of self.card_details and self.card_error accordingly.
Open AddComponent in Code mode.
In the __init__ method add the highlighted code:
:linenos:
:lineno-start: 11
:emphasize-lines: 11 - 18
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
self.subject = ""
self.details = ""
self.start = None
self.due = None
# Any code you write here will run before the form opens.
self.label_message.visible = False
if anvil.users.get_user():
self.card_details.visible = True
self.card_error.visible = False
self.button_add.visible = True
else:
self.card_details.visible = False
self.card_error.visible = True
self.button_add.visible = False
:class: notice
- **line 21** → checks if there is a user currently logged in
- **lines 22 - 24** → sets the UI to display the elements appropriate for a logged in user
- **lines 26 - 28** → sets the UI to display the elements appropriate for no logged in user
Use the same logic to display the correct elements in the CalendarComponent.
In CalendarComponents __init__ method, add the code below:
:linenos:
:lineno-start: 11
:emphasize-lines: 6 - 11
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# Any code you write here will run before the form opens.
if anvil.users.get_user():
self.card_details.visible = True
self.card_error.visible = False
else:
self.card_details.visible = False
self.card_error.visible = True
The Home page code is trickier, since it involves two components. Luckily we have centralised all component loading into the switch_component method in the MainForm. We can check for user status there and load the HomeComponent is a user is logged in or load the WelcomeComponent if there is no user logged in.
Open the MainForm in Code mode.
First, if we are going to load the WelcomeComponent, we need to import it. Add the highlighted code to the import statement.
:linenos:
:lineno-start: 1
:emphasize-lines: 13
from ._anvil_designer import MainFormTemplate
from anvil import *
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
from ..HomeComponent import HomeComponent
from ..CalendarComponent import CalendarComponent
from ..AddComponent import AddComponent
from ..AccountComponent import AccountComponent
from ..SetDetailsComponent import SetDetailsComponent
from ..WelcomeComponent import WelcomeComponent
Now in the switch_component method add the following code:
:linenos:
:lineno-start: 25
:emphasize-lines: 4-7
def switch_component(self, state):
# set state
if state == "home":
if anvil.users.get_user():
cmpt = HomeComponent()
else:
cmpt = WelcomeComponent()
breadcrumb = self.breadcrumb_stem
- line 27 → note this code is only executed when the home page is being loaded
- line 28 → checks if there is a user currently logged in
- line 29 → loads the HomeComponent
- line 30 & 31 → loads the WelcomeComponent is no user is logged in
Launch your website. Your should be logged in. Make sure that you can access all three of the pages we have worked on:
- Home
- Add
- Calendar
Then logout and check all three pages again.
By the end of this tutorial your code should be the same as below:
:linenos:
from ._anvil_designer import MainFormTemplate
from anvil import *
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
from ..HomeComponent import HomeComponent
from ..CalendarComponent import CalendarComponent
from ..AddComponent import AddComponent
from ..AccountComponent import AccountComponent
from ..SetDetailsComponent import SetDetailsComponent
from ..WelcomeComponent import WelcomeComponent
class MainForm(MainFormTemplate):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
self.breadcrumb_stem = self.label_title.text
# Any code you write here will run before the form opens.
self.switch_component("home")
def switch_component(self, state):
# set state
if state == "home":
if anvil.users.get_user():
cmpt = HomeComponent()
else:
cmpt = WelcomeComponent()
breadcrumb = self.breadcrumb_stem
elif state == "account":
cmpt = AccountComponent()
breadcrumb = self.breadcrumb_stem + " - Account"
elif state == "add":
cmpt = AddComponent()
breadcrumb = self.breadcrumb_stem + " - Add"
elif state == "calendar":
cmpt = CalendarComponent()
breadcrumb = self.breadcrumb_stem + " - Calendar"
elif state == "details":
cmpt = SetDetailsComponent()
breadcrumb = self.breadcrumb_stem + " - Account - Set Details"
# execution
self.content_panel.clear()
self.content_panel.add_component(cmpt)
self.label_title.text = breadcrumb
self.set_active_link(state)
def set_active_link(self, state):
if state == "home":
self.link_home.role = "selected"
else:
self.link_home.role = None
if state == "add":
self.link_add.role = "selected"
else:
self.link_add.role = None
if state == "calendar":
self.link_calendar.role = "selected"
else:
self.link_calendar.role = None
self.link_register.visible = not anvil.users.get_user()
self.link_login.visible = not anvil.users.get_user()
self.link_account.visible = anvil.users.get_user()
self.link_logout.visible = anvil.users.get_user()
# --- link handlers
def link_home_click(self, **event_args):
self.switch_component("home")
def link_calendar_click(self, **event_args):
self.switch_component("calendar")
def link_add_click(self, **event_args):
self.switch_component("add")
def link_account_click(self, **event_args):
"""This method is called when the link is clicked"""
self.switch_component("account")
def link_register_click(self, **event_args):
anvil.users.signup_with_form(allow_cancel=True)
self.switch_component("details")
def link_login_click(self, **event_args):
anvil.users.login_with_form(allow_cancel=True)
self.switch_component("home")
def link_logout_click(self, **event_args):
anvil.users.logout()
self.switch_component("home")
:linenos:
from ._anvil_designer import AddComponentTemplate
from anvil import *
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
class AddComponent(AddComponentTemplate):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
self.subject = ""
self.details = ""
self.start = None
self.due = None
# Any code you write here will run before the form opens.
self.label_message.visible = False
if anvil.users.get_user():
self.card_details.visible = True
self.card_error.visible = False
self.button_add.visible = True
else:
self.card_details.visible = False
self.card_error.visible = True
self.button_add.visible = False
def button_add_click(self, **event_args):
# validation
if not self.text_box_subject.text:
self.display_error("Subject name needed")
elif not self.text_box_details.text:
self.display_error("Assessment details needed")
elif not self.date_picker_start.date:
self.display_error("Start date needed")
elif not self.date_picker_due.date:
self.display_error("Due date needed")
else:
self.subject = self.text_box_subject.text
self.details = self.text_box_details.text
self.start = self.date_picker_start.date
self.due = self.date_picker_due.date
self.display_save(f"{self.subject} {self.details} assessment: {self.start} to {self.due} recorded")
anvil.server.call('add_assessment', self.subject, self.details, self.start, self.due)
self.reset_form()
def display_error(self, message):
self.label_message.visible = True
self.label_message.foreground = "#ff0000"
self.label_message.icon = "fa:exclamation-triangle"
self.label_message.bold = True
self.label_message.text = message
def display_save(self, message):
self.label_message.visible = True
self.label_message.foreground = "#000000"
self.label_message.icon = "fa:save"
self.label_message.bold = False
self.label_message.text = message
def reset_form(self):
self.subject = ""
self.details = ""
self.start = None
self.due = None
self.text_box_subject.text = ""
self.text_box_details.text = ""
self.date_picker_start.date = None
self.date_picker_due.date = None
:linenos:
from ._anvil_designer import CalendarComponentTemplate
from anvil import *
import anvil.server
import anvil.tables as tables
import anvil.tables.query as q
from anvil.tables import app_tables
import anvil.users
class CalendarComponent(CalendarComponentTemplate):
def __init__(self, **properties):
# Set Form properties and Data Bindings.
self.init_components(**properties)
# Any code you write here will run before the form opens.
if anvil.users.get_user():
self.card_details.visible = True
self.card_error.visible = False
else:
self.card_details.visible = False
self.card_error.visible = True




