Skip to content

Instantly share code, notes, and snippets.

@mghdotdev
Last active September 1, 2017 16:45
Show Gist options
  • Save mghdotdev/e9b73d224115a97161f9d5a942662d58 to your computer and use it in GitHub Desktop.
Save mghdotdev/e9b73d224115a97161f9d5a942662d58 to your computer and use it in GitHub Desktop.
Date-Picker Custom Batch Report

Date-Picker Custom Batch Report

Items to be assigned

Code Module
content Content
readytheme ReadyTheme
ry_toolbelt PCI Net Tool Belt
store Standard Store Fields
urls CSSUI URLs

Here is a CSV for use in Advanced Search

content,readytheme,ry_toolbelt,store,urls

<mvt:comment>
CONFIG
</mvt:comment>
<mvt:assign name="g.CONFIG:table_name" value="''" />
<mvt:assign name="g.CONFIG:dt_column" value="''" />
<mvt:comment> ================================================================================ </mvt:comment>
<mvt:comment> Set Content Type </mvt:comment>
<mvt:assign name="l.succes" value="miva_output_header( 'Content-Type', 'application/json' )" />
<mvt:miva output="on" compresswhitespace="on" />
<mvt:comment>
Handle initial request
</mvt:comment>
<mvt:if expr="ISNULL g.Offset">
<mvt:assign name="g.Offset" value="0" />
</mvt:if>
<mvt:comment>
Validate date range
</mvt:comment>
<mvt:if expr="(ISNULL g.Start_Date) OR (ISNULL g.End_Date)">
{
"success": 0,
"message": "Error: Missing parameters g.Start_Date or g.End_Date"
"data": ""
}
<mvt:exit />
</mvt:if>
<mvt:comment>
Status MAP
</mvt:comment>
<mvt:assign name="g.status[100]" value="'Processing'" />
<mvt:assign name="g.status[200]" value="'Shipped'" />
<mvt:assign name="g.status[201]" value="'Partially Shipped'" />
<mvt:assign name="g.status[300]" value="'Cancelled'" />
<mvt:assign name="g.status[400]" value="'Backordered'" />
<mvt:assign name="g.status[500]" value="'RMA Issued'" />
<mvt:assign name="g.status[600]" value="'Returned'" />
<mvt:comment> Get Data </mvt:comment>
<mvt:item name="ry_toolbelt" param="assign|g.sql|'SELECT * FROM ' $ MySqlEscape( g.store_table_prefix ) $ MySqlEscape( g.CONFIG:table_name ) $ ' WHERE ' $ MySqlEscape( g.CONFIG:dt_column ) $ ' >= ' $ MySqlEscape( g.Start_Date ) $ ' AND ' $ MySqlEscape( g.CONFIG:dt_column ) $ ' <= ' $ MySqlEscape( g.End_Date ) $ ' ORDER BY ' $ MySqlEscape( g.CONFIG:dt_column ) $ ' ASC LIMIT ' $ MySqlEscape( g.Offset ) $ ', ' $ MySqlEscape( g.Per_Page )" />
<mvt:item name="ry_toolbelt" param="query|g.sql|DataArray" />
<mvt:comment> Load Additional Data </mvt:comment>
<mvt:foreach iterator="data" array="DataArray">
<mvt:comment> ______ CUSTOM CODE HERE ______ </mvt:comment>
</mvt:foreach>
<mvt:comment> Set "Next_Offset" </mvt:comment>
<mvt:assign name="g.Next_Offset" value="(g.Offset + g.Per_Page)" />
<mvt:comment> End Conditional</mvt:comment>
<mvt:if expr="(g.Offset GE g.Per_Page) AND (miva_array_elements( l.settings:DataArray ) EQ 0)">
{
"success": 2,
"message": "Done! Processing your CSV file now.",
"query": "&mvtj:global:sql;"
}
<mvt:else>
{
"success": 1,
"message": "Data loaded for offset &mvtj:global:Offset;. Loading... &mvtj:global:Next_Offset;.",
"query": "&mvtj:global:sql;",
"next_offset": "&mvtj:global:Next_Offset;",
"data": <mvt:do file="g.Module_JSON" name="l.success" value="JSON_Output( l.settings:DataArray )" />
}
</mvt:if>
<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>&nbsp;&mdash;&nbsp;</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>&nbsp;</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>&nbsp;</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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment