Metadata Updation in Badgeyay

Badgeyay is a simple badge generator service to develop badges for technical events and conferences developed by FOSSASIA. Badgeyay is a SPA (Single Page Application) developed in ember, whose backend is in Flask. Now when user logins, he can see an option for user profile, in which all the metadata of its profile can be seen (extracted from Firebase). Now user should be able to change its metadata like profile image and username etc. So we will look how the profile image is being changed and updated in badgeyay. Procedure Create function in frontend to listen for onclick events and initiate a file upload dialog box for selecting an image. We will use document property to initiate a dummy click event, else there will be a button with the text to upload a file and that won’t look consistent as we only need an image and nothing else on the UI. class="ui small circular image profile-image">     "{{user.photoURL}}">     "display: none;" id="profileImageSelector" type="file" onchange={{action "profileImageSelected"}}>     "profile-change" onclick={{action "updateProfileImage"}}>Change </div>   Function to upload file and initiate a dummy click event updateProfileImage() {     // Initate a dummy click event     document.getElementById('profileImageSelector').click();   },   profileImageSelected(event) {     const reader = new FileReader();     const { target } = event;     const { files } = target;     const [file] = files;     const _this = this;     reader.onload = () => {       _this.get('sendProfileImage')(reader.result, file.type.split('/')[1]);     };     reader.readAsDataURL(file);   }   Profile update function in the main controller to call the API endpoint to upload the data to backend. This will send the payload to backend which will later upload the image to cloud storage and save in the link in the database. updateProfileImage(profileImageData, extension) {     const _this = this;     const user = this.get('store').peekAll('user');     user.forEach(user_ => {       _this.set('uid', user_.get('id'));     });     let profileImage = _this.get('store').createRecord('profile-image', {       image   : profileImageData,       uid   : _this.uid,       extension : '.' + extension     });     profileImage.save()       .then(record => {         user.forEach(user_ => {           user_.set('photoURL', record.photoURL);         });       })       .catch(err => {         let userErrors = profileImage.get('errors.user');         if (userErrors !== undefined) {           _this.set('userError', userErrors);         }       });   } Route to update profile image from backend @router.route('/profileImage', methods=['POST']) def update_profile_image():   try:       data = request.get_json()['data']['attributes']   except Exception:       return ErrorResponse(PayloadNotFound().message, 422, {'Content-Type': 'application/json'}).respond()   if not data['image']:       return ErrorResponse(ImageNotFound().message, 422, {'Content-Type': 'application/json'}).respond()   if not data['extension']:       return ErrorResponse(ExtensionNotFound().message, 422, {'Content-Type': 'application/json'}).respond()   uid = data['uid']   image = data['image']   extension = data['extension']   try:       imageName = saveToImage(imageFile=image, extension=extension)   except Exception:       return ErrorResponse(ImageNotFound().message, 422, {'Content-Type': 'application/json'}).respond()   fetch_user, imageLink = update_database(uid, imageName)   return jsonify(UpdateUserSchema().dump(fetch_user).data)   This will first create a temp file with the data URI and them upload that file to cloud storage and generate the link and then update the user in the database. def update_database(uid, imageName):   fetch_user = User.getUser(user_id=uid)   if fetch_user is None:       return ErrorResponse(UserNotFound(uid).message, 422, {'Content-Type': 'application/json'}).respond()   imagePath = os.path.join(app.config.get('BASE_DIR'), 'static', 'uploads', 'image') + '/' + imageName   imageLink = fileUploader(imagePath, 'profile/images/' + imageName)   fetch_user.photoURL = imageLink   fetch_user.save_to_db()   try:       os.unlink(imagePath)   except Exception:       print('Unable to delete the temporary file')   return fetch_user, imageLink   Link to PR - Link Topics Involved Google Cloud Admin Storage SDK Ember data Resources Firebase admin sdk documentation - Link Google Cloud…

Continue ReadingMetadata Updation in Badgeyay

User Guide for the PSLab Remote-Access Framework

The remote-lab framework of the pocket science lab has been designed to enable user to access their devices remotely via the internet. The pslab-remote repository includes an API server built with Python-Flask and a webapp that uses EmberJS. This post is a guide for users who wish to test the framework. A series of blog posts have been previously written which have explored and elaborated various aspect of the remote-lab such as designing the API server, remote execution of function strings, automatic deployment on various domains etc. In this post, we shall explore how to execute function strings, execute example scripts, and write a script ourselves. A live demo is hosted at pslab-remote.surge.sh . The API server is hosted at pslab-stage.herokuapp.com, and an API reference which is being developed can be accessed at pslab-stage.herokuapp.com/apidocs . A screencast of the remote lab is also available Create an account Signing up at this point is very straightforward, and does not include any third party verification tools since the framework is under active development, and cannot be claimed to be ready for release yet. Click on the sign-up button, and provide a username, email, and password. The e-mail will be used as the login-id, and needs to be unique. Login to the remote lab Use the email-id used for signing up, enter the password, and the app will redirect you to your new home-page, where you will be greeted with a similar screen. Your home-page On the home-page, you will find that the first section includes a text box for entering a function string, and an execute button. Here, you can enter any valid PSLab function such as `get_resistance()` , and click on the execute button in order to run the function on the PSLab device connected to the API server, and view the results. A detailed blog post on this process can be found here. Since this is a new account, no saved scripts are present in the Your Scripts section. We will come to that shortly, but for now, there are some pre-written example scripts that will let you test them as well as view their source code in order to copy into your own collection, and modify them. Click on the play icon next to `multimeter.py` in order to run the script. The eye icon to the right of the row enables you to view the source code, but this can also be done while the app is running. The multimeter app looks something like this, and you can click on the various buttons to try them out. You may also click on the Source Code tab in order to view the source Create and execute a small python script We can now try to create a simple script of our own. Click on the `New Python Script` button in the top-bar to navigate to a page that will allow you to create and save your own scripts. We shall write a small 3-line code to print some sinusoidal coordinates, save…

Continue ReadingUser Guide for the PSLab Remote-Access 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

Designing A Remote Laboratory With PSLab: execution of function strings

In the previous blog post, we introduced the concept of a ‘remote laboratory’, which would enable users to access the various features of the PSLab via the internet. Many aspects of the project were worked upon, which also involved creation of a web-app using EmberJS that enables users to create accounts , sign in, and prepare Python programs to be sent to the server for execution. A backend APi server based on Python-flask was also developed to handle these tasks, and maintain a postgresql database using sqlalchemy . The following screencast shows the basic look and feel of the proposed remote lab running in a web browser. This blog post will deal with implementing a way for the remote user to submit a simple function string, such as get_voltage(‘CH1’), and retrieve the results from the server. There are three parts to this: Creating a dictionary of the functions available in the sciencelab instance. The user will only be allowed access to these functions remotely, and we may protect some functions as the initialization and destruction routines by blocking them from the remote user Creating an API method to receive a form containing the function string, execute the corresponding function from the dictionary, and reply with JSON data Testing the API using the postman chrome extension Creating a dictionary of functions : The function dictionary maps function names against references to the actual functions from an instance of PSL.sciencelab . A simple dictionary containing just the get_voltage function can be generated in the following way: from PSL import sciencelab I=sciencelab.connect() functionList = {'get_voltage':I.get_voltage} This dictionary is then used with the eval method in order to evaluate a function string: result = eval('get_voltage('CH1')',functionList) print (result) 0.0012 A more efficient way to create this list is to use the inspect module, and automatically extract all the available methods into a dictionary functionList = {} for a in dir(I): attr = getattr(I, a) if inspect.ismethod(attr) and a!='__init__': functionList[a] = attr In the above, we have made a dictionary of all the methods except __init__ This approach can also be easily extrapolated to automatically generate a dictionary for inline documentation strings which can then be passed on to the web app. Creating an API method to execute submitted function strings We create an API method that accepts a form containing the function string and option that specifies if the returned value is to be formatted as a string or JSON data. A special case arises for numpy arrays which cannot be directly converted to JSON, and the toList function must first be used for them. @app.route('/evalFunctionString',methods=['POST']) def evalFunctionString(): if session.get('user'): _stringify=False try: _user = session.get('user')[1] _fn = request.form['function'] _stringify = request.form.get('stringify',False) res = eval(_fn,functionList) except Exception as e: res = str(e) #dump string if requested. Otherwise json array if _stringify: return json.dumps({'status':True,'result':str(res),'stringified':True}) else: #Try to simply convert the results to json try: return json.dumps({'status':True,'result':res,'stringified':False}) # If that didn't work, it's due to the result containing numpy arrays. except Exception as e: #try to convert the…

Continue ReadingDesigning A Remote Laboratory With PSLab: execution of function strings

Designing a Remote Laboratory with PSLab using Python Flask Framework

In the introductory post about remote laboratories, a general set of tools to create a framework and handle its various aspects was also introduced. In this blog post, we will explore the implementation of several aspects of the backend app designed with python-flask, and the frontend based on EmberJS. A clear separation of the frontend and backend facilitates minimal disruption of either sections due to the other. Implementing API methods in Python-Flask In the Flask web server, page requests are handled via ‘routes’ , which are essentially URLs linked to a python function. Routes are also capable of handling payloads such as POST data, and various return types are also supported. We shall use an example to demonstrate how a Sign-Up request sent from the sign-up form in the remote lab frontend for PSLab is handled. @app.route('/signUp',methods=['POST']) def signUp(): """Sign Up for Virtual Lab POST: Submit sign-up parameters. The following must be present: inputName : The name of your account. does not need to be unique inputEmail : e-mail ID used for login . must be unique. inputPassword: password . Returns HTTP 404 when data does not exist. """ # read the posted values from the UI _name = request.form['inputName'] _email = request.form['inputEmail'] _password = request.form['inputPassword'] # validate the received values if _name and _email and _password: _hashed_password = generate_password_hash(_password) newUser = User(_email, _name,_hashed_password) try: db.session.add(newUser) db.session.commit() return json.dumps({'status':True,'message':'User %s created successfully. e-mail:%s !'%(_name,_email)}) except Exception as exc: reason = str(exc) return json.dumps({'status':False,'message':str(reason)})   In this example, the first line indicates that all URL requests made to <domain:port>/signUp will be handled by the function signUp . During development, we host the server on localhost, and use the default PORT number 8000, so sign-up forms must be submitted to 127.0.0.1:8000/signUp . For deployment on a globally accessible server, a machine with a static IP, and a DNS record must be used. An example for such a deployment would be the heroku subdomain where pslab-remote is automatically deployed ; https://pslab-stage.herokuapp.com/signUp A closer look at the above example will tell you that POST data can be accessed via the request.form dictionary, and that the sign-up routine requires inputName,inputEmail, and inputPassword. A password hash is generated before writing the parameters to the database. Testing API methods using the Postman chrome extension The route described in the above example requires form data to be submitted along with the URL, and we will use a rather handy developer tool called Postman to help us do this. In the frontend apps , AJAX methods are usually employed to do such tasks as well as handle the response from the server.   The above screenshot shows Postman being used to submit form data to /signUp on our API server running at localhost:8000 . The fields inputName, inputDescription, and inputPassword are also posted along with it. In the bottom section, one can see that the server returned a positive status variable, as well as a descriptive message. Submitting the sign up form via an Ember controller. Setting up a…

Continue ReadingDesigning a Remote Laboratory with PSLab using Python Flask Framework

Creating a notification dropdown in semantic UI for Open Event Frontend

Semantic UI comes packaged with highly responsive components to cater to all front end needs. The area of front-end development is so large, it is never possible to cover all the possible requirements of a developer with pre built components. Currently there is no means to display notifications on the navbar in Open Event Front-end project. In this article we are going to build a notification dropdown from scratch which will be used there to display notifications. So we begin by generating a new component via ember CLI $ ember generate component notification-dropdown This should generate the boiler-plate code for our component, with the template file located at: templates/components/notification-dropdown.hbs and the JS file located at components/notification-dropdown.js  It is assumed that you already have a basic ember app with at least a navbar set up. The notification drop down will be integrated with the navbar as a separate component. This allows us great flexibility in terms of location of the navbar, and also helps us  in not cluttering the code in one file. We will use the popup component of semantic ui as the underlying structure of our dropdown. I have used some dummy data stored in a separate file, you can use any dummy data you wish, either  by directly hardcoding it or importing it from a js file stored somewhere else. It’s preferred if the mock data is called from a js file, because it helps in simulating the server response in a much more genuine way. We will make use of the floating label of semantic UI to display the number of unread notifications. A mail outline icon should make for a good choice to use the primary icon to denote the notifications. Also, the floating label will require additional styling to make it overlap with the icon perfectly. For the header in the dropdown we can give a ‘mark all as read’ button aligned to the right and the ‘notification’ header to the left. Also for best user experience even on small devices, we will make each notification item clickable as a whole instead of individual clickable elements in it. A selection link list of semantic UI should be perfect to display individual notifications as it gives a hovering effect and also, allows us to display a header. Moving onto individual notification items, it will have 3 sub parts A header Description Human friendly notification time For the header we will use the ‘header’ class predefined in semantic UI for list items.We will use ‘content’ class for description which is again a predefined semantic UI class, And finally the time can be displayed via moment-from-now helper of ember to display the time in a human friendly format. <.i class="mail outline icon"> <./i> <.div class="floating ui teal circular mini label">{{notifications.length}}<./div> <.div class="ui wide notification popup bottom left transition ">  <.div class="ui basic inverted horizontal segments">    <.div class="ui basic left aligned segment weight-800">      <.p>{{t 'Notifications'}}<./p>    <./div>    <.div class="ui basic right aligned segment weight-400">      <.a href="#">{{t 'Mark all as Read'}}<./a>…

Continue ReadingCreating a notification dropdown in semantic UI for Open Event Frontend

Step by step guide for Beginners in Web Development for Open Event Frontend

Originally the frontend and backend of the Open Event Server project were handled by FLASK with jinja2 being used for rendering templates. As the size of the project grew, it became difficult to keep track of all the modifications made on the frontend side. It also increased the complexity of the code. As a result of this, a new project Open Event Frontend was developed by decoupling the backend and frontend of the Open Event Orga Server. Now the server is being converted fully into functional API and database and the open event frontend project is primarily the frontend for the Open event server API where organisers, speakers and attendees can sign-up and perform various functions.      The Open Event Frontend project is built on JavaScript web application framework, “Ember.js”. To communicate with the server API Ember.js user Ember data which is a data persistence module via the exposed endpoints. Suppose if you’re coming from the Android background, soon after diving into the web development you can relate that the web ecosystem is much larger than the mobile one and for the first timers it can be difficult to adopt with it because of the reason that in web there are multiple ways to perform a task which can be restricted to very few in the case of Android. For web applications, one can find that much more components are involved in setting up the project while in android one can easily start contributing to project soon after compiling it in Android Studio. One thing which is relatable for both the android and web development is that in the case of android one has to deal with the varying screen sizes and compatibility issue while in the web one has to deal with adding support for different browsers and versions which can be really annoying. Now let’s see how one can start contributing to the Open event frontend project while having no or a little knowledge of web development. In case if you’ve previous knowledge of JavaScript then you can skip the step 1 and move directly to another step which is learning the framework. (Here all the steps have been explained in reference if you’re switching from Android  to Web development.) Step 1. Learning the Language - JavaScript Now that when you’ve already put your feet into the web development it’s high time to get acquainted with the JavaScript. Essentially in the case of Ember which is easy to comprehend, you can though start with learning the framework itself but the executables file are written in JavaScript so to write them you must have basic knowledge of the concepts in the language. Understanding of JavaScript will help in letting know where the language ends and where the framework starts. It will also help in better understanding of the framework. In my opinion, the basic knowledge of JavaScript like the scope of variables, functions, looping, conditional statements, modifying array and dictionaries, ‘this’ keyword etc. helps in writing and understanding the…

Continue ReadingStep by step guide for Beginners in Web Development for Open Event Frontend

Adding dynamic segments to a route in Open Event Frontend Project

When we talk about a web application the first thing comes up is how to decide what to display at a given time which in most of the application is decided with the help of the URL. The URL of the application can be set either by loading the application or by writing the URL manually or may be by clicking some link. In our Open Event Frontend project which is written in Ember.js, an incredibly powerful JavaScript framework for creating web applications, the URL is mapped to the router handlers with the helper of router to render the template for the page, to load the data model to display, to navigate within the application or to handle any actions within the page like button clicking etc. Suppose the user opens the open event application for the very first time what s/he will see a page containing the list of all the events which are going to happen in the near future along with their details like event name, timings, place, tags etc. If the user clicks one of the events from the list, the current page will be redirected to the detailed specific page for that particular event. The behaviour of changing the content of the page which we observed during this process can be explained with the help of the dynamic segments concept. The dynamic segment is a section of the path for a route which changes based on the content of a page. This post will focus on how we have added dynamic segments to the route in the open event frontend project. Let’s demonstrate the process of adding the dynamic segments to the route by taking an example of sessions routes where we can see the list of all the accepted, pending, confirmed and rejected sessions along with their details. To add a dynamic segment, we need to have a route with path which we add to the route definition in app/router.js file this.route('sessions', function() { this.route('list', { path: '/:sessions_state' }); }); Dynamic segments are made up of a : followed by an identifier. Ember follows the convention of :model-name_id for two reasons. The first reason is that routes know how to fetch the right model by default if we follow the convention. The second is that params is an object, and can only have one value associated with a key. After defining the path in app/router.js file we need to add template file,  app/templates/events/sessions/list.hbs which contain the markup to display the data which is defined in the file, app/routes/events/sessions/list.js under the model hook of the route in order to display the correct content for the specified option. Code containing the markup for the page in app/templates/events/sessions/list.hbs file <div class="sixteen wide column"> <table class="ui tablet stackable very basic table"> <thead> <tr> <th>{{t 'State'}}</th> <th>{{t 'Title'}}</th> <th>{{t 'Speakers'}}</th> <th>{{t 'Track'}}</th> <th>{{t 'Short Abstract'}}</th> <th>{{t 'Submission Date'}}</th> <th>{{t 'Last Modified'}}</th> <th>{{t 'Email Sent'}}</th> <th></th> <th></th> </tr> </thead> <tbody> {{#each model as |session|}} <tr> <td> {{#if (eq session.state "confirmed")}}…

Continue ReadingAdding dynamic segments to a route in Open Event Frontend Project

Using Ember.js Components in Open Event Frontend

Ember.js is a comprehensive JavaScript framework for building highly ambitious web applications. The basic tenet of Ember.js is convention over configuration which means that it understands that a large part of the code, as well as development process, is common to most of the web applications. Talking about the components which are nothing but the elements whose role remain same with same properties and functions within the entire project. Components allow developers to bundle up HTML elements and styles into reusable custom elements which can be called anywhere within the project. In Ember, the components consist of two parts: some JavaScript code and an HTMLBars template. The JavaScript component file defines the behaviour and properties of the component. The behaviours of the component are typically defined using actions. The HTMLBars file defines the markup for the component's UI. By default, the component will be rendered into a 'div' tag element, but a different element can be defined if required. A great thing about templates in Ember is that other components can be called inside of a component's template. To call a component in an Ember app, we must use {{curly-brace-syntax}}. By design, components are completely isolated which means that they are not directly affected by any surrounding CSS or JavaScript. Let’s demonstrate a basic Ember component in reference to Open Event Frontend Project for displaying the text as a popup. The component will render a simple text view which will display the entire text. The component is designed with the purpose that many times due to unavailability of space we’re unable to show the complete text so such cases the component will compare the available space with the space required by the whole text view to display the text. If in case the available space is not sufficient then the text will be ellipsized and on hovering the text a popup will appear where the complete text can be seen. Generating the component The component can be generated using the following command: $ ember g component smart-overflow Note: The components name needs to include a hyphen. This is an Ember convention, but it is an important one as it'll ensure there are no naming collisions with future HTML elements.This will create the required .js and .hbs files needed to define the component, as well as an Ember integration test. The Component Template In the app/templates/components/smart-overflow.hbs file we can create some basic markup to display the text when the component is called. <span> {{yield}} </span> The {{yield}} is handlebars expressions which will be helpful in rendering the data to display when the component is called. The JavaScript Code In the app/components/smart-overflow.js file, we will define the how the component will work when it is called. import Ember from 'ember'; const { Component } = Ember; export default Component.extend({ classNames: ['smart-overflow'], didInsertElement() { this._super(...arguments); var $headerSpan = this.$('span'); var $header = this.$(); $header.attr('data-content', $headerSpan.text()); $header.attr('data-variation', 'tiny'); while ($headerSpan.outerHeight() > $header.height()) { $headerSpan.text((index, text) => { return text.replace(/\W*\s(\S)*$/, '...'); }); $header.popup({ position: 'top…

Continue ReadingUsing Ember.js Components in Open Event Frontend

Forms and their validation using Semantic UI in Open Event Frontend

A web form acts as a communication bridge that allows a user to communicate with the organisation and vice versa. In the Open Event project, we need forms so users can contact the organisation, to register themselves, to log into the website, to order a ticket or to query for some information. Here are a few things which were kept in mind before we designed forms in the Open Event Frontend Project: The forms were designed on the principle of keeping it simple which means that it should ask only for the relevant information which is required in actual. They contained the relevant fields ordered in a logical way according to their importance. They offered clear error messages instantly to give direct feedback and allow users to make instant corrections. The clear examples were shown in the front of the field. Proper spacing among the fields was maintained to display proper error messages to the respective form fields. The mandatory fields are highlighted using ‘*’ to avoid confusion. Proper colour combinations have been used to inform the user about the progress while filling the form. For eg. red for any ‘error or incomplete’ information while green signifies ‘correct’. Saving the current data in case the user has to go back to make any corrections later. Allowing to toggle through the form using the keyboard. The above designing principles helped in avoiding the negative user experience while using the forms. Let’s take a closer look at the form and the form validation in case of purchase a new ticket form on the Orders page in Open Event Front-end application. Creating a form Let’s start by writing some HTML for the form: <form class="ui form" {{action 'submit' on='submit' }}> <div class="ui padded segment"> <h4 class="ui horizontal divider header"> <i class="ticket icon"></i> {{t 'Ticket Buyer'}} </h4> <div class="field"> <label class="required" for="firstname">{{t 'First Name'}}</label> {{input type='text' name='first_name' value=buyer.firstName}} </div> <div class="field"> <label class="required" for="lastname">{{t 'Last Name'}}</label> {{input type='text' name='last_name' value=buyer.lastName}} </div> <div class="field"> <label class="required" for="email">{{t 'Email'}}</label> {{input type='text' name='email' value=buyer.email}} </div> <h4 class="ui horizontal divider header"> <i class="ticket icon"></i> {{t 'Ticket Holder\'s Information'}} </h4> {{#each holders as |holder index|}} <div class="inline field"> <i class="user icon"></i> <label>{{t 'Ticket Holder '}}{{inc index}}</label> </div> <div class="field"> <label class="required" for="firstname">{{t 'First Name'}}</label> {{input type='text' name=(concat 'first_name_' index) value=holder.firstName}} </div> <div class="field"> <label class="required" for="lastname">{{t 'Last Name'}}</label> {{input type='text' name=(concat 'last_name_' index) value=holder.lastName}} </div> <div class="field"> <label class="required" for="email">{{t 'Email'}}</label> {{input type='text' name=(concat 'email_' index) value=holder.email}} </div> <div class="field"> {{ui-checkbox label=(t 'Same as Ticket Buyer') checked=holder.sameAsBuyer onChange=(action 'fillHolderData' holder)}} </div> {{/each}} <p> {{t 'By clicking "Pay Now", I acknowledge that I have read and agree with the Open Event terms of services and privacy policy.'}} </p> <div class="center aligned"> <button type="submit" class="ui teal submit button">{{t 'Pay Now'}}</button> </div> </div> </form>   The complete code for the form can be seen here. In the above code, we have used Semantic UI elements like button, input, label, icon, header and modules like dropdown, checkbox to create the basic structure of…

Continue ReadingForms and their validation using Semantic UI in Open Event Frontend