Professional Documents
Culture Documents
Outline 1 How To 2
Outline 1 How To 2
Outline 1 How To 2
Table of Contents
Outline 1
How to 2
Overview of the Cinemas and Sessions 2
Cinemas and Sessions Screens 4
Using the Device Location 10
Create a Cordova Plugin 19
Test the Dialogs Plugin the OMSDb Mobile App 31
Outline
In this exercise, we will add Cinemas and Sessions to the OSMDb Mobile application. The
application will have two new Screens: Cinemas and Sessions. In the Cinemas Screen we will list
all the Cinemas that are airing a particular movie. In the Sessions Screen, we will list all the
sessions for a movie, in a particular cinema.
These Screens are only accessible by Registered or OSMDbAdmin users and when the app is
online. The OSMDb_Core_Mobile module already has the Cinema and the Session Entities
defined, as well as the logic to Bootstrap the data.
The list of Cinemas will be displayed sorted by the distance between the device and the actual
cinema. To accomplish that, we will use two Forge components: the LocationPlugin t o get the
location of the device and the DistanceFromCoordinate to calculate the distance between the
device and another location.
We will also implement a Cordova Plugin: DialogsPlugin. This Plugin will be used to implement
confirmation messages and alerts that will appear to the end-user when saving the information
about a movie.
1
At the end of the exercise, we need to generate the native package again and try out the
application in the device.
How to
In this section, we’ll describe, step by step, the exercise 6.2 - Mobile Plugins.
The Cinema Entity has the Name, the City where the Cinema is located, the latitude and the
longitude. The Session Entity has a relationship with the Cinema and the Movie, as well as the
day and the starting and ending times of the session.
2
The final piece of the Bootstrap logic is to Bootstrap the Sessions. That logic does not use an
Excel. For the purpose of the exercise, we create static sessions, always starting and ending at
the same times.
3
Then, create the Sessions Screen, which will display the Sessions for a movie in a particular
Cinema. It can only be accessible via the Cinemas Screen.
4
d. Create a Database Aggregate with the Cinema and Session Entities as Sources.
f. Add a new Filter to guarantee that only the cinemas that have the movie, that
matches the MovieId Input Parameter, in session will be fetched.
Session.MovieId = MovieId
g. Since we just want to display the cinemas, but the Aggregate has a Join with the
Sessions, we have repeated cinema information being fetched.
To avoid repetition, G
roup By the Id, Name, City, Lat and Long attributes of the
Cinema Entity.
5
3. Link the MovieDetail Screen to the Cinemas Screen and from the Cinemas Screen back to
the MovieDetail Screen.
a. Drag a Container a
nd drop it below the List. Set a Margin Top of 20px.
6
b. Still on the Cinemas Screen, add a Link below the List, with the text Back to Movie,
with Destination set to the M
ovieDetail S
creen.
7
d. Add a new Aggregate with the Session Entity as Source. Create two Filters by
MovieId and CinemaId. Make sure the name of the Aggregate is set to
GetSessionsByCinemaId
8
f. Expand the GetSessionsByCinemaId Aggregate and the Session Entity within it.
Drag the Day a
ttribute and drop it on the List.
j. Create a Link w
ith the Text Back to Cinema, to go back to the Cinemas S
creen.
9
m. Test the application on the device. Do not forget that the Cinemas Screen is only
available when online.
When accessing the Cinemas Screen, the location of the device needs to be calculated. Then,
the Distance attribute of the Cinema Screen can be used to hold in memory the distance from
the device to the cinemas, which will then be used to sort the List in the UI.
1. Reference the C
heckLocationPlugin and the G
etLocation Client Actions from the
LocationPlugin. Also, reference the C
ountDistance Server Action from the
DistanceFromCoordinate.
2. Use the On Initialize Event of the Cinemas Screen to calculate the current device
location. Use two Local Variables to save the device latitude and longitude.
10
b. Select the Cinemas Screen, set the On Initialize Event to a new Client Action.
c. Drag a Run Client Action node and drop it in the new On Initialize Action flow.
11
e. Drag an If n
ode and drop it below the CheckLocationPlugin Action. Set its
Condition to CheckLocationPlugin.IsAvailable
NOTE: This verification is crucial before using any plugin. This guarantees that
older versions of the app, without the Location Plugin included in the native app
package, will continue to work properly.
g. Drag a Message n
ode and drop it to the right of the If. Set the Message p
roperty
to “Current location unavailable” and the T
ype to W
arning. Connect the If with the
Message.
12
h. Drag an End n
ode and drop it to the right of the Message. Connect the two
nodes.
i. Drag a Run Client Action and drop it below the If. Set the Action to the
GetLocation Action from the Location Plugin.
NOTE: This calculates the latitude and longitude of the current location of the
device. It also creates a warning in Service Studio, since the Screen Events should
be used with care, to avoid slowing the Screen down. However, this calculation is
necessary to know the device location and it is not inefficient.
j. Drag an Assign n
ode and drop it after the GetLocation Action. Set the following
Assignments
CurLat = GetLocation.Location.Latitude
CurLong = GetLocation.Location.Longitude
3. Now that we know the device current location, we need to sort the List accordingly. The
distance of all cinemas should be calculated after the cinemas are fetched, which could
lead to use of the On After Fetch Event. Despite that being a possibility, the
CountDistance Action is a Server Action. So, when doing that, we would get a warning
for having multiple calls to a server being made (one calculation per cinema). So, we can
use a D
ata Action instead, place the Aggregate inside it and do the distance calculations
before sorting the List. For now, let’s create the Data Action, place the Aggregate inside it
and create a Structure that will hold the Cinema and the distance to each cinema, to help
us do the necessary calculations.
13
d. Add another attribute and set its Name t o Distance and its Data Type to Decimal
e. Go back to the Cinemas Screen and set the Output Parameter of the
GetCinemasWithDistance Data Action to be called C
inemas, with Data Type set to
CinemaWithDistance List.
14
g. Drag a new Assign node and drop it after the GetCinemas Aggregate. Set the
Assignment to be:
Cinemas = GetCinemas.List
Automatically, the platform does a mapping of the Cinema Entity attributes to the
ones in the CinemaWithDistance Structure, except for the Distance, which will be
calculated later.
15
j. There’s only one more error to go. Select the ListItem widget and set the value
passed as parameter to the Sessions Screen to be:
GetCinemasWithDistance.Cinemas.Current.Cinema.Id
4. Calculate the Distance from the device location to the cinemas in the list.
16
c. Drag a Run Server Action node and drop it to the right of the For Each. Select the
CountDistance Action from the DistanceFromCoordinate Forge component.
IsMetricSystem = True
Lat_Center = CurLat
Lng_Center = CurLong
Lat_Compare = Cinemas.Current.Cinema.Lat
Lng_Compare = Cinemas.Current.Cinema.Long
17
This will calculate the distance between the device and the cinema processed in
the loop.
f. Drag an Assign a
nd drop it below the CountDistance Action. Set the Assignment
to be:
Cinemas.Current.Distance = CountDistance.Distance
g. Connect the Assign back to the For Each to close the loop.
h. Drag a Run Server Action and drop it below the For Each and before the End
node. Select the ListSort A
ction.
18
7. To test the application in the device, we need to generate a new native package, to
include the code of the LocationPlugin, except when using OutSystems Now.
8. Make sure the Cinemas appear sorted by the distance in the List of Cinemas.
For that purpose, we will create a new application, with a Blank module, and define three
Actions based on JavaScript code: C
heckDialogsPlugin, to verify if the Plugin is available, A
lert, to
display an alert message to the user, and C
onfirm, to ask for confirmation from the user before
performing an operation in the app.
This section of the exercise can only be properly tested using the native package of the app.
19
a. In the main Applications tab in Service Studio, create a New Application and
choose P
hone App.
2. In the new module, we will reference the public repository of the plugin in the
Extensibility Configurations property:
https://github.com/apache/cordova-plugin-dialogs.git. This will allow the module to have
access to the Plugin’s methods. The Extensibility Configurations property expects a JSON
20
structure. We will also modify the module icon to use the same of the application, using
the smaller icon available in the Resources.
NOTE: To reference an existing Cordova Plugin we should create a new app with
a Blank module. Then, use the Extensibility Configurations property to reference
the public repository URL of the plugin, using a JSON structure. You can find the
documentation about the Dialogs Plugin here.
b. Add the following to the Extensibility Configurations dialog and close the window
{
"plugin": {
"url": "https://github.com/apache/cordova-plugin-dialogs.git"
}
}
21
c. Open the drop down for the Icon property of the module and choose ( Change
Icon…), then select the DialogsPlugin32.png image file from the Resources folder.
3. Let’s now create the first Action of the Dialogs Plugin, the CheckDialogsPlugin Client
Action. This Action will verify if the D
ialogsPlugin has been loaded on the device and can
be used. We need to use JavaScript to help us define this logic. The Action should return
if the plugin is available or not.
22
23
d. Drag a JavaScript n
ode and drop it in the Action flow.
e. Open the JavaScript editor, right-click the Parameters folder and add an Output
Parameter named I sAvailable.
24
$parameters.IsAvailable = !!navigator.notification;
i. Drag an Assign node and drop it between the JavaScript statement and the End
and define the following assignment
IsAvailable = JavaScript1.IsAvailable
25
b. Change the I con of the Client Action to the image file d
ialogs-icon32.png, located
in the Resources f older.
● Success (Boolean)
● ErrorMessage (Text)
e. Drag a JavaScript n
ode and drop it in the Action flow.
f. Inside the JavaScript editor, add an Input Parameter to the JavaScript statement
by right-clicking the Parameters folder, then set its Name to Title and D
ata Type
to Text.
g. Repeat the previous step for the Message and ButtonName Input Parameters
with the same data type.
h. Inside the JavaScript editor, add an Output Parameter named Success with D
ata
Type Boolean.
26
NOTE: JavaScript nodes act as black boxes, therefore all data that is needed
inside the JavaScript code must be sent as Input Parameter into the JavaScript
node. The same happens with data sent out of the JavaScript node.
j. In the text editor area add the following JavaScript code and click Done.
if($actions.CheckDialogsPlugin()) {
navigator.notification.alert(
$parameters.Message, // message
function (){ // callback
$resolve();
$parameters.Success = true;
},
$parameters.Title, // title
$parameters.ButtonName // buttonName
);
} else {
$parameters.Success = false;
$parameters.ErrorMessage = "Dialogs plugin is not available";
}
27
k. Select the JavaScript node and define the Input Parameters to use the
corresponding Client Action Input Parameters.
l. Drag an Assign node and drop it between the JavaScript and the End, then define
the following assignments
Success = JavaScript1.Success
ErrorMessage = JavaScript1.ErrorMessage
5. Create a Confirm C
lient Action to provide a confirmation process for the end-user. This
Action will have two Input Parameters: T itle ( Text, mandatory) and Message ( Text,
mandatory). It also has three Output Parameters: C
onfirmed (Boolean) that returns if the
user confirmed the operation or not, S
uccess (Boolean) to make sure the Action was
successful and E
rrorMessage ( Text) to be displayed when an error occurs. As above, we
need some JavaScript to help us define the logic for this Action.
b. Change the Client Action I con to the dialogs-icon32.png image, located in the
Resources folder.
c. Add two new Input Parameters to the Client Action, called T itle a
nd Message, with
Text D
ata Type.
28
● Confirmed (Boolean)
● Success (Boolean)
● ErrorMessage (Text)
e. Drag a JavaScript statement, drop it on the Action flow and open it.
f. Add the proper Input Parameters and Output Parameters, matching the ones on
the Client Action, just like in the previous steps.
29
g. In the text editor area add the following JavaScript code and click Done.
if($actions.CheckDialogsPlugin()) {
navigator.notification.confirm(
$parameters.Message, // message
function (buttonIndex){ // callback
$parameters.Success = true;
$parameters.Confirmed = (buttonIndex === 1);
$resolve();
},
$parameters.Title, // title
['Yes', 'No'] // buttons
);
} else {
$parameters.Success = false;
$parameters.ErrorMessage = "Dialogs plugin is not available";
}
h. Set the Title and Message properties of the JavaScript statement to the Input
Parameters of the Client Action.
i. Drag an Assign and drop it between the JavaScript and End, then define the
following assignments
Confirmed = JavaScript1.Confirmed
Success = JavaScript1.Success
ErrorMessage = JavaScript1.ErrorMessage
j. Click the 1-Click Publish button and verify that the module was successfully
published.
30
We will make sure that a confirmation dialog appears when the user tries to create or edit a
movie in the database, in the M
ovieDetail Screen. Also, if the user confirms and the local
storage is cleared, an A
lert message will appear informing the user of that.
1. Reference the Actions created in the DialogsPlugin in the OSMDb Mobile, using the
Manage Dependencies dialog.
2. In the MovieDetail Screen, we will now add a Confirmation dialog appearing to the
end-user, whenever the user tries to save the information about a movie. Only after the
user confirms the operation, then the operation to save the information will proceed,
including the form validations. Don’t forget to check if the plugin exists before using the
Action and also to check if the Action was successful and confirmed.
31
b. Drag a Run Client Action node and drop it right after the Start node. In the new
dialog, choose the CheckDialogsPlugin C
lient Action from the D
ialogsPlugin
module.
CheckDialogsPlugin.IsAvailable
d. Drag a new Run Client Action node and drop it to the right of recently added If.
Select the Confirm C
lient Action from the D
ialogsPlugin.
32
f. Create the T
rue b
ranch connector from the If to the Confirm A
ction.
NOTE: If the plugin is available, the Confirm Action for the plugin is executed.
Now, we need to check if the message appeared successfully, which is done in
this If. Next, we need to check if the end-user confirmed that the Action should
proceed as expected.
g. Drag an If n
ode and drop it to the right of the Confirm Action. Create the
connector between both. Set the Condition property to
Confirm.Success
h. Drag another I f node and drop it on the right of the previous one. Create the
True b
ranch connector from the If created above to the new one.
Confirm.Confirmed
33
j. Create the F
alse branch connector from the C
onfirm.Success? If to the first
validation in the Action flow. This means that the Dialogs did not work
successfully, then the Action flow should continue as expected and planned.
k. Create the T
rue b
ranch connector from the Confirm.Confirmed? If to the first
form validation. This means that the user confirmed that the Action should
proceed as planned.
34
NOTE: The logic created above is designed in such a way that in the case that the
Dialogs Plugin is not available (e.g. the app installed in the device was not
upgraded yet), the logic will still work without errors.
When integrating with newly added native plugins it is important that the
application is designed in such a way that allows for both use cases: plugin is
available and not available. This way, we ensure that end-users have an error-free
experience in case the plugin is not yet available in the native app they have
installed on their device, or even if the mobile device does not support the plugin.
35
a. Drag an If and drop it between the LocalMovieCreateOrUpdate Action and the
Success Message. Set the C
ondition property to
CheckDialogsPlugin.IsAvailable
b. To save some space for the next piece of logic, drag the Success message and
leave it below the LocalMovieCreateOrUpdate Action.
c. Drag a Run Client Action node and drop it on the right of the If statement.
Choose the A
lert C
lient Action from the DialogsPlugin.
d. Create the T
rue b
ranch connector from the If to the Alert A
ction.
36
Alert.Success
NOTE: The logic above is defined in such a way that if the DialogsPlugin is not
available, the built-in Message will appear. The same happens if the Alert does
not work properly. However, if the DialogsPlugin is available, then the Alert from
the DialogsPlugin will appear.
4. Publish the module and test the application on the device. Make sure that the dialogs
properly appear when they are expected. Notice that a new version of the native
package was generated, since the Plugin is now referenced on the app and needs to be
included. This only happens when the native app was already generated (at least) once.
37