Are you passionate about open-source development and enjoy working across the stack and infrastructure? Join FOSSASIA, a global community advancing technology through open-source projects. We’re offering an exciting internship opportunity for a Fullstack Developer with DevOps expertise to contribute to the Eventyay platform—an open-source event management system powering ticketing, speaker management, and virtual events.
If you thrive in a collaborative environment and are eager to tackle development challenges independently while leveraging AI tools to speed up workflows, we’d love to hear from you.
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.
Procedure
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.
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.
Getting the generated badge link from the last promise resolved to set the value of the variable in the controller action.
This will set the value of the variable to the received object from backend.
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}}
. . .
{{/if}}
This content will be only be shown in the present state and when the user revisits the route the state will be resetted.
This blog post illustrates how to manage multiple promises simultaneously using a library known as RSVP in Open Event frontend.
What are Promises?
Promises are used to manage synchronous calls in javascript. Promises represent a value/object that may not be available yet but will become available in near future. To quote from MDN web docs:
The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value.
What about RSVP?
Rsvp is a lightweight library used to organize asynchronous code. Rsvp provides several ways to handle promises and their responses. A very simple promise implementation using rsvp looks something like this.
varRSVP=require('rsvp');varpromise=newRSVP.Promise(function(resolve,reject){// succeedresolve(value);// or rejectreject(error);});promise.then(function(value){// success}).catch(function(error){// failure});
It’s simple, right? So, what it is doing is after it defines a promise it assumes two possible states of a promise which are resolve or reject and after promise has completed it executes the respective function.
Use in Open Event Frontend?
Almost all calls to open event server APIs are done asynchronously. One of the most significant use of rsvp comes when handling multiple promises in frontend and we want all of them to be evaluated at together. Unlike normal promises where each promises resolved or rejected individually, rsvp provides a promise.all() method which accepts array of promises and evaluates all at once. It then calls resolve or reject based on the status of all promises. A typical example where we use promise.all() is given here.
importControllerfrom'@ember/controller';importRSVPfrom'rsvp';importEventWizardMixinfrom'open-event-frontend/mixins/event-wizard';exportdefaultController.extend(EventWizardMixin,{actions:{save(){this.set('isLoading',true);this.get('model.data.event').save().then(data=>{letpromises=[];promises.push(this.get('model.data.event.tickets').toArray().map(ticket=>ticket.save()));promises.push(this.get('model.data.event.socialLinks').toArray().map(link=>link.save()));if(this.get('model.data.event.copyright.licence')){letcopyright=this.setRelationship(this.get('model.data.event.copyright.content'),data);promises.push(copyright.save());}if(this.get('model.data.event.tax.name')){lettax=this.setRelationship(this.get('model.data.event.tax.content'),data);if(this.get('model.event.isTaxEnabled')){promises.push(tax.save());}else{promises.push(tax.destroyRecord());}}RSVP.Promise.all(promises).then(()=>{this.set('isLoading',false);this.get('notify').success(this.get('l10n').t('Your event has been saved'));this.transitionToRoute('events.view.index',data.id);},function(){this.get('notify').error(this.get('l10n').t('Oops something went wrong. Please try again'));});}).catch(()=>{this.set('isLoading',false);this.get('notify').error(this.get('l10n').t('Oops something went wrong. Please try again'));});},}
Here we made array of promises and then pushed each of the promises to it. Then at the end used this array of promises in RSVP.promise.all() which then evaluated it based on success or failure of the promises.
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:
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.
Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python.
Badgeyay has many features related to enhancement in generation of badges. It gives choice of uploading data entries i.e by CSV or manually. There are options available for choosing Badge Background and font specifications. Now the next important thing from User perspective is that there should be a feature in My badges panel where user can see all badges & other details and should be able to edit them if he want to, so moving forward with this feature I have implemented Badge Name update functionality in the frontend.
In this blog, I will be discussing how I implemented Update Badge Name functionality in my Pull Request so that the User can change his Badge Name at any point of time in my badges panel.
Let’s get started and understand it step by step.
Step 1:
Create Badge Name component with Ember CLI.
$ ember g component badge-name
Step 2:
Make changes in Handlebar of Badge Name. We will be using semantic UI form for making the changes in Handlebars.
The Badgeyay Ember JS frontend has many features like Login and Sign up features and Login with OAuth and most important, the badge generation feature is also up and running. Now the next important thing from User perspective is that there should be a settings panel where user can see its account details like username, Email & password and he should be able to change them if he want to.
I have implemented the setting panel in Badgeyay where user can see his account details. In this blog, I will be discussing how I implemented Update Password functionality in my Pull Request so that the User can change his Password at any point of time.
Let’s get started and understand it step by step.
Step 1:
Generate User Password component with help of ember cli.
Step 2:
Make changes in Handlebar of User Password. We will be using semantic UI form for making the changes in Handlebars.
<h2class="ui header">Password</h2><h5class="ui dividing header">Change your password.</h5><formclass="ui form"{{action'updateUserPassword'on="submit"}}>
</div></div><buttontype="submit"class="ui basic orange button"tabindex="0">
Save Changes
</button></form>
We have used action on submitting the Form for changing and updating the Password in Database and Firebase.
Step 3:
We will now define the action in user component JS file. We will also add the validations in Form so that empty form cannot be submitted to the server.
import Component from '@ember/component';
exportdefault Component.extend({
init() {
this._super(...arguments);
},
actions: {
updateUserPassword() {
let password =this.get('newPassword');
this.get('sendUserPassword')(password);
}
},
didRender() {
this.$('.ui.form')
.form({
inline :true,
delay :false,
fields : {
newPassword: {
identifier :'newPassword',
rules : [
{
type :'empty',
prompt :'Please enter a password'
},
{
type :'minLength[6]',
prompt :'Your password must have at least {ruleValue} characters'
}
]
},
newPasswordVerify: {
identifier :'newPasswordVerify',
rules : [
{
type :'match[newPassword]',
prompt :'Passwords do not match'
}
]
}
}
});
}
});
Step 4:
We will now configure the controller to customize the action that we have defined above.
We have configured the frontend for sending the details to backend. Now, we have to edit the endpoint so that if Password changes in params, It should change the password and send the response with the updated user schema.
The Badgeyay Ember JS frontend has many features like Login and Sign up features and Login with OAuth and the most important, the badge generation feature is also up and running. Now the next important thing from User perspective is that there should be a settings panel where user can see its account details like username, Email & password and he should be able to change them if he want to.
I have implemented the setting panel in Badgeyay where user can see his account details. In this blog, I will be discussing how I implemented Update Username functionality in my Pull Request so that the User can change his username at any point of time.
Let’s get started and understand it step by step.
Step 1:
Generate User account component with help of ember cli.
$ ember g component user-component/user-account
Step 2:
Make changes in Handlebar of User Account. We will be using semantic UI form for making the changes in Handlebars.
We have used action on submitting the Form for changing and updating the username in Database and Firebase.
Step 3:
We will now define the action in user component JS file. We will also add the validations in Form so that empty form cannot be submitted to the server.
We have configured the frontend for sending the details to backend. Now, we have to edit the endpoint so that if username is change in params, It should change the username and send the response with the updated username.
Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python.
Badgeyay comes with many features for customising the process of generation of Badges. Badgeyay also keeps record of all the badges generated by user and also gives option to directly download the previously generated badges.
All the badges appear on single page which creates problem when a user has generated lot of badges and all the badges listed on single page.
To resolve this issue and make Badgeyay more user friendly I have implemented pagination in listing badges so that if there are more number of badges, user can see the badges listed in multiple pages in my Pull Request.
To implement this, I have used actions and made the changes accordingly.
Let’s get started and understand it step by step.
Step 1:
We will use semantic icons in handlebars for changing pages.
Step 2:
I will add action for changing page to next and previous page.
Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python.
Badgeyay comes with many features for customising the process of generation of Badges. It gives freedom to user to choose Input Badge data which is to be printed on the individual badges, choosing the badge size, applying custom background to the badges and then optional features of font customization helps to generate cool badges.You have to just click on create badges and the generated badge with download link appear at bottom of form. But a problem arises with the generated badges link that after logout/login or generation of new badges just after creating badges one time, the link of the previously created badges is still there which is a bit confusing, as user might think the previous link to be the new link and press on that in order to download and find the old badges downloaded.
To resolve this issue, I have used the power of Ember notify library and customized it to show the generated badges link and disappear after a specified time in my Pull Request and after that user can always see his previously generated badges in My Badges route.
Let’s get started and understand it.
Customizing Notify library and making the changes in the send Badge data function to show the generated badge link just after the completion of badge generation process.
import Controller from '@ember/controller';
import { inject as service } from '@ember/service';
exportdefault Controller.extend({
....
routing : service('-routing'),
notify : service('notify'), // importing Notify service
.....
sendBadge(badgeData) {
const _this =this;
let badgeRecord = _this.get('store').createRecord('badge', badgeData);
badgeRecord.save()
.then(record => {
_this.set('badgeGenerated', true);
_this.set('genBadge', record);
var notify = _this.get('notify');
var link = record.download_link; // Assigning download link to a variable var message = notify.success( // Configuring the message of notify service
{ html:// Adding the html in notify message'
Badge generated successfully.
'+'<p>Visit this<b>'+'<a href='+ link
+'> Link </a></b> to download badge.</p>',
closeAfter:10000 }); // Specifying the time of closing the message
})
.catch(err => {
_this.get('notify').error('Unable to generate badge');
});
},
I have implemented the customized notify function to show the badge generation link for a specific time.
Now run the server to see the implemented changes by following command.
$ ember serve
Ember Notify service showing the generated Badges link:
Now, I am done with the implementation of customised notify function to show the badge generation link for a specific time of 10 seconds.
Badgeyay project is divided into two parts i.e front-end with Ember JS and back-end with REST-API programmed in Python.
Badgeyay comes with many features for customising the process of generation of Badges. It gives freedom to user to choose Input Badge data which is to be printed on the individual badges, choosing the badge size, applying custom background to the badges and then optional features of font customization helps to generate cool badges. If a helper is not there for the directions to use these features then these features may be difficult to use for a user.
To resolve this issue and make Badgeyay more user friendly I have implemented a User Guide to help user to go through the User Manual before generating Badges in my Pull Request.
To implement user guide, I have used Semantic UI tables to give examples for CSV format and used other components for Manual format.
Let’s get started and understand it step by step.
Step 1:
Create User Guide component with Ember CLI.
$ ember g component user-component/user-guide
Step 2:
Now, We will use Semantic UI while editing Handlebars.
class="user-guide">
class="ui center aligned huge header">User-Input Guide
class="ui center aligned small header">
Please check what is the "Correct Format"?
class="ui segments">
class="ui segment">
class="ui raised segment">
class="ui header">class="file excel icon">
class="content">
CSV Format
</div></div>
class="ui bulleted list">
class="item">The CSV must be uploaded with 5 columns of data.
class="item">Five comma (',') seperated values should be present in the CSV
You must be logged in to post a comment.