diff --git a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js index 46ca65ad40..353fe12cb8 100644 --- a/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js +++ b/src/Umbraco.Web.UI.Client/src/common/resources/member.resource.js @@ -22,8 +22,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { } return { - - getPagedResults: function (memberTypeAlias, options) { + getPagedResults: function(memberTypeAlias, options) { if (memberTypeAlias === 'all-members') { memberTypeAlias = null; @@ -87,7 +86,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { 'Failed to retrieve member paged result'); }, - getListNode: function (listName) { + getListNode: function(listName) { return umbRequestHelper.resourcePromise( $http.get( @@ -119,7 +118,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { * @returns {Promise} resourcePromise object containing the member item. * */ - getByKey: function (key) { + getByKey: function(key) { return umbRequestHelper.resourcePromise( $http.get( @@ -150,7 +149,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { * @returns {Promise} resourcePromise object. * */ - deleteByKey: function (key) { + deleteByKey: function(key) { return umbRequestHelper.resourcePromise( $http.post( umbRequestHelper.getApiUrl( @@ -190,7 +189,7 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { * @returns {Promise} resourcePromise object containing the member scaffold. * */ - getScaffold: function (alias) { + getScaffold: function(alias) { if (alias) { return umbRequestHelper.resourcePromise( @@ -240,42 +239,8 @@ function memberResource($q, $http, umbDataFormatter, umbRequestHelper) { * @returns {Promise} resourcePromise object containing the saved media item. * */ - save: function (member, isNew, files) { + 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) { - - })); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js b/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js index bcfb5df0a7..f99cca9543 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/menuactions.service.js @@ -8,9 +8,18 @@ * @description * Defines the methods that are called when menu items declare only an action to execute */ -function umbracoMenuActions($q, treeService, $location, navigationService, appState) { +function umbracoMenuActions($q, treeService, $location, navigationService, appState, umbRequestHelper) { return { + + "ExportMember": function(args) { + var url = umbRequestHelper.getApiUrl( + "memberApiBaseUrl", + "ExportMemberData", + [{ key: args.entity.id }]); + + umbRequestHelper.downloadFile(url); + }, /** * @ngdoc method @@ -74,4 +83,4 @@ function umbracoMenuActions($q, treeService, $location, navigationService, appSt }; } -angular.module('umbraco.services').factory('umbracoMenuActions', umbracoMenuActions); \ No newline at end of file +angular.module('umbraco.services').factory('umbracoMenuActions', umbracoMenuActions); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 6488ee7515..273d1c55df 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -333,6 +333,112 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ failureCallback.apply(this, [data, status, headers, config]); } }); + }, + + /** + * Downloads a file to the client using AJAX/XHR + * Based on an implementation here: web.student.tuwien.ac.at/~e0427417/jsdownload.html + * See https://stackoverflow.com/a/24129082/694494 + */ + downloadFile : function (httpPath) { + // Use an arraybuffer + $http.get(httpPath, { responseType: 'arraybuffer' }) + .success(function (data, status, headers) { + + var octetStreamMime = 'application/octet-stream'; + var success = false; + + // Get the headers + headers = headers(); + + // Get the filename from the x-filename header or default to "download.bin" + var filename = headers['x-filename'] || 'download.bin'; + + // Determine the content type from the header or default to "application/octet-stream" + var contentType = headers['content-type'] || octetStreamMime; + + try { + // Try using msSaveBlob if supported + console.log("Trying saveBlob method ..."); + var blob = new Blob([data], { type: contentType }); + if (navigator.msSaveBlob) + navigator.msSaveBlob(blob, filename); + else { + // Try using other saveBlob implementations, if available + var saveBlob = navigator.webkitSaveBlob || navigator.mozSaveBlob || navigator.saveBlob; + if (saveBlob === undefined) throw "Not supported"; + saveBlob(blob, filename); + } + console.log("saveBlob succeeded"); + success = true; + } catch (ex) { + console.log("saveBlob method failed with the following exception:"); + console.log(ex); + } + + if (!success) { + // Get the blob url creator + var urlCreator = window.URL || window.webkitURL || window.mozURL || window.msURL; + if (urlCreator) { + // Try to use a download link + var link = document.createElement('a'); + if ('download' in link) { + // Try to simulate a click + try { + // Prepare a blob URL + console.log("Trying download link method with simulated click ..."); + var blob = new Blob([data], { type: contentType }); + var url = urlCreator.createObjectURL(blob); + link.setAttribute('href', url); + + // Set the download attribute (Supported in Chrome 14+ / Firefox 20+) + link.setAttribute("download", filename); + + // Simulate clicking the download link + var event = document.createEvent('MouseEvents'); + event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null); + link.dispatchEvent(event); + console.log("Download link method with simulated click succeeded"); + success = true; + + } catch (ex) { + console.log("Download link method with simulated click failed with the following exception:"); + console.log(ex); + } + } + + if (!success) { + // Fallback to window.location method + try { + // Prepare a blob URL + // Use application/octet-stream when using window.location to force download + console.log("Trying download link method with window.location ..."); + var blob = new Blob([data], { type: octetStreamMime }); + var url = urlCreator.createObjectURL(blob); + window.location = url; + console.log("Download link method with window.location succeeded"); + success = true; + } catch (ex) { + console.log("Download link method with window.location failed with the following exception:"); + console.log(ex); + } + } + + } + } + + if (!success) { + // Fallback to window.open method + console.log("No methods worked for saving the arraybuffer, using last resort window.open"); + window.open(httpPath, '_blank', ''); + } + }) + .error(function (data, status) { + console.log("Request failed with status: " + status); + + // Optionally write the error out to scope + $scope.errorDetails = "Request failed with status: " + status; + }); } }; } diff --git a/src/Umbraco.Web.UI.Client/src/views/member/Export.html b/src/Umbraco.Web.UI.Client/src/views/member/Export.html deleted file mode 100644 index afda77ba89..0000000000 --- a/src/Umbraco.Web.UI.Client/src/views/member/Export.html +++ /dev/null @@ -1,12 +0,0 @@ -
-