Implementing Sign up Feature through Email in Badgeyay

Badgeyay project is divided into two parts i.e front-end of Ember JS and back-end with REST-API programmed in Python. We already have logging In features implemented with the help of Firebase Authentication. A User can login in the Badgeyay with the help of Google, Facebook and Twitter credentials through a single click. Now, the challenging part is to implement the sign up with Email feature in Frontend and Backend to enable the user to signup and Login with the help of Email and Password In this blog, I will be discussing how I set up Sign up feature in Badgeyay frontend to send the data in backend besides having Oauth logging features in Badgeyay integrated with Firebase in my Pull Request. The sign up form is already implemented and I have already mentioned in my previous blog. So we need to send the form data to backend to register user so that user can login using the registered credentials. We need an Adapter, Signup action, controller , Signup Data model  and a serializer for doing this task. Let’s get started and understand the terminologies before implementing the feature. What is Ember Data ? It is a data management library for Ember Framework which help to deal with persistent application data. We will generate Ember data model using Ember CLI in which we will define the data structure we will be requiring to provide to our application for User Signup. Step 1 : Generate ember data model for signup. $ ember g model user-signup   Step 2: Define the user-signup data model. import DS from 'ember-data'; const { Model, attr } = DS; export default Model.extend({ username : attr('string'), email : attr('string'), password : attr('string') });   What are Actions ? We already have the signup form implemented in frontend. Now we need to provide a action to the form when the user enters the data in form. If we add the {{action}} helper to any HTML DOM element, when a user clicks the element, the named event will be sent to the template's corresponding component or controller. <button class="ui orange submit button" {{ action 'signUp' }}>Sign Up</button>   We need to add signUp action in sign-up component and controller. // Signup Controller import Controller from '@ember/controller'; import { inject as service } from '@ember/service'; export default Controller.extend({ routing : service('-routing'), actions : { signUp(email, username, password) { const _this = this; let user_ = this.get('store').createRecord('user-signup', { email, username, password }); user_.save() .then(record => { _this.transitionToRoute('/'); }) .catch(err => { console.log(err); }); } } }); // Sign up Component import Component from '@ember/component'; export default Component.extend({ init() { this._super(...arguments); }, email : '', password : '', isLoading : false, actions: { signUp(event) { event.preventDefault(); let email = ''; let password = ''; let username = ''; email = this.get('email'); password = this.get('password'); username = this.get('username'); this.get('signUp')(email, username, password); } }, });   What is an Adapter ? An adapter determines how the data is persisted to a backend data store. We…

Continue ReadingImplementing Sign up Feature through Email in Badgeyay

Creating Forms and their validation using Semantic UI in Badgeyay

