Skip to content

Instantly share code, notes, and snippets.

@sibijohn72
Forked from zomarg/controllers.application.js
Last active February 11, 2019 13:05
Show Gist options
  • Save sibijohn72/c7f45ddc4c868bedd175d3ceeae23c2e to your computer and use it in GitHub Desktop.
Save sibijohn72/c7f45ddc4c868bedd175d3ceeae23c2e to your computer and use it in GitHub Desktop.
Gfk 02/2019
import RESTAdapter from 'ember-data/adapters/rest';
export default RESTAdapter.extend({
host: "https://5c57fdfb9815f6001490359a.mockapi.io/"
});
import DS from 'ember-data';
import { decamelize } from '@ember/string';
export default DS.JSONSerializer.extend({
serializeIntoHash(data, type, record, options) {
var root = decamelize(type.modelName);
data[root] = this.serialize(record, options);
}
});
import Ember from 'ember';
export default Ember.Component.extend({
tagName:'',
actions:{
inputChanged(){
Ember.set(this,'value',!this.get('value'));
}
}
});
<input type="checkbox" checked={{value}} onchange={{action "inputChanged" value="target.value"}}>
import Ember from 'ember';
export default Ember.Controller.extend({
appName: 'Gfk Excercise'
});
import Ember from 'ember';
export default Ember.Component.extend({
tagName:'',
isFormValid: Ember.computed('employee.validations.isValid', function () {
return this.get('employee.validations.isValid');
}),
classNames: ['content'],
didInsertElement() {
this._super(...arguments);
Ember.$('.list-content-container').removeClass('col-md-12');
Ember.$('.list-content-container').addClass('col-md-4');
},
willDestroyElement() {
this._super(...arguments);
Ember.$('.list-content-container').addClass('col-md-12');
Ember.$('.list-content-container').removeClass('col-md-4');
}
});
<form id="employee-form" class="form-horizontal" onsubmit={{action (route-action 'saveEmployee' employee)}} style="margin-top:20px">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label class="col-sm-2 control-label">Name</label>
<div class="col-sm-10">
{{input type="text" classNames="form-control" placeholder="Name" value=employee.name disabled=disabled}}
{{employee.validations.attrs.name.message}}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Country</label>
<div class="col-sm-10">
{{#if disabled}}
{{input type="text" classNames="form-control" placeholder="Name" value=(if employee.country employee.country.name 'NA') disabled=disabled}}
{{else}}
{{#power-select selected=(find-by 'id' employee.country.id countries) disabled=disabled options=countries renderInPlace=true
searchField='name' searchEnabled=true onchange=(action (mut employee.country)) as |country|}}
{{country.name}}
{{/power-select}}
{{employee.validations.attrs.country.message}}
{{/if}}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Phone</label>
<div class="col-sm-10">
{{input type="tel" classNames="form-control" placeholder="Phone" value=employee.phone disabled=disabled }}
{{employee.validations.attrs.phone.message}}
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label class="col-sm-2 control-label">Surname</label>
<div class="col-sm-10">
{{input type="text" classNames="form-control" placeholder="Surname" value=employee.surname disabled=disabled}}
{{employee.validations.attrs.surname.message}}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Address</label>
<div class="col-sm-10">
{{textarea classNames="form-control" placeholder="Address" value=employee.address cols="80" rows="6" disabled=disabled}}
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">Email</label>
<div class="col-sm-10">
{{input type="email" classNames="form-control" placeholder="Email" value=employee.email disabled=disabled}}
{{employee.validations.attrs.email.message}}
</div>
</div>
</div>
</div>
{{#unless disabled}}
<button type="submit" class='btn btn-success' disabled={{not isFormValid}}>
Save
</button>
{{#link-to 'ems.employees' classNames='btn btn-warning' tagName="button"}}
Cancel
{{/link-to}}
{{/unless}}
</form>
import ApplicationSerializer from '../application/serializer';
export default ApplicationSerializer.extend({
keyForRelationship: function(key, relationship/*, method*/) {
if (/*method === 'deserialize' && */relationship === 'belongsTo') {
return `${key}Id`;
} else {
return this._super(...arguments);
}
},
});
import Controller from '@ember/controller';
import {computed} from '@ember/object';
export default Controller.extend({
allEmployeeSelected: computed('selectedEmployeeList',function(){
return this.get('employees').length === this.get('selectedEmployeeList').length;
}),
selectedEmployeeList: computed('employees.@each.selected',function(){
return this.get('employees').filterBy('selected',true);
}),
actions:{
selectEmployees(){
if(this.get('allEmployeeSelected'))
this.get('employees').setEach('selected',false);
else
this.get('employees').setEach('selected',true);
}
}
});
import Ember from 'ember';
export default Ember.Route.extend({
model(){
return Ember.Object.create({
employee: this.store.createRecord('employee', {}),
});
},
setupController(controller){
this._super(...arguments);
this.store.findAll('country').then(function(countries){
controller.set('countries',countries);
});
},
actions:{
saveEmployee(employee,e){
let self=this;
e.preventDefault();
employee.save().then(function(){
self.transitionTo('ems.employees.employee',employee.get('id'))
});
},
willTransition(transition) {
const {employee} = this.get('currentModel');
if (Object.keys(employee.changedAttributes()).length > 0) {
const discardEdit = window.confirm('There are some unsaved changes to the employee. Discard changes?');
if (!discardEdit) {
transition.abort();
}
}
this.store.unloadRecord(employee);
},
}
});
{{#if countries}}
{{employee-form employee=model.employee countries=countries}}
{{/if}}
import Ember from 'ember';
export default Ember.Route.extend({
model(){
return this.modelFor('ems.employees.employee');
},
setupController(controller){
this._super(...arguments);
this.store.findAll('country').then(function(countries){
controller.set('countries',countries);
});
},
actions:{
saveEmployee(employee,e){
let self=this;
e.preventDefault();
employee.save().then(function(){
self.transitionTo('ems.employees.employee',employee.get('id'))
});
},
willTransition(transition) {
const employee = this.get('currentModel');
if (employee.get('hasDirtyAttributes')) {
const discardEdit = window.confirm('There are some unsaved changes to the employee. Discard changes?');
if (discardEdit) {
employee.rollbackAttributes();
} else {
transition.abort();
}
}
},
}
});
{{#if countries}}
{{employee-form employee=model countries=countries}}
{{/if}}
import Ember from 'ember';
export default Ember.Route.extend({
model(){
return this.modelFor('ems.employees.employee');
},
actions:{
saveEmployee(){
}
}
});
<div class="row">
<div class="btn-group pull-right">
{{#link-to "ems.employees.employee.edit" model.id tagName='button' classNames="btn btn-primary"}}
Edit
{{/link-to}}
{{#link-to 'ems.employees' classNames='btn btn-warning' tagName="button"}}
Cancel
{{/link-to}}
</div>
</div>
{{employee-form employee=model countries=countries disabled=true}}
import Ember from 'ember';
export default Ember.Route.extend({
model(params){
let id=params.id || 1;
return this.store.findRecord('employee',id);
}
});
import Route from '@ember/routing/route';
export default Route.extend({
notify:Ember.inject.service('notify'),
model(){
return this.store.findAll('employee');
},
setupController(controller,model){
this._super(...arguments);
controller.set('employees',model);
},
actions:{
deleteEmployees(employees){
let self=this;
let deletedSuccessfully=true;
employees.forEach(employee=>{
employee.destroyRecord().then(function(){},function(error){
deletedSuccessfully=false;
self.get('notify').alert(error.message);
}).finally(function(){
if(employee==employees.get('lastObject') && deletedSuccessfully)
{
self.get('notify').success("All selected employees were deleted successfully");
self.transitionTo('ems.employees');
}
});
});
}
}
});
<div class="container-fluid" style="padding:25px">
<div class="row">
<div class="list-content-container col-md-12">
<div class="row">
<div style="float:right">
{{#link-to 'ems.employees.create' tagName='button' classNames='btn btn-primary'}}New Employee{{/link-to}}
<button disabled={{if (gt selectedEmployeeList.length 0) false true}} {{action (route-action "deleteEmployees" selectedEmployeeList)}} class="btn btn-danger">({{selectedEmployeeList.length}}) Delete</button>
</div>
</div>
<div class="row" style="margin-top:10px">
<table class="table table-bordered">
<thead>
<tr>
<th>Select</th>
<th>Name</th>
<th>Country</th>
</tr>
</thead>
<tbody>
{{#each employees as |employee|}}
{{#if employee.id}}
<tr>
<th scope="row">
{{check-box value=employee.selected}}
</th>
{{#link-to 'ems.employees.employee' employee.id tagName='td'}}
{{employee.name}}
{{/link-to}}
{{#link-to 'ems.employees.employee' employee.id tagName='td'}}
{{if employee.country employee.country.name "NA"}}
{{/link-to}}
</tr>
{{/if}}
{{/each}}
</tbody>
</table>
</div>
</div>
<div class="col-md-8">
{{outlet}}
</div>
</div>
</div>
import Ember from 'ember';
export default Ember.Route.extend({
});
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand">GfK</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav">
<li class="active">
{{#link-to "ems.employees"}}
Employees List <span class="sr-only">(current)</span>
{{/link-to}}
</li>
</ul>
</div><!-- /.navbar-collapse -->
</div><!-- /.container-fluid -->
</nav>
{{outlet}}
{{ember-notify messageStyle='bootstrap'}}
import Ember from 'ember';
export function findBy(params/*, hash*/) {
return params[2].findBy(params[0],params[1]);
}
export default Ember.Helper.helper(findBy);
import DS from 'ember-data';
import attr from 'ember-data/attr';
export default DS.Model.extend({
name: attr('string')
});
import DS from 'ember-data';
import attr from 'ember-data/attr';
import {belongsTo} from 'ember-data/relationships';
import { validator, buildValidations } from 'ember-cp-validations';
const Validations = buildValidations({
name: {
validators: [
validator('presence', true),
validator('length', {
min: 1
})
]
},
surname: {
validators: [
validator('presence', true),
validator('length', {
min: 1
})
]
},
country: {
validators: [
validator('presence', true),
validator('length', {
min: 1
})
]
},
phone: {
validators: [
validator('number', {
allowString: true,
integer: true,
allowBlank: true
})
]
},
email: {
validators: [
validator('format', {
type: 'email',
allowBlank: true,
message: "Invalid Email"
})
]
}
});
export default DS.Model.extend(Validations, {
"name":attr("string"),
"surname":attr("string"),
"country":belongsTo('country',{async:true}),
"address":attr("string"),
"email":attr("string"),
"phone":attr("number"),
});
<h2>Requirements: Employees List</h2>
<div class='col-md-12 request'>
<p> This image represents the list of the employees.</p>
<img src="https://i.ibb.co/v3JZS3d/32408a5bbe054ed8b0123fc5b98e7fe2.png" alt="32408a5bbe054ed8b0123fc5b98e7fe2" border="0">
<ul class='list'>
<li>
<p>You can always click New Employee button which redirects to create a new employee. </p>
</li>
<li>
<p>The delete button is enabled only when there is at least one employee selected, otherwise it is disabled.
</p>
</li>
<li>
<p>When there are multiple employees selected it needs to show text "(2) Delete" that means the number of employees selected plus Delete text.</p>
</li>
<li>
<p>When Employees are deleted it should just notify us that employees were deleted successfully, or in case an error happens show the error in a friendly way.</p>
</li>
<li>
<p>
When you click on one of the employees it should redirect you to the employee detail.
</p>
</li>
</ul>
<blockquote>
<p>API Endpoints:</p>
<a href='http://5c57fdfb9815f6001490359a.mockapi.io/employees' target="_blank">http://5c57fdfb9815f6001490359a.mockapi.io/employees</a>
</blockquote>
<pre>GET /employees - returns list of employees</pre>
<pre>GET /employees/{id} - returns one</pre>
</div>
<h2>Requirements: Employee Details</h2>
<div class='col-md-12 request'>
<p> This image represents the list of the employees.</p>
<img src="https://i.ibb.co/XC2xkYD/Dd072554dab2e85d6da2972b43d550537.png" alt="Dd072554dab2e85d6da2972b43d550537" border="0">
<ul class='list'>
<li>
Screen is accessible when you edit an employee or create a new one.
</li>
<li>When you create a new one the screen is empty.</li>
<li>When you edit an employee it contains the information of the employee.</li>
<li>
To create an employee the fields that are mandatory include:
*Name, Surname, Country</li>
<li>
If you provide the phone number which is optional it needs to validate it to contain only numbers.</li>
<li>
The Email address is optional but if given it needs to contain a valid email
</li>
<li>Save button is enabled only when all mandatory fields are filled and in case of optional fields if they are filled they need to be valid.</li>
<li>Cancel button will take you back to the list.</li>
</ul>
<blockquote>
<p>API Endpoints:</p>
<a href='http://5c57fdfb9815f6001490359a.mockapi.io/employees' target="_blank">http://5c57fdfb9815f6001490359a.mockapi.io/employees</a>
<a href='http://5c57fdfb9815f6001490359a.mockapi.io/employees' target="_blank">http://5c57fdfb9815f6001490359a.mockapi.io/countries</a>
</blockquote>
<pre>GET /employees/{id} - returns one employee</pre>
<pre>POST /employees - saves an employee</pre>
<pre>PUT /employees/{id} - updates an employee</pre>
<pre>GET /countries - returns list of countries</pre>
<pre>GET /countries/{id} - returns one country by id</pre>
</div>
import EmberRouter from '@ember/routing/router';
import config from './config/environment';
const Router = EmberRouter.extend({
location: 'none',
rootURL: config.rootURL
});
Router.map(function() {
this.route('requirements');
this.route('ems', { path: '/' }, function() {
this.route('employees', function() {
this.route('employee', {path: '/:id'}, function() {
this.route('edit');
});
this.route('create');
});
this.route('employee');
});
});
export default Router;
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.request {
color: #131516;
font-size: 12px;
}
[data-ember-action] {
cursor: pointer;
}
.table>tbody>tr>td.active {
background-color: lightblue !important;
}
.ember-power-select-trigger{
display: block;
width: 100%;
height: 34px;
padding: 6px 12px;
font-size: 14px;
line-height: 1.42857143;
color: #555;
background-color: #fff;
background-image: none;
border: 1px solid #ccc;
border-radius: 4px;
}
import { run } from '@ember/runloop';
export default function destroyApp(application) {
run(application, 'destroy');
}
import Ember from 'ember';
import Application from '../../app';
import config from '../../config/environment';
const { run } = Ember;
const assign = Ember.assign || Ember.merge;
export default function startApp(attrs) {
let application;
let attributes = assign({rootElement: "#test-root"}, config.APP);
attributes.autoboot = true;
attributes = assign(attributes, attrs); // use defaults, but you can override;
run(() => {
application = Application.create(attributes);
application.setupForTesting();
application.injectTestHelpers();
});
return application;
}
import Application from '../app';
import config from '../config/environment';
import { setApplication } from '@ember/test-helpers';
import { start } from 'ember-qunit';
import { assign } from '@ember/polyfills';
let attributes = assign({ rootElement: '#main' }, config.APP);
setApplication(Application.create(attributes));
start();
{
"version": "0.15.1",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": true,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js",
"bootstrap": "https://stackpath.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css",
"ember": "2.12.0",
"ember-template-compiler": "2.12.0",
"ember-testing": "2.12.0"
},
"addons": {
"ember-data": "2.12.2",
"ember-notify": "5.2.1",
"ember-power-select": "1.10.4",
"ember-route-action-helper": "2.0.6",
"ember-truth-helpers": "2.1.0",
"ember-cp-validations": "3.5.1"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment