Refactoring to UI

This commit is contained in:
Stian Thorgersen 2013-07-24 14:56:02 +01:00
parent e26e1db98c
commit 28f3e1e01c
74 changed files with 2334 additions and 1161 deletions

View file

@ -13,19 +13,10 @@
<description /> <description />
<dependencies> <dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<scope>provided</scope>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project> </project>

View file

@ -0,0 +1,105 @@
package org.keycloak.ui.example;
import java.net.URI;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@ApplicationPath("ui/api")
@Path("")
public class Admin extends javax.ws.rs.core.Application {
private static Map<String, Realm> realms = new HashMap<String, Realm>();
private static Map<String, Application> applications = new HashMap<String, Application>();
@DELETE
@Path("/applications/{key}")
public void delete(@PathParam("key") String applicationKey) {
applications.remove(applicationKey);
}
@DELETE
@Path("/realms/{key}")
public void deleteRealm(@PathParam("key") String key) {
realms.remove(key);
}
@GET
@Path("/applications/{key}")
@Produces(MediaType.APPLICATION_JSON)
public Application getApplication(@PathParam("key") String applicationKey) {
return applications.get(applicationKey);
}
@GET
@Path("/applications")
@Produces(MediaType.APPLICATION_JSON)
public List<Application> getApplications() {
return new LinkedList<Application>(applications.values());
}
@GET
@Path("/realms/{key}")
@Produces(MediaType.APPLICATION_JSON)
public Realm getRealm(@PathParam("key") String key) {
return realms.get(key);
}
@GET
@Path("/realms")
@Produces(MediaType.APPLICATION_JSON)
public List<Realm> getRealms() {
return new LinkedList<Realm>(realms.values());
}
@POST
@Path("/applications")
@Consumes(MediaType.APPLICATION_JSON)
public Response save(Application application) {
String key = UUID.randomUUID().toString();
application.setKey(key);
applications.put(key, application);
return Response.created(URI.create("/applications/" + application.getKey())).build();
}
@POST
@Path("/realms")
@Consumes(MediaType.APPLICATION_JSON)
public Response save(Realm realm) {
String key = UUID.randomUUID().toString();
realm.setKey(key);
realms.put(key, realm);
return Response.created(URI.create("/realms/" + realm.getKey())).build();
}
@PUT
@Path("/applications/{key}")
@Consumes(MediaType.APPLICATION_JSON)
public void save(@PathParam("key") String applicationKey, Application application) {
applications.put(applicationKey, application);
}
@PUT
@Path("/realms/{key}")
@Consumes(MediaType.APPLICATION_JSON)
public void save(@PathParam("key") String key, Realm realm) {
realms.put(key, realm);
}
}

View file

@ -0,0 +1,114 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.ui.example;
import java.util.List;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@XmlRootElement
public class Application {
private String callbackUrl;
private String key;
private String name;
private String owner;
private String javaScriptOrigin;
private List<IdentityProviderConfig> providers;
private String secret;
private String realm;
public String getCallbackUrl() {
return callbackUrl;
}
public String getJavaScriptOrigin() {
return javaScriptOrigin;
}
public String getKey() {
return key;
}
public String getName() {
return name;
}
public String getOwner() {
return owner;
}
public List<IdentityProviderConfig> getProviders() {
return providers;
}
public String getSecret() {
return secret;
}
public String getRealm() {
return realm;
}
public void setCallbackUrl(String callbackUrl) {
this.callbackUrl = callbackUrl;
}
public void setJavaScriptOrigin(String javaScriptOrigin) {
this.javaScriptOrigin = javaScriptOrigin;
}
public void setKey(String key) {
this.key = key;
}
public void setName(String name) {
this.name = name;
}
public void setOwner(String owner) {
this.owner = owner;
}
public void setProviders(List<IdentityProviderConfig> providers) {
this.providers = providers;
}
public void setSecret(String secret) {
this.secret = secret;
}
public void setRealm(String realm) {
this.realm = realm;
}
}

