Skip to content

Instantly share code, notes, and snippets.

@tomaash
Last active December 24, 2015 09:39
Show Gist options
  • Select an option

  • Save tomaash/6778540 to your computer and use it in GitHub Desktop.

Select an option

Save tomaash/6778540 to your computer and use it in GitHub Desktop.
Sample angular code
angular.module('card.services.wizard', [])
.factory('CardWizard', [
function () {
return {
stepNames: [],
currentStep: 0,
first: function() {
return this.currentStep === 0;
},
last: function() {
return this.currentStep == this.maxStep;
},
updateSteps: function () {
var self = this;
self.steps = [];
if (this.stepNames) {
self.maxStep = this.stepNames.length - 1;
}
_.forEach(self.stepNames, function (step, i) {
var done, lineDone, active, last;
if (i <= self.currentStep) {
done = true;
}
if (i <= self.currentStep - 1) {
lineDone = true;
}
if (i == self.currentStep) {
active = true;
}
if (i == self.stepNames.length - 1) {
last = true;
}
self.steps.push({
type: 'circle',
title: step,
className: done ? "circle done" : "circle",
titleClassName: active ? "title active" : "title",
active: active});
if (!last) {
self.steps.push({type: 'line', className: lineDone ? "line done" : "line"});
}
});
},
previous: function () {
if (!this.first()) {
this.currentStep -= 1;
this.updateSteps();
}
},
next: function () {
if (!this.last()) {
this.currentStep += 1;
this.updateSteps();
}
}
};
}]);
<div style="width: 100%">
<ul class="wizard-steps">
<li ng-repeat="step in CardWizard.steps" ng-class="step.className" ng-switch="step.type">
<span ng-class="step.titleClassName" ng-bind="step.title" ng-switch-when="circle"></span>
<hr ng-class="step.className" ng-switch-when="line">
</li>
</ul>
</div>
<button class="btn" ng-click="CardWizard.previous()" ng-bind="CardWizard.first && 'Cancel' || 'Previous'"></button>
<button class="btn" ng-click="CardWizard.next()" ng-bind="CardWizard.last && 'Finish' || 'Next'"></button>
directives.directive "infiniteElementScroll", ->
(scope, element, attrs) ->
container = element[0]
angular.element(container).bind 'scroll', (e) ->
scroll = container.scrollTop + container.offsetHeight
height = container.scrollHeight
if scroll >= height
scope.$apply attrs.infiniteElementScroll
.vspan5.scrollable.border-thin(infinite-element-scroll='loadChildren()')
table.table.table-hover.table-striped(ng-show='tree.length>0')
tr(ng-repeat='place in tree track by $index', ng-class='{success: destinationCache[place.id], lightsuccess:(isParentDestination&&!destinationCache[place.id])}')
td.hover-pointer(ng-click='loadChildren(place)') {{place.intername}}
button.btn.btn-primary(type='submit',
ng-click='createDestination()', ng-disabled='places.length==0')
i.icon-ok.icon-white
| {{editMode && 'Update' || 'Create'}}
span.spacer
button.btn.btn-danger(type='submit',
ng-click='cancelEdit()', ng-show='editMode') Cancel
services = angular.module("coolApp.services", [])
services.factory "Facebook",
['$rootScope','$location','$http', '$window',
($rootScope, $location, $http, $window) ->
callback = null
callbackOut = null
storeData = (response) ->
if response && response.status is "connected"
$http.post("/auth/facebook/login", response.authResponse)
.success (data) ->
$rootScope.auth = data
callback?()
else
$rootScope.$apply ->
$rootScope.auth = null
callbackOut?()
checkStatus: (response) ->
if response.status is "connected"
storeData(response)
else if response.status is "not_authorized"
FB.login storeData
else
FB.login storeData
login: (fun) ->
callback = fun
FB.getLoginStatus @checkStatus
autoLogin: (fun) ->
callback = fun
FB.getLoginStatus storeData
logout: (fun) ->
if $rootScope?.auth?.provider == 'evernote'
$window.location.href = '/logout'
callbackOut = fun
callbackOut or= ->
$location.path('/login')
FB.logout storeData
]
services.factory 'AuthRestangular',
['Restangular'
(Restangular) ->
(token) ->
Restangular.withConfig (RestangularConfigurer) ->
RestangularConfigurer.setBaseUrl '/api'
RestangularConfigurer.setDefaultRequestParams({access_token: token})
]
services.value 'PathUtils',
getParentPath: (path, level) ->
return null if not path
return path if level == 0
pathData = path.split('#')
level = 1 if not level
len = pathData.length
pathData.splice(len - level, level)
pathData.join('#')
getParentId: (path) ->
pathData = path.split('#')
previous = pathData.pop()
if pathData.length > 1
return pathData.pop()
else
return previous
getId: (path) ->
pathData = path.split('#')
if pathData.length > 1
return pathData.pop()
else
return path
getHumanPath: (path) ->
if not path
return false
pathData = path.split('#')
pathData.shift()
if pathData.length > 0
return pathData
else
return false
listName: (place) ->
return '' if not place
if place.parent.id != 'geo-earth'
parentName = ", #{place.parent.intername}"
else
parentName = ''
return "#{place.intername} (#{place.country}#{parentName})"
.container-beach
.inner
header
a.back.ir(navigate-back='navigate-back', ng) back
.title
span.city {{document.title}}
.main
.sub
img.imgsmall(ng-src='{{friend.picture}}', ng-repeat='friend in recipients', ng-click='toggleFriend(friend)')
a.share-facebook(ng-click='share()', ng-class='{disabled: shareProgress}', ng-disabled='shareProgress' ) Send
ul.items.list.friends
li(ng-repeat='friend in friends')
a(ng-click='toggleFriend(friend)')
span.icon(ng-class='{selected: selected[friend.userID]}')
img(ng-src='{{friend.picture}}')
span.name {{friend.fullName}}
@ShareCtrl = ($scope, $rootScope, $http, $resource, $routeParams, $location, AuthRestangular) ->
restangular = AuthRestangular($rootScope.auth.token)
facebookResource = restangular.all('facebook')
documentResource = restangular.one('documents', $routeParams.id)
$scope.document = documentResource.get()
$scope.recipients = []
$scope.selected = {}
$scope.loadFriends = () ->
facebookResource.customGETLIST('friends').then (data) ->
$scope.friends = data
$scope.loadFriends()
$scope.toggleFriend = (friend) ->
pos = _.indexOf $scope.recipients, friend
if pos == -1
$scope.selected[friend.userID] = true
$scope.recipients.push friend
else
$scope.selected[friend.userID] = false
$scope.recipients.splice(pos,1)
clearRecipients = ->
$scope.recipients = []
$scope.selected = {}
$scope.share = () ->
return if $scope.recipients.length == 0
$scope.shareProgress = true
facebookResource.customPOST('share',{},{}, {
document: $routeParams.id
friends: $scope.recipients.map (x) -> x.userID
}).then (data) ->
$scope.shareProgress = false
clearRecipients()
window.history.back()
, (err) ->
$scope.shareProgress = false
ShareCtrl.$inject = ['$scope', '$rootScope', '$http', '$resource', '$routeParams', '$location', 'AuthRestangular']
<ul>
<li class="dropdown" ng-controller="SwitchUserCtrl" ng-show="showSwitchUser">
<a class="dropdown-toggle" data-toggle="dropdown" href="#"><i class="icon-exchange"></i></a>
<div class="dropdown-menu">
<div class="list-container">
<div ng-hide="selectOrgs">
<div class="input-group spacer">
<div class="switchBackLink" ng-show="EffectiveUser.identity.guid != EffectiveUser.realUser.guid">
<a href="#" ng-click="switchBack()">Switch back to me</a></div>
<div class="input-prepend">
<span class="add-on"><i class="icon-search"></i> </span> <input class="list-input" type="text"
placeholder="... start typing to search"
ng-model="inputText" ng-change="inputChange()"/>
</div>
</div>
<div class="search-list-container">
<ul class="search-list add-margin-top">
<li class="title" ng-show="matchingUsers.length > 0">Users ({[{ matchingUsers.length }]})</li>
<li class="pointer"
ng-repeat="user in matchingUsers"
ng-click="switchUser(user)"
ng-bind-html="makeUserHtml(user)">
</li>
</ul>
<ul class="search-list">
<li class="title" ng-show="matchingOrgs.length > 0">Organizations ({[{ matchingOrgs.length }]})</li>
<li ng-repeat="org in matchingOrgs"
ng-bind-html="makeBoldHtml(org.name, inputText)">
</li>
</ul>
</div>
<div ng-show="error" class="alert alert-error error-container">
<button type="button" class="close" ng-click="error=null">&times;</button>
<span ng-bind-html="error"></span>
</div>
</div>
<div ng-show="selectOrgs">
<ul class="search-list">
<li class="title pointer" ng-click="deselectUser()">
{[{currentUser.email}]}'s organizations <span class='append-icon'><i class='icon-chevron-left'></i></span>
</li>
<li class="pointer" ng-repeat="org in selectOrgs" ng-click="selectOrg(org)"> {[{ org.name }]}</li>
</ul>
</div>
</div>
</div>
</li>
</ul>
'use strict';
angular.module('union.controllers.switchUser', [
'union.services.unionHttp',
'union.services.effective-user'])
.controller('SwitchUserCtrl', ['$scope', '$timeout', '$document', '$window', '$sce',
'TileProxy', 'UnionHttp', 'EffectiveUser',
function SwitchUserCtrl($scope, $timeout, $document, $window, $sce,
TileProxy, UnionHttp, EffectiveUser) {
var SEARCH_DELAY = 300,
typingTimeout,
lastTextValue;
$scope.currentUser = null;
$scope.currentOrg = null;
$scope.selectOrgs = null;
$scope.showSwitchUser = false;
$scope.error = null;
var caseInsensitiveRegExp = function (text) {
return new RegExp(text, 'gi');
};
$scope.checkPrivileges = function () {
UnionHttp.call( {url : '/api/v1/union/user/permission/user.possess', 'use-real-user':1 })
.then(function(response) {
$scope.showSwitchUser = (response.data.Decision === "Permit");
EffectiveUser.userPossess = true;
});
};
$scope.loadMatchingUsers = function () {
var userAction = {
"app": 'idp',
"endpoint": "/api/v1/users?search=email=~'" + $scope.inputText + "'",
"method": "GET",
"use-real-user": 1
};
TileProxy.call(userAction).then(function (response) {
var data = response.data.results;
data.forEach(function(user){
user.organizations = _.values(user.organizations);
});
$scope.matchingUsers = _.filter(data, function (user) {
return user.email.match(caseInsensitiveRegExp($scope.inputText));
});
});
};
$scope.loadMatchingOrgs = function () {
var orgAction = {
"app": 'idp',
"endpoint": "/api/v1/organizations?search=name=~'" + $scope.inputText + "'",
"method": "GET",
"use-real-user": 1
};
TileProxy.call(orgAction).then(function (response) {
$scope.matchingOrgs = _.filter(response.data.results, function (org) {
return org.name.match(caseInsensitiveRegExp($scope.inputText));
});
});
};
$scope.loadEverything = function () {
if ($scope.inputText && $scope.inputText !== "") {
$scope.loadMatchingUsers();
$scope.loadMatchingOrgs();
}
};
$scope.inputChange = function () {
$scope.error = null;
if ($scope.inputText && $scope.inputText !== "") {
if (!lastTextValue || ($scope.inputText != lastTextValue)) {
lastTextValue = $scope.inputText;
if (typingTimeout) {
window.clearTimeout(typingTimeout);
}
typingTimeout = window.setTimeout($scope.loadEverything, SEARCH_DELAY);
}
} else {
$scope.matchingUsers = null;
$scope.matchingOrgs = null;
lastTextValue = null;
}
};
$scope.deselectUser = function () {
$scope.selectOrgs = null;
$scope.currentUser = null;
};
$scope.makeBold = function (item, snippet) {
return item.replace(caseInsensitiveRegExp(snippet), function (match) {
return "<b><u>" + match + "</u></b>";
});
};
$scope.makeBoldHtml = function (item, snippet) {
return $sce.trustAsHtml($scope.makeBold(item, snippet));
};
$scope.makeUserHtml = function (user) {
var cnt = user.organizations.length;
var single = (cnt==1);
var multi = (cnt>1);
var org = user.organizations[0];
var text = $scope.makeBold(user.email, $scope.inputText) + ', in ' +
(single && org.name || ' ' +cnt + ' orgs') + (multi && +
'<span class=\'append-icon\'><i class=\'icon-chevron-right\'></i></span>' || '');
return $sce.trustAsHtml(text);
};
$scope.selectOrg = function (org) {
$scope.selectOrgs = null;
$scope.currentOrg = org;
$scope.makeSwitch();
};
$scope.switchUser = function (user) {
$scope.selectOrgs = null;
$scope.currentOrg = null;
$scope.currentUser = user;
if (user.organizations && user.organizations.length == 1) {
$scope.currentOrg = user.organizations[0];
$scope.makeSwitch();
} else {
$scope.selectOrgs = user.organizations;
$scope.error = null;
}
};
$scope.switchBack = function() {
$scope.currentOrg = EffectiveUser.realUser.organizations[0];
$scope.currentUser = EffectiveUser.realUser;
$scope.makeSwitch();
};
$scope.makeSwitch = function () {
$scope.error = null;
UnionHttp.call({
method: 'PUT',
url : '/api/v1/union/identity/effective/'+
$scope.currentOrg.goid +'/' + $scope.currentUser.guid })
.then(function(response) {
$scope.deselectUser();
$window.location.reload();
}, function(err){
var message = '';
if (err && err.data && err.data.errors && err.data.errors.length > 0) {
message = err.data.errors[0].message;
}
$scope.error = $sce.trustAsHtml("Can't switch to <b>" +
$scope.currentUser.email +
'</b> at <b>' +
$scope.currentOrg.name +
'</b>. ' + message);
$scope.deselectUser();
});
};
$scope.checkPrivileges();
}]);
'use strict';
describe('SwitchUserCtrl', function () {
var $scope, ctrl, $httpBackend, $rootScope;
beforeEach(module('union.controllers.switchUser'));
beforeEach(module('union.controllers'));
beforeEach(module('union.services'));
beforeEach(module('tile.services'));
beforeEach(inject(function ($injector, $controller) {
$rootScope = $injector.get('$rootScope');
$scope = $rootScope.$new();
$httpBackend = $injector.get('$httpBackend');
$httpBackend.whenGET('/api/v1/union/user/permission/user.possess?').respond({"Decision": "Permit"});
ctrl = $controller('SwitchUserCtrl', {
$scope: $scope
});
}));
describe('switchUser function', function () {
it('should set email on scope', function () {
var mockUser = {
email: 'foo'
};
$scope.switchUser(mockUser);
expect($scope.currentUser.email).toBe('foo');
});
it('should set organization on scope and call api when called with one organization ', function () {
var mockOrg = {name:'org234', goid: '123'};
var mockUser = {
email: 'foo',
guid: '456',
organizations: [mockOrg]
};
$httpBackend.expectPUT('/api/v1/union/identity/effective/123/456?').respond({});
$scope.switchUser(mockUser);
expect($scope.currentOrg).toBe(mockOrg);
});
it('should set organizations to select on scope when called with multiple organizations', function () {
var mockUser = {
email: 'foo',
organizations: ['o1', 'o2', 'o3']
};
$scope.switchUser(mockUser);
expect($scope.selectOrgs.length).toBe(3);
});
});
describe('selectOrg function', function () {
it('should set organization and clear list of orgs', function () {
var mockOrg = {name:'org234', goid: '123'};
var mockUser = {
email: 'foo',
guid: '456',
organizations: [mockOrg]
};
$httpBackend.expectPUT('/api/v1/union/identity/effective/123/456?').respond({});
$scope.currentUser = mockUser;
$scope.selectOrg(mockOrg);
expect($scope.currentOrg.name).toBe('org234');
expect($scope.selectOrgs).toBeFalsy();
});
});
describe('makeBold function', function () {
it('should set make matched text bold and udeline', function () {
var output = $scope.makeBold('foobar', 'ba');
expect(output).toBe('foo<b><u>ba</u></b>r');
});
});
describe('inputChange function', function () {
beforeEach(function () {
jasmine.Clock.useMock();
});
it('should load data after timeout', function () {
spyOn($scope, 'loadEverything');
$scope.inputText = "a";
$scope.inputChange();
jasmine.Clock.tick(10000);
expect($scope.loadEverything).toHaveBeenCalled();
});
it('should load data after timeout', function () {
spyOn($scope, 'loadEverything');
$scope.inputText = "a";
$scope.inputChange();
jasmine.Clock.tick(10000);
expect($scope.loadEverything).toHaveBeenCalled();
});
it('should not load data after a serie of short changes', function () {
spyOn($scope, 'loadEverything');
$scope.inputText = "f";
$scope.inputChange();
jasmine.Clock.tick(50);
$scope.inputText = "fo";
$scope.inputChange();
jasmine.Clock.tick(50);
$scope.inputText = "foo";
$scope.inputChange();
jasmine.Clock.tick(50);
expect($scope.loadEverything).not.toHaveBeenCalled();
$scope.inputText = "foobar";
$scope.inputChange();
jasmine.Clock.tick(10000);
expect($scope.loadEverything).toHaveBeenCalled();
});
});
describe('loadMatchingUsers', function () {
it('should load users', function () {
var userGet = new RegExp("users.*foo");
$httpBackend.expectGET(userGet).respond({ results: [{email:'foobar', guid: '123'}] });
$scope.inputText = "foo";
$scope.loadMatchingUsers();
});
});
describe('loadMatchingOrgs', function () {
it('should load orgs', function () {
var userGet = new RegExp("organizations.*foo");
$httpBackend.expectGET(userGet).respond({ results: [{name:'foobar', guid: '123'}] });
$scope.inputText = "foo";
$scope.loadMatchingOrgs();
});
});
describe('switch to admin-class user' , function () {
it('should display error dialog', function () {
$httpBackend.expectPUT('/api/v1/union/identity/effective/123/456?').respond(404,{message:'error'});
$scope.currentOrg = {name:'org234', goid: '123'};
$scope.currentUser = {
email: 'foo',
guid: '456'
};
$scope.makeSwitch();
$httpBackend.flush();
expect($scope.error).toBeTruthy();
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment