Add MemberManage dashboard
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
/**
|
||||
* @ngdoc controller
|
||||
* @name MemberManager.Dialogs.Member.EditController
|
||||
* @function
|
||||
*
|
||||
* @description
|
||||
* The controller for the member editor
|
||||
*
|
||||
* @param {any} $scope Scope
|
||||
* @param {any} $routeParams Route Parameters
|
||||
* @param {any} $q Queue
|
||||
* @param {any} memberResource Member Resource
|
||||
* @param {any} entityResource Entity Resource
|
||||
* @param {any} serverValidationManager Server Validation Manager
|
||||
* @param {any} contentEditingHelper Content Editing Helper
|
||||
* @param {any} fileManager File Manager
|
||||
* @param {any} formHelper Form Helper
|
||||
*/
|
||||
function MemberEditDialogController($scope, $routeParams, $q, memberResource, entityResource, serverValidationManager, contentEditingHelper, fileManager, formHelper) {
|
||||
//setup scope vars
|
||||
$scope.model = {};
|
||||
$scope.model.defaultButton = null;
|
||||
$scope.model.subButtons = [];
|
||||
$scope.model.nodeId = 0;
|
||||
$scope.loaded = false;
|
||||
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
|
||||
function performGet() {
|
||||
var deferred = $q.defer();
|
||||
if (angular.isObject(dialogOptions.entity)) {
|
||||
$scope.loaded = true;
|
||||
deferred.resolve(dialogOptions.entity);
|
||||
} else {
|
||||
if (dialogOptions.create) {
|
||||
//we are creating so get an empty member item
|
||||
memberResource.getScaffold(dialogOptions.contentType)
|
||||
.then(function (data) {
|
||||
|
||||
$scope.loaded = true;
|
||||
deferred.resolve(data);
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (dialogOptions.key && dialogOptions.key.toString().length < 9) {
|
||||
entityResource.getById(dialogOptions.key, "Member").then(function (entity) {
|
||||
memberResource.getByKey(entity.key).then(function (data) {
|
||||
|
||||
//in one particular special case, after we've created a new item we redirect back to the edit
|
||||
// route but there might be server validation errors in the collection which we need to display
|
||||
// after the redirect, so we will bind all subscriptions which will show the server validation errors
|
||||
// if there are any and then clear them so the collection no longer persists them.
|
||||
serverValidationManager.executeAndClearAllSubscriptions();
|
||||
$scope.loaded = true;
|
||||
|
||||
deferred.resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
//we are editing so get the content item from the server
|
||||
memberResource.getByKey(dialogOptions.key)
|
||||
.then(function (data) {
|
||||
|
||||
$scope.loaded = true;
|
||||
|
||||
//in one particular special case, after we've created a new item we redirect back to the edit
|
||||
// route but there might be server validation errors in the collection which we need to display
|
||||
// after the redirect, so we will bind all subscriptions which will show the server validation errors
|
||||
// if there are any and then clear them so the collection no longer persists them.
|
||||
serverValidationManager.executeAndClearAllSubscriptions();
|
||||
|
||||
deferred.resolve(data);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
function performSave(args) {
|
||||
var deferred = $q.defer();
|
||||
|
||||
$scope.busy = true;
|
||||
|
||||
if (formHelper.submitForm({ scope: $scope, statusMessage: args.statusMessage })) {
|
||||
|
||||
$scope.busy = true;
|
||||
|
||||
args.saveMethod($scope.model.entity, $routeParams.create, fileManager.getFiles())
|
||||
.then(function (data) {
|
||||
|
||||
formHelper.resetForm({ scope: $scope, notifications: data.notifications });
|
||||
|
||||
contentEditingHelper.handleSuccessfulSave({
|
||||
scope: $scope,
|
||||
savedContent: data,
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.model.entity, data)
|
||||
});
|
||||
|
||||
$scope.busy = false;
|
||||
deferred.resolve(data);
|
||||
|
||||
}, function (err) {
|
||||
|
||||
contentEditingHelper.handleSaveError({
|
||||
redirectOnFailure: false,
|
||||
err: err,
|
||||
rebindCallback: contentEditingHelper.reBindChangedProperties($scope.model.entity, err.data)
|
||||
});
|
||||
|
||||
$scope.busy = false;
|
||||
deferred.reject(err);
|
||||
});
|
||||
} else {
|
||||
$scope.busy = false;
|
||||
deferred.reject();
|
||||
}
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
performGet().then(function (content) {
|
||||
$scope.model.entity = $scope.filterTabs(content, dialogOptions.tabFilter);
|
||||
});
|
||||
|
||||
$scope.filterTabs = function (entity, blackList) {
|
||||
if (blackList) {
|
||||
_.each(entity.tabs, function (tab) {
|
||||
tab.hide = _.contains(blackList, tab.alias);
|
||||
});
|
||||
}
|
||||
|
||||
return entity;
|
||||
};
|
||||
|
||||
$scope.save = function () {
|
||||
performSave({ saveMethod: memberResource.save, statusMessage: "Saving..." })
|
||||
.then(function (content) {
|
||||
if (dialogOptions.closeOnSave) {
|
||||
$scope.submit(content);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("MemberManager.Dialogs.Member.EditController", MemberEditDialogController);
|
||||
@@ -0,0 +1,45 @@
|
||||
<form novalidate name="contentForm"
|
||||
ng-controller="MemberManager.Dialogs.Member.EditController"
|
||||
ng-show="loaded"
|
||||
ng-submit="save()"
|
||||
val-form-manager>
|
||||
|
||||
<div class="umb-panel">
|
||||
<div class="umb-panel-header">
|
||||
<umb-content-name placeholder="@placeholders_entername"
|
||||
ng-model="model.entity.name" />
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-body with-footer">
|
||||
<div id="tab{{tab.id}}" ng-repeat="tab in model.entity.tabs">
|
||||
<div class="umb-pane" ng-if="!tab.hide">
|
||||
<h5>{{tab.label}}</h5>
|
||||
<umb-property property="property"
|
||||
ng-repeat="property in tab.properties">
|
||||
<umb-editor model="property"></umb-editor>
|
||||
</umb-property>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-footer">
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="btn-toolbar umb-btn-toolbar pull-right">
|
||||
<a href ng-click="close()" class="btn btn-link">
|
||||
<localize key="general_close">Close</localize>
|
||||
</a>
|
||||
|
||||
|
||||
<div class="btn-group dropup">
|
||||
<!-- primary button -->
|
||||
<a class="btn btn-success" href="#" ng-click="save()" prevent-default>
|
||||
Save
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,116 @@
|
||||
angular.module("umbraco").controller("MemberManager.Dialogs.Member.ExportController",
|
||||
function ($scope, memberExtResource) {
|
||||
|
||||
$scope.defaultButton = null;
|
||||
$scope.subButtons = [];
|
||||
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
|
||||
$scope.filterData = dialogOptions.filterData;
|
||||
$scope.columns = dialogOptions.columns;
|
||||
//$scope.memberType = dialogOptions.filterData.memberType;
|
||||
$scope.totalItems = dialogOptions.totalItems;
|
||||
$scope.memberTypes = dialogOptions.memberTypes;
|
||||
$scope.format = "Excel";
|
||||
|
||||
$scope.allColumnsSelected = false;
|
||||
|
||||
function init() {
|
||||
var buttons = {
|
||||
defaultButton: createButtonDefinition("E"),
|
||||
subButtons: []
|
||||
};
|
||||
|
||||
$scope.defaultButton = buttons.defaultButton;
|
||||
$scope.subButtons = buttons.subButtons;
|
||||
|
||||
memberExtResource.getMemberColumns(dialogOptions.filterData.memberType).then(function (data) {
|
||||
// We use this to preserve the original filter data.
|
||||
$scope.columnList = setSelected(data, $scope.columns);
|
||||
$scope.allColumnsSelected = $scope.allSelected($scope.columnList);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function createButtonDefinition(ch) {
|
||||
switch (ch) {
|
||||
case "E":
|
||||
//export action
|
||||
return {
|
||||
letter: ch,
|
||||
labelKey: "memberManager_export",
|
||||
label: "Export",
|
||||
handler: $scope.export,
|
||||
hotKey: "ctrl+e",
|
||||
hotKeyWhenHidden: true,
|
||||
alias: "export"
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through a list of select options and set selected for values that appear in a filter list
|
||||
setSelected = function (list, filter) {
|
||||
// Convert string arrays to a select item object.
|
||||
list = _.map(list, function (item) {
|
||||
if (typeof item === "string") {
|
||||
let value = item;
|
||||
item = {
|
||||
id: value.replace(" ", "_"),
|
||||
name: value,
|
||||
alias: value,
|
||||
selected: false
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
if (filter) {
|
||||
for (var i = 0; i < filter.length; i++) {
|
||||
for (var j = 0; j < list.length; j++) {
|
||||
if (list[j].id === filter[i].replace(" ", "_")) {
|
||||
list[j].selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
processColumnList = function (list) {
|
||||
var filteredList = _.filter(list, function (i) {
|
||||
return i.selected;
|
||||
});
|
||||
|
||||
return _.map(filteredList, function (item) {
|
||||
return item.alias;
|
||||
});
|
||||
};
|
||||
|
||||
// Methods to manage select/deselect all in checkbox lists.
|
||||
$scope.selectAll = function (selectionList) {
|
||||
_.each(selectionList, function (item) { item.selected = $scope.allColumnsSelected; });
|
||||
};
|
||||
|
||||
$scope.allSelected = function (selectionList) {
|
||||
return _.filter(selectionList, function (item) { return item.selected; }).length === selectionList.length;
|
||||
};
|
||||
|
||||
$scope.export = function () {
|
||||
$scope.submit(processColumnList($scope.columnList));
|
||||
};
|
||||
|
||||
// this method is called for all action buttons and then we proxy based on the btn definition
|
||||
$scope.performAction = function (btn) {
|
||||
|
||||
if (!btn || !angular.isFunction(btn.handler)) {
|
||||
throw "btn.handler must be a function reference";
|
||||
}
|
||||
|
||||
btn.handler.apply(this);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,90 @@
|
||||
<form novalidate name="contentForm"
|
||||
ng-controller="MemberManager.Dialogs.Member.ExportController"
|
||||
ng-submit="export()"
|
||||
val-form-manager
|
||||
class="umb-mini-editor">
|
||||
|
||||
<div class="umb-panel">
|
||||
<div class="umb-panel-header">
|
||||
<h1>
|
||||
<localize key="memberManager_export">Export</localize>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="umb-panel-body with-footer">
|
||||
<div class="umb-pane filter-options">
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label">Exportable records:</label> <span>{{totalItems}} members</span>
|
||||
<div class="alert alert-warning" ng-if="totalItems > 100">Exporting a large number of members may take some time.</div>
|
||||
</div>
|
||||
<div class="umb-el-wrap" ng-if="filterData.display">
|
||||
<label class="control-label">Applied Filters: </label>
|
||||
|
||||
<div class="filter-display">
|
||||
<div ng-repeat="displayFilter in filterData.display">
|
||||
<strong>{{displayFilter.title}}</strong>
|
||||
<span>{{displayFilter.value}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-el-wrap filter-checkbox-list" ng-show="columnList && columnList.length > 1">
|
||||
<h5>Columns</h5>
|
||||
<p>Select the columns to include in the exported data</p>
|
||||
<div class="filter-header">
|
||||
<div>
|
||||
<input type="checkbox" ng-model="allColumnsSelected" ng-click="selectAll(columnList)" id="column-all" />
|
||||
<label class="control-label" for="column-all">Select / deselect all columns</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-content">
|
||||
<div ng-repeat="column in columnList">
|
||||
<input type="checkbox" ng-model="column.selected" id="column-{{column.id}}" />
|
||||
<label class="control-label" for="column-{{column.id}}">{{column.name}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label">Format: </label>
|
||||
<div class="controls controls-row">
|
||||
<select ng-model="format">
|
||||
<option value="Excel">Excel Spreadsheet (*.xlsx)</option>
|
||||
<option value="CSV">Comma Separated Values (*.csv)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-footer">
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="btn-toolbar umb-btn-toolbar pull-right">
|
||||
<a ng-click="close()" class="btn btn-link">
|
||||
<localize key="general_close">Close</localize>
|
||||
</a>
|
||||
|
||||
|
||||
<div class="btn-group dropup" ng-if="defaultButton">
|
||||
<!-- primary button -->
|
||||
<a class="btn btn-success" href="#" ng-click="performAction(defaultButton)" prevent-default>
|
||||
<localize key="{{defaultButton.labelKey}}">{{defaultButton.label}}</localize>
|
||||
</a>
|
||||
|
||||
<a class="btn btn-success dropdown-toggle" data-toggle="dropdown" ng-if="subButtons.length > 0">
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<!-- sub buttons -->
|
||||
<ul class="dropdown-menu bottom-up" role="menu" aria-labelledby="dLabel" ng-if="subButtons.length > 0">
|
||||
<li ng-repeat="btn in subButtons">
|
||||
<a href="#" ng-click="performAction(btn)" prevent-default>
|
||||
<localize key="{{btn.labelKey}}">{{btn.label}}</localize>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -0,0 +1,167 @@
|
||||
angular.module("umbraco").controller("MemberManager.Dialogs.Member.FilterController",
|
||||
function ($scope) {
|
||||
|
||||
$scope.defaultButton = null;
|
||||
$scope.subButtons = [];
|
||||
var dialogOptions = $scope.$parent.dialogOptions;
|
||||
|
||||
$scope.filterData = dialogOptions.filterData;
|
||||
$scope.memberTypes = dialogOptions.memberTypes;
|
||||
$scope.memberGroups = dialogOptions.memberGroups;
|
||||
|
||||
function init() {
|
||||
var buttons = {
|
||||
defaultButton: createButtonDefinition("F"),
|
||||
subButtons: [
|
||||
createButtonDefinition("C")
|
||||
]
|
||||
};
|
||||
|
||||
$scope.defaultButton = buttons.defaultButton;
|
||||
$scope.subButtons = buttons.subButtons;
|
||||
|
||||
// We use this to preserve the original filter data.
|
||||
$scope.memberGroupFilter = setSelected($scope.memberGroups, $scope.filterData.memberGroups);
|
||||
}
|
||||
|
||||
function createButtonDefinition(ch) {
|
||||
switch (ch) {
|
||||
case "F":
|
||||
//publish action
|
||||
return {
|
||||
letter: ch,
|
||||
labelKey: "memberManager_applyFilter",
|
||||
label: "Apply Filter",
|
||||
handler: $scope.applyFilter,
|
||||
hotKey: "ctrl+f",
|
||||
hotKeyWhenHidden: true,
|
||||
alias: "applyFilter"
|
||||
};
|
||||
case "C":
|
||||
//send to publish
|
||||
return {
|
||||
letter: ch,
|
||||
labelKey: "memberManager_clearFilter",
|
||||
label: "Clear Filter",
|
||||
handler: $scope.clearFilter,
|
||||
hotKey: "ctrl+c",
|
||||
hotKeyWhenHidden: true,
|
||||
alias: "sendToPublish"
|
||||
};
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate model for representing the search
|
||||
getFilterModel = function () {
|
||||
var displaySearch = new Array();
|
||||
|
||||
//if ($scope.filterData.filter) {
|
||||
// displaySearch.push({ title: "Search", value: $scope.filterData.filter });
|
||||
//}
|
||||
if ($scope.filterData.memberType) {
|
||||
displaySearch.push({ title: "Member Type", value: _getMemberTypeName() });
|
||||
}
|
||||
if ($scope.filterData.f_umbracoMemberApproved) {
|
||||
displaySearch.push({ title: "Approved", value: $scope.filterData.f_umbracoMemberApproved === "true,1" ? "Approved" : "Suspended" });
|
||||
}
|
||||
|
||||
if ($scope.filterData.f_umbracoMemberLockedOut) {
|
||||
displaySearch.push({ title: "Locked Out", value: $scope.filterData.f_umbracoMemberLockedOut === "true,1" ? "Locked Out" : "Active" });
|
||||
}
|
||||
|
||||
return {
|
||||
filter: $scope.filterData.filter,
|
||||
memberType: $scope.filterData.memberType,
|
||||
memberGroups: processFilterList(displaySearch, "Member Groups", $scope.memberGroupFilter),
|
||||
f_umbracoMemberApproved: !$scope.filterData.f_umbracoMemberApproved ? "" : $scope.filterData.f_umbracoMemberApproved,
|
||||
f_umbracoMemberLockedOut: !$scope.filterData.f_umbracoMemberLockedOut ? "" : $scope.filterData.f_umbracoMemberLockedOut,
|
||||
|
||||
display: displaySearch
|
||||
};
|
||||
};
|
||||
|
||||
function _getMemberTypeName() {
|
||||
|
||||
var type = _.filter($scope.memberTypes, function (item) {
|
||||
return item.alias === $scope.filterData.memberType;
|
||||
});
|
||||
|
||||
return _.map(type, function (item) {
|
||||
return ' ' + item.name;
|
||||
}).join();
|
||||
|
||||
}
|
||||
|
||||
// Loop through a list of select options and set selected for values that appear in a filter list
|
||||
setSelected = function (list, filter) {
|
||||
// Convert string arrays to a select item object.
|
||||
list = _.map(list, function (item) {
|
||||
if (typeof item === "string") {
|
||||
let value = item;
|
||||
item = {
|
||||
id: value.replace(" ", "_"),
|
||||
name: value,
|
||||
alias: value,
|
||||
selected: false
|
||||
};
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
if (filter) {
|
||||
for (var i = 0; i < filter.length; i++) {
|
||||
for (var j = 0; j < list.length; j++) {
|
||||
if (list[j].id === filter[i].replace(" ", "_")) {
|
||||
list[j].selected = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
};
|
||||
|
||||
|
||||
processFilterList = function (display, title, list) {
|
||||
var filteredList = _.filter(list, function (i) {
|
||||
return i.selected;
|
||||
});
|
||||
|
||||
var displayVal = _.map(filteredList, function (item) {
|
||||
return ' ' + item.name;
|
||||
}).join();
|
||||
|
||||
if (displayVal) {
|
||||
display.push({ title: title, value: displayVal });
|
||||
}
|
||||
return _.map(filteredList, function (item) {
|
||||
return item.alias;
|
||||
});
|
||||
};
|
||||
|
||||
$scope.applyFilter = function () {
|
||||
$scope.submit(getFilterModel());
|
||||
};
|
||||
|
||||
$scope.clearFilter = function () {
|
||||
$scope.filterData = {
|
||||
filter: null
|
||||
};
|
||||
$scope.submit($scope.filterData);
|
||||
};
|
||||
|
||||
// this method is called for all action buttons and then we proxy based on the btn definition
|
||||
$scope.performAction = function (btn) {
|
||||
|
||||
if (!btn || !angular.isFunction(btn.handler)) {
|
||||
throw "btn.handler must be a function reference";
|
||||
}
|
||||
|
||||
btn.handler.apply(this);
|
||||
};
|
||||
|
||||
|
||||
init();
|
||||
});
|
||||
@@ -0,0 +1,95 @@
|
||||
<form novalidate name="contentForm"
|
||||
ng-controller="MemberManager.Dialogs.Member.FilterController"
|
||||
ng-submit="applyFilter()"
|
||||
val-form-manager
|
||||
class="umb-mini-editor">
|
||||
|
||||
<div class="umb-panel">
|
||||
<div class="umb-panel-header">
|
||||
<h1>
|
||||
<localize key="memberManager_filter">Filter</localize>
|
||||
</h1>
|
||||
</div>
|
||||
<div class="umb-panel-body with-footer">
|
||||
<div class="umb-pane filter-options">
|
||||
<div class="umb-property">
|
||||
<label class="control-label">Search</label>
|
||||
<div class="controls controls-row">
|
||||
<input type="text" ng-model="filterData.filter" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-el-wrap" ng-show="memberTypes && memberTypes.length > 1">
|
||||
<label class="control-label">Member Type</label>
|
||||
<div class="controls controls-row">
|
||||
<select ng-model="filterData.memberType">
|
||||
<option value="">- All -</option>
|
||||
<option ng-repeat="memberType in memberTypes" ng-value="{{memberType.alias}}">{{memberType.name}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-checkbox-list" ng-show="memberGroupFilter && memberGroupFilter.length > 1">
|
||||
<h5>Member Groups</h5>
|
||||
<div class="filter-content">
|
||||
<div ng-repeat="group in memberGroupFilter">
|
||||
<input type="checkbox" ng-model="group.selected" id="group-{{group.id}}" />
|
||||
<label class="control-label" for="group-{{group.id}}">{{group.name}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label">Approved</label>
|
||||
<div class="controls controls-row">
|
||||
<select ng-model="filterData.f_umbracoMemberApproved">
|
||||
<option value="">- All -</option>
|
||||
<option value="true,1">Approved Only</option>
|
||||
<option value="false,0">Suspended Only</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="umb-el-wrap">
|
||||
<label class="control-label">Locked Out</label>
|
||||
<div class="controls controls-row">
|
||||
<select ng-model="filterData.f_umbracoMemberLockedOut">
|
||||
<option value="">- All -</option>
|
||||
<option value="true,1">Locked Out Only</option>
|
||||
<option value="false,0">Active Only</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="umb-panel-footer">
|
||||
<div class="umb-el-wrap umb-panel-buttons">
|
||||
<div class="btn-toolbar umb-btn-toolbar pull-right">
|
||||
<a ng-click="close()" class="btn btn-link">
|
||||
<localize key="general_close">Close</localize>
|
||||
</a>
|
||||
|
||||
|
||||
<div class="btn-group dropup" ng-if="defaultButton">
|
||||
<!-- primary button -->
|
||||
<a class="btn btn-success" href="#" ng-click="performAction(defaultButton)" prevent-default>
|
||||
<localize key="{{defaultButton.labelKey}}">{{defaultButton.label}}</localize>
|
||||
</a>
|
||||
|
||||
<a class="btn btn-success dropdown-toggle" data-toggle="dropdown" ng-if="subButtons.length > 0">
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
|
||||
<!-- sub buttons -->
|
||||
<ul class="dropdown-menu bottom-up" role="menu" aria-labelledby="dLabel" ng-if="subButtons.length > 0">
|
||||
<li ng-repeat="btn in subButtons">
|
||||
<a href="#" ng-click="performAction(btn)" prevent-default>
|
||||
<localize key="{{btn.labelKey}}">{{btn.label}}</localize>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
Reference in New Issue
Block a user