This guide is intended for developers participating in the Flutter Dev Contest 2023 Edition.
The guide contains step-by-step instructions to build, deploy and test the backend of the app to be submitted, including a ready-to-use Livebase engine model as a starting point, and a compatible dataset for testing.
Ready to start? It should take less than an hour. Feel free to contact us at support@livebase.com if you need help.
1. Get on board the Livebase platform #
Since the backend application has to be developed on the Livebase platform, you’ll have to first create an account and setup the modeling environment on a Cloudlet. The next steps will guide you through the account activation process.
1.1 Create a free evaluation account #
Go to the Request a free evaluation account
page on our website (under the Dev Resources menu). The form shown on the right will appear in your browser. Fill in the form and press the Send request button.Shortly after, you will receive a confirmation email similar to the one shown beside. The email will include as attachments the terms and conditions for using the Livebase platform.
Click on the link to navigate to the account activation page.
On the account activation page, fill in the form and press the Activate account button.
If the account activation is successful, the message shown beside will be displayed.
1.2 Install the Dashboard #
Select your operating system, then click on the corresponding download link and follow the installation procedure:
For Microsoft Windows, download LivebaseDashboard.exe and launch it.
For Mac OS, download LivebaseDashboard.dmg and launch it.
For Linux Debian, download LivebaseDashboard.deb and launch it.
For other Linux distributions, download LivebaseDashboard.tar.gz and run the following commands on the console:
tar xvfz LivebaseDashboardf.tar.gz
cd LivebaseDashboard
./Dashboard
1.3 Log into the Dashboard #
Launch the Dashboard and then log in using your credentials.
The Dashboard is a desktop client connected to the Livebase Cloud Services, providing a user interface to control and operate all other components of the Livebase platform. This light-weight control panel allows developers to create and manage their Cloudlets across their entire lifecycle (creation, start/stop and deletion).
Once logged in, the Dashboard appears as shown:
the Engine models tab (on the left) contains a versioned repository named Library, that you can use to archive, retrieve and reuse your engine models.
the Cloudlets tab (on the right) allows you to manage all your Cloudlets. The tab contains a control panel for each Cloudlet.
2. Use Livebase to create the backend of your Flutter app #
2.1 Create a Cloudlet #
Cloudlets are headless server components providing advanced (business-level) transactional data services via a secure GraphQL API. Cloudlets are generated and deployed by Livebase starting from high-level conceptual models (engine models) without coding.
To create your first Cloudlet, click on the + New cloudlet button at the bottom right of the Cloudlets tab. The creation process will take about five minutes. A panel will then appear in the Cloudlets section of the Dashboard, allowing you to manage the Cloudlet you’ve just created.
A Cloudlet panel is divided into three sections:
the top section displays the name and the URL address of the Cloudlet;
the middle section displays three icons that provide information and access to the key components of the Cloudlet, namely the list of its members (i.e. the users allowed to invoke the Cloudlet API), the engine and the database.
the bottom section displays the status of the Cloudlet (e.g. Running or Stopped). At the moment, you cannot start your Cloudlet because it has no engine yet, and therefore the Cloudlet status is Cannot start (missing engine). By clicking on the icon, a drop-down menu appears, giving you access to the Cloudlet settings and commands.
Rename the Cloudlet as Meetings-Registry by double-clicking on its name. You can also click on the menu icon and select the Rename
command.
2.2 Jump-start the Cloudlet configuration with an engine model provided by us #
Press the + New engine model button in the bottom right corner of the Engine models tab. A new (empty) engine model will appear in the Library.
Open the newly created engine model by clicking on its icon: the Designer (the modeling environment of the Livebase platform) will pop up in a dedicated window, showing an empty canvas.
At this point, you would be normally required to draw you engine model. For the sake of this contest, however, you can download a preconfigured
engine model (Meetings_Registry.xml) and import it into the Designer using the Import XML...
command under the File
menu.
Save your engine model (now version number 2.0.0) and close the Designer.
Rename the engine model as Meetings_Registry by double-clicking on its name.
It’s now time to turn the engine model you’ve just stored in the Library into an actual engine installed into the Cloudlet. This can be easily be archived by dragging the engine model icon from the Library onto the Cloudlet panel; the header of the Cloudlet panel will light up (as shown in the image beside) to notify that you’re allowed to drop the icon.
The Cloudlet panel with the engine installed will look as shown in the image beside.
The Cloudlet is now ready to start although a database is still missing (as shown by the status line at the bottom of the Cloudlet panel); in fact, an empty database is created automatically the first time a Cloudlet is started.
Before starting the Cloudlet, however, please go through the following section to take a closer look at the engine you’ve just installed.
2.3 Take a closer look at the engine just installed on your Cloudlet #
Understanding the basics of the engine you’ve just installed on your Cloudlet is essential to properly invoke its GraphQL API.
Click on the icon inside the Cloudlet panel. The Designer will pop up and show the model of the engine installed on the Cloudlet.
The engine consists of a single diagram drawn on three types of layers named schemas. Each schema defines a different aspect of the GraphQL engine, like a thematic layer for a geographical map.
- On the left are two tabs: Schemas and Classes; the former collects the model views, while the latter lists the classes;
- On the right is the canvas, with a tab for each diagram and a special tab for notes.
2.4 Upload some test data to your Cloudlet #
Close the Designer and return on the Dashboard.
With an engine installed, your Cloudlet is now ready to start; in fact, an empty database with a engine-compatible structure is created automatically when the Cloudlet is started for the first time.
In order to let you perform some significant queries on the Cloudlet GraphQL API, however, we have prepared a dump of an already populated database, that you can easily upload.
Download Meetings_registry_data.sql and drag it onto the Cloudlet panel. Once the header lights up, drop the file inside the Cloudlet panel area.
The database uploaded is automatically checked to detect any compatibility issues with engine installed. This process will take a few seconds.
Once the upload is complete, your Cloudlet will look as shown in the image beside.
2.5 Create an end user for the Cloudlet #
In order to test the GraphQL API of your Cloudlet you need to authenticate as a valid end user.
Beside configuring the Cloudlet to connect an existing Single-Sign-On (SSO) Keyclock instance, you can also create local end user accounts, conventionally named Members of the Cloudlet, as shown in the image beside.
To create a new member for your Cloudlet, open the Members of the Cloudlet dialog by clicking on the icon in the Cloudlet panel, then click on the Create Member button.
Each member has a unique username and a password (credentials) that can be used to authenticate on the Cloudlet’s GraphQL API.
Fill in the member creation form, select Administrator from the profile dropdown menu and tick the Admin checkbox. Finally, press the OK button to confirm.
2.6 Start the Cloudlet and test its GraphQL API #
From the Dashboard, click the Start button on the Cloudlet panel.
Please wait about five minutes while the Cloudlet is built and deployed. The Cloudlet panel will show a log of the operations performed during the process.
At the end of the build/deploy process, the Cloudlet will be in the Running state, as highlighted in the status line in the bottom left corner of the panel.
To connect the Cloudlet API programmatically (from your own client application or from a generic GraphQL console), you need to know its endpoints.
Click the GraphQL icon at the top right corner of the Cloudlet panel to open a list of all its API endpoints (just one in your case).
GraphiQL is a widely used open-source console for GraphQL APIs. By clicking on the URL at the top of the Cloudlet panel you can launch an instance of GraphiQL already connected to the Cloudlet, ready to execute GraphQL queries.
Authenticate using the credentials of the member created previously, and you’re all set to test the sample GraphQL queries described in the following sections.
To execute any of the sample queries described below, copy the GraphQL code into the left panel of the GraphiQL console as shown in the image beside, then press the play button.
This simple query retrieves a list of all customers.
Copy the GraphQL query on the right and paste it into the GraphiQL console and press the play button at the top of the console.
query ALL_CUSTOMERS {
Customer___getPage {
items {
name
}
}
}
This query retrieves a list of all projects. For each project, it retrieves name, customer and the list of all the meeting held for that project. For each these meetings it also retrieves the date and the list of the employees who attended.
Copy the GraphQL query on the right and paste it into the GraphiQL console and press the play button at the top of the console.
query ALL_PROJECTS_AND_THEIR_MEETINGS {
Project___getPage {
items {
name
meetings_ {
items {
date
employees_attending_ {items {full_name}}
}
}
}
}
}
3. Update the backend to support additional requirements #
Let’s now refine the Cloudlet engine in order to meet the additional requirements specified in last section of the app requirements page.
Stop the Cloudlet and open the Designer by clicking on the engine icon on the Cloudlet panel.
3.1 Calculate the total meeting effort spent on all the projects of a given customer #
In this section we modify the model of the Cloudlet’s engine in order to satisfy the following additional requirement:
When showing the details of a customer, the app must calculate and show the cumulated meeting effort (man/hours) spent by the company for all the projects commissioned by that customer.
With Livebase, the requirement can be easily satisfied by adding a derived attribute to the Customer class in the engine model, and by configuring such derived attribute with a query expression that sums the efforts of all the meetings held for projects commissioned by a customer.
By doing so, whenever requested to retrieve a customer from the database, the Cloudlet’s GraphQL API will transparently calculate the value of the new derived attribute and will return it as if it had actually read it from the database.
The Livebase Designer allows you to define the query expression of a derived attribute either manually or interactively. The latter one is definitely faster and more intuitive: just drag the /effort
attribute (which is also derived, by the way) from the Meeting class, and drop it onto the Customer class.
As soon as you release the /effort
attribute on the Meeting class, a contextual dropdown menu appears; select the Link here
option.
In the Query expression path selector that appears immediately after, you can choose the right path for the query expression of the new derived attribute, which in this case is clearly the third one: Customer.projects_.meetings_.effort
.
In the Query expression editor that will then pop up, select the SUM - Sum
aggregation function from the dropdown menu as shown beside, then press the OK button to confirm.
Rename the newly created attribute as total_meeting_effort
. Since this is a derived attribute, Livebase automatically adds the /
prefix to its name.
By selecting /total_meeting_effort
on the Customer class, you can double-check the path of its query. The source attribute (/effort
on the Meeting class) is circled in red.
3.2 Prevent archiving contacts still involved in active projects #
In this section we modify the model of the Cloudlet’s engine in order to satisfy the following additional requirement:
When modifying a contact, the app must show a warning and refuse to save the changes if the contact has been marked as archived while it’s still referred as primary contact by one or more active projects (i.e. the contact can be saved as archived only if all projects referring to it as their primary contact are not active).
In order to support this requirement, you can modify the engine model in two steps:
on the Database schema, add to the Contact class a new derived attribute named
has_active_projects
, whose expression evaluates true if a contact is involved in one or more active projects;on the Application schema, add to the Contact class a Class warnings that prevents saving or updating a contact if both its attributes
is_archived
andhas_active_projects
evaluate true.
Each of the two above-mentioned steps are detailed hereunder.
Drag the is_active
attribute from the Project class and drop it onto the Contact class, then select the Link here
option from the contextual dropdown menu.
In the Query expression path selector that appears immediately after, select the right path, which in this case is the first one: Contact.projects_managed_.is_active
.
In the Query expression editor that will then pop up, select the OR - Logical OR
aggregation function from the dropdown menu as shown beside, then press the OK button to confirm.
Rename the newly created attribute as has_active_projects
. Since this a derived attribute, Livebase automatically adds the /
prefix to its name.
By selecting /has_active_projects
on the Contact class, you can double-check the path of its query. The source attribute (is_active
on the Project class) is circled in red.
Select Application in the Schemas tab on the left side of the Designer. The diagram will now appear with all the active modeling elements colored in yellow, as shown in the image beside.
Right-click on the Contact class to open its Class menu and select the Set warnings...
option.
The Class warnings manager will appear, allowing you to manage all the warnings defined for this class. Click on the Add button to create a new Class warning.
In the Class warning editor, shown on the right, type is_archived && has_active_projects
as the condition that will raise the warning and tick the Save New
and Save Existing
checkboxes in the Evaluated on section of the panel.
In the Class warning edito Replace the default message with a more informative one (like the one shown beside), and tick the Block action when message is displayed
checkbox.
Finally, rename the Class warning with an explanatory identifier (e.g.“Cannot_archive_contacts_still_working_on_active_projects”) and press the OK button to confirm.
If you followed the previous steps correctly, the new Class warning will be listed in the Class warnings manager, as shown in the image beside.
3.3 Restart the Cloudlet #
Close the Designer and return to the Dashboard, then click on the Start button on the Cloudlet panel.
4 Test the updated backend #
4.1 Retrieve the total meeting effort of each customer #
This query retrieves, for each customer, the /total_meeting_effort
derived attribute that we have just added to the engine model.
query ALL_CUSTOMERS {
Customer___getPage {
items {
name
total_meeting_effort
}
}
}
4.2 Retrieve all customers and their active contacts #
This query retrieves a list of all customers and their active contacts (i.e. contacts who are primary for at least one active project).
query ALL_CUSTOMERS_AND_THEIR_ACTIVE_CONTACTS {
Customer___getPage {
items {
name
contacts_(options: {filter: {is_archived___eq: false}}){
items {
_id
full_name
has_active_projects
}
}
}
}
}
4.3 Try to archive a contact with active projects #
This mutation checks the enforcement of the last additional requirement. We pick the _id
of one of the contacts that is referred to as primary by an active project, and try to mark it as archived. If you followed the steps of this guide correctly up until this point, the mutation should fail, triggering the Class warning we defined in section 3.2 on the Contact class.
mutation ARCHIVE_CONTACT {
Customer___update(data: {_id: 11304, contacts_:
{update: {_id: 11309, is_archived: true}}}) {
contacts_ {
items {
_id
full_name
is_archived
}
}
}
}