All-In-One Travel App with AppGyver – SAP No Code Challenge


1. Purpose

This is my entry for SAP no-code challenge. I entered because I never used AppGyver before and want to familiarize with low-code app development as well as getting the hands-on experience.

2. My App

I love travelling and visiting new places. It’s great but I feel like you need to depend on so many apps/websites from different places to get the information you need. That’s why I decided to create an app that user can access travel related information in one place.

All-In-One Travel App helps you with basic needs and provide essential information in single app platform, wherever you are travelling to.

I will go through each page of the app for a simple tutorial, as well as what AppGyver features are used and the logic behind them.

The app is deployed to https://all-in-one-travelapp.appgyverapp.com/

2.1 Home page

The first page asks user to enter the travel destination. The input field have autocomplete as the user types in the names. If the country is entered, the city will be suggested by all cities from that country. Of course, there is an empty check when the search button is pressed.

2.2 Overview page

The Overview page shows the general description about the city, as well as currency, language, calling code, population, etc. There is also “Add to My Favorite button”, which will register the city as your favorite and selectable from the Home page.

2.3 Currency Converter

Currency converter is absolute necessity when shopping in foreign currencies(at least for me!).

2.4 Map

Map shows the city you are visiting in default with red marker. It also detects the GPS location of your device and shows your current location with blue marker so you can navigate through the city. Unfortunately I am in Europe right now so it’s shown on the other side of the map😅.

2.5 Weather forecast

Sometimes your trip can be affected by the weather, so it’s good idea to check the forecast. This page shows the weather forecast of the city with span of 3 hours.

2.6 Google Translate

Exactly as the title says, app is calling google translator web page. There is no free public translator API(at least I did not find it) so I decided to just call WebView in AppGyver. I obviously got lazy here… but this way was the best way to create a translator page.

2.7 Step counter

I often like to activate step counter on my phone during my trip and get satisfied how many steps I walked in one day(or is it only me?). I tried to create the same kind of counter with AppGyver sensor variables.

2.8 Personal Calendar

Keeping track of your travel plan and schedule is a part of a smooth and successful trip. This calendar shows you the current date/month, where you can register/unregister your plans to the date you pressed. 

2.9 Customer support chat bot

My initial motivation was that I wanted to integrate SAP Conversational AI in AppGyver, and thought every legitimate app has chatbot these days, so I integrated my SAP CAI chatbot in this app. It’s a QA chat bot that answers certain questions with predefined answers.

Page navigation

Video clip

*Disclaimer*

As some components are not supported on the web, I’ve only tested the app on my preview app on Iphone. The app may show misalignment and different positioning of components, some features will not be supported and other issues if it’s used on web browser.

3. Technical details and AppGyver features

3.1 Data source

Since I don’t have any subscription to paid API or data source, nor do I have server of my own to expose my own API, the data this app is pulling from are all free public API & data source. I do have SAP BTP trail account but there is 365 days limit and data will be deleted after the trial ends so I decided not use it for this challenge.

So all the free API used in the app are: OpenWeather, Rest Countries, Countries Now, ExchangeRate, and WikiAPI.

Besides API, my personal Google Firestore(free) is used to pull the population data. There I’ve only mapped population of some of the biggest cities from the internet.

3.2 Input with autocomplete

Firstly, store all the values(in my case countries) into a variable. Then create component trees as below. In the text component, repeat with the variable and the repeated data will be named “current”. Then set the content of the text component as “current.name_of_your_value”. Go back to “Repeat with” and use formula to find the match for the value entered by user.

What it’s doing is to find matching countries from obj_country(list of countries) that contains the current user input value(search_country), and create a range item of 3 rows.

SLICE(SELECT(appVars.obj_country, CONTAINS(LOWERCASE(item.country_name), LOWERCASE(pageVars.search_country))), 0, 3)

3.3 Scrollable background cover with viewport height/width

This app has 2 main background cover, a city at night on the Home page and beautiful blue sky on the rest of the page(both from MS PowerPoint open pictures). I think the background looks nice because it stretches over the whole screen. On the scrollable pages like Overview page and Weather page, the image will not cut off even if user scrolls over to the edge.

To create such background, first place a container with background image of your choice. Set containers width/height to the below formulas. Then make sure to set absolute as its position set 0px for left and top so that the container starts from the top left corner.

systemVars.dimensions.viewport.width
systemVars.dimensions.viewport.height

Finally, check on “Stretch to the viewport height” checkbox on the page style tab.

If the page needs to be scrolled, add Scroll view inside that container and set the viewport width/height as well.

3.4 Struggle with step counter logic

The best way to detect steps would be to use accelerometer but I am novice and didn’t even know what x,y,z return variables represent(for how to interpret the data, refer to this). I later found out that proper step counter needs complex algorithm. I cannot wrap my head around the complexity of this, but still I gave it a try with my own logic.

So each variable represents movement of x = forward/back, y = left/right, z = up/down. The formula is basically saying if either of below is true, increment the step count.

  • If any of xyz is greater than 1(which is the power needed to accelerate the movement). This includes less than -1 because negative means how much acceleration is slowing down.
  • None of xyz has to be greater than 1(or less than  -1), but if all of them combines create a acceleration of more than 1.5(or less than 1.5).
( ABS(outputs["Get single accelerometer value"].value.x) >= 1 || ABS(outputs["Get single accelerometer value"].value.y) >= 1 ) || ( ABS(outputs["Get single accelerometer value"].value.x) + ABS(outputs["Get single accelerometer value"].value.y) + ABS(outputs["Get single accelerometer value"].value.z) > 1.5 )

It works ok if you just mock the actual steps by shaking the phone. But if I put the phone in my pocket, the count is not accurate.

I understand my logic is very premature, so if anyone who is experienced with sensor and accelerometer, I’d highly appreciate your advise!

3.5 Custom calendar with containers

The logic behind this custom calendar is not a simple one, but since the “Date picker calendar” from the market is not flexible and only supported on web, I decided to do my own.

A. First step is to create the calendar design. Create a component trees like below by inserting containers into one another. You should get page design like below. Next, create page variables with below data types. In “Current Month Days”, set repeated with “calendar_days”.  

B. Do the followings to make the containers look like a calendar.

  • Check “Wrap overflowing components to new row” in “Calendar Days” and make it horizontal.
  • Set width of “Current Month Days” to 14% of the parent container, which will divide each repeated container to approximately 1/7th of the size.
  • Set width of “Past Days” to the following formula, which calculates how many days is before the current date and how much space needed for the padding.
    MOD(FLOOR(DATETIME_DIFFERENCE(SET_DATETIME_COMPONENT(pageVars.current_date, 1, "date"), "2020-01-06T00:00:00Z", "days", true)), 7)*14+"%"​

C. Now for the logic, create a flow of logic as below when the page is mounted. Please note that “Set component property” has nothing to do with the calendar so it can be ignored.

In the first two Set page variable , set current date/time using NOW() to  “current_date” & “selected_date”. In the last one, use below formula to map the date of the month to “calendar_days”.

ADD_DURATION to get the next month of the current date. SET_DATETIME_COMPONENT to get the last date of the previous month by passing 0(pretty neat!). Then get that date, which is the last date of the current month, and generate range and map it to “calendar_days”.

MAP(GENERATE_RANGE(1, GET_DATETIME_COMPONENT( SET_DATETIME_COMPONENT(ADD_DURATION(pageVars.current_date, 1, "months"), 0, "date"), "date")),{id: item})

D. To detect the date user has pressed, add flow logic to set the date pressed to “current_date” with following formula.

SET_DATETIME_COMPONENT(pageVars.current_date, repeated.current.id, "date")

Finally, add below formula to the date text to change the style of the text when the date is selected.

//Font color of the date text
IF(DATETIME_IS_SAME(pageVars.selected_date, SET_DATETIME_COMPONENT(pageVars.current_date, repeated.current.id, "date"),"day"),theme.$smartColorPalette_app.secondary, IF(DATETIME_IS_BEFORE(SET_DATETIME_COMPONENT(pageVars.current_date, repeated.current.id,"date"),NOW(),"day"),theme.$smartColorPalette_app.secondaryLowContrast,theme.$smartColorPalette_positive.positive)) //Font weight of the date text
IF(DATETIME_IS_SAME(SET_DATETIME_COMPONENT(pageVars.current_date, repeated.current.id,"date"),NOW(),"day"),"700","400")

3.6 Composite Component

I had to reuse the scrollable menu bar at the bottom over and over, so that part is made into a composite component. It was tricky at first when you can’t access all your variables bur once I’m used to using two-way biding properties & receiving/triggering events, it saves so much time not having to create the same menu bar over and over.

3.7 Cloud Firestore Integration

Population information in the overview page is pulled from my Cloud Firestore account. The configuration is so simple and AppGyver provides great implementation guide.

3.8 On-device storage

“Add to favorite city” on the overview and events on the calendar page are both stored into on-device storage. ID field is the key and mandatory to use for data structure, which is bit less flexible. Other than that, I feel like it’s a great feature!

3.9 SAP Conversational AI Integration

Chatbot page is calling my QA bot from SAP CAI trial account. CAI provides light-weighted, easy to integrate channel to embed the bot into html page. All you need is to add the below script to html.

So I thought using Web View Component from the market will display my bot using html content rendering. However, apparently there is a limit to what Web View can render and chatbot is not showing. So as a workaround, I hosted my html code to my GitHub account and published the page. The published GitHub URL are called by Web View in AppGyver and this way it shows the bot on the app properly.

Now checking the required capabilities for the no code challenge…

  • Connect to a free, public REST/OData service ✔️->3.1
  • Create a data store on your device ✔️->3.8
  • Incorporate native capabilities of your mobile device ✔️->2.4, 2.7
  • Use a formula ✔️->3.2, 3.4, 3.5 and so on..
  • Create at least 3 pages and a menu for navigation within your app ✔️->2
  • Use one item from the Component Marketplace or Flow Function Market ✔️->Embedded map view in 2.4, Web view in 2.6 and so on..
  • Use at least 1 page parameter or page variable to store data ✔️->3.2, 3.5 and so on..
  • Create a composite component ✔️->3.6
  • Set the theme, and change the colors of your components ✔️->3.5 and most components of the app
  • Build and deploy your app to SAP AppGyver server ✔️->https://all-in-one-travelapp.appgyverapp.com/

4. My experience

4.1 What I found cool about AppGyver:👏👏

Formula is powerful

Formula allows you to play around with data object and access different part of the object node and assign the value to another part of variable. The flexibility is worth noting. Another cool part is that the function dictionary and examples are at your tip of your finger. No need to search for official documents on the browser!

Ctr+C, Ctr+V, Ctr+Z all the time!

Copy paste works the same way in AppGyver too. This saves so much efforts in reusing components, flow logic, etc.

Version management

AppGyver’s own version management system. It shows which page is changed and can rollback to the version. Version list can be accessed by the history button. It seems like it only keep certain number of versions.

API handling and response property schema detection 

It’s been so easy to handle API calls. What amazes me more is the auto detection of response property schema. This saves me from defining the data structure to consume the API. It saves so much effort that I feel like being spoiled.

..and above all, user friendly app development platform that produces simple ~ complex apps effectively and quickly.

4.2 Feature request on AppGyver:✋

Dependency check

When I change one variable to another name, I have to fix it wherever it’s used, but there is no dependency check. If you forget to change in one place, you will not find out until you face an error and debug it. Is there dependency check in AppGyver?

Property scan(source scan)

When the app is big and many complex formula are used, I forget which component has which formula used and which flow logic is in which buttons. Maybe not a necessary feature but definitely a useful if we can scan with keywords(IF, GET_DATETIME_COMPONENT, etc) and get the list of components that is using the keyword.

Comment

When the logic gets complex, there is nowhere to add comments.

Not supported/only supported on web 

Some components(map, webview) are not supported on the browser.

Final words

Overall a big thumb up👍 for AppGyver. I never used AppGyver before this challenge and now I am a big fan! Thank you Daniel Wroblewski for hosting this challenge and for this learning opportunity.

I work with SAP development(mostly ABAP and some UI5) and cannot wait for the day I can try AppGyver out in BTP and consume Odata from S4 HANA. I’m not sure if deploying BTP AppGyver apps to S4 UI5 repository and convert into BSP application is in the road map or not, but if it is, that would be very exciting(because then no need to develop custom UI with ABAP and SAPUI5).

Either way, I will definitely invest more time on AppGyver and looking forward to the feature update and the road map in SAP BTP.