Emoticon Map Markers in Emoji Heatmapper App

As I’ve been exploring and trying to learn what’s possible in the maps of OpenLayers 3 using LokLak API, I wondered about map markers. The markers which i used earlier seem to be so dull on the map, and as I am working on Emoji Heatmapper I couldn’t help but think about 🍩,  😻, 🍦 and 🔮. And sure, the more practical 🏡 , 🏢, ☕ and 🌆.

Emojis as map markers? I had to give it a try.

I didn’t know how one acquires the emoji trove, so I searched around Github. Sure enough, I found many solutions on GitHub. I sifted through all of them until Emoji-picker caught my attention. So i tried giving a dropdown using the emoji-picker as searching would be lot more easier for the user.

Emoji-picker will convert an emoji keyword to the image internally. That is why when you hover over an emoji in the drop-down menu, it shows the corresponding keyword. For instance, the image 🚀 when hovered on it, it displays :rocket: .

 

All the emojis are saved as data URIs, so I don’t need to worry about lugging around hundreds of images. All I need is emoji-picker.js, and few more *.js files  hooked up on my page, and a little JavaScript to get everything working accordingly.

Armed with hundreds of emojis, my next step was to swap markers with emoji keywords. After a few clicks around emoji-picker documentation, I landed on data-emoji-input=”unicode” . It allows you to replace the traditional marker with a unicode emojis so the search outputs data. You can add a class to that lead emoji-picker-container and data-emoji-input=”unicode” for the HTML option.

Style the Open Layers 3 map:

var style = new ol.style.Style({
    stroke: new ol.style.Stroke({
        color: [64, 200, 200, 0.5],
        width: 5
    }),
    text: new ol.style.Text({
        font: '30px sans-serif',
        text: document.getElementById('searchField').value !== '' ? document.getElementById('searchField').value : '',
        fill: new ol.style.Fill({
            color: [64, 64, 64, 0.75]
        })
    })
});

 

and 🎇 I have an emoji map marker.

Resources:

Continue ReadingEmoticon Map Markers in Emoji Heatmapper App

OpenLayers 3 Map that Animates Emojis Using LokLak API

OpenLayers3 maps are fully functional maps which offer additional interactive features. In the Emoji Heatmapper app in Loklak Apps, I am using interactive OpenLayers3 maps to visualize the data. In this blog post, I am going to show you how to build an OpenLayers 3 map that animates emojis according to the query entered and location tracked from the LokLak Search API.

We start with a simple map using just one background layer in a clean style.

var map = new ol.Map({
target: 'map',  // The DOM element that will contains the map
renderer: 'canvas', // Force the renderer to be used
layers: [
// Add a new Tile layer getting tiles from OpenStreetMap source
new ol.layer.Tile({
    source: new ol.source.OSM()
}),
vectorLayer
],
// Create a view centered on the specified location and zoom level
view: new ol.View({
    center: ol.proj.transform([2.1833, 41.3833], 'EPSG:4326', 'EPSG:3857'),
    zoom: 2
})
});

 

Sample Output which displays map:

The data set for the locations of tweets containing emoji in them are tracked using search API of LokLak, which is in the form of simplified extract as JSON file. The file contains a list of coordinates named as location_point, the coordinate consists of lat and long values. With the coordinates, we will create a circle point i.e.,marker on the map showing where the emoji have been recently used from the tweets posted.

In the callback of the AJAX request we loop through the list of coordinates. The coordinate of the resulting line string are in EPSG:4326. Usually, when loading vector data with a different projection, OpenLayers will automatically re-project the geometries to the projection of the map. Because we are loading loading the data ourself, we manually have to transform the line to EPSG:3857. Then we could add the feature to the vector source.

for(var i = 0; i < tweets.statuses.length; i++) {
        if(tweets.statuses[i].location_point !== undefined){
            // Creation of the point with the tweet's coordinates
            //  Coords system swap is required: OpenLayers uses by default
            //  EPSG:3857, while loklak's output is EPSG:4326
            var point = new ol.geom.Point(ol.proj.transform(tweets.statuses[i].location_point, 'EPSG:4326', 'EPSG:3857'));
            vectorSource.addFeature(new ol.Feature({  // Add the point to the data vector
                geometry: point
            }));
        }
    }
});

 

Markers on the Map:

We can also style the markers which gets rendered onto the map using the feature ol.style.Style provided by OpenLayers.

var style = new ol.style.Style({
    stroke: new ol.style.Stroke({
        color: [64, 200, 200, 0.5],
        width: 5
    }),
    text: new ol.style.Text({
        font: '30px sans-serif',
        text: document.getElementById('searchField').value !== '' ? document.getElementById('searchField').value : '', //any text can be given here
        fill: new ol.style.Fill({
            color: [64, 64, 64, 0.75]
        })
    })
});

 

Styled Markers on the Map:

So these were a few tips and tricks to use the interactive OpenLayers3 Maps.

The full code of the example is available here.

Resources:

Continue ReadingOpenLayers 3 Map that Animates Emojis Using LokLak API

Automatically Generating index for documentation in Yaydoc

Yaydoc which uses Sphinx Documentation Generator internally needs a document named index.rst describing the overall layout of the documentation to generate a proper table of contents. Without an index.rst present, the build fails. With this week’s update that constraint has been relaxed. Now if yaydoc detects that index.rst has not been supplied, it automatically generates a minimal index for basic use. Although it is still recommended to provide your own index, you won’t be punished for its absence. The following sections show how this was implemented and also shows this feature in action.

Implementation

For generating a minimal index.rst, we perform the following steps:

  • If the repository has a README.rst or a README.md, we include it in the index
  • Several toctrees are generated as per how the documents in the repository are arranged.

The following code snippet returns a valid rst block which includes the document dirpath/filename

def get_include(dirpath, filename):
    ext = os.path.splitext(filename)[1]
    if ext == '.md':
        directive = 'mdinclude'
    else:
        directive = 'include'
    template = '.. {directive}:: {document}'
    path = os.path.relpath(os.path.join(dirpath, filename))
    document = path.replace(os.path.sep, '/')
    return template.format(directive=directive, document=document)

The following code snippet returns a valid rst block which creates a toctree of dirpath.

def get_toctree(dirpath, filenames):
    toctree = ['.. toctree::', '   :maxdepth: 1']
    caption_template = '   :caption: {caption}'
    content_template = '   {document}'

    caption = os.path.basename(dirpath).replace('_', ' ').title()
    if caption == os.curdir:
        caption = 'Contents'
    toctree.append(caption_template.format(caption=caption))
    # Inserting a blank line
    toctree.append('')

    valid = False
    for filename in filenames:
        path, ext = os.path.splitext(os.path.join(dirpath, filename))
        if ext not in ('.md', '.rst'):
            continue
        document = path.replace(os.path.sep, '/')
        document = document.lstrip('./').rstrip('/')
        toctree.append(content_template.format(document=document))
        valid = True

    if valid:
        return '\n'.join(toctree)
    else:
        return ''

The following code snippet walks the documentation directory and returns a valid content to be written to index.rst.

def get_index(root):
    index = []
    # Include README from root
    root_files = next(os.walk(root))[2]
    if 'README.rst' in root_files:
        index.append(get_include(root, 'README.rst'))
    elif 'README.md' in root_files:
        index.append(get_include(root, 'README.md'))
    # Add toctrees as per the directory structure
    for (dirpath, dirnames, filenames) in os.walk(os.curdir):
    if filenames:
        toctree = get_toctree(dirpath, filenames)
        if toctree:
            index.append(toctree)
    return '\n\n'.join(index) + '\n'

Result

Let’s assume that a sample project has the following directory tree for documentation.

+---_README.md
+---_docs/
|   +---_installation_guide/
|   |   +--- setup_heroku.md
|   |   +--- setup_docker.md
|   +---_tutorial/
|   |   +--- basic.md
|   |   +--- advanced.md

The following index.rst would be generated from the above tree

.. mdinclude:: ../README.md

.. toctree::
   :caption: Installation Guide
   :maxdepth: 1

   setup_heroku
   setup_docker

.. toctree::
   :caption: Tutorial
   :maxdepth:

   basic
   advanced

As you can see, this index.rst would be enough for most use cases. This update decreases the entry barrier for yaydoc. More features are on the way.

Resources

Continue ReadingAutomatically Generating index for documentation in Yaydoc

Step by step guide for Beginners in Web Development for Open Event Frontend

Originally the frontend and backend of the Open Event Server project were handled by FLASK with jinja2 being used for rendering templates. As the size of the project grew, it became difficult to keep track of all the modifications made on the frontend side. It also increased the complexity of the code. As a result of this, a new project Open Event Frontend was developed by decoupling the backend and frontend of the Open Event Orga Server. Now the server is being converted fully into functional API and database and the open event frontend project is primarily the frontend for the Open event server API where organisers, speakers and attendees can sign-up and perform various functions.     

The Open Event Frontend project is built on JavaScript web application framework, “Ember.js”. To communicate with the server API Ember.js user Ember data which is a data persistence module via the exposed endpoints. Suppose if you’re coming from the Android background, soon after diving into the web development you can relate that the web ecosystem is much larger than the mobile one and for the first timers it can be difficult to adopt with it because of the reason that in web there are multiple ways to perform a task which can be restricted to very few in the case of Android. For web applications, one can find that much more components are involved in setting up the project while in android one can easily start contributing to project soon after compiling it in Android Studio. One thing which is relatable for both the android and web development is that in the case of android one has to deal with the varying screen sizes and compatibility issue while in the web one has to deal with adding support for different browsers and versions which can be really annoying.

Now let’s see how one can start contributing to the Open event frontend project while having no or a little knowledge of web development. In case if you’ve previous knowledge of JavaScript then you can skip the step 1 and move directly to another step which is learning the framework.

(Here all the steps have been explained in reference if you’re switching from Android  to Web development.)

Step 1. Learning the Language – JavaScript

Now that when you’ve already put your feet into the web development it’s high time to get acquainted with the JavaScript. Essentially in the case of Ember which is easy to comprehend, you can though start with learning the framework itself but the executables file are written in JavaScript so to write them you must have basic knowledge of the concepts in the language. Understanding of JavaScript will help in letting know where the language ends and where the framework starts. It will also help in better understanding of the framework. In my opinion, the basic knowledge of JavaScript like the scope of variables, functions, looping, conditional statements, modifying array and dictionaries, ‘this’ keyword etc. helps in writing and understanding the .js files easily. Also, sometimes in JavaScript, an error might not be thrown as an exception while compiling but it may evaluate the program to undefined, knowledge of the language will help in debugging the code.

Step 2. Learning the Framework – Ember

Ember is a JavaScript Framework which works on Model-View-Controller(MVC) approach. The Ember is a battery included framework which generates all the boilerplate code including components, routes. Templates etc.  required for building an application’s frontend. It is very easy to understand and comprehend. In Ember, we can easily define the data models and relationships and ember will automatically guess the correct API endpoints. Apart from this, the documentation of the ember on its website is very much sufficient to start with. One can easily start developing applications after going through the tutorial mentioned on the ember’s website.  

Step 3. Testing

In the case of Android application development to write test we use android libraries like Mockito and Robolectric. Also, testing is a bit more difficult in Android app development because we have to explicitly write the test but it is a lot easier in the case of web development. In the case of Ember, it provides an ease of testing which no other framework and libraries provide. While generating a component or template ember itself generates the test files for them and all we have to do is to change them according to our requirement. Ember generates unit, acceptance and integration tests by making testing easier. So we don’t have to write the test explicitly we only have to modify the test files generated by ember.    

Step 4. Styling

In Android we have colors.xml, styles.xml, drawables, gradients, shapes etc. for styling our application but in the case of Web, we have Cascading Style Sheets (CSS) for styling our application. Simply using pure CSS make design complicated and difficult to understand, so to make it easier we combine a bunch of design elements with a style file and use Syntactically Awesome Style Sheets (Saas) with mixins to do that which makes creating styles a lot easier and more straightforward. So for styling, our web application one should have the knowledge of HTML as well as CSS.

In conclusion, I can say that learning web development requires learning a few things in parallel which includes learning a language, learning a framework, how to perform testing and different styling skills to make an application beautiful. Due to dynamic nature of the JavaScript and the sheer number of packages and components involved, as opposed to the safe environment that Android Studio provides, it can be sometimes really frustrating.  However, once learned the basics, the knowledge and skills can be easily transferred and applied over and over again.    

Continue ReadingStep by step guide for Beginners in Web Development for Open Event Frontend

Using Root Directory as the Documentation Directory with Yaydoc

In our test builds for Yaydoc, we found that If we set the root as the documentation directory, the build would fail with a very long build log. In the build process, we create some temporary directories such as a virtual environment and the build directory in the root. After some inspection of the build logs, we found out that when the root is itself used as the documentation directory, we were accidently recursively copying the build directory into itself which led to build failure. Together with this, since the virtual environment directory was also being accidently copied to the build directory, we were actually building the documentation of the entire Python standard library on each build.

Once the problem and It’s cause was known, the course of action to be taken was clear. We needed to ensure that any temporary directories which we create as part of the build process was not being copied to the build directory. The following changes were made to achieve that.

  • The virtual environment directory was now being created in the HOME directory instead of the root.
  • Any other temporary directories which except the main build directory was now deleted before copying.
  • To prevent the recursive copying, we used the –exclude parameter of rsync.
rsync --exclude=BUILD_DIR DOCS_DIR/ BUILD_DIR/

After this patch, root can also be used as the documentation directory with Yaydoc. To do so, just set the environment variable DOCPATH as “.”

Continue ReadingUsing Root Directory as the Documentation Directory with Yaydoc

Adding dynamic segments to a route in Open Event Frontend Project

When we talk about a web application the first thing comes up is how to decide what to display at a given time which in most of the application is decided with the help of the URL. The URL of the application can be set either by loading the application or by writing the URL manually or may be by clicking some link. In our Open Event Frontend project which is written in Ember.js, an incredibly powerful JavaScript framework for creating web applications, the URL is mapped to the router handlers with the helper of router to render the template for the page, to load the data model to display, to navigate within the application or to handle any actions within the page like button clicking etc.

Suppose the user opens the open event application for the very first time what s/he will see a page containing the list of all the events which are going to happen in the near future along with their details like event name, timings, place, tags etc. If the user clicks one of the events from the list, the current page will be redirected to the detailed specific page for that particular event. The behaviour of changing the content of the page which we observed during this process can be explained with the help of the dynamic segments concept. The dynamic segment is a section of the path for a route which changes based on the content of a page.
This post will focus on how we have added dynamic segments to the route in the open event frontend project.

