|
<mvt:comment> |
|
Run on Itteration |
|
</mvt:comment> |
|
<mvt:if expr="g.ajax EQ 1"> |
|
<mvt:item name="content" /> |
|
<mvt:exit /> |
|
</mvt:if> |
|
|
|
<html> |
|
<head> |
|
<mvt:if expr="NOT ISNULL l.settings:page:title"> |
|
<title>&mvt:page:title;</title> |
|
<mvt:else> |
|
<title>&mvt:store:name;: &mvt:page:name;</title> |
|
</mvt:if> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/7.0.0/normalize.min.css" /> |
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-moment-picker/0.10.1/angular-moment-picker.min.css" /> |
|
<style> |
|
/* #1EABBD */ |
|
/* #F7394A */ |
|
.message,.or{font-style:italic}*{box-sizing:border-box}body,html{margin:0;padding:0}body{font-size:100%;font-family:Arial,Helvetica,sans-serif;line-height:1.5}main{padding:2rem 1rem}p{margin:0 0 1rem}input[type=text]{height:3em;line-height:3;border:1px solid #dfdfdf;padding:0 .5rem;border-radius:.25rem}label,legend{display:block;font-weight:700;font-size:.875rem;cursor:pointer;margin-bottom:.125rem}.inline,label.inline{display:inline}label.inline{font-weight:400;font-size:inherit;margin:0}.or,.small{font-size:.75rem}hr{border-style:solid;border-color:#dfdfdf;margin:0 0 1.5rem}button[disabled]{cursor:not-allowed;opacity:.5}.cta,a{cursor:pointer}a{color:#1EABBD;text-decoration:underline}datepicker{float:none}.align-right{text-align:right}.form-row{margin-bottom:1.5rem}.inline-block,.or{display:inline-block}.nm{margin:0}.bar{width:100%;background-color:#1EABBD;padding:.25rem 1rem;color:#fff}.or{color:#999;margin:0 .5rem}.cta{height:3em;line-height:3;color:#fff;background-color:#F7394A;border:1px solid #F7394A;border-radius:.25rem;min-width:6em;max-width:100%;padding:0 .5rem;text-transform:uppercase}.message{padding:.5rem 1rem;border-radius:.25rem;font-size:.875rem}.message:first-child{margin-top:0}.message.error{background-color:#FF6B59;color:#fff}.message.success{background-color:#27ae60;color:#fff}.message.info{background-color:#f7f7f7;color:#333} |
|
.moment-picker .moment-picker-container { |
|
min-width: 30em; |
|
} |
|
</style> |
|
</head> |
|
<body ng-app="BatchReport" ng-controller="BatchReportController" ng-cloak> |
|
|
|
<header class="bar"> |
|
<h2 class="nm">&mvt:page:name;</h2> |
|
</header> |
|
|
|
<main> |
|
<form name="batchReportForm" ng-show="(running === 0)"> |
|
<p class="message info"> |
|
Please select a {{ ::dateRangeType }} date range. |
|
</p> |
|
|
|
<section class="form-row"> |
|
<div class="inline-block"> |
|
<label for="startDate">Start:</label> |
|
<input moment-picker="formattedStartDate" ng-model="startDate" format="{{ datePickerSettings.format }}" locale="en" today="true" type="text" id="startDate" required /> |
|
</div> |
|
<span> — </span> |
|
<div class="inline-block"> |
|
<label for="endDate">End:</label> |
|
<input moment-picker="formattedEndDate" ng-model="endDate" format="{{ datePickerSettings.format }}" locale="en" today="true" min-date="startDate" type="text" id="endDate" required /> |
|
</div> |
|
<span> </span> |
|
<div class="inline-block"> |
|
<a ng-click="clear();" class="small">Clear</a> |
|
</div> |
|
</section> |
|
|
|
<hr> |
|
<section class="form-row"> |
|
<button class="cta" ng-click="run();" ng-disabled="batchReportForm.$invalid">Run</button> |
|
</section> |
|
</form> |
|
<div ng-show="(running === 1) || (running === 2)"> |
|
<h4 ng-show="(running === 1)">Loading...</h4> |
|
<p class="message" ng-show="lastResponse.message !== undefined" ng-class="{ 'info': (lastResponse.success === 1), 'success': (lastResponse.success === 2), 'error': (lastResponse.success === 0) }"> |
|
{{ lastResponse.message }} |
|
</p> |
|
<div ng-if="(running === 2)"> |
|
<hr> |
|
<button class="cta" ng-csv="csv.rows" quote-strings="true" csv-header="getCSVHeader(reportMode);" filename="{{ ::csv.filename }}">Download</button> |
|
<span> </span> |
|
<div class="inline-block"> |
|
<a ng-click="reset();" class="small">Reset</a> |
|
</div> |
|
</div> |
|
</div> |
|
</main> |
|
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-moment-picker/0.10.1/angular-moment-picker.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular-sanitize.min.js"></script> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/ng-csv/0.3.6/ng-csv.min.js"></script> |
|
<script> |
|
|
|
// ==================== CONFIG ==================== // |
|
var CONFIG = { |
|
url: "&mvtj:urls:_self:auto;", |
|
defaultFormData: { |
|
"AJAX": "1", |
|
"Per_Page": "100", |
|
"Offset": "0", |
|
"Store_Code": "&mvtj:global:Store_Code;", |
|
"Function": "&mvtj:global:Function;", |
|
"Module_Code": "&mvtj:global:Module_Code;", |
|
"Report_Code": "&mvtj:global:Report_Code;", |
|
"Session_Type": "&mvtj:global:Session_Type;", |
|
"Session_ID": "&mvtj:global:Session_ID;" |
|
}, |
|
dateRangeType: '', |
|
datePickerSettings: { |
|
format: 'MM/DD/YYYY hh:mm A' |
|
}, |
|
csvHeader: [ |
|
|
|
/* ______ CUSTOM CODE HERE ______ */ |
|
/** |
|
* Define your CSV Header Row here. |
|
* The format is an array of strings. Index 0 = Column A within an Excel file. |
|
* Columns can be left blank by adding an empty string value. |
|
*/ |
|
|
|
], |
|
done: function(DataArray, $scope, $filter) { |
|
// Define ROWS |
|
var ROWS = []; |
|
|
|
/* ______ CUSTOM CODE HERE ______ */ |
|
/** |
|
* Write your "ROW" building script here. |
|
* Data from all itterations will be contained within the "DataArray" variable. |
|
* |
|
* The format for a single row index is: |
|
``` |
|
{ |
|
a: 'This is column 1.', |
|
b: 'This is column 2.', |
|
c: 'The letter used within this object directly relates to the position of the "csvHeader" array within the CONFIG.' |
|
d: '', |
|
e: 'You can use empty strings to skip columns/leave them blank like I did in "d".' |
|
f: 'Reference documentation for ng-csv.js library can be found here: https://github.com/asafdav/ng-csv' |
|
} |
|
``` |
|
* Once you are done building your single row object, push it into ROWS. |
|
* The return statement at the end of this function will expose your data to the angular scope and build your CSV file. |
|
*/ |
|
|
|
// Return ROWS |
|
return ROWS; |
|
} |
|
}; |
|
|
|
// ================================================================================ // |
|
|
|
// Resize Popup Window |
|
window.resizeTo( 800, 900 ); |
|
|
|
// ================================================================================ // |
|
|
|
// -------------------- HELPER FUNCTIONS -------------------- // |
|
function objGet(n,t){return t.split(".").reduce(function(n,t){return void 0===n||null===n?n:n[t]},n)}; |
|
"function"!=typeof Object.assign&&(Object.assign=function(n){"use strict";if(null==n)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(n),r=1;r<arguments.length;r++){var e=arguments[r];if(null!=e)for(var o in e)Object.prototype.hasOwnProperty.call(e,o)&&(t[o]=e[o])}return t}); |
|
|
|
// -------------------- BOOT -------------------- // |
|
var app = angular.module('BatchReport', [ |
|
'moment-picker', |
|
'ngSanitize', |
|
'ngCsv' |
|
]); |
|
app.config(['momentPickerProvider', function (momentPickerProvider) { |
|
momentPickerProvider.options({ |
|
minutesStep: 1 |
|
}); |
|
}]); |
|
|
|
// -------------------- FILTERS -------------------- // |
|
app.filter('epoch', function() { |
|
return function(str) { |
|
return (new Date(str).getTime() / 1000); |
|
} |
|
}); |
|
|
|
// -------------------- CONTROLLER -------------------- // |
|
app.controller('BatchReportController', ['$scope', '$http', '$filter', function($scope, $http, $filter) { |
|
|
|
// ---- Define Scope Variables ---- // |
|
$scope.dateRangeType = CONFIG.dateRangeType; |
|
$scope.datePickerSettings = CONFIG.datePickerSettings; |
|
$scope.running = 0; |
|
$scope.lastResponse = undefined; |
|
$scope.csv = { |
|
filename: (CONFIG.defaultFormData.Report_Code + '.csv'), |
|
header: CONFIG.csvHeader, |
|
rows: [] |
|
}; |
|
|
|
// ---- Public Methods ---- // |
|
$scope.clear = function() { |
|
$scope.startDate = ''; |
|
$scope.endDate = ''; |
|
}; |
|
$scope.reset = function() { |
|
$scope.running = 0; |
|
$scope.csv.rows = []; |
|
DataArray = []; |
|
}; |
|
$scope.run = function() { |
|
|
|
// Build request form data |
|
var formData = { |
|
'Start_Date': $filter('epoch')($scope.startDate), |
|
'End_Date': $filter('epoch')($scope.endDate) |
|
}; |
|
|
|
// Merge with default form data |
|
Object.assign(formData, CONFIG.defaultFormData); |
|
|
|
// Show "running" template |
|
$scope.running = 1; |
|
|
|
// Make first request |
|
_makeRequest(formData); |
|
|
|
}; |
|
$scope.getCSVHeader = function() { |
|
return CONFIG.csvHeader; |
|
}; |
|
|
|
// ---- Private Methods ---- // |
|
var DataArray = []; |
|
var _makeRequest = function(formData, nextOffset) { |
|
// Add "nextOffset" variable to "formData" |
|
formData = formData || {}; |
|
formData['Offset'] = nextOffset; |
|
|
|
// Make request |
|
$http({ |
|
method: 'POST', |
|
url: CONFIG.url, |
|
params: formData, |
|
headers: { |
|
'Content-Type': 'application/x-www-form-urlencoded' |
|
} |
|
}).then(function(response) { |
|
_itteration(response, formData); |
|
}); |
|
}; |
|
_itteration = function(response, formData) { |
|
var lastResponse = response.data; |
|
|
|
// Handle errors/successes |
|
if (lastResponse.success === 1) { |
|
DataArray = DataArray.concat(lastResponse.data); |
|
_makeRequest( formData, lastResponse.next_offset ); |
|
} |
|
else if (lastResponse.success === 0) { |
|
console.error(lastResponse.message); |
|
} |
|
else { |
|
_buildCSV(); |
|
} |
|
|
|
// Expose the lastResponse data to the template |
|
$scope.lastResponse = lastResponse; |
|
}; |
|
_buildCSV = function() { |
|
$scope.csv.rows = CONFIG.done(DataArray, $scope, $filter); |
|
$scope.running = 2; |
|
}; |
|
|
|
}]); |
|
|
|
</script> |
|
</body> |
|
</html> |