Skip to content

Instantly share code, notes, and snippets.

@neborn
Last active February 9, 2021 04:23
Show Gist options
  • Save neborn/a94c8150ff6837f0423797a07437d969 to your computer and use it in GitHub Desktop.
Save neborn/a94c8150ff6837f0423797a07437d969 to your computer and use it in GitHub Desktop.
Add Employees To Group Example
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
import { cached } from 'tracked-toolbox';
export default class AddEmployeesToGroupComponent extends Component {
@service groupActions;
@cached
get flowModel() {
return this.groupActions.createAddEmployeesToGroupFlow({
group: this.args.groupId,
onSuccess: this.args.onClose
});
}
}
import Component from '@glimmer/component';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
export default class GroupListComponent extends Component {
@service groupActions;
_addEmployeesToGroupFlowController;
get addEmployeesToGroupFlowController() {
return this._addEmployeesToGroupFlowController;
}
constructor() {
super(...arguments);
this._addEmployeesToGroupFlowController =
this.groupActions.createAddEmployeesToGroupFlowController();
}
willDestroy() {
this.addEmployeesToGroupFlowController.cleanup();
}
}
import Component from '@glimmer/component';
import { inject as service } from '@ember/service';
export default class RowActionsComponent extends Component {
@service groupActions;
}
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('group-list', { path: '/group-list' });
});
export default Router;
import Service from '@ember/service';
import { tracked } from '@glimmer/tracking';
export default class ConfigurationService extends Service {
@tracked currentEmployerId = 'employer1';
@tracked currentEmployerName = 'Test Employer';
}
import Service, { inject as service } from '@ember/service';
import Object from '@ember/object';
import { action } from '@ember/object';
import AddEmployeesToGroupFlow from '../view-models/add-employees-to-group-flow';
import AddEmployeesToGroupFlowController from '../view-models/add-employees-to-group-flow-controller';
import Evented from '@ember/object/evented';
export const Events = {
ADD_EMPLOYEES_TO_GROUP: 'ADD_EMPLOYEES_TO_GROUP'
};
class EventBus extends Object.extend(Evented) {}
export default class GroupActionsService extends Service {
@service configuration;
_eventBus = EventBus.create();
get eventBus() {
return this._eventBus;
}
@action
performEmployeeTypeaheadSearch(params) {
// use configuration service to construct the API request
const results = [
{ name: 'Employee 1', email: 'employee1@business.test' },
{ name: 'Employee 2', email: 'employee2@business.test' },
{ name: 'Employee 3', email: 'employee3@business.test' },
{ name: 'Employee 4', email: 'employee4@business.test' }
];
return new Promise(
resolve => setTimeout(() => resolve(results), 500)
);
}
@action
performAddEmployeesToGroup(params) {
// use configuration service to construct the API request
return new Promise(resolve => setTimeout(resolve, 500));
}
@action
createAddEmployeesToGroupFlow({ group, onSuccess }) {
return new AddEmployeesToGroupFlow({
group,
onSuccess,
actionsService: this
});
}
@action
createAddEmployeesToGroupFlowController() {
return new AddEmployeesToGroupFlowController({
actionsService: this
});
}
@action
startAddEmployeesToGroupFlow(group) {
this.eventBus.trigger(Events.ADD_EMPLOYEES_TO_GROUP, { group });
}
}
<nav>
<ul>
<li><LinkTo @route="group-list">Group List</LinkTo></li>
</ul>
</nav>
<main>
{{outlet}}
</main>
<article>
<h2>Add Employees to Group</h2>
<p>Adding employees to {{@groupId}}</p>
<section>
<h3>Search for employees</h3>
<Input @value={{this.flowModel.typeaheadSearchString}} autocomplete="off"/>
{{#if this.flowModel.typeaheadResults.isRunning}}
<p>Loading ...</p>
{{else}}
<ul>
{{#each this.flowModel.typeaheadResults.value as |employee|}}
<li>
<div>name: {{employee.name}}</div>
<div>email: {{employee.email}}</div>
<button type="button" {{on "click" (fn this.flowModel.selectEmployee employee)}}>select</button>
</li>
{{/each}}
</ul>
{{/if}}
</section>
<section>
<h3>Selected employees</h3>
<ul>
{{#each this.flowModel.selectedEmployees as |employee|}}
<li>
<div>name: {{employee.name}}</div>
<div>email: {{employee.email}}</div>
<button type="button" {{on "click" (fn this.flowModel.deselectEmployee employee)}}>deselect</button>
</li>
{{/each}}
</ul>
</section>
<section>
{{#if this.flowModel.errorMessage}}
<p style="color:red">{{this.flowModel.errorMessage}}</p>
{{/if}}
{{#if this.flowModel.submitTask.isRunning}}
{{#if this.flowModel.successMessage}}
<p>{{this.flowModel.successMessage}}</p>
{{else}}
<p>Adding employees...</p>
{{/if}}
{{else}}
<button type="button" {{on "click" @onClose}}>Cancel</button>
<button type="button" {{on "click" this.flowModel.submit}}>Add employees to group</button>
{{/if}}
</section>
</article>
<h1>Group List</h1>
<ul>
<li>
Group 1 <RowActions @groupId="group1"/>
</li>
<li>
Group 2 <RowActions @groupId="group2"/>
</li>
<li>
Group 3 <RowActions @groupId="group3"/>
</li>
</ul>
{{#let this.addEmployeesToGroupFlowController as |controller|}}
{{#if controller.modalIsOpen}}
<AddEmployeesToGroup
@groupId={{controller.currentGroup}}
@onClose={{controller.closeModal}}/>
{{/if}}
{{/let}}
<button type="button" {{on "click" (fn this.groupActions.startAddEmployeesToGroupFlow @groupId)}}>
Add Employees
</button>
{
"version": "0.17.1",
"EmberENV": {
"FEATURES": {},
"_TEMPLATE_ONLY_GLIMMER_COMPONENTS": false,
"_APPLICATION_TEMPLATE_WRAPPER": true,
"_JQUERY_INTEGRATION": true
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.js",
"ember": "3.18.1",
"ember-template-compiler": "3.18.1",
"ember-testing": "3.18.1"
},
"addons": {
"@glimmer/component": "1.0.0",
"ember-concurrency": "1.3.0",
"tracked-built-ins": "1.0.2",
"tracked-toolbox": "1.2.1"
}
}
import { Events } from '../services/group-actions';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
export default class AddEmployeesToGroupFlowController {
_actionsService;
@tracked
_currentGroup = null;
get currentGroup() {
return this._currentGroup;
}
get modalIsOpen() {
return !!this._currentGroup;
}
constructor({
actionsService
}) {
this._actionsService = actionsService;
this._actionsService.eventBus.on(
Events.ADD_EMPLOYEES_TO_GROUP,
this.openModal
);
}
@action
cleanup() {
this._actionsService.eventBus.off(
Events.ADD_EMPLOYEES_TO_GROUP,
this,
this.openModal
);
}
@action
openModal(event) {
this._currentGroup = event.group;
}
@action
closeModal() {
this._currentGroup = null;
}
}
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import { task, timeout } from 'ember-concurrency';
import { TrackedSet } from 'tracked-built-ins';
import { cached } from 'tracked-toolbox';
export default class AddEmployeesToGroupFlow {
_group;
_onSuccess;
_actionsService;
@tracked
_errorMessage = '';
@tracked
_selectedEmployees = new TrackedSet();
@tracked
_successMessage = '';
get errorMessage() {
return this._errorMessage;
}
get selectedEmployees() {
return this._selectedEmployees;
}
get successMessage() {
return this._successMessage;
}
@tracked
typeaheadSearchString = '';
get group() {
return this._group;
}
@cached
get typeaheadResults() {
this._typeaheadSearchTask.perform(this.typeaheadSearchString);
return this._typeaheadSearchTask.last;
}
constructor({
group,
onSuccess,
actionsService
}) {
this._group = group;
this._onSuccess = onSuccess;
this._actionsService = actionsService;
}
@action
selectEmployee(employee) {
this._selectedEmployees.add(employee);
}
@action
deselectEmployee(employee) {
this._selectedEmployees.delete(employee);
}
@action
submit() {
this._errorMessage = !this._selectedEmployees.size ? 'Please select employees to add to the group' : '';
if (this._errorMessage) return;
this.submitTask.perform([...this._selectedEmployees])
}
@(task(function * (employees) {
yield this._actionsService.performAddEmployeesToGroup({
employees,
group: this.group
});
this._successMessage = 'Employees added...';
yield timeout(2000);
this._onSuccess();
}).drop())
submitTask;
@(task(function * (searchString) {
if (!searchString) {
return [];
}
yield timeout(100);
return yield this._actionsService.performEmployeeTypeaheadSearch(searchString);
}).restartable())
_typeaheadSearchTask;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment