Personal Insights
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.
2.2 Overview page
2.3 Currency Converter
2.4 Map
2.5 Weather forecast
2.6 Google Translate
2.7 Step counter
2.8 Personal Calendar
2.9 Customer support chat bot
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: OpenWeatherMap, RestCountries API, CountriesNow(by Postman API), ExchangeRate API(from AppGyver marketplace), 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
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
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
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 )
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.
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+"%"
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 defined outside of composite component but 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” and “Mark as visited” on the overview & 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
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
・Ctr+C, Ctr+V, Ctr+Z all the time!
・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.
・Very basic yet AG debugger works fine
AG debugger includes only events/function flow, console and variable state. No break-point, no step-in/step-out buttons, no stack information. Yet debugging was not a struggle at all for me. Only thing I realized is custom JS cannot be debugged and the syntax error cannot be caught at the time of compiling. One way to check is to use Console in debugger. Syntax error will be displayed there and anything Console.log() shows will be displayed as well.
..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.
・Analytical/Data visualizing components
So far there is only “D3.js/Google chart” when it comes to the data analysis/visualizing component, and it seems you need custom JS to be able to use it. More of those chart/graph components would be nice.
・Not supported/only supported on web
Some components(map, webview) are not supported on the browser.
In summary
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.
Amazing stuff!
I was wondering if I could use your blog post in our documentation to showcase an example project that was made with SAP AppGyver. Let me know if that is alright with you and if you want credit to be put in place (for instance a link to your SAP Profile or the original blog).
Sure thing! Feel free to use this blog and profile and it'd be nice to get credit for my work as well. Thanks a lot!
Hi Aocheng Yang,
Congrats for your win with this great use case!
Would you be able to add "SAP Conversational AI" as a primary tag in your article so our community of chatbot builders can be aware of it?
Thanks a lot
Hi Paul, thanks! "SAP Conversational AI" tag is added now.
do you know how to show multiple markers on map to show multiple locations from an API like this : https://api.openchargemap.io/v3/poi/?output=json&countrycode=US&maxresults=100&compact=true&verbose=false&key=YOUR_KEY_VALUE