Fixes to admin console

This commit is contained in:
Stian Thorgersen 2014-05-21 14:10:59 +01:00
parent 73f59417bd
commit 10ae457237
10 changed files with 4205 additions and 5248 deletions

View file

@ -15,7 +15,7 @@
<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/angular-route.js"></script> <script src="lib/angular/angular-route.js"></script>
<script src="lib/angular/ui-bootstrap-tpls-0.4.0.js"></script> <script src="lib/angular/ui-bootstrap-tpls-0.11.0.js"></script>
<script src="lib/jquery/jquery.idletimer.js" type="text/javascript"></script> <script src="lib/jquery/jquery.idletimer.js" type="text/javascript"></script>
<script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script> <script src="lib/jquery/jquery.idletimeout.js" type="text/javascript"></script>
@ -39,6 +39,7 @@
</head> </head>
<body class="admin-console" data-ng-controller="GlobalCtrl" data-ng-cloak> <body class="admin-console" data-ng-controller="GlobalCtrl" data-ng-cloak>
<div id="idletimeout"> <div id="idletimeout">
You will be logged off in <strong><span></span> seconds</strong> due to inactivity. You will be logged off in <strong><span></span> seconds</strong> due to inactivity.
<a id="idletimeout-resume" href="#">Click here to continue using this web page</a>. <a id="idletimeout-resume" href="#">Click here to continue using this web page</a>.

View file

