Sorting language-translation in Open Event Server project using Jinja 2 dictsort.

Working on the Open Event Server project an issue about arranging language-translation listing in alphabetical order came up. To solve this issue of language listing arrangement i.e. #2817, I found the ‘d0_dictsort’ function in jinja2 to sort dictionaries. It is a defined in jinja2.filters. Python dicts are unsorted and in our web application we at times may want to order them by either their key or value. So this function comes handy.

This is what the function looks like:

do_dictsort(value, case_sensitive=False, by='key')

We can write them in three ways as:

{% for record in my_dictionary|dictsort %}
    case insensitive and sort the dict by key

{% for record in my_dictionary|dicsort(true) %}
    case sensitive and sort the dict by key

{% for record in my_dictionary|dictsort(false, 'value') %}
    sort the dict by value, normally sorted and case insensitive
  1.       The first way is easily understood that dict has been sorted by key not taking case into consideration. It is just in the same way written as dictsort(false).
  2.       Second way is basically the first being case sensitive. dictsort(true) here tells us that case is sensitive.
  3.      Third way is dictsort(false,’value’). The first parameter defines that case insensitive while second parameter defines that it is sorted by ‘value’.

The issues was to sort translation selector for the page in alphabetical order. The languages were stored in a dictionary which to change in order, I found this function very easy and useful.

Basically what we had was:

This is how the function was used in the code for the sort. Like this:

<ul class="dropdown-menu lang-list">
   {% for code in all-languages|dictsort(false,'value') %}
       <li><a  href="#" style="#969191" class="translate" id="{{ code[0] }}">{{  all_languages[code[0]] }}<>a><li>
    {% endfor %}
<ul>


Here:
{{ all_languages }} is the list which contained the languages like French, English, etc., which could be accessed with its global language code. code here(index for all_languages) is a tuple of {‘global_language_code’,’language’} (An example would be (‘fr’,’French’), so code[0] gave me the language_code.

Finally, the result:

This is one of the simple ways to sort your dictionaries.

Continue ReadingSorting language-translation in Open Event Server project using Jinja 2 dictsort.

Open Event Server: No (no-wrap) Ellipsis using jquery!

Yes, the title says it all i.e., Enabling multiple line ellipsis. This was used to solve an issue to keep Session abstract view within 200 characters (#3059) on FOSSASIA‘s Open Event Server project.

There is this one way to ellipsis a paragraph in html-css and that is by using the text-overflow property:

.div_class{
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}’’

But the downside of this is the one line ellipis. Eg: My name is Medozonuo. I am…..

And here you might pretty much want to ellipsis after a few characters in multiple lines, given that your div space is small and you do want to wrap your paragraph. Or maybe not.

So jquery to the rescue.

There are two ways you can easily do this multiple line ellipsis:

1) Height-Ellipsis (Using the do-while loop):

//script:
if ($('.div_class').height() > 100) {
    var words = $('.div_class').html().split(/\s+/);
    words.push('...');

    do {
        words.splice(-2, 1);
        $('.div_class').html( words.join(' ') );
    } while($('.div_class').height() > 100);
}

Here, you check for the div content’s height and split the paragraph after that certain height and add a “…”, do- while making sure that the paragraphs are in multiple lines and not in one single line. But checkout for that infinite loop.

2) Length-Ellipsis (Using substring function):  

//script:
$.each($('.div_class'), function() {
        if ($(this).html().length > 100) {
               var cropped_words = $(this).html();
               cropped_words = cropped_words.substring(0, 200) + "...";
               $(this).html(cropped_words);
        }
 });

Here, you check for the length/characters rather than the height, take in the substring of the content starting from 0-th character to the 200-th character and then add in extra “…”.

This is exactly how I used it in the code.

$.each($('.short_abstract',function() {
   if ($(this).html().length > 200) {
       var  words = $(this).html();
       words = words.substring(0,200 + "...";
       $(this).html(words);
    }
});


So ellipsing paragraphs over heights and lengths can be done using jQuery likewise.

Continue ReadingOpen Event Server: No (no-wrap) Ellipsis using jquery!

ember.js – the right choice for the Open Event Front-end

With the development of the API server for the Open Event project we needed to decide which framework to choose for the new Open Event front-end. With the plethora of javascript frameworks available, it got really difficult to decide, which one is actually the right choice. Every month a new framework arrives, and the existing ones keep actively updating themselves often. We decided to go with Ember.js. This article covers the emberJS framework and highlights its advantages over others and  demonstrates its usefulness.

EmberJS is an open-source JavaScript application front end framework for creating web applications, and uses Model-View-Controller (MVC) approach. The framework provides universal data binding. It’s focus lies on scalability.

Why is Ember JS great?

Convention over configuration – It does all the heavy lifting.

Ember JS mandates best practices, enforces naming conventions and generates the boilerplate code for the various components and routes itself. This has advantages other than uniformity. It is easier for other developers to join the project and start working right away, instead of spending hours on existing codebase to understand it, as the core structure of all ember apps is similar. To get an ember app started with the basic route, user doesn’t has to do much, ember does all the heavy lifting.

ember new my-app
ember server

After installing this is all it takes to create your app.

Ember CLI

Similar to Ruby on Rails, ember has a powerful CLI. It can be used to generate boiler plate codes for components, routes, tests and much more. Testing is possible via the CLI as well.

ember generate component my-component
ember generate route my-route
ember test

These are some of the examples which show how easy it is to manage the code via the ember CLI.

Tests.Tests.Tests.

Ember JS makes it incredibly easy to use test-first approach. Integration tests, acceptance tests, and unit tests are in built into the framework. And can be generated from the CLI itself, the documentation on them is well written and it’s really easy to customise them.

ember generate acceptance-test my-test

This is all it takes to set up the entire boiler plate for the test, which you can customise

Excellent documentation and guides

Ember JS has one of the best possible documentations available for a framework. The guides are a breeze to follow. It is highly recommended that, if starting out on ember, make the demo app from the official ember Guides. That should be enough to get familiar with ember.

Ember Guides is all you need to get started.

Ember Data

It sports one of the best implemented API data fetching capabilities. Fetching and using data in your app is a breeze. Ember comes with an inbuilt data management library Ember Data.

To generate a data model via ember CLI , all you have to do is

ember generate model my-model

Where is it being used?

Ember has a huge community and is being used all around. This article focuses on it’s salient features via the example of Open Event Orga Server project of FOSSASIA. The organizer server is primarily based on FLASK with jinja2 being used for rendering templates. At the small scale, it was efficient to have both the front end and backend of the server together, but as it grew larger in size with more refined features it became tough to keep track of all the minor edits and customizations of the front end and the code started to become complex in nature. And that gave birth to the new project Open Event Front End which is based on ember JS which will be covered in the next week.

With the orga server being converted into a fully functional API, the back end and the front end will be decoupled thereby making the code much cleaner and easy to understand for the other developers that may wish to contribute in the future. Also, since the new front end is being designed with ember JS, it’s UI will have a lot of enhanced features and enforcing uniformity across the design would be much easier with the help of components in ember. For instance, instead of making multiple copies of the same code, components are used to avoid repetition and ensure uniformity (change in one place will reflect everywhere)

<.div class="{{if isWide 'event wide ui grid row'}}">
  {{#if isWide}}
    {{#unless device.isMobile}}
      <.div class="ui card three wide computer six wide tablet column">
        <.a class="image" href="{{href-to 'public' event.identifier}}">
          {{widgets/safe-image src=(if event.large event.large event.placeholderUrl)}}
        <./a>
      <./div>
    {{/unless}}
  {{/if}}
  <.div class="ui card {{unless isWide 'event fluid' 'thirteen wide computer ten wide tablet sixteen wide mobile column'}}">
    {{#unless isWide}}
      <.a class="image" href="{{href-to 'public' event.identifier}}">
        {{widgets/safe-image src=(if event.large event.large event.placeholderUrl)}}
      <./a>
    {{/unless}}
    <.div class="main content">
      <.a class="header" href="{{href-to 'public' event.identifier}}">
        <.span>{{event.name}}<./span>
      <./a>
      <.div class="meta">
        <.span class="date">
          {{moment-format event.startTime 'ddd, MMM DD HH:mm A'}}
        <./span>
      <./div>
      <.div class="description">
        {{event.shortLocationName}}
      <./div>
    <./div>
    <.div class="extra content small text">
      <.span class="right floated">
        <.i role="button" class="share alternate link icon" {{action shareEvent event}}><./i>
      <./span>
      <.span>
        {{#if isYield}}
          {{yield}}
        {{else}}
          {{#each tags as |tag|}}
            <.a>{{tag}}<./a>
          {{/each}}
        {{/if}}
      <./span>
    <./div>
  <./div>
<./div>

This is a perfect example of the power of components in ember, this is a component for event information display in a card format which in addition to being rendered differently for various screen sizes can act differently based on passed parameters, thereby reducing the redundancy of writing separate components for the same.

Ember is a step forward towards the future of the web. With the help of Babel.js it is possible to write ES6/2015 syntax and not worry about it’s compatibility with the browsers. It will take care of it.

This is perfectly valid and will be compatible with majority of the supported browsers.

actions: {
  submit() {
    this.onValid(()=> {
    });
  }
}

 

Some references used for the blog article:

  1. https://www.codeschool.com/blog/2015/10/26/7-reasons-to-use-ember-js/
  2. https://www.quora.com/What-are-the-advantages-of-using-Ember-js
  3. Official Ember Guides: https://guides.emberjs.com

 
This page/product/etc is unaffiliated with the Ember project. Ember is a trademark of Tilde Inc

Continue Readingember.js – the right choice for the Open Event Front-end

DetachedInstanceError: Dealing with Celery, Flask’s app context and SQLAlchemy in the Open Event Server

In the open event server project, we had chosen to go with celery for async background tasks. From the official website,

What is celery?

Celery is an asynchronous task queue/job queue based on distributed message passing.

What are tasks?

The execution units, called tasks, are executed concurrently on a single or more worker servers using multiprocessing.

After the tasks had been set up, an error constantly came up whenever a task was called

The error was:

DetachedInstanceError: Instance <User at 0x7f358a4e9550> is not bound to a Session; attribute refresh operation cannot proceed

The above error usually occurs when you try to access the session object after it has been closed. It may have been closed by an explicit session.close() call or after committing the session with session.commit().

The celery tasks in question were performing some database operations. So the first thought was that maybe these operations might be causing the error. To test this theory, the celery task was changed to :

@celery.task(name='lorem.ipsum')
def lorem_ipsum():
    pass

But sadly, the error still remained. This proves that the celery task was just fine and the session was being closed whenever the celery task was called. The method in which the celery task was being called was of the following form:

def restore_session(session_id):
    session = DataGetter.get_session(session_id)
    session.deleted_at = None
    lorem_ipsum.delay()
    save_to_db(session, "Session restored from Trash")
    update_version(session.event_id, False, 'sessions_ver')


In our app, the app_context was not being passed whenever a celery task was initiated. Thus, the celery task, whenever called, closed the previous app_context eventually closing the session along with it. The solution to this error would be to follow the pattern as suggested on http://flask.pocoo.org/docs/0.12/patterns/celery/.

def make_celery(app):
    celery = Celery(app.import_name, broker=app.config['CELERY_BROKER_URL'])
    celery.conf.update(app.config)
    task_base = celery.Task

    class ContextTask(task_base):
        abstract = True

        def __call__(self, *args, **kwargs):
            if current_app.config['TESTING']:
                with app.test_request_context():
                    return task_base.__call__(self, *args, **kwargs)
            with app.app_context():
                return task_base.__call__(self, *args, **kwargs)

    celery.Task = ContextTask
    return celery

celery = make_celery(current_app)


The __call__ method ensures that celery task is provided with proper app context to work with.

 

Continue ReadingDetachedInstanceError: Dealing with Celery, Flask’s app context and SQLAlchemy in the Open Event Server

Event-driven programming in Flask with Blinker signals

Setting up blinker:

The Open Event Project offers event managers a platform to organize all kinds of events including concerts, conferences, summits and regular meetups. In the server part of the project, the issue at hand was to perform multiple tasks in background (we use celery for this) whenever some changes occurred within the event, or the speakers/sessions associated with the event.

The usual approach to this would be applying a function call after any relevant changes are made. But the statements making these changes were distributed all over the project at multiple places. It would be cumbersome to add 3-4 function calls (which are irrelevant to the function they are being executed) in so may places. Moreover, the code would get unstructured with this and it would be really hard to maintain this code over time.

That’s when signals came to our rescue. From Flask 0.6, there is integrated support for signalling in Flask, refer http://flask.pocoo.org/docs/latest/signals/ . The Blinker library is used here to implement signals. If you’re coming from some other language, signals are analogous to events.

Given below is the code to create named signals in a custom namespace:


from blinker import Namespace

event_signals = Namespace()
speakers_modified = event_signals.signal('event_json_modified')

If you want to emit a signal, you can do so by calling the send() method:


speakers_modified.send(current_app._get_current_object(), event_id=event.id, speaker_id=speaker.id)

From the user guide itself:

“ Try to always pick a good sender. If you have a class that is emitting a signal, pass self as sender. If you are emitting a signal from a random function, you can pass current_app._get_current_object() as sender. “

To subscribe to a signal, blinker provides neat decorator based signal subscriptions.


@speakers_modified.connect
def name_of_signal_handler(app, **kwargs):

 

Some Design Decisions:

When sending the signal, the signal may be sending lots of information, which your signal may or may not want. e.g when you have multiple subscribers listening to the same signal. Some of the information sent by the signal may not be of use to your specific function. Thus we decided to enforce the pattern below to ensure flexibility throughout the project.


@speakers_modified.connect
def new_handler(app, **kwargs):
# do whatever you want to do with kwargs['event_id']

In this case, the function new_handler needs to perform some task solely based on the event_id. If the function was of the form def new_handler(app, event_id), an error would be raised by the app. A big plus of this approach, if you want to send some more info with the signal, for the sake of example, if you also want to send speaker_name along with the signal, this pattern ensures that no error is raised by any of the subscribers defined before this change was made.

When to use signals and when not ?

The call to send a signal will of course be lying in another function itself. The signal and the function should be independent of each other. If the task done by any of the signal subscribers, even remotely affects your current function, a signal shouldn’t be used, use a function call instead.

How to turn off signals while testing?

When in testing mode, signals may slow down your testing as unnecessary signals subscribers which are completely independent from the function being tested will be executed numerous times. To turn off executing the signal subscribers, you have to make a small change in the send function of the blinker library.

Below is what we have done. The approach to turn it off may differ from project to project as the method of testing differs. Refer https://github.com/jek/blinker/blob/master/blinker/base.py#L241 for the original function.


def new_send(self, *sender, **kwargs):
    if len(sender) == 0:
        sender = None
    elif len(sender) > 1:
        raise TypeError('send() accepts only one positional argument, '
                        '%s given' % len(sender))
    else:
        sender = sender[0]
    # only this line was changed
    if not self.receivers or app.config['TESTING']:
        return []
    else:
        return [(receiver, receiver(sender, **kwargs))
                for receiver in self.receivers_for(sender)]
                
Signal.send = new_send

event_signals = Namespace
# and so on ....

That’s all for now. Have some fun signaling 😉 .

 

Continue ReadingEvent-driven programming in Flask with Blinker signals

Exporting Speakers and Sessions list download as CSV in the Open Event Server

In an event management system there is a need for organizers to get speakers data from the system and be able to use and process it elsewhere. Organizers might need a list of emails, phone numbers or other information. An “export” of speakers and sessions in a CSV file that can be opened in any spreadsheet application is a good way to obtain this data. Therefore we implemented an export as CSV funtion in the Open Event Server.

 

Now the Open Event Orga Server allows event organizers to export a list of speakers and details about their sessions such as Session status, Session title, Session speaker, Session track.

The speaker csv includes details about the speaker such as Name, Sessions, Email, Status, Mobile, Organisation, and Position.

 

How did we implement it:

When clicking on the Export As CSV button on either of the pages it calls the download_speakers_as_csv / download_sessions_as_csv  from speakers / sessions tab .

The Speaker’s Tab

Session’s Tab

The functions are defined in sessions.py file.

First we get data from the sessions table by event_id and the event details from event table :

sessions = DataGetter.get_sessions_by_event_id(event_id)

# This is for getting event name to put as the filename

event = DataGetter.get_event(event_id)

 

Then we go on with creating the csv file.

We iterate through all the sessions and find the speaker associated with each. We save each row in a new list named data and after each iteration add it to a main list .

main = [["Session Title", "Session Speakers", \
         "Session Track", "Session Abstract", "Email Sent"]]
for session in sessions:
    if not session.deleted_at:
        data = [session.title + " (" + session.state + ")" if session.title else '']
        if session.speakers:
            inSession = ''
            for speaker in session.speakers:
                if speaker.name:
                    inSession += (speaker.name + ', ')
            data.append(inSession[:-2])
        data.append(session.track.name if session.track.name else '')
        data.append(strip_tags(session.short_abstract) if session.short_abstract else '')
        data.append('Yes' if session.state_email_sent else 'No')
        main.append(data)

In the last part of the code python’s csv  module is used to create a csv file out of the nested lists. The csv module takes care of properly escaping the characters such as punctuation marks ( like comma ) and appending a newline character in the end of each list .

Snippet of Code from sessions.py file

 

In the last few lines of this code section , you can see the headers being added , necessary for downloading the file on the user’s end.

The make_response function is imported from flask package.

make_response : Converts the return value from a view function to a real response object  ( as documented here).

 

The  exported filename format is like :

‘%event-name%-Speakers.csv’ , ‘%event-name%-Sessions.csv

Thus getting the list of speakers and session details as csv files.

Speaker’s CSV

Session’s CSV

 

Continue ReadingExporting Speakers and Sessions list download as CSV in the Open Event Server

Using Cloud storage for event exports

Open-event orga server provides the ability to the organizer to create a complete export of the event they created. Currently, when an organizer triggers the export in orga server, A celery job is set to complete the export task resulting asynchronous completion of the job. Organizer gets the download button enabled once export is ready.

Till now the main issue was related to storage of those export zip files. All exported zip files were stored directly in local storage and that even not by using storage module created under orga server.

local storage path

On a mission to solve this, I made three simple steps that I followed to solve this issue.

These three steps were:

  1. Wait for shutil.make_archive to complete archive and store it in local storage.
  2. Copy the created archive to storage ( specified by user )
  3. Delete local archive created.

The easiest part here was to make these files upload to different storage ( s3, gs, local) as we already have storage helper

def upload(uploaded_file, key, **kwargs):
    """
    Upload handler
    """

The most important logic of this issue resides to this code snippet.

    dir_path = dir_path + ".zip"
 
     storage_path = UPLOAD_PATHS['exports']['zip'].format(
         event_id = event_id
     )
     uploaded_file = UploadedFile(dir_path, dir_path.rsplit('/', 1)[1])
     storage_url = upload(uploaded_file, storage_path)
 
    if get_settings()['storage_place'] != "s3" or get_settings()['storage_place'] != 'gs':
        storage_url = app.config['BASE_DIR'] + storage_url.replace("/serve_","/")
    return storage_url

From above snippet, it is clear that we are extending the process of creating the zip. Once the zip is created we will make storage path for cloud storage and upload it. Only one thing will take the time to understand here is the last second and third line of above snippet.

if get_settings()['storage_place'] != "s3" or get_settings()['storage_place'] != 'gs':
        storage_url = app.config['BASE_DIR'] + storage_url.replace("/serve_","/")

Initial the plan was simple to serve the files through “serve_static” but then the test cases were expecting a file at this location thus I had to remove “serve_” part for local storage and then it works fine on those three steps.

Next thing on this storage process need to be discussed is the feature to delete old exports. I believe one reason to keep them would be an old backup of your event will be always there with us at our cloud storage.

Continue ReadingUsing Cloud storage for event exports

Ticket Ordering or Positioning (back-end)

One of the many feature requests that we got for our open event organizer server or the eventyay website is ticket ordering. The event organizers wanted to show the tickets in a particular order in the website and wanted to control the ordering of the ticket. This was a common request by many and also an important enhancement. There were two main things to deal with when ticket ordering was concerned. Firstly, how do we store the position of the ticket in the set of tickets. Secondly, we needed to give an UI in the event creation/edit wizard to control the order or position of a ticket. In this blog, I will talk about how we store the position of the tickets in the backend and use it to show in our public page of the event.

Continue ReadingTicket Ordering or Positioning (back-end)

The Open Event Ecosystem

This post contains data collected and compiled from various sources that include (but not limited to) project readme files, my presentation from FOSSASIA 17, Wikipedia, my head.

This aims to be a place for any new contributor to know the basics about the entire Open Event Project.

This could also help newcomers choose an Open Event sub-project of their liking and start contributing .

The Open Event Project offers event managers a platform to organise all kinds of events including concerts, conferences, summits and regular meet-ups. The components support organisers in all stages from event planning to publishing, marketing and ticket sales. Automated web and mobile apps help attendees to get information easily.

There are seven components of the project:

  • Open Event Universal Format – A standard JSON Schema specification for data sharing/transfer/import/export between various components of Open Event.
  • Open Event API Server – The core of the project. The API Server and database.
  • Open Event Frontend – The primary frontend for the Open Event API Server where organisers, speakers and attendees can sign-up and perform various functions.
  • Open Event Organiser App – A cross-platform mobile application for Organisers with ticketing, checking and quick management capabilities.
  • Open Event Android application generator – An android application generator that allows event organisers to generate customised android applications for their events.
  • Open Event Web application generator – A web application generator that allows event organisers to generate customised static easily-hostable web pages for their events.
  • Open Event Data scrappers – A scrapper that allows users to scrape events from popular websites such as eventbrite into the Open Event Universal Format for it to be imported into Open Event.

Open Event Universal Format

A standard JSON Schema specification for data sharing/transfer/import/export between various components of Open Event.

Repository: fossasia/open-event.

Open Event API Server

The core of the project. The API Server and database.

Repository: fossasia/open-event-orga-server.

The system exposes a RESTful API to fetch and modify data. It also provides endpoints that allow organisers to import and export event data in a standard compressed file format that includes the event data in JSON (Open Event Universal Format) and binary media files like images and audio.

The Open Event API Server comprises of:

  • Flask web framework – Flask is a microframework for python to create web applications. Flask also provided us with a Jinja2 templating engine.
  • PostgreSQL – Our database. PostgreSQL is an open-sourced Object-relational database management system (ORDBMS). We use SQLAlchemy ORM to communicate with the database and perform database operations.
  • Celery – Celery is a Distributed Task Queue. It allows us to run time consuming and/or resource intensive tasks in the background (or) on a separate worker server. We use celery to process event import/export tasks to process email send requests.
  • Redis – Redis is an in-memory data structure store. It’s generally used for caching and for message brokering b/w different services due it’s insanely fast read-write speeds (since it’s an in-memory data store). We use it for caching results of time-consuming less volatile database calls and also for brokering jobs and their statuses b/w the web server and Celery task queue.

In the near future, we plan to implement more additional components too.

  • Elasticsearch – a distributed, RESTful search and analytics engine. To start with, we’ll be using it to index our events and provide much fast search results to the user.
  • Kibana – data visualization and analytics plugin for elasticsearch. It will allow us to better understand search trends, user demographics and help us provide a better user experience.

We’re now in the process of slowly phasing out the Open Event Server’s existing UI and keep it only as an API Server since we’re moving towards an API-Centric approach with a Fresh new Open Event Frontend.

The Open Event server’s repository contains multiple branches each serving a specific purpose.

  • development – All development goes on in this branch. If you’re making a contribution, please make a pull request to development. PRs to must pass a build check and a unit-test check on Travis (https://open-event-dev.herokuapp.com – Is running off the development branch. It is hosted on Heroku.). This is probably the most unstable branch of all.
  • master – This contains shipped code. After significant features/bug-fixes are accumulated on development, we make a version update, and make a release. (https://eventyay.com – Is running off the master branch. (whichever is the latest release.) Hosted on Google Cloud Platform (Google Container Engine + Kubernetes).
  • staging – This branch is mainly for testing eventyay server configurations on a staging server without affecting the production environment. Push access is restricted to the devops team.
  • gh-pages – This contains the documentation website on http://dev.eventyay.com. The site is build automatically on each commit in the development branch through a script and using travis. It includes the md files of the Readme and /docs folder.

The Open Event Server has Unit tests to ensure each part of the server works as expected. This is also part of our workflow. So, every PR made to the repository, is tested by running the Unit tests and the code coverage is reported on the PR itself. (We use travis and codecov for continuous integration and code coverage reporting respectively).

Open Event Frontend

The primary frontend for the Open Event API Server where organisers, speakers and attendees can sign-up and perform various functions.

Repository: fossasia/open-event-frontend.

Open Event frontend is built on Ember.js – A javascript web application framework. Ember.js uses Ember data – its data persistence module to communicate with the Open Event API Server via the exposed RESTful endpoints.

The frontend is built upon components that are re-usable across various parts of the application. This reduces code duplication and increases maintainability.

The frontend also has various services to share data and functionality b/w components/routes/controllers.

Each merge into the Open Event frontend repository triggers two deployments:

Currently, both the staging and development use the development branch since the frontend is still under active development. Once we reach the release stage, staging & production deployments will start using the master branch just like the Open Event API Server.

As a part of the development workflow, to ensure proper code-styles throughout the project, and to prevent regressions, the project has Acceptance tests, Integration tests, Unit tests and lint checks on both javascript (*.js) and handlebar files (*.hbs). These tests are run for every PR made to the repository. (We use travis and codecov for continuous integration and code coverage reporting respectively).

Open Event Organizer App

A cross-platform mobile application for Organiser with ticketing, checking and quick management capabilities.

Repository: fossasia/open-event-orga-app.

The organiser application is a mobile application that can run on Android, iOS and Windows Phone. It is built using Ionic Framework – cross-platform app development framework. The app uses the RESTful APIs exposed by the Open Event API Server to get data and perform operations.

The core features of this application are

  • Scan a QR code from an attendee’s ticket to view information about the attendee and to check him/her in.
  • Check-in attendees (Attendees can be searched for using name and/or email)
  • Continuous data sync with the Open Event Organiser Server

Other planned feature include:

  • Overview of sales – The organisers can see how their event is performing with just a few taps
  • Overview of tracks and sessions – They can see what sessions are next and can use that information to (for example) get everything ready for that session.
  • Quick session re-scheduling – They can re-schedule sessions if required. This should also trigger notification to participant that have registered for that event.
  • Push notifications for certain triggers – (for example) Organisers can get notifications if any session proposal is received.

This project has only one development branch (master). Each commit to that branch triggers an apk deployment to the apk branch via Travis.

Open Event Android Application Generator

An android application generator that allows event organisers to generate customised android applications for their events.

Repository: fossasia/open-event-android.

This project consists of two components.

  • The App Generator – A web application that is hosted on a server and generates an event Android app from a zip with JSON and binary files (examples here) or through an API.
  • A generic Android app – the output of the app generator. The mobile app can be installed on any Android device for browsing information about the event. Updates can be made automatically through API endpoint connections from an online source (e.g. server), which needs to defined in the provided event zip with the JSON files. The Android app has a standard configuration file, that sets the details of the app (e.g. color scheme, logo of event, link to JSON app data).

  • Flask web framework – Flask is a microframework for python to create web applications. Flask also provided us with a Jinja2 templating engine.
  • Celery – Celery is a Distributed Task Queue. It allows us to run time consuming and/or resource intensive tasks in the background (or) on a separate worker server. The android application compile and build process is run as a celery job. This also allows multiple users to simultaneously use the generator.
  • Redis – Redis is an in-memory data structure store. It’s generally used for caching and for message brokering b/w different services due it’s insanely fast read-write speeds (since it’s an in-memory data store). We use it for brokering jobs and their statuses b/w the web server and Celery task queue.
  • Java Development Kit (JDK) – Java Development Kit provides us with a set of tools consisting of (but not limited to) a compiler, runtime environment, loader which enables us to compiler, build and run java based applications.
  • Android SDK Tools – The Android SDK Toolset provides us with Android API libraries, debugging tools, emulation capabilities and other tools that are needed to develop, build and run java based android applications.
  • Gradle Build Tool – Gradle is an open source build automation system. It allows developers to define a build process as a set of tasks that can be easily executed on any machine with predictable outputs as long as the gradle files are available.

As with other projects, this also has multiple branches each serving a different purpose

  • development – All development goes on in this branch. If you’re making a contribution, you are supposed to make a pull request to development. PRs to master must pass a build check and a unit-test (app/src/test) check on Travis.
  • master – This contains shipped code. After significant features/bugfixes are accumulated on development, we make a version update, and make a release. All tagged commits on master branch will automatically generate a release on Github with a copy of fDroid-debug and GooglePlay-debug apks.
  • apk – This branch contains two apk’s, that are automatically generated on merged pull request a) from the dev branch and b) from the master branch using the Open Event sample of the FOSSASIA Summit. This branch also assists in deploying the generator to http://droidgen.eventyay.com by triggering a travis build every time an apk is pushed to this branch. The reason this type of a round-about way was implemented is that, travis doesn’t allow android and docker builds on the same branch. So, we’re forced to use the apk branch to do the docker build for us.

Open Event Web application generator

A web application generator that allows event organisers to generate customised static easily-hostable web pages for their events.

Repository: fossasia/open-event-webapp.

The Open Event Web App project has two components :

  • An event website generator – A web application that generates the event website based on event data provided by the user either in the form of an archive as per the Open Event Universal Format or an API Endpoint to an Open Event API Server instance
  • A generic web application – This will be customised and additional pages will be generated from a set of templates by the generator based on the provided event data. The generated website bundle can be hosted on any static hosting provider (Github pages, any simple web hosting service, or any web server that can serve HTML files etc).

The generator also gives you the ability to directly upload the generated files to any server (via FTP) or to the gh-pages branch of any repository on GitHub.

  • Express.js – A web application framework for Node.js. The web application generator’s user-facing frontend runs on Express.js framework.
  • Socket.IO – A javascript library for real-time web applications. It allows a client and a server to communicate with each other simultaneously in a real-time manner. (Confusing ? If you wanna build something like a chat-room … you’d need something like Socket.IO). The web application generator uses Socket.IO to handle multiple clients and also to show the correct progress of the website generation to each of those clients in a real-time manner.
  • The web generator also uses SASS – which adds awesome features (Superpowers as their site says) to good-old CS, and Handlebars – which is a templating engine that let’s you easily generate HTML output based on a templates from a given javascript object.

The branches are similar to other projects under Open Event.

  • development – All development goes on in this branch. If you’re making a contribution, you are supposed to make a pull request to development. PRs to master must pass a build check and a unit-test (test/serverTest.js) check on Travis. Gets deployed automatically to https://opev-webgen-dev.herokuapp.com .
  • master – This contains shipped code. After significant features/bugfixes are accumulated on development, we make a version update, and make a release.

Open Event Data Scrappers

A scrapper that allows users to scrape events from popular websites such as eventbrite into the Open Event Universal Format for it to be imported into Open Event.

Repository: fossasia/event-collect.

As of now, only eventbrite is supported for data scrapping. This allows new users of Open Event to import their events from other ticketing/event management websites very easily. The scrapper accepts a query from the user, and gets the event page for that query on eventbrite, parses the HTML DOM to get the required data and compiles everything into the Open Event Universal Format so that it could be imported into Open Event.

The scrapper is written in Python and uses Beautiful Soup to parse the DOM.

Future plans include combining fossasia/query-server, Open Event server and event collect to enable automatic import of events from other websites based on user searches on eventyay.


The Open Event Ecosystem is vast and has plenty of contribution opportunities to both beginners and experts alike. Starting with contributions is as easy as picking a project, choosing an issue and submitting a PR. No strings attached. (Oh wait. there is just one string attached. Ensure you read & follow the “Best Practices at FOSSASIA Guide”)

{ Repost from my personal blog @ https://blog.codezero.xyz/open-event-ecosystem }

Continue ReadingThe Open Event Ecosystem

Open Source Developer Guide and Best Practices at FOSSASIA

I would request you to please guide me as to how can I collaborate with you and also how can I contribute effectively to the organization.

At times I might get up to 20 private mails per day about “How to contribute to Open Source”. Usually I will direct developers to our mailing list or chat channels if they are asking about a specific project. But, how do contributions work at FOSSASIA? How can new developers join projects effectively? We have tried many different ways and spent a lot of time communicating with newcomers, many of them new to Git and Open Source development.

Over the years we have gotten better at helping new developers, designers and other contributors to join up. We have more than 1300 registered developers in our GitHub organization today. Not all of them can contribute every day, but we do have thousands of commits every year.

So, how are we able to scale up? I believe one reason are our Best Practices. We didn’t have a document “FOSSASIA Best Practices” yet, but in our daily work we have established excellent (mostly unwritten) best practices, that I would like to share in a concise form here now as a reference for new developers.

Happy to get your feedback and comments.

Development Best Practices at FOSSASIA

Culture and Communication

  • Please adapt your language to non-native English speakers and be super friendly. Remember we are an international community with contributors mainly from Asia and Europe. We are not used to swearing and will mostly understand words literally. At all times ensure your tone stays appropriate and friendly in the FOSSASIA community.
  • Stay modest. Sometimes newcomers already have an amazing knowledge in some areas. Still remember, it is no reason to be arrogant. Even the best developer does not know everything.
  • Be nice and welcoming. Why not add “please” in an issue or a comment “Thank you” in a pull request if someone did a good job? Show your appreciation for the good work of your co-developers.
  • If you are involved in a topic you don’t understand yet, try to learn yourself as much as possible from public channels (wikipedia, stackoverflow) but also do not hesitate to ask questions to other developers.

Communication Channels

Every project at FOSSASIA has its own channels. Many projects use Gitter, some Slack or IRC. Usually you will find information of the main communication channels of a project in the Readme.md.

While we are a community of Open Source and Free Software developers we still reserve our right to use whatever tools we deem necessary to help us to achieve our goal of developing the best possible Open Technologies – software and hardware. It is one step at a time 🙂

Private and Public Chat or Issue Tracker

Chat is a great way to connect with other contributors, but not all contributors are there all the time (consider time difference and personal schedules) and they are not always available to chat. Chat tends to be unstructured and with lots of people in a room there are often a number of threads. Therefore chat is great for help on setup issues and things where you got stuck.

Do not use chat for feature requests and detailed discussions on issues. These things are best for the issue tracker, where people from different timezones can join and where a focused conversation on one specific topic can happen.

Some people try to overcome the unstructured chats by switching to private communication. This shuts out other contributors who might have similar issues. A result I often observed is also, that contributors will bring up arguments in discussions like “I have discussed this already with xyz privately and he agrees”. Other contributors have not seen this discussion if it has not been taken place in public and we haven’t seen the arguments. We don’t know if xyz really agrees or if it was misunderstood. Private conversations are not transparent. Surely, there are cases where private chat is needed, e.g. for specific deployment questions of projects, but whenever you talk about development, please switch to public chat or open an issue.

Feature Requests and Bug Reports

  • Some newcomers are not accustomed to issue trackers and might try to inform developers on the mailing list, chat or even write private emails about bugs and features, but the right place to do this is: The issue tracker of a project.
  • Any bug or feature, please open an issue in the issue tracker right away and indicate if you want to work on it yourself.
  • Please include all relevant information when you submit an issue and wherever possible a link, information about the code that has issues and a screenshot.
  • When you file a bug report on the issue tracker, make sure you add steps to reproduce it. Especially if that bug is some weird/rare one.

Join Development

  • Before you join development, please set up the project on your local machine, run it and go through the application completely. Press on any button you can find and see where it leads to. Explore. (Don’t worry. Nothing will happen to the app or to you due to the exploring. Only thing that will happen is, you’ll be more familiar with what is where and might even get some cool ideas on how to improve various aspects of the app.).
  • If you would like to work on an issue, drop in a comment at the issue. If it is already assigned to someone, but there is no sign of any work being done, please free to drop in a comment so that the issue can be assigned to you if the previous assignee has dropped it entirely.

Commits/Pull Requests

  • All pull requests need to be associated to an issue.
  • All PRs need to be assigned to the person working on it.
  • If an issue cannot be completed in less than a day, it should be broken up into multiple issues.
  • Make pull requests from your own forks (even if you have write rights to the repository, do not create new branches, develop on your own branches).
  • State the actual change or enhancement in the commit message of PRs (do not just state “Fixes issue #123”).
  • Add the issue number into the description (this helps to speed up reviews as reviewers can simply click to get more info in the issue itself).
  • Write clear meaningful git commit messages (Do read http://chris.beams.io/posts/git-commit/).
  • Match pull requests with issues and make sure your pull requests description contains GitHub’s special keyword references that automatically close the related issue when the pull request is merged. (More info at https://github.com/blog/1506-closing-issues-via-pull-requests).
  • When you make very minor changes to a pull request of yours (like for example fixing a failing travis build or some small style corrections or minor changes requested by reviewers) make sure you squash your commits afterwards so that you don’t have an absurd number of commits for a very small fix (Learn how to squash at https://davidwalsh.name/squash-commits-git).
  • Add a screenshot if you changed anything in the UI of a project. When you’re submitting a pull request for a UI-related issue, please add a screenshot of your change or a link to a deployment where it can be tested out along with your pull request. It makes it much easier for the reviewers and helps to speed up the process. You’ll also get reviews quicker.
  • Add a link to your deployment of the project, where reviewers can check out what you have changed (especially for smaller changes this is very helpful as the reviewer might not even need to set up the system itself and test it. Again this speeds up the review process a lot).
  • Always ensure CI and tests are successful.
  • Help to resolve merge conflicts (especially if there are several PRs at the same time, merge conflicts are common. Help the reviewers and solve merge conflicts to speed up the process.).
  • Merging Pull Requests should only happen if at least two contributors reviewed the PR and approved it.

Scope of Issues and Commits

  • Stay focused on the issue and its specifics: Sometimes it is tempting to do more changes in a pull request and simply add a nice little feature after mentioning it in the issue tracker. Please do not do this. Contributors will look at the title of issues usually to check if it is relevant for them. For example, if an issue is about changing a font, do not also change the color even if this seems like small change to you. Many projects have a design template and standard colors etc. that they want to achieve. So your changes might need to be discussed in a bigger setting even if they seem small to you. Same applies to many other areas.
  • Do only the changes in a pull request that are mentioned in the issue. Do not change anything else without ever mentioning it (remember match issues with pull requests).

Branch Policies

Most FOSSASIA Projects have:

  • a development branch (which is the working branch. Please commit to this branch.) and
  • a master branch (which is the stable branch).

Some projects also keep additional branches e.g.:

  • gh-pages for documentation purposes (often autogenerated from md-files in docs folder)
  • apk branches for Android apps (often autogenerated with travis).

Getting Started

  • Newcomers are sometimes afraid to make a pull request. Don’t be! It is the responsibility of reviewers to review them. And Git is a beautiful tool when it comes to reverting pull requests with errors.
  • In simple issues keep it simple and “simply” contribute, e.g. in an issue “change the color of the button from green to red”, there is no need to mention and ask “here is a screenshot where I changed the color to red. Should I make a PR now?”. Just make the pull request and wait for the feedback of the reviewer.
  • Take on responsibility early and help to review other contributions. Even though you do not have write access in a repository you can already help to review other commits.

Documentation

  • Please ensure you provide information about your code and the functioning of your app as part of every code contribution.
  • Add information on technologies and the code into the code itself and into documentation files e.g. into the Readme.md or /docs folder. Documentation is not a thing that should be done at the end after a few weeks or months of coding! Documentation is a continuous effort at every step of software development.
  • If you add new libraries or technologies add information about them into the Readme file.
  • If you implement a different design or change the css in a web project, please add information to the design specifications/template. If there are not any design specifications in the project yet, why not start them and add a section into the Readme.md to start with?
  • Always help to keep documentation up to date and make it easy for new contributors to join the project.

 

Thank you for helping to define many of the practices while working on the Open Event project to the developer team and for additional input and links to Niranjan Rajendran.

Links to Other Resources

Continue ReadingOpen Source Developer Guide and Best Practices at FOSSASIA