From bee064ad82ec2264fb15d7d760faffbe76a252ba Mon Sep 17 00:00:00 2001 From: Bill Erickson Date: Fri, 4 Apr 2014 14:19:35 -0400 Subject: [PATCH] web staff : grid CSV file download Signed-off-by: Bill Erickson --- Open-ILS/src/templates/staff/parts/t_autogrid.tt2 | 7 ++- Open-ILS/web/js/ui/default/staff/services/grid.js | 75 +++++++++++++++++++++-- Open-ILS/web/js/ui/default/staff/test/app.js | 5 +- 3 files changed, 81 insertions(+), 6 deletions(-) diff --git a/Open-ILS/src/templates/staff/parts/t_autogrid.tt2 b/Open-ILS/src/templates/staff/parts/t_autogrid.tt2 index a9726a75b3..f5e4868a5a 100644 --- a/Open-ILS/src/templates/staff/parts/t_autogrid.tt2 +++ b/Open-ILS/src/templates/staff/parts/t_autogrid.tt2 @@ -97,6 +97,11 @@ [% l('Hide All Columns') %] +
  • + + [% l('Download CSV') %] +
  • - {{grid.dataProvider.itemFieldValue(item, col) | egGridvalueFilter:col}} + {{grid.dataProvider.itemFieldValue(item, col) | egGridValueFilter:col}} diff --git a/Open-ILS/web/js/ui/default/staff/services/grid.js b/Open-ILS/web/js/ui/default/staff/services/grid.js index 034c521b24..c9ef91b7e2 100644 --- a/Open-ILS/web/js/ui/default/staff/services/grid.js +++ b/Open-ILS/web/js/ui/default/staff/services/grid.js @@ -54,8 +54,10 @@ angular.module('egGridMod', controller : [ '$scope','egIDL','egAuth','egNet', 'egGridFlatDataProvider','egGridColumnsProvider', + '$filter','$window', function($scope, egIDL, egAuth, egNet, - egGridFlatDataProvider, egGridColumnsProvider) { + egGridFlatDataProvider, egGridColumnsProvider, + $filter, $window) { var grid = this; @@ -313,6 +315,7 @@ angular.module('egGridMod', grid.collect(); } + // show / hide the grid configuration row grid.toggleConfDisplay = function() { if (grid.showGridConf) { grid.showGridConf = false; @@ -323,6 +326,8 @@ angular.module('egGridMod', } } + // called when a dragged column is dropped onto itself + // or any other column grid.onColumnDrop = function(target) { if (angular.isUndefined(target)) return; if (target == grid.dragColumn) return; @@ -347,6 +352,68 @@ angular.module('egGridMod', $scope.$apply(); } + // prepares a string for inclusion within a CSV document + // by escaping commas and quotes and removing newlines. + grid.csvDatum = function(str) { + str = ''+str; + if (!str) return ''; + str = str.replace(/\n/g, ''); + if (str.match(/\,/) || str.match(/"/)) { + str = str.replace(/"/g, '""'); + str = '"' + str + '"'; + } + return str; + } + + // sets the download file name and inserts the current CSV + // into a Blob URL for browser download. + grid.generateCSVExportURL = function() { + + // let the file name describe the grid + grid.csvExportFileName = + (grid.mainLabel || grid.persistKey || 'eg_grid_data') + .replace(/\s+/g, '_') + '_' + grid.page(); + + // toss the CSV into a Blob and update the export URL + var csv = grid.generateCSV(); + var blob = new Blob([csv], {type : 'text/plain'}); + grid.csvExportURL = + ($window.URL || $window.webkitURL).createObjectURL(blob); + } + + // generates CSV for the currently visible grid contents + grid.generateCSV = function() { + var csvStr = ''; + var colCount = grid.columnsProvider.columns.length; + + // columns + angular.forEach(grid.columnsProvider.columns, + function(col, idx) { + csvStr += grid.csvDatum(col.name); + if (idx < colCount -1) csvStr += ','; + } + ); + + csvStr += "\n"; + + // items + angular.forEach(grid.items, function(item) { + angular.forEach(grid.columnsProvider.columns, + function(col, idx) { + // bare value + var val = grid.dataProvider.itemFieldValue(item, col); + // filtered value (dates, etc.) + val = $filter('egGridValueFilter')(val, col); + csvStr += grid.csvDatum(val); + if (idx < colCount -1) csvStr += ','; + } + ); + csvStr += "\n"; + }); + + return csvStr; + } + // asks the dataProvider for a page of data grid.collect = function() { grid.items = []; @@ -695,9 +762,9 @@ angular.module('egGridMod', * value. (Though we could manually translate instead..) * Others likely to follow... */ -.filter('egGridvalueFilter', ['$filter', function($filter) { - return function(value, item) { - switch(item.datatype) { +.filter('egGridValueFilter', ['$filter', function($filter) { + return function(value, column) { + switch(column.datatype) { case 'bool': // Browser will translate true/false for us return Boolean(value == 't'); diff --git a/Open-ILS/web/js/ui/default/staff/test/app.js b/Open-ILS/web/js/ui/default/staff/test/app.js index 27e6fe1e71..6d9f7e3e73 100644 --- a/Open-ILS/web/js/ui/default/staff/test/app.js +++ b/Open-ILS/web/js/ui/default/staff/test/app.js @@ -1,9 +1,12 @@ angular.module('egTestApp', ['ngRoute', 'ui.bootstrap', 'egCoreMod', 'egUiMod', 'egGridMod']) -.config(function($routeProvider, $locationProvider) { +.config(function($routeProvider, $locationProvider, $compileProvider) { $locationProvider.html5Mode(true); + // necessary for file download via Blob URLs (e.g. grid CSV export) + $compileProvider.aHrefSanitizationWhitelist(/^\s*(blob):/); + var resolver = {delay : function(egStartup) { return egStartup.go() }}; $routeProvider.when('/test/autogrid', { -- 2.11.0