Building the Scheduler UI

{ Repost from my personal blog @ }

If you hadn’t already noticed, Open Event has got a shiny new feature. A graphical and an Interactive scheduler to organize sessions into their respective rooms and timings.

As you can see in the above screenshot, we have a timeline on the left. And a lot of session boxes to it’s right. All the boxes are re-sizable and drag-drop-able. The columns represent the different rooms (a.k.a micro-locations). The sessions can be dropped into their respective rooms. Above the timeline, is a toolbar that controls the date. The timeline can be changed for each date by clicking on the respective date button.

The Clear overlaps button would automatically check the timeline and remove any sessions that are overlapping each other. The Removed sessions will be moved to the unscheduled sessions pane at the left.

The Add new micro-location button can be used to instantly add a new room. A modal dialog would open and the micro-location will be instantly added to the timeline once saved.

The Export as iCal allows the organizer to export all the sessions of that event in the popular iCalendar format which can then be imported into various calendar applications.

The Export as PNG saves the entire timeline as a PNG image file. Which can then be printed by the organizers or circulated via other means if necessary.

Core Dependencies

The scheduler makes use of some javascript libraries for the implementation of most of the core functionality

  • Interact.js – For drag-and-drop and resizing
  • Lodash – For array/object manipulations and object cloning
  • jQuery – For DOM Manipulation
  • Moment.js – For date time parsing and calculation
  • Swagger JS – For communicating with our API that is documented according to the swagger specs.
Retrieving data via the API

The swagger js client is used to obtain the sessions data using the API. The client is asynchronously initialized on page load. The client can be accessed from anywhere using the javascript function initializeSwaggerClient.

The swagger initialization function accepts a callback which is called if the client is initialized. If the client is not initialized, the callback is called after that.

