Python / JS Full Stack Developer for Open Event Project


As a Full Stack Engineer at FOSSASIA, you’ll work together with a global community to develop the Open Event project and to maintain our web service at Our services are entirely Free/Open Source. We use Flask as a backend and Ember.js (transitioning to React) as a frontend technology. The system is deployed on a Hetzner cloud server. You’ll own what you build, making technical decisions and applying our best practices to every piece of code. The team uses scrum emails for the daily standup and Gitter for continuous chat communication.

Candidates who have started contributing code to one of our projects and to the Open Event backend and frontend specifically will have an advantage.

Number of Positions: Several

[Apply Here]

About the team

  • We are a team working with a community of FOSS developers
  • We work remotely in different timezones
  • Our system is built using Ember (frontend) and we need someone who can help us to transition to ReactJS
  • We use Flask/Python for the backend
  • We have an informal and collaborative environment
  • We embrace Continuous Integration


  • Assume leadership and responsibility for the technical tasks and deliverables
  • Become project owner of Open Event development and provide daily code commits
  • Deploy project on the server using Docker
  • Write unit tests for all portions of our applications
  • Automate the software deployment process
  • Support community developers and review PRs
  • Work according to FOSSASIA Best Practices
  • Provide daily scrums, code contributions and communicate on chat
  • Participate and lead weekly developer meeting
  • Ensure related apps (Android/iOS) work with APIs and review PRs
  • Take on responsibilities in other FOSSASIA projects as needed


  • Experience working in a remote setting, or with a remote team and across multiple time zones
  • Professional experience using HTML, CSS, and Javascript
  • Experience with Flask/Python
  • Experience with Ember.js and ReactJS (or the desire to learn it)
  • Experience with Continuous Integration and Docker
  • Understanding of best practices for web development and software design
  • Not afraid of going deep on backend code to understand features
  • Enjoy writing tested and modular code
  • Working time overlaps with European and Singapore time
  • You have good spoken/written English
  • Self-motivated and independent


Please check out the project on GitHub before applying.

Open Event Server:

Open Event Frontend:


Depending on position or freelance agreement.


  • Visit Singapore and participate in annual FOSSASIA Summit
  • Participate in local Open Source meetups and conferences
  • Work with a community of enthusiastic software developers




Please apply through our online form.

[Submit Application Here]


Continue ReadingPython / JS Full Stack Developer for Open Event Project

Addition Of Landing Pages For Mobile Apps

In this Blog-Post, I will showcase the landing pages on the Android frontend of Eventyay. As the Eventyay Android App has been launched on Play Store as well as F-Droid, We needed to make sure users know that they can access all the details regarding their event on their phones too. Now EventYay features two landing pages for each of its mobile apps :

EventYay Attendee App 

EventYay Orga App

Addition Of Landing Pages was a 3-Step Procedure, which is stated below :

  1. ) Defining The Needed Routes and Making Space in Footer.
  2. ) Writing the Code and Designing the Layout for the web-page.
  3. ) Writing Integration Tests for both of the pages.

I will explain each one of the processes involved in making Landing Pages for Mobile Apps in brief in this Blog-Post.

1. Defining The Needed Routes and Making Space in Footer.

To add any web-page in the Open-Event Frontend , we need to define its route in the Application Router File. The code snippet which adds them is:-

// app/router.js {

After successfully defining the routes, We need to create the HandleBars for the corresponding routes. To access those routes we need to create a section on EventYay Footer to show to the users.

The following code will result in showing the links to the landing page in footer-section

2. Writing the Code and Designing the Layout for the web-page.

After successfully defining the routes and links, its time we move on to writing the HandleBars for the above pages. The first design for the page would be the pointing menu offered by Semantic-UI v.2.0, which would describe the current tab.

After the designing of Navigation Menu in the AttendeeApp.hbs, Its time we design the main outlet and the body of the page. The Design of the layout page is based on the Landing Pages Created in Other Platforms Like Event.IO, EventBrite etc. A Mobile View on the right side with the Key Features of The App on the left side

3. Writing Integration Tests for both of the Pages.