Badgeyay project is now divided into two parts i.e front-end of Ember JS and back-end with REST-API programmed in Python. After a discussion, we have finalized to go with Semantic UI framework which uses simple, common language for parts of interface elements, and familiar patterns found in natural languages for describing elements. Semantic allows to build beautiful websites fast, with concise HTML, intuitive javascript and simplified debugging, helping make front-end development a delightful experience. Semantic is responsively designed allowing a web application to scale on multiple devices. Semantic is production ready and partnered with Ember framework which means we can integrate it with Ember frameworks to organize our UI layer alongside our application logic. In this blog, I will be discussing how I added Log In and Signup Forms and their validations using Semantic UI for badgeyay frontend in my Pull Request. Let’s get started and understand it step by step. Step 1: Generate ember components of Login and Sign up by using the following command : $ ember generate component forms/login-form $ ember generate component forms/signup-form   Step 2: Generate Login and Sign up route by following commands. $ ember generate route login $ ember generate route signup   Step 3: Generate Login and Sign up controller by following commands. $ ember generate controller login $ ember generate controller signup   Step 4: Now we have set up the components, routes, and controllers for adding the forms for login and Sign up. Now let’s start writing HTML in handlebars, adding validations and implementing validations for the form components. In this blog, I will be sharing the code of Login form and actions related to logging In of user. You can check the whole code my Pull Request which I have made for adding these Forms. Step 4.1: Creating a Login Form <div class="ui hidden divider"></div> <div class="ui raised segment"> <div class="ui stackable column doubling centered grid"> <div class="ui middle aligned center aligned grid"> <div class="row" > <div class="column"> <h1 class="ui orange header"> Welcome back ! <div class="sub header">We're happy helping you get beautiful name badges.</div> </h1> <div class="ui hidden divider"></div> <form class="ui form"> <div class="ui stacked element"> <div class="field required"> <div class="ui left icon input"> <i class="mail icon"></i> {{input type="text" value=email name="email" placeholder="E-mail address"}} </div> </div> <div class="field required"> <div class="ui left icon input"> <i class="lock icon"></i> {{input type="password" value=password name="password" placeholder="Password"}} </div> </div> <button class="ui button orange fluid" style="margin-bottom: 10px;" {{ action 'logIn' 'password' }}>Log In</button> <a href="#" class="text muted"> Forgot your password ?</a> <div class="ui divider"></div> <a href="{{href-to 'signup'}}" class="text muted weight-800">Don't have an account yet? Signup</a> </div> </form> <div class="ui horizontal divider"> Or </div> <h1 class="ui header"> <div class="sub header">Login with</div> </h1> </div> </div> <div class="three column row"> <div class="column"> <div class="ui vertical animated red button fluid" {{ action 'logIn' 'google' }}> <div class="hidden content">Google</div> <div class="visible content"> <i class="google plus icon"></i> </div> </div> </div> <div class="column"> <div class="ui vertical animated violet button fluid" tabindex="0" {{ action 'logIn' 'facebook' }}> <div class="hidden content">Facebook</div> <div class="visible content">…

Continue ReadingCreating Forms and their validation using Semantic UI in Badgeyay

Structure of Open Event Frontend

In Open Event Frontend, new contributors always fall into a dilemma of identifying the proper files where they have to make changes if they want to contribute. The project structure is quite complex and which is obvious because it is a large project. So, in this blog, we will walk through the structure of Open Event Frontend. Following are the different folders of the project explained: Root: The root of the project contains folders like app, config, kubernetes, tests, scripts. Our main project is in the app folder where all the files are present. The config folder in the root has files related to the deployment of the app in development, production, etc. It also has the environment setup such as host, api keys, etc. Other files such as package.json, bower.json, etc are basically to store the current versions of the packages and to ease the installation of the project. App: The app folder has all the files and is mainly classified into the following folder: adapters components controllers helpers Initializers mixins models routes serializers services styles templates transforms utils The folders with their significance are listed below: Adapters: This folder contains the files for building URLs for our endpoints. Sometimes it happens to have a somewhat customised URL for an endpoint which we pass through adapter to modify it. Components: This folder contains different components which we reuse in our app. For example, the image uploader component can be used at multiple places in our app, so we keep such elements in our components. This folder basically contains the js files of all the components(since when we generate a component, a js file and a hbs template is generated). Controllers: This folder contains the controller associated with each route. Since the main principle of ember js is DDAU i.e data down actions up, all the actions are written in the files of this folder. Helpers: Many a time it happens that, we want to format date, time, encode URL etc. There are some predefined helpers but sometimes custom helpers are also needed. All of them have been written in helpers folder. Initializers: This folder has a file for now called ‘blanket.js’ which basically injects the services into our routes, components. So if you want to write any service and want to inject it into routes/components, it should go in here. Mixins: In EmberJS the Mixin class can create objects whose properties and functions can be shared amongst other classes and instances. This allows for an easy way to share behavior between objects as well as design objects that may need multiple inheritance. All of them used for the application are in the mixins folder. Models: This folder contains the schema’s for our data. Since we are using ember data, we need to have proper skeleton of the data. All of this goes it this folder. Observing this folder will show you some models like user, event, etc. Routes: This folder contains the js files of the routes created. Routes…