View file

@ -0,0 +1,68 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.ui.example;
import javax.xml.bind.annotation.XmlRootElement;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
@XmlRootElement
public class IdentityProviderConfig {
private Long id;
private String key;
private String providerId;
private String secret;
public Long getId() {
return id;
}
public String getKey() {
return key;
}
public String getProviderId() {
return providerId;
}
public String getSecret() {
return secret;
}
public void setKey(String key) {
this.key = key;
}
public void setProviderId(String providerId) {
this.providerId = providerId;
}
public void setSecret(String secret) {
this.secret = secret;
}
}

View file

@ -0,0 +1,60 @@
/*
* JBoss, Home of Professional Open Source.
* Copyright 2012, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.keycloak.ui.example;
/**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/
public class Realm {
private String key;
private String name;
private String owner;
public String getKey() {
return key;
}
public String getName() {
return name;
}
public String getOwner() {
return owner;
}
public void setKey(String key) {
this.key = key;
}
public void setName(String name) {
this.name = name;
}
public void setOwner(String owner) {
this.owner = owner;
}
}

View file

@ -0,0 +1,24 @@
[ {
"callbackUrl" : "http://localhost:8080/test",
"key" : "7301af66-c481-4f54-a280-16529e11a153",
"name" : "Foo application",
"owner" : "root",
"javaScriptOrigin" : null,
"providers" : [ {
"id" : 7,
"key" : "google-key",
"providerId" : "google",
"secret" : "google-secret"
} ],
"secret" : "77f78140-e0ee-4912-a504-32c51180e918",
"realm" : "5ee722cc-7bdb-49fe-b76c-8b246e699065"
}, {
"callbackUrl" : "http://localhost:8080/bar",
"key" : "f3ab7d43-7737-4507-a7a8-2e261f77298d",
"name" : "Bar application",
"owner" : "root",
"javaScriptOrigin" : null,
"providers" : [],
"secret" : "7d833773-d1e9-41f3-8749-8698f4c5ed03",
"realm" : "7d01c3cd-f483-414b-a02f-c260815224cc"
} ]

View file

@ -1,276 +0,0 @@
'use strict';
var eventjugglerServices = angular.module('eventjugglerAdminServices', [ 'ngResource' ]);
eventjugglerServices.factory('Notifications', function($rootScope, $timeout) {
var notifications = {};
var scheduled = null;
var schedulePop = function() {
if (scheduled) {
$timeout.cancel(scheduled);
}
scheduled = $timeout(function() {
$rootScope.notification = null;
scheduled = null;
}, 3000);
};
if (!$rootScope.notifications) {
$rootScope.notifications = [];
}
notifications.success = function(message) {
$rootScope.notification = {
type : "success",
message : message
};
schedulePop();
};
return notifications;
});
eventjugglerServices.factory('Application', function($resource) {
return $resource('/ejs-identity/api/admin/applications/:key', {
key : '@key'
}, {
update : {
method : 'PUT'
}
});
});
eventjugglerServices.factory('ApplicationListLoader', function(Application, $q) {
return function() {
var delay = $q.defer();
Application.query(function(applications) {
delay.resolve(applications);
}, function() {
delay.reject('Unable to fetch applications');
});
return delay.promise;
};
});
eventjugglerServices.factory('ApplicationLoader', function(Application, $route, $q) {
return function() {
var key = $route.current.params.key;
if (key == 'new') {
return {};
} else {
var delay = $q.defer();
Application.get({
key : key
}, function(application) {
delay.resolve(application);
}, function() {
delay.reject('Unable to fetch application ' + key);
});
return delay.promise;
}
};
});
eventjugglerServices.factory('Provider', function($resource) {
return $resource('/ejs-identity/api/admin/providers');
});
eventjugglerServices.factory('ProviderListLoader', function(Provider, $q) {
return function() {
var delay = $q.defer();
Provider.query(function(providers) {
delay.resolve(providers);
}, function() {
delay.reject('Unable to fetch providers');
});
return delay.promise;
};
});
eventjugglerServices.factory('Realm', function($resource) {
return $resource('/ejs-identity/api/admin/realms/:key', {
key : '@key'
}, {
update : {
method : 'PUT'
}
});
});
eventjugglerServices.factory('RealmListLoader', function(Realm, $q) {
return function() {
var delay = $q.defer();
Realm.query(function(realms) {
delay.resolve(realms);
}, function() {
delay.reject('Unable to fetch realms');
});
return delay.promise;
};
});
eventjugglerServices.factory('RealmLoader', function(Realm, $route, $q) {
return function() {
var key = $route.current.params.realmKey;
if (key == 'new') {
return {};
} else {
var delay = $q.defer();
Realm.get({
key : key
}, function(realm) {
delay.resolve(realm);
}, function() {
delay.reject('Unable to fetch key ' + key);
});
return delay.promise;
}
};
});
eventjugglerServices.factory('User', function($resource) {
return $resource('/ejs-identity/api/im/:realmKey/users/:userId', {
realmKey : '@realmKey',
userId : '@userId'
}, {
save : {
method : 'PUT'
}
});
});
eventjugglerServices.factory('UserListLoader', function(User, $route, $q) {
return function() {
var delay = $q.defer();
User.query({
realmKey : $route.current.params.realmKey
}, function(users) {
delay.resolve(users);
}, function() {
delay.reject('Unable to fetch users');
});
return delay.promise;
};
});
eventjugglerServices.factory('UserLoader', function(User, $route, $q) {
return function() {
var userId = $route.current.params.userId;
if (userId == 'new') {
return {};
} else {
var delay = $q.defer();
User.get({
realmKey : $route.current.params.realmKey,
userId : userId
}, function(user) {
delay.resolve(user);
}, function() {
delay.reject('Unable to fetch user ' + $route.current.params.userId);
});
return delay.promise;
}
};
});
eventjugglerServices.factory('Activities', function($resource) {
var activities = {};
activities.events = $resource('/ejs-activities/api/events');
activities.statistics = $resource('/ejs-activities/api/statistics');
return activities;
});
eventjugglerServices.factory('ActivitiesStatisticsLoader', function(Activities, $q) {
return function() {
var delay = $q.defer();
Activities.statistics.get(function(statistics) {
delay.resolve(statistics);
}, function() {
delay.reject('Unable to fetch statistics');
});
return delay.promise;
};
});
eventjugglerServices.factory('ActivitiesEventsLoader', function(Activities, $q) {
return function() {
var delay = $q.defer();
Activities.events.query({
"max" : 10
}, function(events) {
delay.resolve(events);
}, function() {
delay.reject('Unable to fetch events');
});
return delay.promise;
};
});
eventjugglerServices.service('Auth', function($resource, $http, $location, $routeParams) {
var auth = {};
auth.user = {};
var parameters = window.location.search.substring(1).split("&");
for ( var i = 0; i < parameters.length; i++) {
var param = parameters[i].split("=");
if (decodeURIComponent(param[0]) == "token") {
auth.token = decodeURIComponent(param[1]);
}
}
if (auth.token) {
$location.search("token", null);
localStorage.setItem("token", auth.token);
} else {
auth.token = localStorage.getItem("token");
}
if (auth.token) {
$http.defaults.headers.common['token'] = auth.token;
auth.user = $resource('/ejs-identity/api/auth/userinfo').get({
appKey : "system",
token : auth.token
}, function() {
if (auth.user.userId) {
auth.loggedIn = true;
auth.root = auth.user.userId == "root";
var displayName;
if (auth.user.firstName || auth.user.lastName) {
displayName = auth.user.firstName;
if (auth.user.lastName) {
displayName = displayName ? displayName + " " + auth.user.lastName : auth.user.lastName;
}
} else {
displayName = auth.user.userId;
}
auth.user.displayName = displayName;
} else {
auth.logout();
}
}, function() {
auth.logout();
});
}
auth.logout = function() {
$resource('/ejs-identity/api/auth/logout').get({
appKey : "system"
});
localStorage.removeItem("token");
$http.defaults.headers.common['token'] = null;
auth.loggedIn = false;
auth.root = false;
$location.url("/");
};
return auth;
});

View file

@ -1,34 +0,0 @@
<div id="wrapper" class="container">
<div class="row">
<aside class="span3" ng-include src="'partials/activities-menu.html'"></aside>
<div id="actions-bg"></div>
<div id="container-right" class="span9">
<h1>
<span class="gray">Events</span>
</h1>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Time</th>
<th>Context Path</th>
<th>Page</th>
<th>Remote Address</th>
<th>Country</th>
<th>User Agent</th>
</tr>
</thead>
<tr ng-repeat="event in events">
<td>{{event.time | date:'medium'}}</td>
<td>{{event.contextPath}}</td>
<td>{{event.page}}</td>
<td>{{event.remoteAddr}}</td>
<td>{{event.country}}</td>
<td>{{event.userAgent}}</td>
</tr>
</table>
</div>
<div id="container-right-bg"></div>
</div>
</div>

View file

@ -1,14 +0,0 @@
<nav id="local-nav">
<ul class="nav nav-list">
<li>
<div>
<span class="toggle">Activities</span>
</div>
<ul>
<li ng-class="!path[1]&& 'active'"><a href="#/activities">Statistics</a></li>
<li ng-class="path[1] == 'pages' && 'active'"><a href="#/activities/pages">Pages</a></li>
<li ng-class="path[1] == 'events' && 'active'"><a href="#/activities/events">Events</a></li>
</ul>
</li>
</ul>
</nav>

View file

@ -1,26 +0,0 @@
<div id="wrapper" class="container">
<div class="row">
<aside class="span3" ng-include src="'partials/activities-menu.html'"></aside>
<div id="actions-bg"></div>
<div id="container-right" class="span9">
<h1>
<span class="gray">Pages</span>
</h1>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Label</th>
<th>Count</th>
</tr>
</thead>
<tr ng-repeat="event in statistics['pageViews']">
<td>{{event.label}}</td>
<td>{{event.count}}</td>
</tr>
</table>
</div>
<div id="container-right-bg"></div>
</div>
</div>

View file

@ -1,30 +0,0 @@
<div id="wrapper" class="container">
<div class="row">
<aside class="span3" ng-include src="'partials/activities-menu.html'"></aside>
<div id="actions-bg"></div>
<div id="container-right" class="span9">
<h1>
<span class="gray">Statistics</span>
</h1>
<fieldset ng-repeat="i in ['Browser', 'Country', 'Language', 'OS', 'User']">
<legend>{{i}}</legend>
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Label</th>
<th>Count</th>
</tr>
</thead>
<tr ng-repeat="event in statistics[i.toLowerCase() + 'Views']">
<td>{{event.label}}</td>
<td>{{event.count}}</td>
</tr>
</table>
</fieldset>
</div>
<div id="container-right-bg"></div>
</div>
</div>

View file

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View file

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View file

Before

Width:  |  Height:  |  Size: 999 B

After

Width:  |  Height:  |  Size: 999 B

View file

Before

Width:  |  Height:  |  Size: 935 B

After

Width:  |  Height:  |  Size: 935 B

View file

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

Before

Width:  |  Height:  |  Size: 80 B

After

Width:  |  Height:  |  Size: 80 B

View file

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

View file

Before

Width:  |  Height:  |  Size: 3 KiB

After

Width:  |  Height:  |  Size: 3 KiB

View file

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View file

@ -1,9 +1,9 @@
<!doctype html> <!doctype html>
<html lang="en" ng-app="eventjugglerAdmin"> <html lang="en" data-ng-app="keycloak">
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<title>EventJuggler Services Admin</title> <title>Keycloak</title>
<link href="lib/bootstrap/css/bootstrap.css" rel="stylesheet"> <link href="lib/bootstrap/css/bootstrap.css" rel="stylesheet">
<link href="lib/bootstrap/css/bootstrap-responsive.css" rel="stylesheet"> <link href="lib/bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
@ -14,28 +14,28 @@
<script src="lib/angular/angular.js"></script> <script src="lib/angular/angular.js"></script>
<script src="lib/angular/angular-resource.js"></script> <script src="lib/angular/angular-resource.js"></script>
<script src="lib/angular/ui-bootstrap-tpls-0.3.0.js"></script> <script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script>
<script src="lib/jquery/jquery-1.9.0.js"></script> <script src="lib/jquery/jquery-1.10.2.js"></script>
<script src="js/app.js"></script> <script src="js/app.js"></script>
<script src="js/controllers.js"></script> <script src="js/controllers.js"></script>
<script src="js/services.js"></script> <script src="js/services.js"></script>
</head> </head>
<body ng-controller="GlobalCtrl"> <body data-ng-controller="GlobalCtrl">
<div class="alert-container" ng-show="notification" ng-click="notification = null"> <div class="alert-container" data-ng-show="notification" data-ng-click="notification = null">
<div class="alert alert-{{notification.type}}">{{notification.message}}</div> <div class="alert alert-{{notification.type}}">{{notification.message}}</div>
</div> </div>
<div id="wrap"> <div id="wrap">
<div ng-include src="'partials/menu.html'"></div> <div data-ng-include data-src="'partials/menu.html'"></div>
<div ng-view id="view" ng-hide="httpProviderError"></div> <div data-ng-view id="view" data-ng-hide="httpProviderError"></div>
<div id="httpProviderError" ng-show="httpProviderError"> <div id="httpProviderError" data-ng-show="httpProviderError">
<button class="btn btn-danger" ng-click="httpProviderError=null"> <button class="btn btn-danger" data-ng-click="httpProviderError=null">
<strong>Error</strong> {{httpProviderError}} <strong>Error</strong> {{httpProviderError}}
</button> </button>
</div> </div>

View file

@ -1,34 +1,10 @@
'use strict'; 'use strict';
var eventjugglerModule = angular.module('eventjugglerAdmin', [ 'eventjugglerAdminServices', 'ui.bootstrap' ]); var module = angular.module('keycloak', [ 'keycloak.services', 'keycloak.controllers', 'ui.bootstrap' ]);
var resourceRequests = 0; var resourceRequests = 0;
eventjugglerModule.config([ '$routeProvider', function($routeProvider) { module.config([ '$routeProvider', function($routeProvider) {
$routeProvider.when('/activities/events', { $routeProvider.when('/applications/:key', {
templateUrl : 'partials/activities-events.html',
resolve : {
events : function(ActivitiesEventsLoader) {
return ActivitiesEventsLoader();
}
},
controller : ActivitiesEventsCtrl
}).when('/activities/pages', {
templateUrl : 'partials/activities-pages.html',
resolve : {
statistics : function(ActivitiesStatisticsLoader) {
return ActivitiesStatisticsLoader();
}
},
controller : ActivitiesStatisticsCtrl
}).when('/activities', {
templateUrl : 'partials/activities-statistics.html',
resolve : {
statistics : function(ActivitiesStatisticsLoader) {
return ActivitiesStatisticsLoader();
}
},
controller : ActivitiesStatisticsCtrl
}).when('/applications/:key', {
templateUrl : 'partials/application-detail.html', templateUrl : 'partials/application-detail.html',
resolve : { resolve : {
applications : function(ApplicationListLoader) { applications : function(ApplicationListLoader) {
@ -44,7 +20,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
return ProviderListLoader(); return ProviderListLoader();
} }
}, },
controller : ApplicationDetailCtrl controller : 'ApplicationDetailCtrl'
}).when('/applications', { }).when('/applications', {
templateUrl : 'partials/application-list.html', templateUrl : 'partials/application-list.html',
resolve : { resolve : {
@ -52,7 +28,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
return ApplicationListLoader(); return ApplicationListLoader();
} }
}, },
controller : ApplicationListCtrl controller : 'ApplicationListCtrl'
}).when('/realms/:realmKey/users/:userId', { }).when('/realms/:realmKey/users/:userId', {
templateUrl : 'partials/user-detail.html', templateUrl : 'partials/user-detail.html',
resolve : { resolve : {
@ -66,7 +42,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
return UserLoader(); return UserLoader();
} }
}, },
controller : UserDetailCtrl controller : 'UserDetailCtrl'
}).when('/realms/:realmKey/users', { }).when('/realms/:realmKey/users', {
templateUrl : 'partials/user-list.html', templateUrl : 'partials/user-list.html',
resolve : { resolve : {
@ -80,7 +56,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
return UserListLoader(); return UserListLoader();
} }
}, },
controller : UserListCtrl controller : 'UserListCtrl'
}).when('/realms/:realmKey', { }).when('/realms/:realmKey', {
templateUrl : 'partials/realm-detail.html', templateUrl : 'partials/realm-detail.html',
resolve : { resolve : {
@ -91,7 +67,7 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
return RealmLoader(); return RealmLoader();
} }
}, },
controller : RealmDetailCtrl controller : 'RealmDetailCtrl'
}).when('/realms', { }).when('/realms', {
templateUrl : 'partials/realm-list.html', templateUrl : 'partials/realm-list.html',
resolve : { resolve : {
@ -99,13 +75,13 @@ eventjugglerModule.config([ '$routeProvider', function($routeProvider) {
return RealmListLoader(); return RealmListLoader();
} }
}, },
controller : RealmListCtrl controller : 'RealmListCtrl'
}).otherwise({ }).otherwise({
templateUrl : 'partials/home.html' templateUrl : 'partials/home.html'
}); });
} ]); } ]);
eventjugglerModule.config(function($httpProvider) { module.config(function($httpProvider) {
$httpProvider.responseInterceptors.push('errorInterceptor'); $httpProvider.responseInterceptors.push('errorInterceptor');
var spinnerFunction = function(data, headersGetter) { var spinnerFunction = function(data, headersGetter) {
@ -121,7 +97,7 @@ eventjugglerModule.config(function($httpProvider) {
}); });
eventjugglerModule.factory('errorInterceptor', function($q, $window, $rootScope, $location) { module.factory('errorInterceptor', function($q, $window, $rootScope, $location) {
return function(promise) { return function(promise) {
return promise.then(function(response) { return promise.then(function(response) {
$rootScope.httpProviderError = null; $rootScope.httpProviderError = null;
@ -133,7 +109,7 @@ eventjugglerModule.factory('errorInterceptor', function($q, $window, $rootScope,
}; };
}); });
eventjugglerModule.factory('spinnerInterceptor', function($q, $window, $rootScope, $location) { module.factory('spinnerInterceptor', function($q, $window, $rootScope, $location) {
return function(promise) { return function(promise) {
return promise.then(function(response) { return promise.then(function(response) {
resourceRequests--; resourceRequests--;

View file

@ -1,7 +1,8 @@
'use strict'; 'use strict';
function GlobalCtrl($scope, Auth, $location, Notifications) { var module = angular.module('keycloak.controllers', [ 'keycloak.services' ]);
module.controller('GlobalCtrl', function($scope, Auth, $location, Notifications) {
$scope.addMessage = function() { $scope.addMessage = function() {
Notifications.success("test"); Notifications.success("test");
}; };
@ -13,21 +14,14 @@ function GlobalCtrl($scope, Auth, $location, Notifications) {
}, function() { }, function() {
$scope.path = $location.path().substring(1).split("/"); $scope.path = $location.path().substring(1).split("/");
}); });
} });
function ActivitiesEventsCtrl($scope, events) {
$scope.events = events;
}
function ActivitiesStatisticsCtrl($scope, statistics) { module.controller('ApplicationListCtrl', function($scope, applications) {
$scope.statistics = statistics;
}
function ApplicationListCtrl($scope, applications) {
$scope.applications = applications; $scope.applications = applications;
} });
function ApplicationDetailCtrl($scope, applications, application, Application, realms, providers, $location, $window, $dialog, Notifications) { module.controller('ApplicationDetailCtrl', function($scope, applications, application, Application, realms, providers, $location, $window, $dialog, Notifications) {
$scope.application = angular.copy(application); $scope.application = angular.copy(application);
$scope.applications = applications; $scope.applications = applications;
$scope.realms = realms; $scope.realms = realms;
@ -159,19 +153,19 @@ function ApplicationDetailCtrl($scope, applications, application, Application, r
}; };
$scope.$watch("providers.length + application.providers.length", updateAvailableProviders); $scope.$watch("providers.length + application.providers.length", updateAvailableProviders);
} });
function RealmListCtrl($scope, realms) { module.controller('RealmListCtrl', function($scope, realms) {
$scope.realms = realms; $scope.realms = realms;
} });
function UserListCtrl($scope, realms, realm, users) { module.controller('UserListCtrl', function($scope, realms, realm, users) {
$scope.realms = realms; $scope.realms = realms;
$scope.realm = realm; $scope.realm = realm;
$scope.users = users; $scope.users = users;
} });
function UserDetailCtrl($scope, realms, realm, user, User, $location, $dialog, Notifications) { module.controller('UserDetailCtrl', function($scope, realms, realm, user, User, $location, $dialog, Notifications) {
$scope.realms = realms; $scope.realms = realms;
$scope.realm = realm; $scope.realm = realm;
$scope.user = angular.copy(user); $scope.user = angular.copy(user);
@ -239,9 +233,9 @@ function UserDetailCtrl($scope, realms, realm, user, User, $location, $dialog, N
} }
}); });
}; };
} });
function RealmDetailCtrl($scope, Realm, realms, realm, $location, $dialog, Notifications) { module.controller('RealmDetailCtrl', function($scope, Realm, realms, realm, $location, $dialog, Notifications) {
$scope.realms = realms; $scope.realms = realms;
$scope.realm = angular.copy(realm); $scope.realm = angular.copy(realm);
$scope.create = !realm.name; $scope.create = !realm.name;
@ -311,4 +305,4 @@ function RealmDetailCtrl($scope, Realm, realms, realm, $location, $dialog, Notif
} }
}); });
}; };
} });

View file

@ -0,0 +1,188 @@
'use strict';
var module = angular.module('keycloak.services', [ 'ngResource' ]);
module.factory('Notifications', function($rootScope, $timeout) {
var notifications = {};
var scheduled = null;
var schedulePop = function() {
if (scheduled) {
$timeout.cancel(scheduled);
}
scheduled = $timeout(function() {
$rootScope.notification = null;
scheduled = null;
}, 3000);
};
if (!$rootScope.notifications) {
$rootScope.notifications = [];
}
notifications.success = function(message) {
$rootScope.notification = {
type : "success",
message : message
};
schedulePop();
};
return notifications;
});
module.factory('Application', function($resource) {
return $resource('/keycloak-server/ui/api/applications/:key', {
key : '@key'
}, {
update : {
method : 'PUT'
}
});
});
module.factory('ApplicationListLoader', function(Application, $q) {
return function() {
var delay = $q.defer();
Application.query(function(applications) {
delay.resolve(applications);
}, function() {
delay.reject('Unable to fetch applications');
});
return delay.promise;
};
});
module.factory('ApplicationLoader', function(Application, $route, $q) {
return function() {
var key = $route.current.params.key;
if (key == 'new') {
return {};
} else {
var delay = $q.defer();
Application.get({
key : key
}, function(application) {
delay.resolve(application);
}, function() {
delay.reject('Unable to fetch application ' + key);
});
return delay.promise;
}
};
});
module.factory('Provider', function($resource) {
return $resource('/ejs-identity/api/admin/providers');
});
module.factory('ProviderListLoader', function(Provider, $q) {
return function() {
var delay = $q.defer();
Provider.query(function(providers) {
delay.resolve(providers);
}, function() {
delay.reject('Unable to fetch providers');
});
return delay.promise;
};
});
module.factory('Realm', function($resource) {
return $resource('/keycloak-server/ui/api/realms/:key', {
key : '@key'
}, {
update : {
method : 'PUT'
}
});
});
module.factory('RealmListLoader', function(Realm, $q) {
return function() {
var delay = $q.defer();
Realm.query(function(realms) {
delay.resolve(realms);
}, function() {
delay.reject('Unable to fetch realms');
});
return delay.promise;
};
});
module.factory('RealmLoader', function(Realm, $route, $q) {
return function() {
var key = $route.current.params.realmKey;
if (key == 'new') {
return {};
} else {
var delay = $q.defer();
Realm.get({
key : key
}, function(realm) {
delay.resolve(realm);
}, function() {
delay.reject('Unable to fetch key ' + key);
});
return delay.promise;
}
};
});
module.factory('User', function($resource) {
return $resource('/ejs-identity/api/im/:realmKey/users/:userId', {
realmKey : '@realmKey',
userId : '@userId'
}, {
save : {
method : 'PUT'
}
});
});
module.factory('UserListLoader', function(User, $route, $q) {
return function() {
var delay = $q.defer();
User.query({
realmKey : $route.current.params.realmKey
}, function(users) {
delay.resolve(users);
}, function() {
delay.reject('Unable to fetch users');
});
return delay.promise;
};
});
module.factory('UserLoader', function(User, $route, $q) {
return function() {
var userId = $route.current.params.userId;
if (userId == 'new') {
return {};
} else {
var delay = $q.defer();
User.get({
realmKey : $route.current.params.realmKey,
userId : userId
}, function(user) {
delay.resolve(user);
}, function() {
delay.reject('Unable to fetch user ' + $route.current.params.userId);
});
return delay.promise;
}
};
});
module.service('Auth', function($resource, $http, $location, $routeParams) {
var auth = {
loggedIn : true
};
auth.user = {
userId : 'test',
displayName: 'Test User'
};
return auth;
});

View file

@ -7,7 +7,6 @@
<li class="divider-vertical-left" ng-class="path[0] == '' && 'active'"><a href="#">Home</a></li> <li class="divider-vertical-left" ng-class="path[0] == '' && 'active'"><a href="#">Home</a></li>
<li class="divider-vertical-left" ng-class="path[0] == 'applications' && 'active'" ng-show="auth.loggedIn"><a href="#/applications">Applications</a></li> <li class="divider-vertical-left" ng-class="path[0] == 'applications' && 'active'" ng-show="auth.loggedIn"><a href="#/applications">Applications</a></li>
<li class="divider-vertical-left" ng-class="path[0] == 'realms' && 'active'" ng-show="auth.loggedIn"><a href="#/realms">Realms</a></li> <li class="divider-vertical-left" ng-class="path[0] == 'realms' && 'active'" ng-show="auth.loggedIn"><a href="#/realms">Realms</a></li>
<li class="divider-vertical-left" ng-class="path[0] == 'activities' && 'active'" ng-show="auth.root"><a href="#/activities">Activities</a></li>
</ul> </ul>
<ul class="nav pull-right" ng-hide="auth.loggedIn"> <ul class="nav pull-right" ng-hide="auth.loggedIn">
<li><a href="/ejs-identity/api/login/system">Login</a></li> <li><a href="/ejs-identity/api/login/system">Login</a></li>