@ -2,9 +2,40 @@
var module = angular.module('keycloak.services', [ 'ngResource', 'ngRoute' ]); var module = angular.module('keycloak.services', [ 'ngResource', 'ngRoute' ]);
module.service('Dialog', function($dialog) { module.service('Dialog', function($modal) {
var dialog = {}; var dialog = {};
var openDialog = function(title, message, btns) {
var controller = function($scope, $modalInstance, title, message, btns) {
$scope.title = title;
$scope.message = message;
$scope.btns = btns;
$scope.ok = function () {
$modalInstance.close();
};
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
};
return $modal.open({
templateUrl: 'templates/kc-modal.html',
controller: controller,
resolve: {
title: function() {
return title;
},
message: function() {
return message;
},
btns: function() {
return btns;
}
}
}).result;
}
var escapeHtml = function(str) { var escapeHtml = function(str) {
var div = document.createElement('div'); var div = document.createElement('div');
div.appendChild(document.createTextNode(str)); div.appendChild(document.createTextNode(str));
@ -13,64 +44,53 @@ module.service('Dialog', function($dialog) {
dialog.confirmDelete = function(name, type, success) { dialog.confirmDelete = function(name, type, success) {
var title = 'Delete ' + escapeHtml(type.charAt(0).toUpperCase() + type.slice(1)); var title = 'Delete ' + escapeHtml(type.charAt(0).toUpperCase() + type.slice(1));
var msg = '<span class="primary">Are you sure you want to permanently delete the ' + escapeHtml(type) + ' <strong>' + escapeHtml(name) + '</strong>?</span>'; var msg = 'Are you sure you want to permanently delete the ' + type + ' ' + name + '?';
var btns = [ { var btns = {
result : 'cancel', ok: {
label : 'Cancel', label: 'Delete',
cssClass : 'btn btn-default' cssClass: 'btn btn-danger'
}, { },
result : 'ok', cancel: {
label : 'Delete', label: 'Cancel',
cssClass : 'btn btn-danger' cssClass: 'btn btn-default'
} ];
$dialog.messageBox(title, msg, btns).open().then(function(result) {
if (result == "ok") {
success();
} }
}); }
openDialog(title, msg, btns).then(success);
} }
dialog.confirmGenerateKeys = function(name, type, success) { dialog.confirmGenerateKeys = function(name, type, success) {
var title = 'Generate new keys for realm'; var title = 'Generate new keys for realm';
var msg = '<span class="primary">Are you sure you want to permanently generate new keys for <strong>' + name + '</strong>?</span>'; var msg = 'Are you sure you want to permanently generate new keys for ' + name + '?';
var btns = [ { var btns = {
result : 'cancel', ok: {
label : 'Cancel', label: 'Generate Keys',
cssClass : 'btn btn-default' cssClass: 'btn btn-danger'
}, { },
result : 'ok', cancel: {
label : 'Generate new keys', label: 'Cancel',
cssClass : 'btn btn-danger' cssClass: 'btn btn-default'
} ];
$dialog.messageBox(title, msg, btns).open().then(function(result) {
if (result == "ok") {
success();
} }
}); }
openDialog(title, msg, btns).then(success);
} }
dialog.confirm = function(title, message, success, cancel) { dialog.confirm = function(title, message, success, cancel) {
var title = title; var title = title;
var msg = '<span class="primary">' + message + '"</span>'; var msg = '<span class="primary">' + message + '"</span>';
var btns = [ { var btns = {
result : 'cancel', ok: {
label : 'Cancel', label: title,
cssClass : 'btn btn-default' cssClass: 'btn btn-danger'
}, { },
result : 'ok', cancel: {
label : title, label: 'Cancel',
cssClass : 'btn btn-danger' cssClass: 'btn btn-default'
} ];
$dialog.messageBox(title, msg, btns).open().then(function(result) {
if (result == "ok") {
success();
} else {
cancel && cancel();
} }
}); }
openDialog(title, msg, btns).then(success).reject(cancel);
} }
return dialog return dialog

View file

@ -37,17 +37,13 @@
</div> </div>
</div> </div>
<div class="form-group clearfix block"> <div class="form-group clearfix block" data-ng-show="authProvider.providerName">
<label class="col-sm-2 control-label" for="passwordUpdateSupported">Password Update Supported</label> <label class="col-sm-2 control-label" for="passwordUpdateSupported">Password Update Supported</label>
<div class="col-sm-4"> <div class="col-sm-4">
<input ng-model="authProvider.passwordUpdateSupported" name="passwordUpdateSupported" id="passwordUpdateSupported" onoffswitch /> <input ng-model="authProvider.passwordUpdateSupported" name="passwordUpdateSupported" id="passwordUpdateSupported" onoffswitch />
</div> </div>
</div> </div>
</fieldset>
<fieldset>
<legend data-ng-show="authProvider.providerName"><span class="text">{{authProvider.providerName|capitalize}}'s provider options</span></legend>
<div data-ng-repeat="option in authProviderOptionNames" class="form-group"> <div data-ng-repeat="option in authProviderOptionNames" class="form-group">
<label class="col-sm-2 control-label">{{option|capitalize}} </label> <label class="col-sm-2 control-label">{{option|capitalize}} </label>

View file

@ -28,7 +28,14 @@
<tr ng-repeat="authProvider in authenticationProviders"> <tr ng-repeat="authProvider in authenticationProviders">
<td><a href="#/realms/{{realm.realm}}/auth-settings/{{$index}}">{{authProvider.providerName|capitalize}}</a></td> <td><a href="#/realms/{{realm.realm}}/auth-settings/{{$index}}">{{authProvider.providerName|capitalize}}</a></td>
<td>{{authProvider.passwordUpdateSupported}}</td> <td>{{authProvider.passwordUpdateSupported}}</td>
<td>{{authProvider.config}}</td> <td>
<table class="table table-striped table-bordered" data-ng-show="authProvider.config">
<tr data-ng-repeat="(key, value) in authProvider.config">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
</td>
</tr> </tr>
<tr data-ng-show="!authenticationProviders || authenticationProviders.length == 0"> <tr data-ng-show="!authenticationProviders || authenticationProviders.length == 0">
<td>No authentication providers available</td> <td>No authentication providers available</td>

View file

@ -1,14 +1,11 @@
<div class="modal-dialog" tabindex="-1" role="dialog"> <div class="modal-header">
<div class="modal-content"> <button type="button" class="close" ng-click="cancel()">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
<span class="pficon pficon-close"></span> <span class="pficon pficon-close"></span>
</button> </button>
<h4 class="modal-title" id="myModalLabel">{{ title }}</h4> <h4 class="modal-title">{{title}}</h4>
</div> </div>
<div class="modal-body"><p ng-bind-html-unsafe="message"></p></div> <div class="modal-body">{{message}}</div>
<div class="modal-footer"> <div class="modal-footer">
<button ng-repeat="btn in buttons" ng-click="close(btn.result)" class="" ng-class="btn.cssClass">{{ btn.label }}</button> <button type="button" data-ng-class="btns.cancel.cssClass" ng-click="cancel()">{{btns.cancel.label}}</button>
</div> <button type="button" data-ng-class="btns.ok.cssClass" ng-click="ok()">{{btns.ok.label}}</button>
</div>
</div> </div>

View file

@ -1,6 +1,6 @@
<ul class="nav nav-tabs nav-tabs-pf"> <ul class="nav nav-tabs nav-tabs-pf">
<li ng-class="{active: !path[2]}"><a href="#/realms/{{realm.realm}}">General</a></li> <li ng-class="{active: !path[2]}"><a href="#/realms/{{realm.realm}}">General</a></li>
<li ng-class="{active: path[2] == 'social'}" data-ng-show="realm.social && access.viewRealm"><a href="#/realms/{{realm.realm}}/social-settings">Social</a></li> <li ng-class="{active: path[2] == 'social-settings'}" data-ng-show="realm.social && access.viewRealm"><a href="#/realms/{{realm.realm}}/social-settings">Social</a></li>
<li ng-class="{active: path[2] == 'roles'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/roles">Roles</a></li> <li ng-class="{active: path[2] == 'roles'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/roles">Roles</a></li>
<li ng-class="{active: path[2] == 'default-roles'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li> <li ng-class="{active: path[2] == 'default-roles'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/default-roles">Default Roles</a></li>
<li ng-class="{active: path[2] == 'required-credentials'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/required-credentials">Credentials</a></li> <li ng-class="{active: path[2] == 'required-credentials'}" data-ng-show="access.viewRealm"><a href="#/realms/{{realm.realm}}/required-credentials">Credentials</a></li>

View file

@ -1,175 +0,0 @@
/**
* @license AngularJS v1.0.7
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
'use strict';
var directive = {};
directive.dropdownToggle =
['$document', '$location', '$window',
function ($document, $location, $window) {
var openElement = null, close;
return {
restrict: 'C',
link: function(scope, element, attrs) {
scope.$watch(function dropdownTogglePathWatch(){return $location.path();}, function dropdownTogglePathWatchAction() {
close && close();
});
element.parent().bind('click', function(event) {
close && close();
});
element.bind('click', function(event) {
event.preventDefault();
event.stopPropagation();
var iWasOpen = false;
if (openElement) {
iWasOpen = openElement === element;
close();
}
if (!iWasOpen){
element.parent().addClass('open');
openElement = element;
close = function (event) {
event && event.preventDefault();
event && event.stopPropagation();
$document.unbind('click', close);
element.parent().removeClass('open');
close = null;
openElement = null;
}
$document.bind('click', close);
}
});
}
};
}];
directive.tabbable = function() {
return {
restrict: 'C',
compile: function(element) {
var navTabs = angular.element('<ul class="nav nav-tabs"></ul>'),
tabContent = angular.element('<div class="tab-content"></div>');
tabContent.append(element.contents());
element.append(navTabs).append(tabContent);
},
controller: ['$scope', '$element', function($scope, $element) {
var navTabs = $element.contents().eq(0),
ngModel = $element.controller('ngModel') || {},
tabs = [],
selectedTab;
ngModel.$render = function() {
var $viewValue = this.$viewValue;
if (selectedTab ? (selectedTab.value != $viewValue) : $viewValue) {
if(selectedTab) {
selectedTab.paneElement.removeClass('active');
selectedTab.tabElement.removeClass('active');
selectedTab = null;
}
if($viewValue) {
for(var i = 0, ii = tabs.length; i < ii; i++) {
if ($viewValue == tabs[i].value) {
selectedTab = tabs[i];
break;
}
}
if (selectedTab) {
selectedTab.paneElement.addClass('active');
selectedTab.tabElement.addClass('active');
}
}
}
};
this.addPane = function(element, attr) {
var li = angular.element('<li><a href></a></li>'),
a = li.find('a'),
tab = {
paneElement: element,
paneAttrs: attr,
tabElement: li
};
tabs.push(tab);
attr.$observe('value', update)();
attr.$observe('title', function(){ update(); a.text(tab.title); })();
function update() {
tab.title = attr.title;
tab.value = attr.value || attr.title;
if (!ngModel.$setViewValue && (!ngModel.$viewValue || tab == selectedTab)) {
// we are not part of angular
ngModel.$viewValue = tab.value;
}
ngModel.$render();
}
navTabs.append(li);
li.bind('click', function(event) {
event.preventDefault();
event.stopPropagation();
if (ngModel.$setViewValue) {
$scope.$apply(function() {
ngModel.$setViewValue(tab.value);
ngModel.$render();
});
} else {
// we are not part of angular
ngModel.$viewValue = tab.value;
ngModel.$render();
}
});
return function() {
tab.tabElement.remove();
for(var i = 0, ii = tabs.length; i < ii; i++ ) {
if (tab == tabs[i]) {
tabs.splice(i, 1);
}
}
};
}
}]
};
};
directive.table = function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
element[0].className = 'table table-bordered table-striped code-table';
}
};
};
directive.tabPane = function() {
return {
require: '^tabbable',
restrict: 'C',
link: function(scope, element, attrs, tabsCtrl) {
element.bind('$remove', tabsCtrl.addPane(element, attrs));
}
};
};
angular.module('bootstrap', []).directive(directive);
})(window, window.angular);