Better fields and validation in Flask Restplus

We at Open Event Server project are using flask-restplus for API. Apart from auto-generating of Swagger specification, another great plus point of restplus is how easily we can set input and output models and the same is automatically shown in Swagger UI. We can also auto-validate the input in POST/PUT requests to make sure that we get what we want.

@api.expect(EVENT_POST, validate=True)
def put(self, id):
    """Modify object at id"""
    pass

As can be seen above, the validate param for namespace.expect decorator allows us to auto-validate the input payloads. This used to work well until one day I realized there were a few problems.

  1. When a field was defined as say for example field.Integer, then it will accept only Integer values, not even null.
  2. If there is a string field and it has required param set to True, then also it is possible to set empty string as its value and the in-built validator won’t catch it.
  3. Even if I somehow managed to hack my way to support null in field, it will also support null even if required=True.
  4. We had no control on what error message was returned.
EVENT = api.model('Event', {
    'id': fields.Integer,
    'name': fields.String(required=True)
})

Specially problem #1 was a huge one as it questioned the whole foundation of the API. So we realized it will be better if we don’t use namespace.expect and use a custom validator. For custom validator, we first had to create custom fields that this validator can benefit from. Luckily flask-restplus comes with a great API for creating custom fields. So we quickly created custom fields for all common fields (Integer, String) and more specific fields like Email, Uri and Color. Creating these specific fields were a huge advantage as now we can show proper example for each field types in the Swagger UI.

class Email(fields.String):
    """
    Email field
    """
    __schema_type__ = 'string'
    __schema_format__ = 'email'
    __schema_example__ = 'email@domain.com'

Consider the above code; now when we use Email as a field for a value, then the example shown for it in Swagger UI will be ‘email@domain.com’. Quite cool, right?

Now we needed a way to validate these fields. For that, what we did was to create a validate method in each of the field-classes. This validate method would get the value and check if it was valid. Consider the following code –

import re
EMAIL_REGEX = re.compile(r'S+@S+.S+')

class Email():
	def validate(self, value):
		if not value:
		    return False if self.required else True
		if not EMAIL_REGEX.match(value):
		    return False
		return True

Once each of the field had their validate methods, we created a validate_payload() function that uses the API model and compares it with the payload. It will first check if all required keys are present in the payload or not. When that is true, it finally validates each field’s value using their field’s classvalidate method.

from flask import abort
from flask_restplus import fields
from custom_fields import CustomField

def validate_payload(payload, api_model):
    # check if any reqd fields are missing in payload
    for key in api_model:
        if api_model[key].required and key not in payload:
            abort(400, 'Required field '%s' missing' % key)
    # check payload
    for key in payload:
        field = api_model[key]
        if isinstance(field, fields.List):
            field = field.container
            data = payload[key]
        else:
            data = [payload[key]]
        if isinstance(field, CustomField) and hasattr(field, 'validate'):
            for i in data:
                if not field.validate(i):
                    abort(400, 'Validation of '%s' field failed' % key)

The CustomField is the base class that each of the custom fields mentioned above inherit. So checking if field was an instance of CustomField is enough to know if it is a custom field or not. Other thing that may look weird in the above code is use of fields.List. If you look closely, I have added this to support custom fields inside lists. So if you have used a custom field in a list, it will also work too. But obviously, this only supports single level lists for now. The thing is we didn’t needed more than that so I let it go. :stuck_out_tongue_winking_eye:

This basically sums up how we are validating input payloads at Open Event. Of course this is very basic but we will keep on improving it as the project progresses. Stay tuned to opev blog if you want to be in touch with the progress of the project.

Links to full code at the time of writing this post are –

  1. Custom Fields
  2. Validate Payload

I hope you found this post useful. Thanks for reading.

 

{{ Repost from my personal blog http://aviaryan.in/blog/gsoc/restplus-validation-custom-fields.html }}

Continue ReadingBetter fields and validation in Flask Restplus

Export Timeline as iCal

iCal or iCalendar is the Internet standard for sharing event schedules or session timelines among each other. The filename extension for iCal is .ics . It is supported by a number of applications such as Google Calendar, Apple Calendar,] Yahoo! Calendar, Lightning extension for Mozilla Thunderbird and SeaMonkey, and partially by Microsoft Outlook . In Open Event Organizer’s Server we have added a feature to export the Schedule of a particular Event in iCal format.

Continue ReadingExport Timeline as iCal

Building interactive elements with HTML and javascript: Drag and Drop

{ Repost from my personal blog @ https://blog.codezero.xyz/building-interactive-elements-with-html-and-javascript-drag-and-drop }

Traditionally, all interactions in a website has been mostly via form inputs or clicking on links/button. The introduction of native Drag-and-drop as a part of the HTML5 spec, opened developers to a new way of Graphical input. So, how could this be implemented ?

Making any HTML element draggable is as simple as adding draggable="true" as an attribute.

<div id="a-draggable-div" draggable=true>  
    <h4>Drag me</h4>
</div>  

This will allow the user to drag div#a-draggable-div. Next, we need to designate a dropzone, into which the user can drop the div.

<div id="dropzone" ondragover="onDragOver(event)">  
</div>  
function onDragOver(e) {  
    // This function is called everytime 
    // an element is dragged over div#dropzone
    var dropzone = ev.target;

}

Now, the user will be able to drag the element. But, nothing will happen when the user drops it into the dropzone. We’ll need to define and handle that event. HTML5 provides ondrop attribute to bind to the drop event.

When the user drops the div into the drop zone, we’ll have to move the div from it’s original position into the drop zone. This has to be done in the drop event.

<div id="dropzone"  
ondrop="onDrop(event)"  
ondragover="onDragOver(event)"> </div>  
function onDrop(e) {  
    e.preventDefault();
    var draggableDiv = document.getElementById("a-draggable-div");
    draggableDiv.setAttribute("draggable", "false");
    e.target.appendChild(draggableDiv);
}

So, when the user drops the div into the drop zone, we’re disabling the draggable property of the div and appending it into the drop zone.

This is a very basic drag and drop implementation. It gets the job done. But, HTML5 provides us with more events to make the user’s experience even better 1.

Event Description
drag Fired when an element or text selection is being dragged.
dragend Fired when a drag operation is being ended (for example, by releasing a mouse button or hitting the escape key).
dragenter Fired when a dragged element or text selection enters a valid drop target.
dragexit Fired when an element is no longer the drag operation’s immediate selection target.
dragleave Fired when a dragged element or text selection leaves a valid drop target.
dragover Fired when an element or text selection is being dragged over a valid drop target
dragstart Fired when the user starts dragging an element or text selection.
drop Fired when an element or text selection is dropped on a valid drop target.

With these events a little bit of css magic a more user friendly experience can be created like highlighting the drop zones when the user starts to drag an element or changing the element’s text based on its state.

Demo:

https://jsfiddle.net/niranjan94/tkbcv3md/16/embedded/

External Resources:
Continue ReadingBuilding interactive elements with HTML and javascript: Drag and Drop

SASS for the theme based concept

Until yesterday, I was exploring all around the internet, to find the best possible way for the theme concept in the web app. The theme concept allows an organizer to choose the theme for the web app from the set of provided themes.

After some time, I realised that this awesomeness to the web app can be added by using Syntactically Awesome Stylesheets.

How SASS supports the theme concept?

 

In the web app, a folder name _scss is added which has the directory structure as shown

tree
_scss folder directory structure

There is a file _config.scss inside the _base folder that includes the SASS variables which are used in all the files after importing it.

Each of the SASS variables uses a flag !default at the end, which means it can be overwritten in any other file. This property of SASS leads to the theme concept.

//_.config.scss

@charset "UTF-8";
 
// Colors
$black: #000;
$white: #fff;
$red: #e2061c;
$gray-light: #c9c8c8;
$gray: #838282;
$gray-dark: #333333;
$blue: #253652;
 
// Corp-Colors
$corp-color: $white !default;
$corp-color-dark: darken($corp-color, 15%) !default;
$corp-color-second: $red !default;
$corp-color-second-dark: darken($corp-color-second, 15%) !default;
 
// Fontbasic
$base-font-size: 1.8 !default;
$base-font-family: Helvetica, Arial, Sans-Serif !default;
$base-font-color: $gray-dark !default;
 
// Border
$base-border-radius: 2px !default;
$rounded-border-radius: 50% !default;
$base-border-color: $gray !default;

The main file that includes all the required style is the application.scss. Here, $corp-color takes default value from  _config.scss. It can be overwritten by the themes.

//application.scss

@charset 'UTF-8';

// 1.Base
@import '_base/_config.scss';

/* Offsets for fixed navbar */
body {
 margin-top: 50px;
 background-color:$corp-color !important;
}

Making a light theme 

 

The light theme will overwrite the $corp-color value to $gray-light which is defined in _config.scss. This will change the background-color defined in application.scss to #c9c8c8. So, in this way a light theme is generated. The similar approach can be followed to generate the dark theme.

//_light.scss

@charset 'UTF-8';
@import '../../_base/config';
// 1.Overwrite stuff
$corp-color: $gray-light;

@import '../../application';

Making a dark theme 

 

//_dark.scss

@charset 'UTF-8';
@import '../../_base/config';
// 1.Overwrite stuff
$corp-color: $gray;

@import '../../application';

How to compile the CSS from SASS files ?

 

  1. We can easily compile these SASS files by using command
    sass /path/application.scss /path/schedule.css

    For generating light theme and dark theme:

    sass /path/_light.scss  /path/schedule.css
    sass /path/_dark.scss  /path/schedule.css

Optimization of Code

 

SASS is very powerful for optimizing the code. It allows the concepts such as nesting, mixins which reduce the line of code. I have rewritten schedule.css into application.scss to make it more optimized.

/* Adjustments for smaller screens */

@media (min-width: 450px) {
 body {
 font-size: 14px
 }
 .session {
   &-list{
     .label{
         font-size: 90%;
         padding: .2em .6em .3em;
           }
         }
    &-title {
         float:left;
         width: 75%;
         }
    &-location {
         float: right;
         width: 25%;
         text-align: right;
        }
  }
}

Further Exploration

 

This is one of the ways to deal with the SASS structure, but there are other resources that can be helpful in dealing with SASS projects.

Also, check out, Jeremy Hexon article here.

Continue ReadingSASS for the theme based concept

Swagger

Swagger is a specification for describing REST APIs. The main aim of Swagger is to provide a REST API definition format that is readable by both machines and humans.

You can think of two entities in a REST API: One the provider of API, and another the client using the API. Swagger essentially covers the gap between them by providing a format that is easy to use by the client and easy for the provider to define.

If not using Swagger, one would most certainly be creating the API first, writing the documentation (human-readable) with it. The client developer would read the documentation and use APIs as required. With Swagger, the specification can be considered as the document itself, helping both the client developer and the provider.

Here’s an example spec I wrote for our GET APIs at Organizer Server: https://gist.github.com/shivamMg/dacada0b45585bcd9cd0fbe4a722eddf

The format, although readable doesn’t really look what a client developer would be asking for.

Remember that the format is machine readable? What does it mean exactly?

Since the Swagger spec is a defined format, the provider can document it and people can write programs that understand the Swagger specification. Swagger itself comes with a set of tools (http://swagger.io/tools/) that use Swagger definitions created by the API provider to create SDKs for the clients to use.

Swagger-UI

One of our most used tools at our server is the Swagger UI (http://swagger.io/swagger-ui/).

It reads an API spec written in Swagger to generate corresponding UI that people can use to explore the APIs. Every API endpoint can have responses and parameters associated with it. For instance our Event endpoint at Server (“/events/:event_id”).

You can see how the UI displays the Model Schema, required parameters and possible response message.

Screenshot from 2016-06-07 19:08:21

Apart from documentation, Swagger UI provides the “Try it out!” tool that lets you make requests to the server for the corresponding API. This feature is incredibly useful for POST requests. No need for long curl commands in the terminal.

Here’s the Swagger config from our demo application: https://open-event.herokuapp.com/api/v2/swagger.json

The Swagger UI for this config can be found at https://open-event.herokuapp.com/api/v2

The UI for the example spec (gist) I linked before can be browsed here.

Swagger-js

https://github.com/swagger-api/swagger-js

Swagger-js is JS library that reads an API spec written in Swagger and provides an interface to the client developer to interact with the API. We will be using Swagger-js for Open Event Webapp.

Here’s an example to show you how it works. Let’s say the following endpoint returns (json) a list of events.

/events

The client developer can create a GET request and render the list with HTML.

$.getJSON("http://example.com/api/v2/events", function(data) {

  var events = "";
  $.each(data, function(i, event) {
    events += "<li id='event_" + i + "'>" + event.name + "</li>";
  });

  $("ul#events").html(events);
});

What if the provider moves the endpoint to “/event/all”? The client developer would need to change every instance of the URL to http://example.com/event/all.

Let’s now take the case of Swagger-js. With Swagger-js the client developer would essentially be writing programs to interact with the API Swagger spec defined by the provider, instead of directly consuming the API.

window.client = new SwaggerClient({
    url: "http://example.com/api/v2/swagger.json",
    success: function() {
      client.event.getEvents({
        responseContentType: 'application/json'
      }, function(data) {

        /* Create `events` string same as before */

        $("ul#events").html(events);
      });
    }
  });

 

The APIs at the Organizer server are getting more complex. Swagger helps in keeping the spec well defined.

That’s all for now. Hope you enjoyed the read.

Continue ReadingSwagger

Webapp: The generator for making schedule pages

Why a static HTML generator

 

Before we start working on more advanced features like push notifications and iCal exports etc, we have been working on getting a generator (a simple node.js script) up, that can take data for an event either in form of json files, or from a given API in open-event data format, and generate a schedule page.

It has been used to generate the programm page of OpenTechSummit 2016 (http://2016.opentechsummit.net/programm/)

It is based on the open-event-scraper   project of FOSSASIA, and some more features had been added when developing it for OTS16. Some of the new features include –

  • Ability to define copyright and license in the API/Json, and generator adds it in the footer
  • Ability to define sponsors (support for upto 3 levels are there), and the generator adds sponsor logos with links at the bottom of the page.
  • Ability to embed audio, slides and videos into the session cards.

How the process works

Right now if you take a look at the open-event-scraper project under opentechsummit (which is a fork from the FOSSASIA repo, and being used to develop the new features) , you’ll see the process goes like this –

  1. The scraper.py file scrapes data about sessions and speakers from an internal Google Sheet we have. Then the event.py file gets data about the event itself (copyright, links to social channels).

    This step is not needed if we are using a JSON API endpoint. This is needed only if the data source is a Google Sheet, then local JSON files are created.

  2. Once we have an endpoint or JSON files locally downloaded, there a node.js script – generator.js   which generates a static HTML page.
  3. The generated HTML page is based on a handelbars template – schedule.tpl where all the required markup is there.
  4. And finally there is our own stylesheet which is called schedule.css  and is a very lightweight styling addition, on top of what is majorly a vanilla bootstrap layout.

The road ahead

Going forward we will pull back in this source code to our main repo https://github.com/fossasia/open-event-webapp .

Then we’ll add some parameters that can be fed to generator.js when calling it, like  –

  • Name of event
  • Color scheme
  • URL of endpoints

This will have a minimal form-like frontend

We can host this on heroku then, where filling the form, will run the generator.js and the generated HTML and associated CSS files will be available as a zip.

Continue ReadingWebapp: The generator for making schedule pages

Self-Contained Folder For Webapp

The first version of Open-event-webapp will be a generator that will create the web app.

This week I have worked on various OTS issues that will become the basis for the web app. The OpenTechSummit web app works along with Open-event-scraper.

The web app can be generated in any empty repository and can be hosted with gh-pages by just running build.sh  file from the Open-event-scraper. This is the build.sh file I have written for doing this.

build file
build.sh

 

How can you create the webapp from scraper in your repository ?

 

1 . Replace the URL of the repository in git clone command.

git clone – – depth=1 < destination repo url > ots-repo

2 . Run the file build.sh from  Open-event-scraper.

./build.sh

 

Utility for transferring content using build.sh

 

The build.sh file is written to make a folder that is self-sufficient. It means it can be taken anywhere and it should work on its own.

The build.sh file first creates a clone of the destination repository in the local Open-event-scraper. It itself make the required folders inside the cloned repository and runs generator.js which provides index.html file according to the template schedule.tpl. The resync command that is known as remote sync is used to transfer the files remotely. A programm folder is created automatically that includes all the CSS, JS,  JSON and other important files used to run the web app.

Finally, the programm folder along with all necessary files is pushed to gh-pages branch of the destination repository.

Working Example

 

To create the web app I have replaced the destination URL as shown in the image.

4

After running the build.sh we will get the output as shown :

1 .

8
Programm folder ( self-sufficient)

2.

9
Sub folders inside Programm folder

That’s how a folder is generated which contains all the necessary files needed to run the web app.

Continue ReadingSelf-Contained Folder For Webapp

Bower Dependency & Configure .bowerrc to use Proxy

2 weeks into GSOC 2016, the project has really started to grow at a rapid pace. There have been a lot of issues related to UI as well as other different bugs. As we use more and more libraries for the user interface of the dashboard, we added bower dependencies to install the libraries.

Why Use Bower?

Some of the benefits of using bower dependencies are:

  • Simplify what might be called declarative dependency management; i.e. you declare your dependencies in bower.json so that other things can determine them easily
  • No need to commit dependencies to version control
  • Semantic versioning is used to help define a range of acceptable versions for a dependency, which makes it easy to update to newer versions within the defined range
  • No need to locate various builds (debug, minified, etc)
  • Simple to use different builds of a dependency for dev vs. prod
  • Bower lets you easily search and install libraries even locking to a specific version. Bower makes it easy to list and update dependencies.
  • You can distribute the bower.json file and everyone can get up to speed with a simple “bower install”

Prerequisites

There are some things you’ll need before you can start working with Bower:

  • The command line.
  • Node and NPM.
  • Git.
  • Global Installation. .

To install Bower globally:

$ npm install -g bower

bower.json

The `bower.json` file looks a lot like Node’s `package.json`. It is a manifest file that allows you to specify the various packages you want to download along with their version number and various features. This is how the `bower.json` looks for the open-event-orga-server project.Screenshot from 2016-06-04 05:25:08.png

.bowerrc

The `.bowerrc` file can be seen as a configure file for bower which dictates various rules to it. Though mostly this file is ignored and is used mainly to specify the directory where the libraries are to be installed instead of the default `bower_components`, however it can be used to do a lot more than that.

Screenshot from 2016-06-04 05:29:50.png

For example, one of the biggest problem you might face while installing using bower is if your organization/institute has a proxy network through all network connections pass. In that case bower install might not be able to install the libraries. However we can configure the .bowerrc to work via proxy.

Configure .bowerrc to use Proxy

To use http proxy, we can add 2 properties to .bowerrc which will make bower search and install libraries using the proxy. The properties are “proxy” and “https-proxy”. This 2 properties dictate that both http:// and https:// links are to be searched via the proxy. So, to make this settings, we can configure the .bowerrc something like this:
Screenshot from 2016-06-04 05:35:13.png

This should then fix your problem of proxy and will install your libraries as desired.

Continue ReadingBower Dependency & Configure .bowerrc to use Proxy

Better project definitions with User Stories and Themes

The Open Event project of FOSSASIA’s consists of a group of applications which involve making an application for managing events including the Open-Event Webapp, the Open-Event Android, Open-Event ios, and Open-Event Server of which I am working on.

The Open-Event Server is responsible for handling all the backend or the database aspect of the Open Event application. All the data for the application – the user details, the sessions details, the event details etc… is being managed by the server. But up till now we only had a basic working server with an prototype UI. In short not ready for people to use for their events . Thus my project was developed – Improving the Open-Event Organization project.

What is my project about?

The first versions of Open Event Server and the other subprojects – the Webapp and Android were not based on a user experience. So what we did this time was to create a user story for each of the projects. For the server, we created a user story wherein we decided what all functionalities will a user encounter when he /she uses our server. Thus step by step our project is being developed based on the user story created.

I have already solved a lot of issues which involve both – adding code to the backend as well as the frontend aspect. We have now a pretty good and properly functioning server with a login system involving Google and Facebook supported login. We also have a very awesome UI all thanks to gentelella. Presently we are working on the sessions part of the event creation wizard which is broken in various stages – Draft, Call for Papers, Schedule, Completed. The Draft part is almost finished and the Call for Papers part is going on.

Continue ReadingBetter project definitions with User Stories and Themes

Transmitting response from a Web page to a server.

{ Re-post from my Medium Post }

My project has pivoted from a standalone android app to a Web page that will generate a custom app for an event organizer’s use.

Read up here on what my project actually is.

So obviously some changes at the server are to be made to make this possible.

How are you planning to do it?

First of we started by providing a Web page that the organizers can use to submit information about the app they need to be built like the App’s name, the link to the API (for fetching the json files) and their email address (for mailing them the apk once it’s generated).

The HTML file for the same can be found here.

Some changes to the Travis build should also be made so that it can use this data for building.

From there on, the details submitted by them will be converted by a json object (using javascript) and further send to the open event server via a POST request where it will be written to a database.

We will be able to fetch this file from the database by the following link

openevent.com/api/v2/customapps/id.

Simultaneously one Travis build will also be trigger using the API that will auto build the latest commit, taking the modified json file data provided by the orga-server.

This configuration will be provided to Travis while the build time.

Cool, any difficulties yet!

One of the main challenges that we are facing is manually triggering the Travis build.

We can do this via the Travis API but that’s still in beta and also we are getting our head around on how to implement it.

I also had a tough time learning javascript and HTML for making the Web page and then I also have to read up on sending a POST request to the server via Ajax.

It’s a bit tough, but should be fun.

So, that was all for now, see you next week and all the best for your projects.✌

Continue ReadingTransmitting response from a Web page to a server.