Merge pull request #2469 from umbraco/temp-U4-10900
Export member data functionality
This commit is contained in:
@@ -2,6 +2,6 @@
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
|
||||
<add key="umbracocore" value="http://www.myget.org/f/umbracocore/" />
|
||||
<add key="umbracocore" value="https://www.myget.org/F/umbracocore/api/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -436,4 +435,4 @@ namespace Umbraco.Core.Models
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Net.Http;
|
||||
using System.Xml.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
@@ -199,6 +200,14 @@ namespace Umbraco.Core.Services
|
||||
/// <param name="memberTypeId">Id of the MemberType</param>
|
||||
void DeleteMembersOfType(int memberTypeId);
|
||||
|
||||
/// <summary>
|
||||
/// Exports member data based on their unique Id
|
||||
/// </summary>
|
||||
/// <param name="key">The unique <see cref="Guid">member identifier</see></param>
|
||||
/// <param name="currentUser">The <see cref="IUser">user</see> requesting the export</param>
|
||||
/// <returns><see cref="HttpResponseMessage"/></returns>
|
||||
HttpResponseMessage ExportMemberData(Guid key, IUser currentUser);
|
||||
|
||||
[Obsolete("Use the overload with 'long' parameter types instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
IEnumerable<IMember> FindMembersByDisplayName(string displayNameToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith);
|
||||
@@ -249,4 +258,4 @@ namespace Umbraco.Core.Services
|
||||
/// <returns><see cref="IEnumerable{IMember}"/></returns>
|
||||
IEnumerable<IMember> GetMembersByPropertyValue(string propertyTypeAlias, DateTime value, ValuePropertyMatchType matchType = ValuePropertyMatchType.Exact);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Web.Security;
|
||||
using System.Xml.Linq;
|
||||
@@ -14,6 +15,9 @@ using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using Umbraco.Core.Security;
|
||||
|
||||
namespace Umbraco.Core.Services
|
||||
@@ -254,6 +258,108 @@ namespace Umbraco.Core.Services
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports member data based on their unique Id
|
||||
/// </summary>
|
||||
/// <param name="key">The unique <see cref="Guid">member identifier</see></param>
|
||||
/// <param name="currentUser">The <see cref="IUser">user</see> requesting the export</param>
|
||||
/// <returns><see cref="HttpResponseMessage"/></returns>
|
||||
public HttpResponseMessage ExportMemberData(Guid key, IUser currentUser)
|
||||
{
|
||||
var httpResponseMessage = new HttpResponseMessage();
|
||||
if (currentUser.HasAccessToSensitiveData() == false)
|
||||
{
|
||||
httpResponseMessage.StatusCode = HttpStatusCode.Forbidden;
|
||||
return httpResponseMessage;
|
||||
}
|
||||
|
||||
var memberPropertyFilter = new List<string>
|
||||
{
|
||||
"RawPasswordValue",
|
||||
"ParentId",
|
||||
"SortOrder",
|
||||
"Level",
|
||||
"Path",
|
||||
"CreatorId",
|
||||
"Version",
|
||||
"ContentTypeId",
|
||||
"HasIdentity",
|
||||
"PropertyGroups",
|
||||
"PropertyTypes",
|
||||
"ProviderUserKey",
|
||||
"ContentType"
|
||||
};
|
||||
var propertiesFilter = new List<string>
|
||||
{
|
||||
"PropertyType",
|
||||
"Version",
|
||||
"Id",
|
||||
"HasIdentity",
|
||||
"Key"
|
||||
};
|
||||
|
||||
var member = GetByKey(key);
|
||||
var memberProperties = member.GetType().GetProperties();
|
||||
var fileName = $"{member.Name}_{member.Email}.txt";
|
||||
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
using (var textWriter = new StreamWriter(memoryStream))
|
||||
{
|
||||
foreach (var memberProperty in memberProperties)
|
||||
{
|
||||
if (memberPropertyFilter.Contains(memberProperty.Name))
|
||||
continue;
|
||||
|
||||
var propertyValue = memberProperty.GetValue(member, null);
|
||||
var type = propertyValue?.GetType();
|
||||
|
||||
if (type == typeof(PropertyCollection))
|
||||
{
|
||||
textWriter.WriteLine("");
|
||||
textWriter.WriteLine("PROPERTIES");
|
||||
textWriter.WriteLine("**********");
|
||||
|
||||
if (propertyValue is PropertyCollection propertyCollection)
|
||||
{
|
||||
foreach (var property in propertyCollection)
|
||||
{
|
||||
var propProperties = property.GetType().GetProperties();
|
||||
|
||||
textWriter.WriteLine("Name : " + property.PropertyType.Name);
|
||||
|
||||
foreach (var p in propProperties)
|
||||
{
|
||||
if (propertiesFilter.Contains(p.Name)) continue;
|
||||
var pValue = p.GetValue(property, null);
|
||||
textWriter.WriteLine(p.Name + " : " + pValue);
|
||||
}
|
||||
|
||||
textWriter.WriteLine("------------------------");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
textWriter.WriteLine(memberProperty.Name + " : " + propertyValue);
|
||||
}
|
||||
}
|
||||
|
||||
textWriter.Flush();
|
||||
}
|
||||
|
||||
httpResponseMessage.Content = new ByteArrayContent(memoryStream.ToArray());
|
||||
httpResponseMessage.Content.Headers.Add("x-filename", fileName);
|
||||
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
|
||||
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
|
||||
httpResponseMessage.StatusCode = HttpStatusCode.OK;
|
||||
|
||||
return httpResponseMessage;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[Obsolete("Use the overload with 'long' parameter types instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public IEnumerable<IMember> FindMembersByDisplayName(string displayNameToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith)
|
||||
@@ -588,7 +694,7 @@ namespace Umbraco.Core.Services
|
||||
Mandate.ParameterCondition(pageIndex >= 0, "pageIndex");
|
||||
Mandate.ParameterCondition(pageSize > 0, "pageSize");
|
||||
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly:true))
|
||||
using (var uow = UowProvider.GetUnitOfWork(readOnly: true))
|
||||
{
|
||||
var repository = RepositoryFactory.CreateMemberRepository(uow);
|
||||
return repository.GetPagedXmlEntriesByPath("-1", pageIndex, pageSize, null, out totalRecords);
|
||||
|
||||
@@ -293,7 +293,7 @@ AnotherContentFinder
|
||||
public void Resolves_Actions()
|
||||
{
|
||||
var actions = _manager.ResolveActions();
|
||||
Assert.AreEqual(38, actions.Count());
|
||||
Assert.AreEqual(39, actions.Count());
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
@@ -10,8 +10,8 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
return umbRequestHelper.postSaveContent({
|
||||
restApiUrl: umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"PostSave"),
|
||||
"memberApiBaseUrl",
|
||||
"PostSave"),
|
||||
content: content,
|
||||
action: action,
|
||||
files: files,
|
||||
@@ -67,35 +67,35 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
}
|
||||
|
||||
var params = [
|
||||
{ pageNumber: options.pageNumber },
|
||||
{ pageSize: options.pageSize },
|
||||
{ orderBy: options.orderBy },
|
||||
{ orderDirection: options.orderDirection },
|
||||
{ orderBySystemField: toBool(options.orderBySystemField) },
|
||||
{ filter: options.filter }
|
||||
{ pageNumber: options.pageNumber },
|
||||
{ pageSize: options.pageSize },
|
||||
{ orderBy: options.orderBy },
|
||||
{ orderDirection: options.orderDirection },
|
||||
{ orderBySystemField: toBool(options.orderBySystemField) },
|
||||
{ filter: options.filter }
|
||||
];
|
||||
if (memberTypeAlias != null) {
|
||||
params.push({ memberTypeAlias: memberTypeAlias });
|
||||
}
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetPagedResults",
|
||||
params)),
|
||||
'Failed to retrieve member paged result');
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetPagedResults",
|
||||
params)),
|
||||
'Failed to retrieve member paged result');
|
||||
},
|
||||
|
||||
getListNode: function (listName) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetListNodeDisplay",
|
||||
[{ listName: listName }])),
|
||||
'Failed to retrieve data for member list ' + listName);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetListNodeDisplay",
|
||||
[{ listName: listName }])),
|
||||
'Failed to retrieve data for member list ' + listName);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -122,12 +122,12 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
getByKey: function (key) {
|
||||
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetByKey",
|
||||
[{ key: key }])),
|
||||
'Failed to retrieve data for member id ' + key);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetByKey",
|
||||
[{ key: key }])),
|
||||
'Failed to retrieve data for member id ' + key);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -152,12 +152,12 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*/
|
||||
deleteByKey: function (key) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"DeleteByKey",
|
||||
[{ key: key }])),
|
||||
'Failed to delete item ' + key);
|
||||
$http.post(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"DeleteByKey",
|
||||
[{ key: key }])),
|
||||
'Failed to delete item ' + key);
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -194,20 +194,20 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
|
||||
if (alias) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetEmpty",
|
||||
[{ contentTypeAlias: alias }])),
|
||||
'Failed to retrieve data for empty member item type ' + alias);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetEmpty",
|
||||
[{ contentTypeAlias: alias }])),
|
||||
'Failed to retrieve data for empty member item type ' + alias);
|
||||
}
|
||||
else {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetEmpty")),
|
||||
'Failed to retrieve data for empty member item type ' + alias);
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"GetEmpty")),
|
||||
'Failed to retrieve data for empty member item type ' + alias);
|
||||
}
|
||||
|
||||
},
|
||||
@@ -242,6 +242,40 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) {
|
||||
*/
|
||||
save: function (member, isNew, files) {
|
||||
return saveMember(member, "save" + (isNew ? "New" : ""), files);
|
||||
},
|
||||
|
||||
exportMemberData: function (key) {
|
||||
return umbRequestHelper.resourcePromise(
|
||||
$http.get(
|
||||
umbRequestHelper.getApiUrl(
|
||||
"memberApiBaseUrl",
|
||||
"ExportMemberData",
|
||||
[{ key: key }]))
|
||||
.success(function (data, status, headers) {
|
||||
|
||||
headers = headers();
|
||||
|
||||
var filename = headers['x-filename'];
|
||||
var contentType = headers['content-type'];
|
||||
|
||||
var linkElement = document.createElement('a');
|
||||
|
||||
var blob = new Blob([data], { type: contentType });
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
|
||||
linkElement.setAttribute('href', url);
|
||||
linkElement.setAttribute("download", filename);
|
||||
|
||||
var clickEvent = new MouseEvent("click", {
|
||||
"view": window,
|
||||
"bubbles": true,
|
||||
"cancelable": false
|
||||
});
|
||||
|
||||
linkElement.dispatchEvent(clickEvent);
|
||||
}).error(function (data, status, header) {
|
||||
|
||||
}));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
12
src/Umbraco.Web.UI.Client/src/views/member/Export.html
Normal file
12
src/Umbraco.Web.UI.Client/src/views/member/Export.html
Normal file
@@ -0,0 +1,12 @@
|
||||
<div class="umb-dialog umb-pane" ng-controller="Umbraco.Editors.Member.ExportController">
|
||||
<div class="umb-dialog-body" auto-scale="90">
|
||||
|
||||
<p class="umb-abstract">
|
||||
<localize key="defaultdialogs_confirmExport">Are you sure you want to export</localize> <strong>{{currentNode.name}}</strong> details?
|
||||
</p>
|
||||
|
||||
<umb-confirm on-confirm="performExport" on-cancel="cancel">
|
||||
</umb-confirm>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -20,13 +20,13 @@
|
||||
<umb-editor-container>
|
||||
|
||||
<umb-tabs-content view="true" class="form-horizontal">
|
||||
<umb-tab id="tab{{tab.id}}" rel="{{tab.id}}" ng-repeat="tab in content.tabs">
|
||||
<umb-tab id="tab{{tab.id}}" rel="{{tab.id}}" ng-repeat="tab in content.tabs">
|
||||
|
||||
<umb-property property="property" ng-repeat="property in tab.properties">
|
||||
<umb-editor model="property"></umb-editor>
|
||||
</umb-property>
|
||||
<umb-property property="property" ng-repeat="property in tab.properties">
|
||||
<umb-editor model="property"></umb-editor>
|
||||
</umb-property>
|
||||
|
||||
</umb-tab>
|
||||
</umb-tab>
|
||||
</umb-tabs-content>
|
||||
|
||||
</umb-editor-container>
|
||||
|
||||
@@ -17,6 +17,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS
|
||||
$scope.page.nameLocked = false;
|
||||
$scope.page.listViewPath = null;
|
||||
$scope.page.saveButtonState = "init";
|
||||
$scope.page.exportButton = "init";
|
||||
$scope.busy = false;
|
||||
|
||||
$scope.page.listViewPath = ($routeParams.page && $routeParams.listName)
|
||||
@@ -171,6 +172,11 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS
|
||||
|
||||
};
|
||||
|
||||
$scope.export = function() {
|
||||
var memberKey = $scope.content.key;
|
||||
memberResource.exportMemberData(memberKey);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Member.EditController", MemberEditController);
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
function MemberExportController($scope, memberResource, treeService, navigationService, editorState, $location, $routeParams) {
|
||||
|
||||
$scope.performExport = function () {
|
||||
//mark it for deletion (used in the UI)
|
||||
$scope.currentNode.loading = true;
|
||||
|
||||
memberResource.exportMemberData($scope.currentNode.id).then(function () {
|
||||
$scope.currentNode.loading = false;
|
||||
|
||||
navigationService.hideMenu();
|
||||
});
|
||||
}
|
||||
|
||||
$scope.cancel = function () {
|
||||
navigationService.hideDialog();
|
||||
};
|
||||
}
|
||||
angular.module("umbraco").controller("Umbraco.Editors.Member.ExportController", MemberExportController);
|
||||
@@ -11,6 +11,7 @@
|
||||
<key alias="changeDocType">Change Document Type</key>
|
||||
<key alias="copy">Copy</key>
|
||||
<key alias="create">Create</key>
|
||||
<key alias="export">Export</key>
|
||||
<key alias="createPackage">Create Package</key>
|
||||
<key alias="createGroup">Create group</key>
|
||||
<key alias="delete">Delete</key>
|
||||
@@ -317,6 +318,7 @@
|
||||
<key alias="nodeNameLinkPicker">Link title</key>
|
||||
<key alias="urlLinkPicker">Link</key>
|
||||
<key alias="anchorInsert">Name</key>
|
||||
<key alias="confirmExport">Export</key>
|
||||
<key alias="assignDomain">Manage hostnames</key>
|
||||
<key alias="closeThisWindow">Close this window</key>
|
||||
<key alias="confirmdelete">Are you sure you want to delete</key>
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<key alias="changeDocType">Change Document Type</key>
|
||||
<key alias="copy">Copy</key>
|
||||
<key alias="create">Create</key>
|
||||
<key alias="export">Export</key>
|
||||
<key alias="createPackage">Create Package</key>
|
||||
<key alias="createGroup">Create group</key>
|
||||
<key alias="delete">Delete</key>
|
||||
@@ -317,7 +318,7 @@
|
||||
<key alias="nodeNameLinkPicker">Link title</key>
|
||||
<key alias="urlLinkPicker">Link</key>
|
||||
<key alias="anchorInsert">Name</key>
|
||||
<key alias="assignDomain">Manage hostnames</key>
|
||||
<key alias="confirmExport">Export</key>
|
||||
<key alias="closeThisWindow">Close this window</key>
|
||||
<key alias="confirmdelete">Are you sure you want to delete</key>
|
||||
<key alias="confirmdisable">Are you sure you want to disable</key>
|
||||
|
||||
@@ -774,5 +774,17 @@ namespace Umbraco.Web.Editors
|
||||
|
||||
return Request.CreateResponse(HttpStatusCode.OK);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Exports member data based on their unique Id
|
||||
/// </summary>
|
||||
/// <param name="key">The unique <see cref="Guid">member identifier</see></param>
|
||||
/// <returns><see cref="HttpResponseMessage"/></returns>
|
||||
[HttpGet]
|
||||
public HttpResponseMessage ExportMemberData(Guid key)
|
||||
{
|
||||
var currentUser = UmbracoContext.Current.Security.CurrentUser;
|
||||
return Services.MemberService.ExportMemberData(key, currentUser);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
using System.Linq;
|
||||
using System.Web.Security;
|
||||
using AutoMapper;
|
||||
using Umbraco.Core;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Services;
|
||||
using Umbraco.Core.Security;
|
||||
@@ -12,10 +11,8 @@ using Umbraco.Web.WebApi.Filters;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
using System.Web.Http;
|
||||
using System.Net;
|
||||
using Umbraco.Core.PropertyEditors;
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using ContentType = System.Net.Mime.ContentType;
|
||||
|
||||
namespace Umbraco.Web.Editors
|
||||
{
|
||||
|
||||
@@ -17,6 +17,7 @@ using Umbraco.Web.Mvc;
|
||||
using Umbraco.Web.WebApi.Filters;
|
||||
using umbraco;
|
||||
using umbraco.BusinessLogic.Actions;
|
||||
using umbraco.cms.Actions;
|
||||
using Umbraco.Web.Models.ContentEditing;
|
||||
using Umbraco.Web.Search;
|
||||
using Constants = Umbraco.Core.Constants;
|
||||
@@ -29,7 +30,7 @@ namespace Umbraco.Web.Trees
|
||||
Constants.Applications.Content,
|
||||
Constants.Applications.Media,
|
||||
Constants.Applications.Members)]
|
||||
[LegacyBaseTree(typeof (loadMembers))]
|
||||
[LegacyBaseTree(typeof(loadMembers))]
|
||||
[Tree(Constants.Applications.Members, Constants.Trees.Members, null, sortOrder: 0)]
|
||||
[PluginController("UmbracoTrees")]
|
||||
[CoreTree]
|
||||
@@ -54,7 +55,7 @@ namespace Umbraco.Web.Trees
|
||||
/// <returns></returns>
|
||||
[HttpQueryStringFilter("queryStrings")]
|
||||
public TreeNode GetTreeNode(string id, FormDataCollection queryStrings)
|
||||
{
|
||||
{
|
||||
var node = GetSingleTreeNode(id, queryStrings);
|
||||
|
||||
//add the tree alias to the node since it is standalone (has no root for which this normally belongs)
|
||||
@@ -116,10 +117,10 @@ namespace Umbraco.Web.Trees
|
||||
"icon-user",
|
||||
false);
|
||||
|
||||
return node;
|
||||
return node;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected override TreeNodeCollection GetTreeNodes(string id, FormDataCollection queryStrings)
|
||||
@@ -173,7 +174,7 @@ namespace Umbraco.Web.Trees
|
||||
createMenuItem.NavigateToRoute("/member/member/edit/-1?create=true");
|
||||
menu.Items.Add(createMenuItem);
|
||||
}
|
||||
|
||||
|
||||
menu.Items.Add<RefreshNode, ActionRefresh>(ui.Text("actions", ActionRefresh.Instance.Alias), true);
|
||||
return menu;
|
||||
}
|
||||
@@ -181,6 +182,12 @@ namespace Umbraco.Web.Trees
|
||||
//add delete option for all members
|
||||
menu.Items.Add<ActionDelete>(ui.Text("actions", ActionDelete.Instance.Alias));
|
||||
|
||||
if (UmbracoContext.Current.Security.CurrentUser.HasAccessToSensitiveData())
|
||||
{
|
||||
menu.Items.Add<ActionExportMember>(ui.Text("actions", ActionExportMember.Instance.Alias));
|
||||
}
|
||||
|
||||
|
||||
return menu;
|
||||
}
|
||||
|
||||
@@ -189,4 +196,4 @@ namespace Umbraco.Web.Trees
|
||||
return _treeSearcher.ExamineSearch(Umbraco, query, UmbracoEntityTypes.Member, pageSize, pageIndex, out totalFound, searchFrom);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
86
src/umbraco.cms/Actions/ActionExportMember.cs
Normal file
86
src/umbraco.cms/Actions/ActionExportMember.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using umbraco.BasePages;
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace umbraco.cms.Actions
|
||||
{
|
||||
public class ActionExportMember: IAction
|
||||
{
|
||||
//create singleton
|
||||
#pragma warning disable 612, 618
|
||||
private static readonly ActionExportMember m_instance = new ActionExportMember();
|
||||
#pragma warning restore 612, 618
|
||||
|
||||
/// <summary>
|
||||
/// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons.
|
||||
/// All Umbraco assemblies should use the singleton instantiation (this.Instance)
|
||||
/// When this applicatio is refactored, this constuctor should be made private.
|
||||
/// </summary>
|
||||
[Obsolete("Use the singleton instantiation instead of a constructor")]
|
||||
public ActionExportMember() { }
|
||||
|
||||
public static ActionExportMember Instance
|
||||
{
|
||||
get { return m_instance; }
|
||||
}
|
||||
|
||||
#region IAction Members
|
||||
|
||||
public char Letter
|
||||
{
|
||||
get
|
||||
{
|
||||
return 'E';
|
||||
}
|
||||
}
|
||||
|
||||
public string JsFunctionName
|
||||
{
|
||||
get
|
||||
{
|
||||
return string.Format("{0}.actionExportMember()", ClientTools.Scripts.GetAppActions);
|
||||
}
|
||||
}
|
||||
|
||||
public string JsSource
|
||||
{
|
||||
get
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public string Alias
|
||||
{
|
||||
get
|
||||
{
|
||||
return "export";
|
||||
}
|
||||
}
|
||||
|
||||
public string Icon
|
||||
{
|
||||
get
|
||||
{
|
||||
return "download-alt";
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowInNotifier
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
public bool CanBePermissionAssigned
|
||||
{
|
||||
get
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -183,6 +183,7 @@
|
||||
<Compile Include="Actions\ActionDisable.cs" />
|
||||
<Compile Include="Actions\ActionEmptyTranscan.cs" />
|
||||
<Compile Include="Actions\ActionExport.cs" />
|
||||
<Compile Include="Actions\ActionExportMember.cs" />
|
||||
<Compile Include="Actions\ActionImport.cs" />
|
||||
<Compile Include="Actions\ActionMove.cs" />
|
||||
<Compile Include="Actions\ActionNew.cs" />
|
||||
|
||||
Reference in New Issue
Block a user