Since writing test is the most important part of the Development Lifecycle. I preferred to write Acceptance Test instead of Integration Test or Unit Test, As both of the pages created were very simple in functionality. In Acceptance Test, We would be checking the URL For Both Of The Pages in every case After Login or Without Login.

Test For Attendee App :

test('visiting /landing-attendee-app without login', async function(assert) {
    await visit('/attendee-app');
    assert.equal(currentURL(), '/attendee-app');

  test('visiting /landing-attendee-app with login', async function(assert) {
    await login(assert);
    await visit('/attendee-app');
    assert.equal(currentURL(), '/attendee-app');


Issue: OpenEventFrontend-2929

Pull Request : OpenEventFrontend-2979

Additional Resources: Routing Guide., Templates in EmberJS.

Tags: OpenEvent, EventYay, Fossasia, Android Apps, Intern-2k19

Continue ReadingAddition Of Landing Pages For Mobile Apps

Working with Route Hooks in Badgeyay

Badgeyay is an open source project developed by FOSSASIA Community to generate badges for conferences and events through a simple user interface.

In this post I am going to explain about the route lifecycle hooks in ember and how we have utilized one lifecycle component to reset the controller state in badge generation form. In Ember every entity has some predefined set of methods, that it goes through the existence of the application. Route is not different from it. Our main goal is to restore the state of the controller every time we entered into a route, so that we receive a clean and new instance and not the previous state. The hook that fits in the situation is setupController(). This method is called after model() hook to set the controller state in the route. We will restore the variables in the controller here in this method to reset it to original state. This will help in removing the messages and progress on the previous state of the page on a new visit.


  1. Open the route, where we want to override the hook, and create a method setupController() this will call the base hook and override its behaviour.
setupController(controller, model) {
  set(controller, ‘defImages’, model.def_images);
  set(controller, ‘user’, model.user);
  this.set(‘controller.badgeGenerated’, false);
  this.set(‘controller.showProgress’, false);


As we can see in the method, it first initialises the super constructor and then we are writing the logic for the reset state. This will reset the badgeGenerated and showProgress variable in the controller to mentioned values.

  1. Getting the generated badge link from the last promise resolved to set the value of the variable in the controller action.
sendBadge(badgeData) {

        this.set(‘badgeGenerated’, true);



This will set the value of the variable to the received object from backend.

  1. Showing the content in frontend based on the values of the variable. When we initially visit the route it is set to as false in the setupController() hook and is changed later on through some promise resolvement in an action.
{{#if badgeGenerated}}

 . . .



This content will be only be shown in the present state and when the user revisits the route the state will be resetted.

Pull Request for the respective issue –


Continue ReadingWorking with Route Hooks in Badgeyay

Cloud Function For Sending Mail On Badge Generation in Badgeyay

The task of badgeyay is to generate badges for events and if the user has provided a large data set, then the system will take time to generate badges and we cannot hold the user on the same page for that time. So instead of showing the user the link of the generated badge on the form, what we can do is that we can send a mail to user with the link of generated badge. However listening for the completion of generated badge from the cloud function is not possible, as cloud functions are based on serverless architecture. This can be done using the listeners for the realtime database events.

Generated badge from the backend will be uploaded to the Firebase Storage, but applying a listener for storage events, will not give us the information of the sender and some other metadata. So after uploading the link on the database, we can use the public link generated and can push a dict to the realtime database with the necessary user information for sending mail.


  1. Fetching the necessary information to be pushed on the Firebase realtime database.
def send_badge_mail(badgeId, userId, badgeLink):
  ref = firebase_db.reference(‘badgeMails’)
  print(‘Pushing badge generation mail to : ‘, badgeId)
  ref.child(userId).child(datetime.datetime.utcnow().isoformat().replace(‘-‘, ‘_’).replace(‘:’, ‘U’).replace(‘.’, ‘D’)).set({
      ‘badgeId’: badgeId,
      ‘badgeLink’: badgeLink
  print(‘Pushed badge generation mail to : ‘, badgeId)


Payload consists of the downloadable link of the badge and the root node is the userID. So whenever any node gets created in this format them the cloud function will be called.

  1. Listening for the database changes at the state of node.
exports.sendBadgeMail = functions.database.ref(‘/badgeMails/{userId}/{date}’)
.onCreate((snapshot, context) => {
  const payload = snapshot.val();
  const uid = context.params.userId;
  return admin.auth().getUser(uid)
    .then(record => {
      return sendBadgeGenMail(uid,, record.displayName, payload[‘badgeId’], payload[‘badgeLink’]);
    .catch(() => { return -1 });


For the realtime database listener, it should listen to node in the form of badgeMails/<user_id>/<date> as whenever a node of such form will be created in the database the function will get triggered and not for any other data insertions in db. This will save the quota for the cloud function execution.

  1. Sending mail to the user from the payload
function sendBadgeGenMail(uid, email, displayName, badgeId, badgeLink) {
const mailOptions = {
  from: `${APP_NAME}<>`,
  to: email,

mailOptions.subject = `Badge Generated ${badgeId}`;
mailOptions.html = `<p> Hello ${displayName || }! Your badge is generated successfully, please visit the <a href=${badgeLink}>link</a> to download badge</p>`;
return mailTransport.sendMail(mailOptions).then(() => {
  writeMailData(uid, “success”, 3);
  return console.log(‘Badge mail sent to: ‘, email)
}).catch((err) => {
  return -1;


This will send the mail to the user with the generated link.

Pull Request for the above feature at link : Link




Continue ReadingCloud Function For Sending Mail On Badge Generation in Badgeyay

Showing Mail Statistics Using Firebase In Badgeyay

In this blog post I will show how we implemented mail statistics on the admin dashboard of Badgeyay. The problem is that we cannot send a request to an external API from firebase cloud functions in free plan and secondly we have to them bypass the call to realtime database and design a logic to sort out the details from the realtime database using python admin sdk. So, our approach in solving this is that we will use the realtime database with the cloud functions to store the data and using the firebase admin sdk will sort the entries and using binary search will count the statistics efficiently..


  1. Configuring the database URL in admin SDK
firebase_admin.initialize_app(cred, {
      ‘storageBucket’: ‘’,
      ‘databaseURL’: ‘’


  1. Write the mail data in realtime database using cloud function on promise resolvement
function writeMailData(uid, state, reason) {
if (state === ‘success’) {

    }, err => {



  1. Fetching the mail data from the realtime database in python admin sdk
def get_admin_stat():
  mail_ref = firebasedb.reference(‘mails’)
  mail_resp = mail_ref.get()

  curr_date = datetime.datetime.utcnow()
  prev_month_date = curr_date – relativedelta(months=1)
  last_three_days_date = curr_date – relativedelta(days=3)
  last_seven_days_date = curr_date – relativedelta(days=7)
  last_day_date = curr_date – relativedelta(days=1)


This will fetch the current date and them generates the relative dates in past. Then it filters out the data using a for loop and a comparison statement with the date to get the count of the mails. Those count is then passed into a dict and sent through schema.

  1. Fetching the mail stats in admin index panel
mails    : await this.get(‘store’).queryRecord(‘admin-stat-mail’, {})


  1. Showing mails on the index page

class=“six wide column”>
          div class=“ui fluid center aligned segment”>
              h3 class=“ui left aligned header”>
              div class=“ui divider”>div>
              h3 class=“ui header”>
                  No. of Sent Mails
              table class=“ui celled table”>
                          td> In last 24 hourstd>
                          td class=“right aligned”>
                          td>In last 3 daystd>
                          td class=“right aligned”>
                          td> In last 7 days td>
                          td class=“right aligned”>
                          td> In last 1 month td>
                          td class=“right aligned”>


PR to the issue:

Benefits of the approach

This approach is best in the case, when we only are using a subset of services firebase offers and do not want to pay for the services that are not required by the system.


Continue ReadingShowing Mail Statistics Using Firebase In Badgeyay

Different Text Color On Each Line In Badgeyay

In this blog post I am going to explain about how to create different text color for each line in badges generation in Badgeyay. As the system now has option for different badge size and paper size, currently the system sets same color for each line by mutating the fill parameter in the SVG. The main challenge in mutating the SVG parameter for each badge is the Id. The ID identifies the element, in our case text, and gives access to iterate the SVG through libraries like lxml. So for implementing this feature we first need to manipulate the SVG and assign id’s to the text tag so that it can be easily manipulated through the algorithm.


  1. Manipulating the text tag in SVG and assigning a proper ID according to the logic for iteration in the function.





The id of the person in first badge and first line is represented as Person_color_1_1, where the first number denotes the number of badge and second number denotes the line number.

  1. Creating a class for the dimensions of the badges
class Dimen(object):
  def __init__(self, badges, badgeSize, paperSize):
      self.badges = badges
      self.badgeSize = badgeSize
      self.paperSize = paperSize
  1. Creating an initialiser function that stores the dimension objects
badge_config = {}

def init_dimen():
  paper_sizes = [‘A2’, ‘A3’, ‘A4’]
  for paper in paper_sizes:
      if paper == ‘A2’:
          badge_config.__setitem__(paper, {‘4×3’: Dimen(18, ‘4×3’, paper)})
          badge_config[paper][‘4.5×4’] = Dimen(15, ‘4.5×4’, paper)
      elif paper == ‘A3’:
          badge_config.__setitem__(paper, {‘4×3’: Dimen(8, ‘4×3’, paper)})
          badge_config[paper][‘4.5×4’] = Dimen(6, ‘4.5×4’, paper)
      elif paper == ‘A4’:
          badge_config.__setitem__(paper, {‘4×3’: Dimen(6, ‘4×3’, paper)})
          badge_config[paper][‘4.5×4’] = Dimen(2, ‘4.5×4’, paper) 
  1. Selecting the dimension config based on the parameters passed in the function.
dimensions = badge_config[paper_size][badge_size]
  1. Looping criteria is to loop through the number of badges mentioned in the dimension config and through the number of lines which will be five.
for idx in range(1, dimensions.badges + 1):

          for row in range(1, 6):
  1. Selecting the text element with the ID as provided above.
_id = ‘Person_color_{}_{}’.format(idx, row)
              path = element.xpath((“//*[@id='{}’]”).format(_id))[0]
  1. Fill the text color argument of the selected object by changing the value of fill.
style_detail[6] = “fill:” + str(fill[row])

That’s it and now when the loop runs each line will have its individual color as passed in the function. The choice of color is passed as the list named fill.


Continue ReadingDifferent Text Color On Each Line In Badgeyay

Implementing Scheduler Actions on Open Event Frontend

After the functionality to display scheduled sessions was added to Open Event Frontend, the read-only implementation of the scheduler had been completed. What was remaining now in the scheduler were the write actions, i.e., the sessions’ scheduling which event organizers do by deciding its timings, duration and venue.

First of all, these actions required the editable flag to be true for the fullcalendar plugin. This allowed the sessions displayed to be dragged and dropped. Once this was enabled, the next task was to embed data in each of the unscheduled sessions so that when they get dropped on the fullcalendar space, they get recognized by the calendar, which can place it at the appropriate location. For this functionality, they had to be jQuery UI draggables and contain an “event” data within them. This was accomplished by the following code:

  zIndex         : 999,
  revert         : true,      // will cause the event to go back to its
  revertDuration : 0  //  original position after the drag

this.$().data('event', {
  title    : this.$().text().replace(/\s\s+/g, ' '), // use the element's text as the event title
  id       : this.$().attr('id'),
  serverId : this.get(''),
  stick    : true, // maintain when user navigates (see docs on the renderEvent method)
  color    : this.get('session.track.color')

Here, “this” refers to each unscheduled session. Note that the session color is fetched via the corresponding session track. Once the unscheduled sessions contain enough relevant data and are of the right type (i.e, jQuery UI draggable type), they’re ready to be dropped on the fullcalendar space.

Now, when an unscheduled session is dropped on the fullcalendar space, fullcalendar’s eventReceive callback is triggered after its drop callback. In this callback, the code removes the session data from the unscheduled sessions’ list, so it disappears from there and gets stuck to the fullcalendar space. Then the code in the drop callback makes a PATCH request to Open Event Server with the relevant data, i.e, start and end times as well as microlocation. This updates the corresponding session on the server.

Similarly, another callback is generated when an event is resized, which means when its duration is changed. This again sends a corresponding session PATCH request to the server. Furthermore, the functionality to pop a scheduled event out of the calendar and add it back to the unscheduled sessions’ list is also implemented, just like in Eventyay version 1. For this, a cross button is implemented, which is embedded in each scheduled session. Clicking this pops the session out of the calendar and adds it back to the unscheduled sessions list. Again, a corresponding PATCH request is sent to the server.

After getting the response of such requests, a notification is displayed on the screen, which informs the users whether the action was successful or not. The main PATCH functionality is in a separate function which is called by different callbacks accordingly, so code reusability is increased:

updateSession(start, end, microlocationId, sessionId) {
    let payload = {
      data: {
        attributes: {
          'starts-at' : start ? start.toISOString() : null,
          'ends-at'   : end ? end.toISOString() : null
        relationships: {
          microlocation: {
            data: {
              type : 'microlocation',
              id   : microlocationId
        type : 'session',
        id   : sessionId

    let config = {
      skipDataTransform: true
    return this.get('loader')
      .patch(`sessions/${sessionId}`, JSON.stringify(payload), config)
      .then(() => {
        this.get('notify').success('Changes have been made successfully');
      .catch(reason => {
        this.set('error', reason);
        this.get('notify').error(`Error: ${reason}`);

This completes the scheduler implementation on Open Event Frontend. Here is how it looks in action:

scheduler actions.gif


Continue ReadingImplementing Scheduler Actions on Open Event Frontend

Implementing Scheduled Sessions in Open Event Scheduler

Until recently, the Open Event Frontend version 2 didn’t have the functionality to display the already scheduled sessions of an event on the sessions scheduler. Displaying the already scheduled sessions is important so that the event organizer can always use the sessions scheduler as a draft and not worry about losing progress or data about scheduled sessions’ timings. Therefore, just like a list of unscheduled sessions was implemented for the scheduler, the provision for displaying scheduled sessions also had to be implemented.

The first step towards implementing this was to fetch the scheduled sessions’ details from Open Event Server. To perform this fetch, an appropriate filter was required. This filter should ideally ask the server to send only those sessions that are “scheduled”. Thus, scheduled sessions need to be defined as sessions which have a non-null value of its starts-at and ends-at fields. Also, few more details are required to be fetched for a clean display of scheduled sessions. First, the sessions’ speaker details should be included so that the speakers’ names can be displayed alongside the sessions. Also, the microlocations’ details need to be included so that each session is displayed according to its microlocation. For example, if a session is to be delivered in a place named ‘Lecture Hall A’, it should appear under the ‘Lecture Hall A’ microlocation column. Therefore, the filter goes as follows:

let scheduledFilterOptions = [
        and: [
            name : 'starts-at',
            op   : 'ne',
            val  : null
            name : 'ends-at',
            op   : 'ne',
            val  : null


After fetching the scheduled sessions’ details, they need to be delivered to the fulllcalendar code for displaying on the session scheduler. For that, the sessions need to be converted in a format which can be parsed by the fullcalendar add-on of emberJS. For example, fullcalendar calls microlocations as ‘resources’. Here is the format which fullcalendar understands:

        title      : `${session.title} | ${speakerNames.join(', ')}`,
        start      : session.startsAt.format('YYYY-MM-DDTHH:mm:SS'),
        end        : session.endsAt.format('YYYY-MM-DDTHH:mm:SS'),
        resourceId : session.microlocation.get('id'),
        color      : session.track.get('color'),
        serverId   : session.get('id') // id of the session on BE


Once the sessions are in the appropriate format, their data is sent to the fullcalendar template, which renders them on the screen:

Screen Shot 2018-08-21 at 8.20.27 PM.png

This completes the implementation of displaying the scheduled sessions of an event on the Open Event Scheduler.


Continue ReadingImplementing Scheduled Sessions in Open Event Scheduler

Implementing Unscheduled Sessions List for Event Scheduler

Until recently, Open Event Server didn’t allow the storage of unscheduled sessions. However, having the provision of unscheduled sessions was necessary so that event organizers can easily schedule the unscheduled sessions and keep track of them. Also, it allows them to remove scheduled sessions from the scheduler and place them in the unscheduled sessions list, so that they can be scheduled later. Also, since the unscheduled sessions list was also present in Eventyay version 1, it was decided to have the same in version 2.

The first step was to enable the storage of unscheduled sessions on the server. For this, the starts-at and ends-at fields of the session model were modified to be non-required (earlier they were mandatory). Once this change was done, the next step was to fetch the list of unscheduled sessions on the frontend, from the server. Unscheduled sessions were the ones which had the starts-at and ends-at fields as null. Also, the speakers’ details needed to be fetched so that their names can be mentioned along with sessions’ titles, in accordance with Eventyay version 1. Thus, the following were the filter options for the unscheduled sessions’ fetching:

let unscheduledFilterOptions = [
        and: [
            name : 'starts-at',
            op   : 'eq',
            val  : null
            name : 'ends-at',
            op   : 'eq',
            val  : null
let unscheduledSessions = await eventDetails.query('sessions', {
      include : 'speakers,track',
      filter  : unscheduledFilterOptions


This gave us the list of unscheduled sessions on the frontend appropriately. After this, the next step was to display this list to the event organizer. For this, the scheduler’s Handlebars template file was modified appropriately. The colors and sizes were chosen so that the list looks similar to the one in Eventyay version 1. Also, the Ember add-on named ember-drag-drop was used to make these unscheduled session components draggable, so that they can be ultimately scheduled on the scheduler. After installing this package and making the necessary changes to the project’s package.json file, the component file for unscheduled sessions was modified accordingly to adapt for the draggable components’ UI. This was the final step and completed the implementation of listing unscheduled sessions.



Continue ReadingImplementing Unscheduled Sessions List for Event Scheduler

Badges Search Functionality In Admin

Badgeyay is a badge generator service developed by FOSSASIA community for generating badges for conferences and events. Project is separated into frontend that is designed in EmberJS and backend that is created in Flask. Now The Badges tab in admin shows the total badges that are in the system. Along with different meta attributes like Badge creator name, date and other data. The main problem is that it doesn’t provide a way to search the badges from the admin panel. In this blog post i am going to explain about integrating badge search functionality in admin.


  1. Integrating form element for searching
<form class=“ui form” {{action ‘findBadges’ on=“submit”}}>


class=“ui action input”>
                          {{input type=“text” autocomplete=‘off’ value=user placeholder=“Search Badges…”}}



  1. Main difficulty is to send the data to route components as we can’t pass the props, like we pass in components. The workaround is to send the query as route parameter.
findBadges() {
    var userTerm = this.get(‘user’);
    this.transitionToRoute(‘admin.badges.list’, userTerm);


  1. Extracting the query parameter and making request to backend
if (params.badge_status === ‘all’) {
    filter.state = ‘all’;
  } else if (params.badge_status === ‘created’) {
    filter.state = ‘created’;
  } else if (params.badge_status === ‘deleted’) {
    filter.state = ‘deleted’;
  } else {
    filter.filter = params.badge_status;


  1. Creating query in controller to fetch the data for the same.
if ‘filter’ in args.keys():
      badges = base_query.filter(User.username.contains(args[‘filter’]))
      badges = badges.paginate(page, app.config[‘POSTS_PER_PAGE’], False)
      schema = AdminBadgeSchema(many=True)
      return jsonify(schema.dump(badges.items).data)



  • Flask Sqlalchemy documentation for query – Link
  • Pull Request for the same – Link
  • Ember Guide – Link
Continue ReadingBadges Search Functionality In Admin