Continue ReadingStructure of Open Event Frontend

Implementing the tickets API at the ‘tickets/add-order’ route

In Open Event Frontend, we have the ‘tickets/add-order’ route for a specific event which facilitates us to add the order based on the tickets that we create at the time of creation of event. The tickets are listed at the ‘tickets/add-order’ route where we can select the tickets required for example, ‘free’, ‘paid’, the payment type and proceed to the ticket buyer’s info page. This is how we achieved implementing the API: We use table to show the data to the user, the columns of which are Ticket Type, Price, Quantity, Item Total something like: So, the workflow to achieve this is as follows: Query the tickets for current event. Have a controller to calculate the ‘Grand Total’ of the individual tickets that the user wants to buy. Show the tickets in our table. Querying the tickets: Since we are using ember data, we query tickets by the following query in our model method of route. model() { return this.modelFor('events.view').query('tickets', {}); } Thus, the above query shows that we get the current event by actually querying the model for route ‘events.view’ which returns the current event and then query the tickets model so that we get the tickets associated with the current event. Since there is no UI table support for ember data, we are using a custom table for all the tables in Open Event Frontend and pass the data to it. To render the data in tables, we follow the following approach. In our controller, we have a columns property as: columns: [ { propertyName : 'name', title : 'Ticket Type' }, { propertyName : 'price', title : 'Price(US$)', disableSorting : true }, { propertyName : '', title : 'Quantity', template : 'components/ui-table/cell/cell-input-number' }, { propertyName : 'itemTotal', title : 'Item Total' } ] The propertyName maps the property of the objects returned from the server i.e in our case, the ‘tickets’. Thus, we pass this skeleton of columns and data from the model to our component so as to render the table in view. {{events/events-table columns=columns data=model useNumericPagination=true showGlobalFilter=true showPageSize=true } Also, as seen from the image shown earlier in this blog post, we can see that we also need to calculate the ‘Grand Total’ of the total purchase. Thus, we have a computed property in controller to do this: total: computed('model.@each.itemTotal', function() { let sum = 0.0; this.get('model').forEach(ticket => { sum += ticket.get('itemTotal'); }); return sum; }), We iterate over the each ‘itemTotal’ in the model and keep on adding it so that the total purchase gets added accordingly. Lastly we show the Grand Total to the user as seen in the image shown earlier in the blog. Thus, the user can select the tickets and proceed towards the checkout. Resources: Ember data official guide Blog on ember data by Andy Crum

Continue ReadingImplementing the tickets API at the ‘tickets/add-order’ route

Creating an Elementary Oscilloscope in PSLab’s Remote Framework

The last couple of blog posts explained how we could put together the versatility of ember components, the visual appeal of jqplot, the flexibility of Python Flask, and the simplicity of Python itself in order to make simple scripts for PSLab that would could be run on a server by a remote client anywhere on the web. We have also seen how callbacks could be assigned to widgets created in these scripts in order to make object oriented applications. In this blog post, we shall see how to assign a capture method to a button, and update a plot with the received data. It will also demonstrate how to use ember-lodash to perform array manipulations. Specifying the return data type in the callback success routine For a more instructive write-up on assigning callbacks, please refer to these posts . Whenever the callback assigned to a button is a function that returns an array of elements, and the target for the resultant data is a plot, the stacking order of the returned array must be specified in order to change its shape to suit the plotting library. The default return data from a capture routine (oscilloscope) is made up of separate arrays for X coordinate and Y coordinate values. Since JQplot requires [X,Y] pairs , we must specify a stacking order of ‘xy’ so that the application knows that it must convert them to pairs (using lodash/zip)  before passing the result to the plot widget. Similarly, different stacking orders for capture2, and capture4 must also be defined. Creating an action that performs necessary array manipulations and plots the received data It can be seen from the excerpt below, that if the onSuccess target for a callback is specified to be a plot in the actionDefinition object, then the stacking order is checked, and the returned data is modified accordingly Relevant excerpt from controllers/user-home.js/runButtonAction if (actionDefinition.success.type === 'update-plot') { if (actionDefinition.success.stacking === 'xy') { $.jqplot(actionDefinition.success.target, [zip(...resultValue)]).replot(); } else if (actionDefinition.success.stacking === 'xyy') { $.jqplot(actionDefinition.success.target, [zip(...[resultValue[0], resultValue[1]]), zip(...[resultValue[0], resultValue[2]])]).replot(); } else if (actionDefinition.success.stacking === 'xyyyy') { $.jqplot(actionDefinition.success.target, [zip(...[resultValue[0], resultValue[1]]), zip(...[resultValue[0], resultValue[2]]), zip(...[resultValue[0], resultValue[3]]), zip(...[resultValue[0], resultValue[4]])]).replot(); } else { $.jqplot(actionDefinition.success.target, resultValue).replot(); } }   With the above framework in place, we can add a plot with the line plt = plot(x, np.sin(x)) , and associate a button with a capture routine that will update its contents with a single line of code: button('capture1',"capture1('CH1',100,10)","update-plot",target=plt) Final Result The following script created on the pslab-remote platform makes three buttons and plots, and sets the buttons to invoke capture1, capture2, and capture4 respectively when clicked. import numpy as np x=np.linspace(0,2*np.pi,30) plt = plot(x, np.sin(x)) button('capture 1',"capture1('CH1',100,10)","update-plot",target=plt) plt2 = plot(x, np.sin(x)) button('capture 2',"capture2(50,10)","update-plot",target=plt2,stacking='xyy') plt3 = plot(x, np.sin(x)) button('capture 4',"capture4(50,10)","update-plot",target=plt3,stacking='xyyyy')                         Resources Ember components documentation : https://www.emberjs.com/api/ember/2.14/classes/Ember.Component Jqplot homepage : http://www.jqplot.com/ JQplot examples : http://www.jqplot.com/examples/line-charts.php Designing A Virtual Laboratory With PSLab Designing a Remote Laboratory with PSLab using Python Flask Framework Designing A Remote Laboratory With PSLab: execution of function…

Continue ReadingCreating an Elementary Oscilloscope in PSLab’s Remote Framework

Implement Sessions API for the ‘admin/sessions’ Route in Open Event Frontend

In Open Event Frontend, under the ‘admin/sessions’ route, the admin can track the record of the sessions. The info which is shown along with the sessions is the speakers for the session, its title, submitted date, start time, end time. So to integrate the sessions API, we followed the following approach: Firstly, we add a sessions model and establish its relationship with the speakers model since we need speaker names also: export default ModelBase.extend({ title : attr('string'), subtitle : attr('string'), startsAt : attr('moment'), endsAt : attr('moment'), j sessionType : belongsTo('session-type'), microlocation : belongsTo('microlocation'), track : belongsTo('track'), speakers : hasMany('speaker'), event : belongsTo('event'), // temporary }); After creating the model for sessions, we do the query to get the sessions. Since, the sessions here are classified into the sections like ‘pending’, ‘accepted’, ‘rejected’, ‘deleted’, etc, we need to filter the response returned by the query: if (params.sessions_state === 'pending') { filterOptions = [ { name : 'state', op : 'eq', val : 'pending' } ]; } else if (params.sessions_state === 'accepted') { filterOptions = [ { name : 'state', op : 'eq', val : 'accepted' } ]; } Above code shows how we filter the response on the server side itself. Hence we pass the filterOptions array to the query as follows: return this.get('store').query('session', { include : 'event,speakers', filter : filterOptions, 'page[size]' : 10 }); Once we get data from the query, we just pass it to our controller to implement the columns. Once we retrieve data from the query, we just pass it to our controller to implement the columns. Since, we are using a different way to render the ember data in the column, the approach goes as follows: In our controller we do: export default Controller.extend({ columns: [ { propertyName : 'event.name', title : 'Event Name', disableSorting : true }, { propertyName : 'title', title : 'Title' }, { propertyName : 'speakers', template : 'components/ui-table/cell/cell-speakers', title : 'Speakers', disableSorting : true } ] }); I have shown here only limited columns, there are others too. Here, we are mapping the propertyName to the attribute returned by the server. Also the ‘title’ indicates the column name. We can also create a custom template(as a component) if we want customization while rendering the data in the rows and columns. For example, if we want to iterate the multiple speaker names for a session, we can do: <div class="ui list"> {{#each record.speakers as |speaker|}} <div class="item"> {{speaker.name}} </div> {{/each}} </div> As a result, we can make custom templates for a particular property. Another example of formatting the response is: <span> {{moment-format record.startsAt 'MMMM DD, YYYY - HH:mm A'}} {{moment-format record.endsAt 'MMMM DD, YYYY - HH:mm A'}} </span> Thus, we get the following view after integration of API: Resources: Ember data Official guide Blog on medium: By “Embedly” publication

Continue ReadingImplement Sessions API for the ‘admin/sessions’ Route in Open Event Frontend

Enhancing the Functionality of User Submitted Scripts in the PSLab-remote framework

The remote-lab framework of the pocket science lab enables users to access their devices remotely via the internet. Its design involves an API server built with Python-Flask and a webapp that uses EmberJS. This post is the latest in a series of blog posts which have explored and elaborated various aspect of the remote-lab such as designing the API server and testing with Postman, remote execution of function strings, automatic deployment on various domains etc. It also supports creating and submitting python scripts which will be run on the remote server, and the console output relayed to the webapp. In this post, we shall take a look at how we can extend the functionality by providing support for object oriented code in user submitted scripts. Let’s take an example of a Python script where the user wishes to create a button which when clicked will read a voltage via the API server, and display the value to the remote user. Clearly, an interpreter that only provides the console output is not enough for this task. We need the interpreter to generate an app structure that also includes callbacks for widgets such as buttons, and JSON objects are an obvious choice for relaying such a structure to the webapp. In a nutshell, we had earlier created an API method that could execute a python script and return a string output, and now we will modify this method to return a JSON encoded structure which will be parsed by the webapp in order to display an output. Let’s elaborate this with an example : Example.py print ('testing') print ('testing some changes..... ') print_('highlighted print statement')   JSON returned by the API [localhost:8000/runScriptById] , for the above script: {"Date": "Tue, 01 Aug 2017 21:39:12 GMT", "Filename": "example.py", "Id": 4, "result": [ {"name": "print", "type": "span", "value": "('testing',)"}, {"name": "print", "type": "span", "value": "('testing some changes..... ',)"}, {"class": "row well", "name": "print", "type": "span", "value": "highlighted print statement"} ], "status": true} Screenshot of the EmberJS webapp showing the output rendered with the above JSON Adding Support for Widgets In the previous section, we laid the groundwork for a flexible platform. Instead of returning a string, the webapp accepts a JSON object and parses it. We shall now add support for a clickable button which can be associated with a valid PSLab function. An elementary JS twiddle has been made by Niranjan Rajendran which will help newbies to understand how to render dynamic templates via JSON objects retrieved from APIs. The twiddle uses two API endpoints; one to retrieve the compiled JSON output, and another to act as a voltmeter method which returns a voltage value. To understand how this works in pslab-remote, consider a one line script called button.py: button('get voltage',"get_voltage('CH1')") The objective is to create a button with the text ‘get voltage’ on it , and which when clicked will run the command ‘get_voltage(‘CH1’)’ on the API server, and display the result. When this script is run on the API server, it returns…

Continue ReadingEnhancing the Functionality of User Submitted Scripts in the PSLab-remote framework

PSLab Remote Lab: Automatically deploying the EmberJS WebApp and Flask API Server to different domains

The remote-lab software of the pocket science lab enables users to access their devices remotely via the internet. Its design involves an API server designed with Python Flask, and a web-app designed with EmberJS that allows users to access the API and carry out various tasks such as writing and executing Python scripts. For testing purposes, the repository needed to be setup to deploy both the backend as well as the webapp automatically when a build passes, and this blog post deals with how this can be achieved. Deploying the API server The Heroku PaaS was chosen due to its ease of use with a wide range of server software, and support for postgresql databases. It can be configured to automatically deploy branches from github repositories, and conditions such as passing of a linked CI can also be included. The following screenshot shows the Heroku configuration page of an app called pslab-test1. Most of the configuration actions can be carried out offline via the Heroku-Cli   In the above page, the pslab-test1 has been set to deploy automatically from the master branch of github.com/jithinbp/pslab-remote . The wait for CI to pass before deploy has been disabled since a CI has not been setup on the repository. Files required for Heroku to deploy automatically Once the Heroku PaaS has copied the latest commit made to the linked repository, it searches the base directory for a configuration file called runtime.txt which contains details about the language of the app and the version of the compiler/interpretor to use, and a Procfile which contains the command to launch the app once it is ready. Since the PSLab’s API server is written in Python, we also have a requirements.txt which is a list of dependencies to be installed before launching the application. Procfile web: gunicorn app:app --log-file - runtime.txt python-3.6.1 requirements.txt gunicorn==19.6.0 flask >= 0.10.1 psycopg2==2.6.2 flask-sqlalchemy SQLAlchemy>=0.8.0 numpy>=1.13 flask-cors>=3.0.0 But wait, our app cannot run yet, because it requires a postgresql database, and we did not do anything to set up one. The following steps will set up a postgres database using the heroku-cli usable from your command prompt. Point Heroku-cli to our app $ heroku git:remote -a pslab-test1 Create a postgres database under the hobby-dev plan available for free users. $ heroku addons:create heroku-postgresql:hobby-dev Creating heroku-postgresql:hobby-dev on ⬢ pslab-test1... free Database has been created and is available ! This database is empty. If upgrading, you can transfer ! data from another database with pg:copy Created postgresql-slippery-81404 as HEROKU_POSTGRESQL_CHARCOAL_URL Use heroku addons:docs heroku-postgresql to view documentation The previous step created a database along with an environment variable HEROKU_POSTGRESQL_CHARCOAL_URL . As a shorthand, we can also refer to it simply as CHARCOAL . In order to make it our primary database, it must be promoted $ heroku pg:promote HEROKU_POSTGRESQL_CHARCOAL_URL The database will now be available via the environment variable DATABASE_URL Further documentation on creating and modifying postgres databases on Heroku can be found in the articles section . At this point, if the app is…

Continue ReadingPSLab Remote Lab: Automatically deploying the EmberJS WebApp and Flask API Server to different domains

Implementing Notifications API in Open Event Frontend

In Open Event Frontend, at the index page of the application, we have a notification dropdown in which a user gets the notifications regarding the events, sessions, etc. Thus, a user gets notified for the particular event or session he wants to receive notifications about. While dealing with an issue, we had to integrate the API with the frontend. We achieved it as follows: First, we create a model of notifications so that we have basic structure ready. It goes as follows: export default ModelBase.extend({ title : attr('string'), message : attr('string'), isRead : attr('boolean', { defaultValue: false }), receivedAt : attr('moment'), user: belongsTo('user') }); Thus, we have fields like title, message, isRead, receivedAt which we will get from the server response as JSON which we will need to show on the page. To show the notifications to the user, first we need to query the notifications for a specific user using ember data. Since we are querying the notifications for a specific user when he is logged in, we are also having relationship between user and notification as shown in the above notification model. In user model we do: notifications: hasMany('notification') Now, we query the notifications in our application route i.e routes/application.js model() { if (this.get('session.isAuthenticated')) { return new RSVP.Promise((resolve, reject) => { this.store.findRecord('user', this.get('authManager.currentUser.id'), { reload: true }) .then(user => { user.get('notifications').then(resolve).catch(reject); }) .catch(reject); }); } } The reason why we used a RSVP promise here was because the authManager couldn’t load the user befor the notifications were queried and returned. Thus, we query the notifications by using currentUser from authManager. Thus, in our template, we iterate over our notifications as follows: {{#each notifications as notification }} <div class="item"> <div class="header"> {{notification.title}} </div> <div class="content weight-600"> {{notification.description}} </div> <div class="left floated content"> {{moment-from-now notification.createdAt}} </div> </div> {{/each}} The notifications are thus shown to the user when he clicks the icon in the nav-bar. As a result, we get the following notifications in the dropdown: Resources: Ember data official guide Blog on Ember data by Embedly.

Continue ReadingImplementing Notifications API in Open Event Frontend

Implementing Email Notifications in Open Event Frontend

In Open Event Frontend, we have a ‘settings/email-preferences’ route where we give the user an access to change the email-notifications that he wants to subscribe for a specific event. For now, we are having three notifications for an event which the user can toggle to on and off. To achieve this, we did the following things: First, we create a model for email-notifications so as to have a skeleton of the data that we are going to receive from the JSON API. export default ModelBase.extend({ /** * Attributes */ nextEvent : attr('boolean'), newPaper : attr('boolean'), sessionAcceptReject : attr('boolean'), sessionSchedule : attr('boolean'), afterTicketPurchase : attr('boolean'), /** * Relationships */ user : belongsTo('user'), event : belongsTo('event') }); Thus, above code shows the attributes which we are going to receive via our JSON API and we will render the data accordingly on the page. We have established the relationship of the email-notifications with user and event so that in future wherever needed, we can query the records from either side. The client side has checkboxes to show the data to the user. Following is the format of the checkboxes: <div class="row"> <div class="column eight wide"> {{t 'New Paper is Submitted to your Event'}} </div> <div class="ui column eight wide right aligned"> {{ui-checkbox class='toggle' checked=preference.newPaper onChange=(pipe-action (action (mut preference.newPaper)) (action 'savePreference' preference))}} </div> </div> <div class="row"> <div class="column eight wide"> {{t 'Change in Schedule of Sessions in your Event'}} </div> <div class="ui column eight wide right aligned"> {{ui-checkbox class='toggle' checked=preference.sessionSchedule onChange=(pipe-action (action (mut preference.sessionSchedule)) (action 'savePreference' preference))}} </div> </div> The states of the checkboxes are determined by the data that we receive from the API. For example, if for a record, the API returns: nextEvent : true, newPaper : false, sessionAcceptReject : true, sessionSchedule : false, afterTicketPurchase : false, Then, the respective states will be shown by the checkbox and the user can toggle the states to change the email-preferences as they want. Thus to get the data sent by the server to the client, we return it as a model and query it as: model() { return this.get('authManager.currentUser').query('emailNotifications', { include: 'event' }); } As we can see, as mentioned earlier, we kept the relationships so that we can query the email-notifications specific to the particular user or specific to particular event. Here, we are showing a user’s email-notifications and hence we queried it with the user relationship. The authManager loads the currentUser and queries the email-notifications for a particular use. We also want the event details to show the email-preferences, hence we include the event model to be fetched in the query also. We also let the user change the preferences of the email-notifications so that he can customise the notifications and keep the ones he wants to receive. We implement the updating of email-preferences API as follows: Whenever a user toggles the checkbox, we are having an action as called ‘savePreference’, which handles the updation of the preferences.   {{ui-checkbox class='toggle' checked=preference.newPaper onChange=(pipe-action (action (mut preference.newPaper)) (action 'savePreference' preference))}} savePreference(emailPreference) { emailPreference.save()…

Continue ReadingImplementing Email Notifications in Open Event Frontend