Let’s demonstrate the process of adding the dynamic segments to the route by taking an example of sessions routes where we can see the list of all the accepted, pending, confirmed and rejected sessions along with their details.

To add a dynamic segment, we need to have a route with path which we add to the route definition in app/router.js file

this.route('sessions',  function() {
   this.route('list', { path: '/:sessions_state' });
});

Dynamic segments are made up of a : followed by an identifier. Ember follows the convention of :model-name_id for two reasons. The first reason is that routes know how to fetch the right model by default if we follow the convention. The second is that params is an object, and can only have one value associated with a key.

After defining the path in app/router.js file we need to add template file,  app/templates/events/sessions/list.hbs which contain the markup to display the data which is defined in the file, app/routes/events/sessions/list.js under the model hook of the route in order to display the correct content for the specified option.

Code containing the markup for the page in app/templates/events/sessions/list.hbs file

<div class="sixteen wide column">
  <table class="ui tablet stackable very basic table">
    <thead>
      <tr>
        <th>{{t 'State'}}</th>
        <th>{{t 'Title'}}</th>
        <th>{{t 'Speakers'}}</th>
        <th>{{t 'Track'}}</th>
        <th>{{t 'Short Abstract'}}</th>
        <th>{{t 'Submission Date'}}</th>
        <th>{{t 'Last Modified'}}</th>
        <th>{{t 'Email Sent'}}</th>
        <th></th>
        <th></th>
      </tr>
    </thead>
    <tbody>
      {{#each model as |session|}}
        <tr>
          <td>
            {{#if (eq session.state "confirmed")}}
              <div class="ui green label">{{t 'Confirmed'}}</div>
            {{else}}
              <div class="ui red label">{{t 'Not Confirmed'}}</div>
            {{/if}}
          </td>
          <td>
            {{session.title}}
          </td>
          <td>
            <div class="ui ordered list">
              {{#each session.speakers as |speaker|}}
                <div class="item">{{speaker.name}}</div>
              {{/each}}
            </div>
          </td>
          <td>
            {{session.track}}
          </td>
          <td>
            {{session.shortAbstract}}
          </td>
          <td>
            {{moment-format session.submittedAt 'dddd, DD MMMM YYYY'}}
          </td>
          <td>
            {{moment-format session.modifiedAt 'dddd, DD MMMM YYYY'}}
          </td>
          <td>
            {{session.emailSent}}
          </td>
          <td>
            <div class="ui vertical compact basic buttons">
              {{#ui-popup content=(t 'View') class='ui icon button' position='left center'}}
                <i class="unhide icon"></i>
              {{/ui-popup}}
              {{#ui-popup content=(t 'Edit') class='ui icon button' position='left center'}}
                <i class="edit icon"></i>
              {{/ui-popup}}
              {{#ui-popup content=(t 'Delete') class='ui icon button' position='left center'}}
                <i class="trash outline icon"></i>
              {{/ui-popup}}
              {{#ui-popup content=(t 'Browse edit history') class='ui icon button' position='left center'}}
                <i class="history icon"></i>
              {{/ui-popup}}
            </div>
          </td>
          <td>
            <div class="ui vertical compact basic buttons">
              {{#ui-dropdown class='ui icon bottom right pointing dropdown button'}}
                <i class="green checkmark icon"></i>
                <div class="menu">
                  <div class="item">{{t 'With email'}}</div>
                  <div class="item">{{t 'Without email'}}</div>
                </div>
              {{/ui-dropdown}}
              {{#ui-dropdown class='ui icon bottom right pointing dropdown button'}}
                <i class="red remove icon"></i>
                <div class="menu">
                  <div class="item">{{t 'With email'}}</div>
                  <div class="item">{{t 'Without email'}}</div>
                </div>
              {{/ui-dropdown}}
            </div>
          </td>
        </tr>
      {{/each}}
    </tbody>
  </table>
</div>

 

Code containing the model hook in app/routes/events/sessions/list.js to display the correct content. We access the dynamic portion of the URL using params.

import Ember from 'ember';

const { Route } = Ember;

export default Route.extend({
  titleToken() {
    switch (this.get('params.session_status')) {
      case 'pending':
        return this.l10n.t('Pending');
      case 'accepted':
        return this.l10n.t('Accepted');
      case 'confirmed':
        return this.l10n.t('Confirmed');
      case 'rejected':
        return this.l10n.t('Rejected');
    }
  },
  model(params) {
    this.set('params', params);
    return [{
      title         : 'Test Session 1',
      speakers      : [{ name: 'speaker 1', id: 1, organization: 'fossasia' }, { name: 'speaker 2', id: 1, organization: 'fossasia' }],
      track         : 'sample track',
      shortAbstract : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      submittedAt   : new Date(),
      modifiedAt    : new Date(),
      emailSent     : 'No',
      state         : 'confirmed'
    },
    {
      title         : 'Test Session 2',
      speakers      : [{ name: 'speaker 3', id: 1, organization: 'fossasia' }, { name: 'speaker 4', id: 1, organization: 'fossasia' }],
      track         : 'sample track',
      shortAbstract : 'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
      submittedAt   : new Date(),
      modifiedAt    : new Date(),
      emailSent     : 'Yes',
      state         : 'confirmed'
    }];
  }
});

 

After the route is fully configured, we need to start linking it from the templates which mean we need to link it in our parent template, app/templates/events/view/sessions.hbs file using the {{link-to}} helper. The code for the linking looks like this:

    {{#tabbed-navigation isNonPointing=true}}
        {{#link-to 'events.view.sessions.index' class='item'}}
          {{t 'All'}}
        {{/link-to}}
        {{#link-to 'events.view.sessions.list' 'pending' class='item'}}
          {{t 'Pending'}}
        {{/link-to}}
        {{#link-to 'events.view.sessions.list' 'accepted' class='item'}}
          {{t 'Accepted'}}
        {{/link-to}}
        {{#link-to 'events.view.sessions.list' 'confirmed' class='item'}}
          {{t 'Confirmed'}}
        {{/link-to}}
        {{#link-to 'events.view.sessions.list' 'rejected' class='item'}}
          {{t 'Rejected'}}
        {{/link-to}}
      {{/tabbed-navigation}} 

 

The User Interface for the above code looks like this:

Fig. : The page containing all the accepted session

To conclude this, we can say the task of the route is to load the modal to display the data. For example, if we have the route this.route(‘sessions’);, the route might load all of the sessions for the app but we want only the particular type of session so the dynamic segments help to load the particular model and make it easier to load and display the data.

Reference: The link to the complete code is here. For getting more knowledge about dynamic segments please visit this.

Continue ReadingAdding dynamic segments to a route in Open Event Frontend Project

Forms and their validation using Semantic UI in Open Event Frontend

A web form acts as a communication bridge that allows a user to communicate with the organisation and vice versa. In the Open Event project, we need forms so users can contact the organisation, to register themselves, to log into the website, to order a ticket or to query for some information. Here are a few things which were kept in mind before we designed forms in the Open Event Frontend Project:

  • The forms were designed on the principle of keeping it simple which means that it should ask only for the relevant information which is required in actual.
  • They contained the relevant fields ordered in a logical way according to their importance.
  • They offered clear error messages instantly to give direct feedback and allow users to make instant corrections.
  • The clear examples were shown in the front of the field.
  • Proper spacing among the fields was maintained to display proper error messages to the respective form fields.
  • The mandatory fields are highlighted using ‘*’ to avoid confusion.
  • Proper colour combinations have been used to inform the user about the progress while filling the form. For eg. red for any ‘error or incomplete’ information while green signifies ‘correct’.
  • Saving the current data in case the user has to go back to make any corrections later.
  • Allowing to toggle through the form using the keyboard.

The above designing principles helped in avoiding the negative user experience while using the forms.

Let’s take a closer look at the form and the form validation in case of purchase a new ticket form on the Orders page in Open Event Front-end application.

Creating a form

Let’s start by writing some HTML for the form:

<form class="ui form" {{action 'submit' on='submit' }}>
  <div class="ui padded segment">
    <h4 class="ui horizontal divider header">
      <i class="ticket icon"></i>
      {{t 'Ticket Buyer'}}
    </h4>
    <div class="field">
      <label class="required" for="firstname">{{t 'First Name'}}</label>
      {{input type='text' name='first_name' value=buyer.firstName}}
    </div>
    <div class="field">
      <label class="required" for="lastname">{{t 'Last Name'}}</label>
      {{input type='text' name='last_name' value=buyer.lastName}}
    </div>
    <div class="field">
      <label class="required" for="email">{{t 'Email'}}</label>
      {{input type='text' name='email' value=buyer.email}}
    </div>
    <h4 class="ui horizontal divider header">
        <i class="ticket icon"></i>
        {{t 'Ticket Holder\'s Information'}}
    </h4>
    {{#each holders as |holder index|}}
      <div class="inline field">
        <i class="user icon"></i>
         <label>{{t 'Ticket Holder '}}{{inc index}}</label>
      </div>
      <div class="field">
        <label class="required" for="firstname">{{t 'First Name'}}</label>
        {{input type='text' name=(concat 'first_name_' index) value=holder.firstName}}
      </div>
      <div class="field">
        <label class="required" for="lastname">{{t 'Last Name'}}</label>
        {{input type='text' name=(concat 'last_name_' index) value=holder.lastName}}
      </div>
      <div class="field">
        <label class="required" for="email">{{t 'Email'}}</label>
        {{input type='text' name=(concat 'email_' index) value=holder.email}}
      </div>
      <div class="field">
        {{ui-checkbox label=(t 'Same as Ticket Buyer') checked=holder.sameAsBuyer onChange=(action 'fillHolderData' holder)}}
      </div>
    {{/each}}
    <p>
      {{t 'By clicking "Pay Now", I acknowledge that I have read and agree with the Open Event terms of services and privacy policy.'}}
    </p>
    <div class="center aligned">
      <button type="submit" class="ui teal submit button">{{t 'Pay Now'}}</button>
    </div>
  </div>
</form>

 

The complete code for the form can be seen here.

In the above code, we have used Semantic UI elements like button, input, label, icon, header and modules like dropdown, checkbox to create the basic structure of the form.

The form is created using the Semantic markup. Along with semantic UI collection “form”, the segment element has been used to create the grouping of similar content like we have a timer and its related description that after 10 minutes the reservation will no longer be held are put together in a segment where they are arranged using semantic UI view “statistic”. Due to the vastness of semantic UI, all the styling has been done using it like fields inlining, button styling, segment background coloring etc.

The form is created using the Semantic markup. Along with semantic UI collection “form”, the segment element has been used to create the grouping of similar content like we have a timer and its related description that after 10 minutes the reservation will no longer be held are put together in a segment where they are arranged using semantic UI view “statistic”. Semantic UI elements like button, input, label, icon, header and modules like dropdown, checkbox have been used. Due to the vastness of semantic UI, all the styling has been done using it like fields inlining, button styling, segment background colouring etc.

The page for the above HTML code looks like this:

Image for the order form

Fig. 1: Order Form to purchase a ticket

The complete form can be seen on this link.

Adding form validations

We can also add validation in HTML format but writing the validation in JavaScript file is considered good practice.

Let’s see how we can add validation to fields in Javascript.

  getValidationRules() {
    let firstNameValidation = {
      rules: [
        {
          type   : 'empty',
          prompt : this.i18n.t('Please enter your first name')
        }
      ]
    };
    let lastNameValidation = {
      rules: [
        {
          type   : 'empty',
          prompt : this.i18n.t('Please enter your last name')
        }
      ]
    };
    let emailValidation = {
      rules: [
        {
          type   : 'empty',
          prompt : this.i18n.t('Please enter your email')
        }
      ]
    };
    let validationRules = {
      inline : true,
      delay  : false,
      on     : 'blur',
      fields : {
        firstName: {
          identifier : 'first_name',
          rules      : [
            {
              type   : 'empty',
              prompt : this.i18n.t('Please enter your first name')
            }
          ]
        },
        lastName: {
          identifier : 'last_name',
          rules      : [
            {
              type   : 'empty',
              prompt : this.i18n.t('Please enter your last name')
            }
          ]
        },
        email: {
          identifier : 'email',
          rules      : [
            {
              type   : 'email',
              prompt : this.i18n.t('Please enter a valid email address')
            }
          ]
        },
        zipCode: {
          identifier : 'zip_code',
          rules   : [
            {
              type   : 'empty',
              prompt : this.i18n.t('Please enter your zip code')
            }
          ]
        } 
    };

Let’s break this up, first, we have an array of validation rules.

  zipCode: {
     identifier : 'zip_code',
        rules   : [
        {
          type   : 'empty',
          prompt : this.i18n.t('Please enter your zip code')
         }
      ]
   }

The first part zipcode is the identifier in Semantic.

The next bit of the identifier, this can match against either id, name or data-validate attributes on the element. We have here picked up the name which we’re using on our labels.

Next bit of the rules, which is an array of objects defining the type of validation, and the message to prompt the user with.

The second part is the settings:

inline : true,

delay : false,

on : 'blur',

This part says we want validation to occur on blur, delayed and to be inline. This gives us the following effect:

Fig. 2: Order Form after validation

To summarise the post, one can say we have seen here how the form to purchase the event ticket has been designed, coded and styled. The complete form can be seen on this link and the complete code can be seen here. The entire form has been designed in such a way to keep it simple, clear and trustworthy without losing the user interaction.

References:

Continue ReadingForms and their validation using Semantic UI in Open Event Frontend

How to make SUSI AI Line Bot

In order to integrate SUSI’s API with Line bot you will need to have a line account first so that you can follow below procedure. You can download app from here.

Pre-requisites:

  • Line app
  • Github
  • Heroku

    Steps:
    1. Install Node.js from the link below on your computer if you haven’t installed it already https://nodejs.org/en/.
    2. Create a folder with any name and open shell and change your current directory to the new folder you created.
    3. Type npm init in command line and enter details like name, version and entry point.
    4. Create a file with the same name that you wrote in entry point in above given step. i.e index.js and it should be in same folder you created.
    5. Type following commands in command line  npm install –save @line/bot-sdk. After bot-sdk is installed type npm install –save express after express is installed type npm install –save request when all the modules are installed check your package.json modules will be included within dependencies portion.

      Your package.json file should look like this.

      {
      "name": "SUSI-Bot",
      "version": "1.0.0",
      "description": "SUSI AI LINE bot",
      "main": "index.js",
      "dependencies": {
         "@line/bot-sdk": "^1.0.0",
         "express": "^4.15.2",
         "request": "^2.81.0"
      },
      "scripts": {
         "start": "node index.js"
       }
      }
    6. Copy following code into file you created i.e index.js
      'use strict';
      const line = require('@line/bot-sdk');
      const express = require('express');
      var request = require("request");
      
      // create LINE SDK config from env variables
      
      const config = {
         channelAccessToken: process.env.CHANNEL_ACCESS_TOKEN,
         channelSecret: process.env.CHANNEL_SECRET,
      };
      
      // create LINE SDK client
      
      const client = new line.Client(config);
      
      
      // create Express app
      // about Express: https://expressjs.com/
      
      const app = express();
      
      // register a webhook handler with middleware
      
      app.post('/webhook', line.middleware(config), (req, res) => {
         Promise
             .all(req.body.events.map(handleEvent))
             .then((result) => res.json(result));
      });
      
      // event handler
      
      function handleEvent(event) {
         if (event.type !== 'message' || event.message.type !== 'text') {
             // ignore non-text-message event
             return Promise.resolve(null);
         }
      
         var options1 = {
             method: 'GET',
             url: 'http://api.asksusi.com/susi/chat.json',
             qs: {
                 timezoneOffset: '-330',
                 q: event.message.text
             }
         };
      
         request(options, function(error, response, body) {
             if (error) throw new Error(error);
             // answer fetched from susi
             //console.log(body);
             var ans = (JSON.parse(body)).answers[0].actions[0].expression;
             // create a echoing text message
             const answer = {
                 type: 'text',
                 text: ans
             };
      
             // use reply API
      
             return client.replyMessage(event.replyToken, answer);
         })
      }
      
      // listen on port
      
      const port = process.env.PORT || 3000;
      app.listen(port, () => {
         console.log(`listening on ${port}`);
      });
    7. Now we have to get channel access token and channel secret to get that follow below steps.

    8. If you have Line account then move to next step else sign up for an account and make one.
    9. Create Line account on  Line Business Center with messaging API and follow these steps:
    10. In the Line Business Center, select Messaging API under the Service category at the top of the page.
    11. Select start using messaging API, enter required information and confirm it.
    12. Click [email protected] Manager option, In settings go to bot settings and Enable messaging API
    13. Now we have to configure settings. Allow messages using webhook and select allow for “Use Webhooks”.
    14. Go to Accounts option at top of page and open LINE Developers.
    15. To get Channel access token for accessing API, click ISSUE for the “Channel access token” item.
    16. Click EDIT and set a webhook URL for your Channel. To get webhook url deploy your bot to heroku and see below steps.
    17. Before deploying we have to make a github repository for chatbot to make github repository follow these steps:

      In command line change current directory to folder we created above and  write

      git init
      git add .
      git commit -m”initial”
      git remote add origin <URL for remote repository> 
      git remote -v
      git push -u origin master 

      You will get URL for remote repository by making repository on your github and copying this link of your repository.

    18. To deploy your bot to heroku you need an account on Heroku and after making an account make an app.
    19. Deploy app using github deployment method.


    20. Select Automatic deployment method.


    21. After making app copy this link and paste it in webhook url in Line channel console page from where we got channel access token.

                https://<your_heroku_app_name>.herokuapp.com/webhook
    22. Your SUSI AI Line bot is ready add this account as a friend and start chatting with SUSI.
      Here is the LINE API reference https://devdocs.line.me/en/
Continue ReadingHow to make SUSI AI Line Bot

Making Open Event Organizer Android App Reactive

FOSSASIA’s Open Event Organizer is an Android Application for Event Management. The core feature it provides is two way attendee check in, directly by searching name in the list of attendees or just by scanning a QR code from ticket. So as attendees of an event can be really large in number like 1000+ or more than that, it should not alter the performance of the App. Just imagine a big event with lot of attendees (lets say 1000+) and if check in feature of the app is slow what will be the mess at entrance where each attendee is waiting for his ticket to be scanned and verified. For example, a check in via QR code scan. A complete process is somewhat like this:

  1. QR scanner scans the ticket code and parse it into the ticket identifier string.
  2. Identifier string is parsed to get an attendee id from it.
  3. Using the attendee id, attendee is searched in the complete attendees list of the event.
  4. On match, attendee’s check in status is toggled by making required call to the server.
  5. On successful toggling the attendee is updated in database accordingly.
  6. And check in success message is shown on the screen.

From the above tasks 1st and 6th steps only are UI related. Remaining all are just background tasks which can be run on non-UI thread instead of carrying them on the same UI thread which is mainly responsible for all the user interaction with the app. ReactiveX, an API for asynchronous programming enables us to do this. Just for clarification asynchronous programming is not multithreading. It just means the tasks are independent and hence can be executed at same time. This will be another big topic to talk about. Here we have used ReactiveX just for running these tasks in background at the same time UI thread is running. Here is our code of barcode processing:

private void processBarcode(String barcode) {
  Observable.fromIterable(attendees)
      .filter(attendee -> attendee.getOrder() != null)
      .filter(attendee -> (attendee.getOrder().getIdentifier() + "-" + attendee.getId()).equals(barcode))
      .subscribeOn(Schedulers.computation())
      .observeOn(AndroidSchedulers.mainThread())
      .subscribe(attendee -> {
          // here we get the attendee and
          // further processing can be called here
          scanQRView.onScannedAttendee(attendee);
      });
  }

In the above code you will see the actual creation of an Observable. Observable class has a method fromIterable which takes list of items and create an Observable which emits these items. So hence we need to search the attendee in the attendees list we have already stored in database. Filter operator filters the items emitted using the function provided. Last two lines are important here which actually sets how our subscriber is going to work. You will need to apply this thread management setting to your observable while working on android. You don’t actually have to worry about it. Just remember subscribeOn sets the thread on which actually the background tasks will run and on item emission subscriber handle it on main thread which is set by observeOn method. Subscribe operator provides the function what actually we need to run on main thread after emitted item is caught. Once we find the attendee from barcode, network call is made to toggle check in status of the attendee. Here is the code of check in method:

public void toggleCheckIn() { eventRepository.toggleAttendeeCheckStatus(attendee.getEventId(), attendeeId)
      .subscribe(completed -> {
          ...
          String status = attendee.isCheckedIn() ? "Checked In" : "Checked Out";
          attendeeCheckInView.onSuccess(status);
      }, throwable -> {
          throwable.printStackTrace();
          ...
      });
}

In the above code toggleAttendeeCheckStatus method returns an Observable. As name suggests the Observable is to be observed and it emits signals (objects) which are caught by a Subscriber. So here observer is Subscriber. So in the above code toggleAttendeeCheckStatus is creating an Obseravable. Lets look into toggleAttendeeCheckStatus code:

public Observable<Attendee> toggleAttendeeCheckStatus(long eventId, long attendeeId) {
  return eventService.toggleAttendeeCheckStatus(eventId, attendeeId, getAuthorization())
      .map(attendee -> {
          ...
          // updating database logic
          ...
          return attendee;
      })
      .subscribeOn(Schedulers.io())
      .observeOn(AndroidSchedulers.mainThread());
}

We have used Retrofit+Okhttp for network calls. In the above code eventService.toggleAttendeeCheckStatus returns an Observable which emits updated Attendee object on server response. Here we have used Map operator provided by ReactiveX which applies function defined inside it on each item emitted by the observable and returns a new observable with these items. So here we have use it to make the related updates in the database. Now with ReactiveX support the complete check in process is:

(Tasks running in background in bold style)

  1. QR scanner scans the ticket code and parse it into the ticket identifier string.
  2. Using the identifier, attendee is searched in the complete attendees list of the event.
  3. On match, attendee’s check in status is toggled by making required call to the server.
  4. On successful toggling the attendee is updated in database accordingly.
  5. And check in success message is shown on the screen.

So now main thread runs only tasks related to the UI. And time consuming tasks are run in background and UI is updated on their completion accordingly. Hence check in process becomes smooth irrespective of size of the attendees. And app never crashes.

Continue ReadingMaking Open Event Organizer Android App Reactive

Conversion of CSS styles into React styles in SUSI Web Chat App

Earlier this week we had an issue where the text in our search box of the SUSI web app was not white even after having all the required styles. After careful inspection it was found that there is a attribute named -webkit-text-fill-color which was set to black.

Now I faced this issue as adding such attribute to our reactJs code will cause lint errors. So after careful searching stackoverflow, i found a way to add css attribute to our react code by using different case. I decided to write a blog on this for future reference and it might come handy to other developers as well.

If you want to write css in javascript, you have to turn dashed-key-words into camelCaseKeys

For example:

background-color => backgroundColor
border-radius => borderRadius
but vendor prefix starts with capital letter (except ms)
-webkit-box-shadow => WebkitBoxShadow (capital W)
-ms-transition => msTransition ('ms' is the only lowercase vendor prefix)

const containerStyle = {
  WebkitBoxShadow: '0 0 0 1000px white inset'
};

So in our case:-

-webkit-text-fill-color became WebkitTextFillColor

The final code of styles looked like: –

const searchstyle = {
      WebkitTextFillColor: 'white',
      color: 'white'
    }

Now, because inline styles gets attached on tags directly instead of using selectors, we have to put this style on the <input> tag itself, not the container.

See the react doc #inline-styles section for more details.

Continue ReadingConversion of CSS styles into React styles in SUSI Web Chat App