Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- <div class="page-section-header">
- <h1 class="list-title">Store Tender Totals</h1>
- </div>
- <act-search-box
- default-type="attendant"
- search="vm.search"
- type="vm.type"
- placeholder="Enter a Store ID"
- type-options="[
- { label: 'Terminal', value : 'terminal' },
- { label: 'Total', value: 'total' },
- { label: 'Attendant', value: 'attendant' }
- ]"
- on-search="vm.getAttendants()">
- </act-search-box>
- <div class="page-section-below-search-box single-width" style="width:27%;">
- <span class="calendarText">Showing totals for</span>
- <act-date-picker model="vm.date" placeholder="Select a date" on-change="vm.getAttendants()">
- </act-date-picker>
- </div>
- <act-expanding-table
- list="vm.attendantNames"
- ng-hide="vm.emptyResult"
- properties="[
- { type: 'attendantName', size: 2, label: 'Attendant Name'},
- { type: 'total', size: 2, label: 'Total', format:'currency'},
- { type: 'runningTotal', size:2, label: 'Running Total', format:'currency'}
- ]"
- allow-selecting="true">
- <div>
- <div class="col-xs-12 form-section-header">
- <h4>Tender Totals</h4>
- </div>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Cash"
- value="$item.tenderTotal.Cash">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Travelers Cash"
- value="$item.tenderTotal.TC">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="UO Dollars"
- value="$item.tenderTotal.UOD">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Master Card"
- value="$item.tenderTotal.MC">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Visa"
- value="$item.tenderTotal.VI">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="AMEX"
- value="$item.tenderTotal.AX">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Discover"
- value="$item.tenderTotal.DI">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="JCB Card"
- value="$item.tenderTotal.JC">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Diners Club"
- value="$item.tenderTotal.DC">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Universal Pay"
- value="$item.tenderTotal.UOP">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Gringott Bucks"
- value="$item.tenderTotal.GN">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Gift Card"
- value="$item.tenderTotal.UOGC">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Loews Hotel Charge"
- value="$item.tenderTotal.HOTEL">
- </act-field>
- <act-field
- format="currency"
- class="col-xs-4"
- label="Guest Vouch"
- value="$item.tenderTotal.NCTNCG">
- </act-field>
- </div>
- </act-expanding-table>
- <act-total-panel ng-if="vm.totals" class="col-md-4 store-total-row">
- <line-item>
- <label>Total</label>
- <value>{{vm.totals | currency : "$"}}</value>
- </line-item>
- </act-total-panel>
- <act-error-message ng-show="vm.errorMessage">{{ vm.errorMessage }}</act-error-message>
- import { digest, showLoader } from 'act/services/events';
- import 'act/components';
- import Searcher from 'act/services/lists/searcher';
- import * as moment from 'moment';
- import * as api from '../services/totals';
- import {header, dev} from 'act/services/logger';
- import {goToError} from 'act/services/controller-helpers';
- import '../components/store-total';
- const defaultStartDate = moment().startOf('day');
- export default class StoreTotalsController {
- constructor() {
- this.attendantNames = [];
- this.emptyResult = true;
- this.totals = 0;//totals variable for the summed values in the Total column
- this.runningTotal = 0;
- }
- getAttendants() {
- showLoader('Searching');
- const baseUrl = '/src/areas/store-totals/services/tender-total-data.json';
- const getStores = new Request(baseUrl, {
- method: 'GET'
- });
- fetch(getStores).then(function(response){
- return response.json();
- }).then(resp => {
- if (!(resp[0] && resp[0].error)) {
- this.attendantNames = resp.stores[0].attendants;
- this.attendantNames.forEach((attendant, index) => {
- this.totals += attendant.total;
- })
- this.emptyResult = false;
- this.errorMessage = null;
- } else {
- this.errorMessage = resp[0].error.name;
- }
- digest();
- //this.calculateRunningTotals();
- showLoader(false);
- });
- }
- /*calculateRunningTotals(){
- console.log("Sorter clicked");
- var attendantTotalCell = 0;
- var total = 0;
- var totalCell="";
- var totalsCells = document.querySelectorAll("td:nth-child(3)");
- totalsCells.forEach(function(cell, index){
- cell.classList.remove('empty');
- totalCell = cell.innerText;
- attendantTotalCell = totalCell.replace(/[^0-9-.]/g, '');
- total = parseInt(attendantTotalCell) + parseInt(total);
- if(cell.nextElementSibling){
- cell.nextElementSibling.innerHTML = '$' + total.toFixed(2).replace(/d(?=(d{3})+.)/g, '$&,');
- }
- })
- }*/
- searchIfReady() {
- if (this.search && this.date && this.date.isValid()) {
- this.getSearch();
- }
- }
- updateDate(date) {
- this.date = moment(date).startOf('day');
- this.searchIfReady();
- }
- }
- StoreTotalsController.$inject = ['$stateParams'];
- import app from 'act/app';
- import * as table from 'act/components/table';
- import './expanding-table.styles.less';
- import * as $ from 'jquery';
- const expander = `
- <td class="col-xs-1 text-center link" ng-click="$event.stopPropagation()">
- <i class="fa fa-chevron-{{$item.expanded ? 'up' : 'down'}}" ng-click="$item.expanded = !$item.expanded"></i>
- </td>
- `;
- const fakeRows = `
- <tbody ng-if="!$table.list.length">
- <tr class="dummy-data" ng-repeat="dummy in $table.fakeRows">
- ${expander}
- <td ng-repeat="property in $table.properties track by property.type">
- dummy
- </td>
- </tr>
- </tbody>
- `;
- const header = `
- <thead>
- <th>
- </th>
- <th ng-repeat="property in $table.properties track by property.type"
- class="col-xs-{{property.size}} clickable" ng-click="$table.sorter.changeType(property.type)">
- {{property.label}}
- <i class="fa fa-caret-{{$table.sorter.directionFor(property.type)}} fa-lg"></i>
- </th>
- </thead>
- `;
- const rows = ({ row, ngRepeat, cell }) => `
- <tbody ng-if="$table.list.length">
- <tr class="clickable"
- ng-repeat-start="${ngRepeat}"
- ng-click="$item.expanded = !$item.expanded"
- ng-init="$item.expanded = false">
- ${row({ cell })}
- </tr>
- <tr class="expanded-row" ng-show="$item.expanded"
- ng-repeat-end>
- <td colspan="12">
- <div expanded-placeholder></div>
- </td>
- </tr>
- </tbody>
- `;
- const row = ({ cell }) => `
- ${expander}
- ${cell}
- `;
- app.directive('actExpandingTable', ['$compile', $compile =>
- table.defaultDirective({
- link: function($scope, $element, $attrs, $tables, $transclude) {
- const $el = $(table.generateTemplate({ header, rows, row, fakeRows }));
- $scope.vm = $scope.$parent.vm;
- $transclude($scope, content => {
- if (content.length > 1) {
- $el.find('[expanded-placeholder]').replaceWith(content);
- } else {
- throw new Error('Expanding table requires transcluded content to show when expanded!');
- }
- $compile($el)($scope, v => $element.append(v));
- });
- },
- })
- ]);
- import './table.styles.less';
- import * as lists from 'act/services/lists';
- import {filter} from 'lodash';
- import './formatters';
- export const defaultTemplates = {
- ngRepeat: `$item in $table.list
- | orderBy:$table.sorter.type:$table.sorter.reverse
- | limitTo:$table.paginator.pageSize:$table.paginator.offset
- | filter:$table.filter track by $index`,
- wrapper: ({ header, content, footer }) => `
- <div>
- <table class="table table-hover">
- ${header}
- ${content}
- </table>
- ${footer}
- </div>
- `,
- header: `
- <thead>
- <th class="col-xs-1" ng-if="$table.allowSelecting">
- <span>
- <input id="locationCheckAll" ng-checked="$table.selector.all" type="checkbox" ng-click="$table.selector.toggleAll($table.list)">
- <label for="locationCheckAll" style="display:inline-block"></label>
- </span>
- </th>
- <th ng-repeat="property in $table.properties track by property.type"
- ng-if="property.type"
- class="col-xs-{{property.size}}"
- ng-class="{ 'clickable': !property.disableSort, 'normal': property.disableSort }"
- ng-click="!property.disableSort && $table.sorter.changeType(property.type)">
- {{property.label}}
- <i class="fa fa-caret-{{$table.sorter.directionFor(property.type)}} fa-lg" ng-hide="property.disableSort"></i>
- </th>
- </thead>
- `,
- fakeRows: `
- <tbody ng-if="!$table.list.length">
- <tr class="dummy-data" ng-repeat="dummy in $table.fakeRows">
- <td class="col-xs-1" ng-click="$event.stopPropagation()" ng-if="$table.allowSelecting">
- <span>
- <input ng-checked="$item.selected" id="$item-{{$item._id}}" type="checkbox">
- <label for="$item-{{$item._id}}" style="display:inline-block"></label>
- </span>
- </td>
- <td ng-repeat="property in $table.properties track by property.type"
- ng-if="property.type">
- dummy
- </td>
- </tr>
- </tbody>
- `,
- rows: ({ ngRepeat, row, cell }) => `
- <tbody ng-if="$table.list.length">
- <tr class="clickable"
- ng-repeat="${ngRepeat}"
- ng-click="$table.onClick({ $item: $item })">
- ${row({ cell })}
- </tr>
- </tbody>
- `,
- row: ({ cell }) => `
- <td class="col-xs-1" ng-click="$event.stopPropagation()" ng-if="$table.allowSelecting">
- <span>
- <input ng-checked="$item.selected" id="$item-{{$item._id}}" type="checkbox" ng-click="$table.selector.toggle($item)">
- <label for="$item-{{$item._id}}" style="display:inline-block"></label>
- </span>
- </td>
- ${cell}
- `,
- cell: `
- <td ng-if="property.type" ng-repeat="property in $table.properties track by property.type"
- act-placeholder
- ng-class="{ 'empty': $item[property.type] == null || $item[property.type].length === 0 }">
- <span ng-if="$item[property.type] != null">
- {{$item[property.type] | picker:property.format}}
- </span>
- <span ng-if="$item[property.type] == null">
- N/A
- </span>
- <span ng-if="$item[property.type].length === 0">
- N/A
- </span>
- </td>
- `,
- footer: `
- <act-paginator ng-if="$table.length() > $table.paginator.pageSize"
- total-count="$table.length()"
- paginator="$table.paginator"
- ></act-paginator>
- `,
- };
- export const generateTemplate = ({
- wrapper = defaultTemplates.wrapper,
- header = defaultTemplates.header,
- fakeRows = defaultTemplates.fakeRows,
- rows = defaultTemplates.rows,
- row = defaultTemplates.row,
- footer = defaultTemplates.footer,
- ngRepeat = defaultTemplates.ngRepeat,
- cell = defaultTemplates.cell
- } = {}) => wrapper({
- header,
- footer,
- content: `
- ${rows({ row, ngRepeat, cell })}
- ${fakeRows}
- `
- });
- export const defaultScope = {
- list: '=',
- sorter: '=?',
- paginator: '=?',
- selector: '=?',
- searcher: '=?',
- properties: '=',
- onClick: '&',
- allowSelecting: '=?',
- filter: '=?',
- defaultSortType: '@',
- defaultSortReverse: '=?',
- fakeRowCount: '@'
- };
- export const defaultController = class DefaultTableController {
- constructor($scope) {
- this.filter = this.filter || (_ => true);
- this.$scope = $scope;
- this.$filtered = [];
- }
- $onInit() {
- this.searcher = this.searcher || {};
- this.paginator = this.searcher.paginator || this.paginator || new lists.Paginator();
- this.sorter = this.searcher.sorter || this.sorter || new lists.Sorter();
- this.sorter.type = this.defaultSortType || this.properties[0].type;
- this.sorter.reverse = this.defaultSortReverse || false;
- this.selector = this.searcher.selector || this.selector || new lists.Selector(() => this.filtered.length);
- this.fakeRowCount = this.fakeRowCount || 25;
- this.fakeRows = [];
- for (let i = 0; i < this.fakeRowCount; i++) { this.fakeRows.push(i); }
- this.$scope.$watch('$table.list', () => this.updateFilter());
- this.$scope.$watch('$table.filter', () => this.updateFilter());
- }
- updateFilter() {
- this.filtered = filter(this.list, this.filter);
- this.calculateRunningTotals();
- }
- calculateRunningTotals(){
- console.log("Calculate running totals was called by the watch function");
- var attendantTotalCell = 0;
- var total = 0;
- var totalCell="";
- var totalsCells = document.querySelectorAll("td:nth-child(3)");
- totalsCells.forEach(function(cell, index){
- totalCell = cell.innerText;
- attendantTotalCell = totalCell.replace(/[^0-9-.]/g, '');
- total = parseInt(attendantTotalCell) + parseInt(total);
- if(cell.nextElementSibling){
- cell.nextElementSibling.innerHTML = '$' + total.toFixed(2).replace(/d(?=(d{3})+.)/g, '$&,');
- }
- })
- }
- length() {
- return this.paginator.virtualized ? this.paginator.totalCount : this.filtered.length;
- }
- };
- defaultController.$inject = ['$scope'];
- export const defaultLink = ({ $compile, template }) => function($scope, $element, $attrs, $ctrls, $transclude) {
- /**
- * hello fellow traveler
- * you might be wondering wtf is going on here
- *
- * let me explain
- *
- * tables are kind of noisey when it comes to boilerplate.
- * pretty much all of the tables in this app need to support sorting and pagination.
- * but they're not all super identical.
- *
- * sometimes we show images in the table cells instead of data, or otherwise custom content.
- * we can capture this in some way through the 'properties' argument passed into the table,
- * but if we only do something on one page (such as the aforementioned images instead of data),
- * it seems like a waste to put it into the component itself.
- *
- * so instead, we can transclude the custom content into the table template.
- * however! necessarily, the custom table row must be able to access row data.
- * by default, transcluded content can not do this.
- *
- * but, we can specify whatever scope we want for the transcluded content.
- * you probably usually shouldn't do this.
- * but it lets us do cool things like this, where we can pass in a template and it 'magically'
- * can access $item, $table, etc. despite being transcluded content.
- */
- // we need to start by reading our template as DOM nodes
- const templateEl = $(template);
- // in order for 'normal' bindings (e.g not referencing $item, $table, etc.)
- // we do a small hack and put the parent scope's vm on this scope. since we ALWAYS
- // controllerAs vm, this will always work.
- $scope.vm = $scope.$parent.vm;
- // kick off transclusion with the TABLE's scope (so we can access row data)
- $transclude($scope, content => {
- // only transclude if we passed in custom row data
- if (content.length > 1) {
- templateEl.find('[act-placeholder]').replaceWith(content);
- }
- // Compile our template nodes, and then append it to our linked element.
- // Note that we are doing custom compilation, and we must put the transcluded template
- // in before we compile, or angular's ng-repeat will be confused
- $compile(templateEl)($scope, v => $element.empty().append(v));
- });
- };
- export const defaultDirective = ({
- $compile,
- template,
- scope = defaultScope,
- controller = defaultController,
- link = defaultLink({ $compile, template }),
- }) => ({
- scope,
- controller,
- link,
- restrict: 'E',
- bindToController: true,
- controllerAs: '$table',
- transclude: true,
- });
- export default class Sorter {
- constructor({ type = 'name',reverse = false, onChanged = () => {} } = {}) {
- this.type = type;
- this.reverse = reverse;
- this.onChanged = onChanged;
- }
- changeType(type) {
- if (this.type !== type) {
- this.type = type;
- this.reverse = false;
- } else {
- this.reverse = !this.reverse;
- }
- this.onChanged('sort');
- this.calculateRunningTotals();
- }
- changeReverse(reverse) {
- if (reverse !== this.reverse) {
- this.reverse = reverse;
- this.onChanged('reverse');
- }
- }
- directionFor(type) {
- if (this.type !== type) return '';
- return this.reverse ? 'up' : 'down';
- }
- }
Add Comment
Please, Sign In to add comment