JSFiddle - React, Tailwind, and code Playground

by flynn_inc

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/1.4.1/jspdf.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf-autotable/2.3.4/jspdf.plugin.autotable.min.js"></script>
<!-- component template -->
<script type="text/x-template" id="grid-template">
  <table class='aus-boxshadow'>
    <thead>
      <tr>
        <th v-for="key in columns"
          @click="sortBy(key.field)"
          :class="{ active: sortKey == key.field }">
          {{ key.headerName | capitalize }}
          <span class="arrow" :class="sortOrders[key.field] > 0 ? 'asc' : 'dsc'">
          </span>
        </th>
      </tr>
    </thead>
    <tbody>
      <tr v-for="entry in filteredData">
        <td v-for="key in columns">
          {{entry[key.field]}}
        </td>
      </tr>
    </tbody>
  </table>
</script>

<!-- demo root element -->
<div id="demo">

    Search <input name="query" v-model="searchQuery">
    Column <select name="searchColumn1" v-model="searchColumn" >
            <option value=''>All</option>          
            <option v-for="gridColumn in gridColumns" value='{{ gridColumn.field }}'>
              {{ gridColumn.headerName }}
            </option>
           </select>

      <demo-grid
        :data="gridData"
        :columns="gridColumns"
        :filter-key="searchQuery"
        :filter-column="searchColumn">
      </demo-grid>

      <button @click="exportPdf">Export PDF</button>
      
      <div id="Timer0"></div>  
      <div id="Timer1"></div>
      <div id="Timer2"></div>
      <div id="Timer3"></div>
      <div id="Timer4"></div>  
      <div id="Timer5"></div>  
      <div id="myBar">0%</div>

      <div id="Timer6"></div>  
      <br />
      <br />
      
</div>

CSS

body {
  font-family: Helvetica Neue, Arial, sans-serif;
  font-size: 14px; 
  color: #444;
}

table {
  border: 2px solid #42b983;
  border-radius: 3px;
  background-color: #fff;
}

th {
  background-color: #42b983;
  color: rgba(255,255,255,0.66);
  cursor: pointer;
  -webkit-user-select: none;
  -moz-user-select: none;
  -ms-user-select: none;
  user-select: none;
}

td {
  background-color: #f9f9f9;
}

th, td {
  min-width: 120px;
  padding: 10px 20px;
}

th.active {
  color: #fff;
}

th.active .arrow {
  opacity: 1;
}

.arrow {
  display: inline-block;
  vertical-align: middle;
  width: 0;
  height: 0;
  margin-left: 5px;
  opacity: 0.66;
}

.arrow.asc {
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-bottom: 4px solid #fff;
}

.arrow.dsc {
  border-left: 4px solid transparent;
  border-right: 4px solid transparent;
  border-top: 4px solid #fff;
}

.aus-boxshadow {
    box-shadow: 10px 10px 5px grey;
}

tbody tr:nth-child(odd) td {
   background-color: #DCDCDC;
}

#myProgress {
  width: 100%;
  background-color: #ddd;
}

#myBar {
  width: 10%;
  height: 30px;
  background-color: #4CAF50;
  text-align: center;
  line-height: 30px;
  color: white;
}

/*
ALTER PROCEDURE [dbo].[spGetLoads]	
AS
BEGIN

	--Setup configuration required once for calling web services from a stored procedure
		--EXEC sp_configure 'show advanced options', 1; 
		--RECONFIGURE;
		--EXEC sp_configure 'Ole Automation Procedures', 1;  
		--RECONFIGURE;
		--EXEC sp_configure 'show advanced options';
		--EXEC sp_configure 'Ole Automation Procedures'

					
	IF ( OBJECT_ID('tempdb..#TTable') IS NOT NULL ) BEGIN DROP TABLE #TTable; END
	
	CREATE TABLE #TTable 
	(
		[LOAD_ID] varchar(32), 
		[PICKUP_DATE] varchar(32), 
		[DELIVERY_DATE] varchar(32), 
		[ORIGIN] varchar(64), 
		[DESTINATION] varchar(64), 
		[MILES] varchar(32), 
		[WEIGHT] varchar(32),...

JavaScript

// register the grid component
        Vue.component('demo-grid', {
          template: '#grid-template',
          props: {
            data: Array,
            columns: Array,
            filterKey: String,
            filterColumn: String
          },
          data: function() {
            var sortOrders = {}
            this.columns.forEach(function(key) {
              sortOrders[key.field] = 1
            })
            return {
              sortKey: '',
              sortOrders: sortOrders
            }
          },
          computed: {
            filteredData: function() {
              var sortKey = this.sortKey;
              var filterKey = this.filterKey && this.filterKey.toLowerCase();
              var filterColumn = this.filterColumn;
              var order = this.sortOrders[sortKey] || 1;
              var data = this.data;
              if (filterKey) {
                data = data.filter(function(row) {
                  if (filterColumn === '') {
                    return Object.keys(row).some(function(key) {
                      return String(row[key]).toLowerCase().indexOf(filterKey) > -1
                    })
                  } else {
                    if (String(row[filterColumn]).toLowerCase().indexOf(filterKey) > -1)
                      return Object.keys(row)
                  }
                })
              }
              if (sortKey) {
                data = data.slice().sort(function(a, b) {
                  a = a[sortKey]
                  b = b[sortKey]
                  return (a === b ? 0 : a > b ? 1 : -1) * order
                })
              }
              return data
            }
          },
          filters: {
            capitalize: function(str) {
              return str.charAt(0).toUpperCase() + str.slice(1)
            }
          },
          methods: {
            sortBy: function(key) {
              this.sortKey = key
             ...