var swaggerConfigUrl = window.location.protocol + "//" + + "/api/v2/swagger.json";  
window.swagger_loaded = false;  
function initializeSwaggerClient(callback) {  
    if (!window.swagger_loaded) {
        window.api = new SwaggerClient({
            url: swaggerConfigUrl,
            success: function () {
                window.swagger_loaded = true;
                if (callback) {

    } else {
        if (callback) {

For getting all the sessions of an event, we can do,

initializeSwaggerClient(function () {  
    api.sessions.get_session_list({event_id: eventId}, function (sessionData) {
        var sessions = sessionData.obj;  // Here we have an array of session objects

In a similar fashion, all the micro-locations of an event can also be loaded.

Processing the sessions and micro-locations

Each session object is looped through, it’s start time and end time are parsed into moment objects, duration is calculated, and it’s distance from the top in the timeline is calculated in pixels. The new object with additional information, is stored in an in-memory data store, with the date of the event as key, for use in the timeline.

The time configuration is specified in a separate time object.

var time = {  
    start: {
        hours: 0,
        minutes: 0
    end: {
        hours: 23,
        minutes: 59
    unit: {
        minutes: 15,
        pixels: 48,
        count: 0
    format: "YYYY-MM-DD HH:mm:ss"

The smallest unit of measurement is 15 minutes and 48px === 15 minutes in the timeline.

Each day of the event is stored in a separate array in the form of Do MMMM YYYY(eg. 2nd May 2013).

The array of micro-location objects is sorted alphabetically by the room name.

Displaying sessions and micro-locations on the timeline

According to the day selected, the sessions for that day are displayed on the timeline. Based on their time, the distance of the session div from the top of the timeline is calculated in pixels and the session box is positioned absolutely. The height of the session in pixels is calculated from it’s duration and set.

For pixels-minutes conversion, the following are used.

 * Convert minutes to pixels based on the time unit configuration
 * @param {number} minutes The minutes that need to be converted to pixels
 * @returns {number} The pixels
function minutesToPixels(minutes) {  
    minutes = Math.abs(minutes);
    return (minutes / time.unit.minutes) * time.unit.pixels;

 * Convert pixels to minutes based on the time unit configuration
 * @param {number} pixels The pixels that need to be converted to minutes
 * @returns {number} The minutes
function pixelsToMinutes(pixels) {  
    pixels = Math.abs(pixels);
    return (pixels / time.unit.pixels) * time.unit.minutes;
Adding interactivity to the session elements

Interact.js is used to provide interactive capabilities such as drag-drop and resizing.

To know how to use Interact.js, you can checkout some previous blog posts on the same, Interact.js + drag-drop and Interact.js + resizing.

Updating the session information in database on every change

We have to update the session information in database whenever it is moved or resized. Every time a session is moved or resized, a jQuery event is triggered on $(document) along with the session object as the payload.

We listen to this event, and make an API request with the new session object to update the session information in the database.

The scheduler UI is more complex than said in this blog post. To know more about it, you can checkout the scheduler’s javascript code atapp/static/js/admin/event/scheduler.js.

Python code examples

I’ve met many weird examples of  behaviour in python language while working on Open Event project. Today I’d like to share some examples with you. I think this knowledge is necessary, if you’d like to increase a  bit your knowledge in python area.

Simple adding one element to python list:

def foo(value, x=[]):
  return x

>>> print(foo(1))
>>> print(foo(2))
>>> print(foo(3, []))
>>> print(foo(4))


[1, 2] 
[1, 2, 4]

First output is obvious, but second not exactly. Let me explain it, It happens because x(empty list) argument is only evaluated once, So on every call foo(), we modify that list, appending a value to it. Finally we have [1,2, 4] output. I recommend to avoid mutable params as default.

Another example:

Do you know which type it is?

>>> print(type([ el for el in range(10)]))
>>> print(type({ el for el in range(10)}))
>>> print(type(( el for el in range(10))))

Again first and second type are obvious <class ‘list’>, <class ‘set’>. You may  think that last one should return type tuple but it returns a generator <class ‘generator’>.


Do you think that below code returns an exception?

list= [1,2,3,4,5]
>>> print(list [8:])

If you think that above expression returns index error you’re wrong. It returns empty list [].

Example funny boolean operators

>>> 'c' == ('c' or 'b')
>>> 'd' == ('a' or 'd')
>>> 'c' == ('c' and 'b')
>>> 'd' == ('a' and 'd')

You can think that that OR and AND operators are broken.

You have to know how python interpreter behaves while looking for OR and AND operators.

So OR Expression takes the first statement and checks if it is true. If the first statement is true, then Python returns object’s value without checking second value. If first statement is false interpreter checks second value and returns that value.

AND operator checks if first statement is false, the whole statement has to be false. So it returns first value, but if first statement is true it checks second statement and returns second value.

Below i will show you how it works

>>> 'c' == ('c' or 'b')
>>> 'c' == 'c'
>>> 'd' == ('a' or 'd')
>>> 'd' == 'a'
>>> 'c' == ('c' and 'b')
>>> 'c' == 'b'
>>> 'd' == ('a' and 'd')
>>> 'd' == 'd'

I hope that i have explained you how the python interpreter checks OR and AND operators. So know above examples should be more understandable.

Testing, Documentation and Merging

As the GSoC period comes to an end the pressure, excitement and anxiety rises. I am working on the finishing steps of my project. I was successfully able to implement all the task I took up. A list of all the tasks and their implementation can be found here.

At the start of this week I had about 26 Pull Requests. Each Pull Request had independent pieces of code for a new task from the list. I had to merge all the pull requests and resolve the conflicts. My earlier tasks involved working on the same code so there were a lot of conflicts. I spend hours looking through the code and resolving conflicts. I also had to test each feature after merging any two of the branches. Finally we were able to combine all our code and come up with a branch that contains all the code implemented by me and Ajinkya Wavare.

These two are the branches we combined all our code in. I finished my work on linux command for sTeam by adding support for the last two tools which are export and import from git. I worked on to include a help to get new users to understand the use of the command.

I also worked on documentation. I started with the testing suite which is implemented by me. I wrote comments to explain the work and also improved the code by removing unnecessary lines of code. After this I added the documentation for the new command in steam-shell that I had implemented. The command to work with groups from the steam-shell. One of the issue with the testing suite still stands unresolved. I have been breaking my head on it for a week now but to no results. I will attempt to solve it in the coming week.

This error occurs for various objects in the first few runs and then the test suite runs normally error free.

PayPal Express Checkout in Python

As per the PayPal documentation …

Express Checkout is a fast, easy way for buyers to pay with PayPal. Express Checkout eliminates one of the major causes of checkout abandonment by giving buyers all the transaction details at once, including order details, shipping options, insurance choices, and tax totals.

The basic steps for using express checkout to receive one-time payments are:

  1. Getting the PayPal API credentials.
  2. Making a request to the API with the transaction details to get a token
  3. Using the token to send the users to the PayPal payment page
  4. Capturing the payment and charging the user after the user completes the payment at PayPal.

We will be using PayPal’s Classic NVP (Name-value pair) API for implementing this.

Getting PayPal API Credentials

To begin with, we’ll need API Credentials.
We’ll be using the Signature API credentials which consists of

  • API Username
  • API Password
  • Signature

To obtain these, you can follow the steps at Creating and managing NVP/SOAP API credentials – PayPal Developer.

You’ll be getting two sets of credentials. Sandbox and Live. We’ll just stick to the Sandbox for now.

Now, we need sandbox test accounts for making and receiving payments. Head over to Creating Sandbox Test Accounts – PayPal Developer and create two sandbox test accounts. One would be the facilitator and one would be the buyer.

PayPal NVP Servers

All the API actions will take place by making a request to the PayPal server. PayPal has 4 different NVP servers for 4 different purposes.

  1. – Sandbox “testing” server for use with API signature credentials.
  2.– PayPal “live” production server for use with API signature credentials.
  3. – Sandbox “testing” server for use with API certificate credentials.
  4. – PayPal “live” production server for use with API certificate credentials.

We’ll be using the Sandbox “testing” server for use with API signature credentials.

Creating a transaction and obtaining the token

To create a transaction, we’ll need to make a request with all the transaction details. We can use Python requests library to easily make the requests. All requests are POST.

We’ll be calling the SetExpressCheckout method of the NVP API to obtain the token.

import requests  
import urlparse

data = {  
    'USER': credentials['USER'],
    'PWD': credentials['PWD'],
    'SIGNATURE': credentials['SIGNATURE'],
    'SUBJECT': credentials['FACILITATOR_EMAIL'],
    'METHOD': 'SetExpressCheckout',
    'VERSION': 93,
    'RETURNURL': 'http://localhost:5000/paypal/return/',
    'CANCELURL': 'http://localhost:5000/paypal/cancel/'
response ='', data=data)  
token = dict(urlparse.parse_qsl(response.text))['TOKEN']


  • USER represents your Sandbox API Username.
  • PWD represents your Sanbox API Password.
  • SIGNATURE represents your Sandbox Signature.
  • SUBJECT represents the facilitator’s email ID.
  • PAYMENTREQUEST_0_AMT is the total transaction amount.
  • PAYMENTREQUEST_0_CURRENCYCODE is the 3 digit ISO 4217 Currency code.
  • RETURNURL is where the user will be sent to after the transaction
  • CANCELURL is where the user will be sent to if he/she cancels the transaction.

A URL-Encoded, Name-value pair response would be obtained. We can decode that into a dict by using Python’s urlparse modules.

From the response, we’re extracting the TOKEN which we will use to generate the payment URL for the user.

This token has to be retained since we’ll be using it in further steps of the process.

Redirecting the user to PayPal for Approval

With the token we obtained, we can form the payment URL.<TOKEN>

We’ll have to send the user to that URL. Once the user completes the transaction at PayPal, he/she will be returned to the RETURNURL where we’ll further process the transaction.

Obtaining approved payment details and capturing the payment

Once the user completes the transaction and gets redirected back to RETURNURL, we’ll have to obtain the confirmed payment details from PayPal. For that we can again use the token ID that we obtained before.

We’ll now be making a request to the GetExpressCheckoutDetails method of the API.

import requests  
import urlparse

data = {  
    'USER': credentials['USER'],
    'PWD': credentials['PWD'],
    'SIGNATURE': credentials['SIGNATURE'],
    'SUBJECT': credentials['FACILITATOR_EMAIL'],
    'METHOD': 'GetExpressCheckoutDetails',
    'VERSION': 93,

response ='', data=data)  
result = dict(urlparse.parse_qsl(response.text))  
payerID = result['PAYERID']

A URL-Encoded, Name-value pair response would be obtained. We can decode that into a dict by using Python’s urlparse modules.

This will provide us with information about the transaction such as transaction time, transaction amount, charges, transaction mode, etc.

But, we’re more interested in the PAYERID which we’ll need to capture/collect the payment. The money is not transferred to the facilitators account until it is captured/collected. So, be sure to collect it.

To collect it, we’ll be making another request to the DoExpressCheckoutPaymentmethod of the API using the token and the PAYERID.

import requests  
import urlparse

data = {  
    'USER': credentials['USER'],
    'PWD': credentials['PWD'],
    'SIGNATURE': credentials['SIGNATURE'],
    'SUBJECT': credentials['FACILITATOR_EMAIL'],
    'METHOD': 'DoExpressCheckoutPayment',
    'VERSION': 93,
    'PAYERID': payerID,

response ='', data=data)  
result = dict(urlparse.parse_qsl(response.text))  
status = result['ACK']

All the details have to be the same as the ones provided while obtaining the token. Once we make the request, we’ll again get a URL-Encoded, Name-value pair response. We can decode that into a dict by using Python’s urlparsemodules.

From the response, ACK (Acknowledgement status) will provide us with the status of the payment.

  • Success — A successful operation.
  • SuccessWithWarning — A successful operation; however, there are messages returned in the response that you should examine.
  • Failure — The operation failed; the response also contains one or more error messages explaining the failure.
  • FailureWithWarning — The operation failed and there are messages returned in the response that you should examine.

And, we have completed the PayPal transaction flow for Express Checkout. These are just the basics and might miss a few stuff. I suggest you go through the following links too for a better understanding of everything:

For Reference:
  1. PayPal Name-Value Pair API Basics – PayPal Developer
  2. How to Create One-Time Payments Using Express Checkout – PayPal Developer

Testing Hero – II

I continued last weeks work on improving the testing framework and adding more test cases. While writing the test cases for create I had to write a separate test case for each kind of object. This caused a lot of repetition of code. Thus the first aim for the week was to design a mechanism to write generalized test cases so that we can have an array of object and loop through them and pass each object to the same test case.

Right now the structure has a central script called test.pike which imports various other scripts containing the test cases. Let us take one of these scripts, suppose move.pike. Now I wanted to write a generalized test case which performs the same action on various objects. So I created one more file containing this generalized test case and imported this into one of the testcases in move.pike. This test case in move.pike is responsible for enumerating the various kinds of objects, sending them to the generalized test case, collect the output and then send the result for the entire test to the central test.pike. Then I went ahead and implemented this model for moving various objects to non existential location and for creating various kinds of objects and the model seemed to work fairly well.

The journey was not so smooth. I had a few troubles on the way. In all the test cases I was deleting any objects that were created and used in the test. To delete any object I need to get a reference to the object. This reference keeps getting dropped for some reason and I get an error for calling the delete function on NULL as the reference no longer exists. I tried finding the cause of this and solve this bug, however I couldn’t and found a work around the errors by using if statements to check that the object references are not null before calling functions on these object references. I continued my work on generalizing the test cases and wrote the general tests for all the test cases in the move and create test suites.

In the later part of the week I started working on some merging with my team mate Ajinkya Wavare. I designed more test cases for checking the creation of groups and users. Groups could be created using the generalized test case however for users I had to add a special test case as the process of creating a user is different from creating other objects. I ended my week by writing the test case for a long standing error, i.e, call to the get_environment function.

testing hero 2
output of test

Adding extensive help for sTeam

This task was something I came up with as an enhancement because of the problems I faced while using sTeam for the first time. During the first week of my using sTeam I had a tough time getting used to commands and that is when I had opened the issue to improve help. Help for commands were one liners and not very helpful so I took up the task to improve it, so that new users don’t have to face the difficulties that I faced.



Not a lot of technical details were involved in this task but it was time consuming. I write down a few lines explaining what each command does and also added a syntax for the commands. While doing these I also realized more improvements that could be made and added them to my task list. My mentor had explained to me how rooms and gates were the same. I discovered that the command gothrough was violating this as it allowed users to gothrough gates but not rooms. I discussed this on the irc and we came up with a solution that we should change this command to enter and allow it to operate on both rooms and gates.

This enhancement became my next task and I worked on changing this command. The function gothrough was changed to enter and the conditions required for it to work on rooms were added. This paved way for my task. The look command showed rooms and gates under different sections. Now that there were no difference between rooms and gates I combined these two sections to change the output of the look command.

gsoc look
output of look before the changes
gsoc look1
output of look after the changes




By the end of the week I had started on my next task, which was a major one. Writing testing framework and test cases for coal command calls. I will be discussing more about this in my next blog post.

One step at a time – The beginnings of CommonsNet

The beginnings

If you have been accepted to a serious project like Google Summer of Code is, you can feel lost and scared. I think it’s nothing special and probably everyone experiences it. You can feel that pressure because you want to fulfill all expectations, follow your obligations and to do your best, but working in such project is something different from working on your own, private and small one.  Your organisation and mentors require something from you, and they can even provide you with a detailed guideline how to behave but doubts may occur anyway.

My advice is not to give up and go through that tought period in order to experience the joy of results and sense of satisfaction, and to learn something to be better in the future. I am going to tell about my beginnings and to provide you with some tips  from my own experience


CommonsNet (feel free to see it) is a new project of FOSSASIA. It focuses on providing users with transparent information about WiFi they may use in public places like hotels, restaurants, stations. The thing is that for now, if you go to a new place, and want to connect to Internet, you look for a free WIFI sign and as soon as you find it you try to connect. But think about it, how much do you know about this connection? Is is safe for your private data? How fast is it? Does the Internet connection have any legal restrictions?  I suppose that you answer ‘no’ to all these questions. But what if you know? Or if you can compare details of different WIFI available in a specific public place and connect to more suitable for your needs. I am sure you will appreciate it. I hope to run this project successfully and I am going to tell you more about it in next posts.

How to start?

Due to the fact that CommonsNet is a new project as I have mentioned before, and for now apart from mentor @agonarch and FOSSASIA leaders @mariobehling @hpdang, I am an only contributor, I am in a good position to tell you what are my steps. Remember not to think about all at once. It will make you crazy.

So first of all – prepare your work. Try to get to know about your project as much as possible. Follow group chat, GitHub repositories, do research in Internet about the subject of area of your project or don’t be afraid to ask your team member. That’s what I have done at first. I have prepared a Google Doc about all WiFi details. I  have tried to get to know as much as possible and to gather this information in a clear, easy-to-understand way.

project details

I need it because I will be preparing a wizard form for users to let them provide all important details about their WiFi. I need to think seriously which data are important and have to be used to do it. It is not finished yet and will be changing (yes, I am going to share it with you and update you about changes!) but for now I want you to follow my view about it, how am I going to use the gathered information. wizard-ui

Next step is to prepare user stories. I think it’s a crucial point before you start to implement your project. I think there is no point of developing something until you think who will your user be. You need to imagine him/her and try to predict what he or she may expect from your app. Remeber – even if app is well coded it’s useless until somebody wants to use it. You can find many tutorials how to write a good user story in Internet. Just type ‘user stories’ in Google search. Some of them are here;

You can also see my user stories created for CommonsNet .

Furthermore, I have prepared a mockups to visualize my ideas. I think it’s also an important part of running your project. It will help you to express and concretize your ideas and let the whole team discuss about it. And there is no doubt that it’s easier to change a simple draft of mockups than coded views. You can see my mockups here: CommonsNet MockupsScreen Shot 2016-06-23 at 12.38.20

As soon as you finish all these activities is a high time to start creating issues on GitHub. Yes, of course, you probably have already started, so have I, but I am talking about further issues which help you to take control over your progress and work, discuss on specific subject and share it with other.

Lost on GitHub?

Is is possible at all? I suppose we all know and use GitHub. It’s a perfect place of working to all programmers. Its possibilities seems to be unlimited. But maybe some of you experience the difficulties which I have experienced at first, because just like me you have used GitHub so far only for your private aims and simply just pushed code and have not worried about creating issues, following discussions and  organizing your work step by step . Let me to explain you why and how to follow GitHub flow.

GitHub issues let you and your team take control over your work. It’s really important to create bigger, let’s say main issues, and then subissues, which help you to divide your work into small parts. Remember – only one step at a time! Using my mockups first I have created some issues which present main tasks like ‘deploying app to Heroku’ or different pages in my app like ‘Home’, ‘About us’. And then I have created many smaller issues – subissues to present what tasks I have to do in each section like ‘Home’ -> ‘Impementing top menu’, ‘Implementing footer’, ‘Implementing big button’. It helps me to control where I am, what have been done, and what do I need to do next. And I think the smaller the tasks are, the more fruitful the discussion and work can be, because you can simply refine each detail. Please feel free to see CommonsNet issues. It’s not finished yet, and while working I am going to add further issues but it presents the main idea I am talking about.

Screen Shot 2016-06-23 at 12.57.48.png

I hope these tips help you to run your work and to go through harder time – easier. And remember even the longest journey starts from the first step!

Please follow CommonsNet webiste to be updated about progress, latest news and tips how to resolve programming problems you may experience.

Feel free to follow us on social media Facebook  Twitter

The Official Beginning

This blog marks the start of the coding period for Google Summer of Code. I will start by talking about the community bonding period and then my plan to begin the summer.

Community bonding was an interesting and intense period. Managing college, assignments, exams and working on the project all at the same time. I think this is the capability that sets us apart. We had started out with fixing small issues in the steam-shell. Steam-shell is a command line interface that allows the user certain limited set of commands to interact with the server. I will list down the issues I solved and the improvements I made.

My first task was to improve the display of commands like ‘look’. This command lists out the gates/files/documents/rooms/conatiners present in the current room. The old display showed one entry in one line. I improved this to make it something similar to the ls command of linux. I used sprintf(“%#-80s”,<variable>) to give the output a structure.

Next I worked on the create command. I found a bug that this command was not working for containers and documents. I fixed it by adding the required conditions in the code and then I worked upon to improve the functionality of the command as suggested by my mentor Trilok. I added the feature to enter the destination where the new object is to be created and a ‘.’ to create it in the present directory. Initially this feature was only for Rooms and Containers, later I extended this to all kinds of objects.

After this I spent a few days studying the COAL protocol. I have already written in detail about this in my previous blog. Though I was not successful in completely understanding the protocol but this gave me an idea of the client-server architecture. This was towards the end of the community bonding period and I decided to spend the rest of my time with steam-shell itself.

Now as the coding period begins officially I will be working to fix the edit command. Currently the edit command opens the file on a vi/vim/emac instance. The vi and vim opens in the same window and it misbehaves. Then I will be extending the feature for multiple documents and in the next week move on to work on COAL again.

Google Summer of Code: A new beginning

I am working on sTeam under FOSSASIA for GSoC 2016. sTeam is collaboration platform. It allows users to form groups and share various kinds of documents. It provides a virtual knowledge space where users can meet and interact. These spaces are called rooms, these can contain various containers to store documents in an organized manner. The rooms are connected by gates to allow the movement of users and documents from one room to another. The most interesting thing about the project is that it is in pike programming language. This is not very commonly used and I will get to learn new things and myriad of experiences.

Now moving into the technical details of my project I will be talking about the first step in my project that is implementing TLS (Transfer Layer Security) Protocol, also known as SSL. Currently all the communication between the server and the command line client is over COAL protocol. COAL is a home grown protocol developed by the original developers of sTeam. Currently COAL does not use any kind of encryption. My first task will be to integrate SSL into COAL, so just like http becomes https COAL will become COALS. After this I will be working on the improving the client interface, which I will talk about in the coming weeks.

For now in the community bonding period I have been actively participating in the discussions on the IRC and working on stash, discovering bugs in the project and getting used to the interface and the code. Recently we received the guidelines for the summer from our mentors Martin and Trilok. The guidelines include clearly mentioned milestones and the tasks we need to complete. We will also be having a team meeting everyday discussing our day’s work and issues.

I would like to thank FOSSASIA for giving me this wonderful oppurtunity to show my skills. All the discussion during this period is just making me feel more professional and getting me excited for the summers. In programmers term

printf(“let the fun begin !”);

searchQuick Apprise: EIGHT #GoogleSummerOfCode #FOSSASIA


The intended searchQuick” (sQuick) is an application to enable a user to search a set of books or texts, like an encyclopedia, or some other topical book collection offline built in the open source platform Pharo 4.0.


Bringing up to the rear of the summers, the project was brought to a penultimate stage by achieving the following tasks:

    • Handling empty string searches by raising error pop ups.
      searchBar accept .
      (myString isEmptyOrNil  ) 
      ifTrue: [self errorPopUp ] 
      ifFalse: [ 
           myString := searchBar getText asString .
                self printSearchResults
                     ] .
    • Adding Help, About and Feedback sections to give an authentic application look and required details to an interested developer.
    • Inserting ScrollPane for BrowseFile list menu
      browseScroll := ScrollPane new.
      browseScroll scroller addMorph: browse.
    • Truncating BrowseFile list menu file titles to have their extent within the #MenuMorph: boundary
      title := anObject truncateWithElipsisTo: 25. 
    • Removal of OK/CANCEL buttons from the Search results accordion widget
      dialog buttons: {}.
    • Implementation of a Search Bar for searching via Search results accordion widget.
    • Categorizing methods as: accessing, initializationsubmorphsadd/remove etc.
    • Removal of unwanted/redundant/commented code lines i.e. scrubbing dead-code.