Tyler Wiegand

Tyler Wiegand

Full Stack Developer

Talent Tracker

One of the nice things about the Talent Tracker (internal name) that we produced for Improve Group was that it gave me an excuse to learn Laravel, and was to be my first MVC design pattern after school. So, I picked up a membership to Laracasts and let Jeffrey Way's silky smooth vocal tones transport me from my school project's manual getters and setters, MySQL statements and PDO queries to Controllers, Migrations and Eloquent.

Quickly taking to the simplicity and elegance of the Laravel framework, I used Elixir (now called Mix) to add some javascript libraries into one big Gulp process. The cherry on top during this project for me personally was discovering the Dropzone.js library that made uploads for user avatars a breeze. Adding Laravel packages became second nature as I tested and removed several packages before settling on Laravel Excel for our report exports feature.

Talent Tracker Export Feature

And so, after going back and forth a few times with Improve Group on design specifications, we settled on what we considered to be the MVP for the project. As this was an internal tool, and we were billing hourly, Improve Group stressed that I not spend much time with aesthetics. There was basic CRUD for Users, Resources (subcontractors), and Resource Roles, and reports in the time ranges that they requested. Later we added more reports to track under-utilized resources and an overview of the amount of skills (roles) that resources had.

This is a quick video showing the search feature over multiple fields and the Dropzone.js library.

All reports were also exportable to Excel format and I was able to import their existing contacts to MySQL from their master spreadsheet. I did not make this a user accessible function as it opened up security risks in my opinion.

Back to Portfolio

Excel Controller

        
          
<?php

namespace App\Http\Controllers;

use App\Http\Requests;
use Carbon\Carbon;
use App\Resource;
use App\Role;
use Excel;
use Gate;
use DB;
use Illuminate\Database\Eloquent\Model;

class ExcelController extends Controller {

	public function spend() {
		if (Gate::denies('regular')) {
			abort(403, 'You cannot export reports.');
		}
		$export = true;
		$now = Carbon::now()->format('Y-m-d');
		$data = Resource::all();
		Excel::create("TPS As Of $now", function($excel) use ($data, $export) {
			$excel->sheet('Total Project Spending', function($sheet) use ($data, $export) {
				$sheet->loadView('reports.spend')->with('data', $data)->with('export', $export);
			});
		})->download('xls');
    }

	public function spendWeek() {
		if (Gate::denies('regular')) {
			abort(403, 'You cannot export reports.');
		}

		$export = true;
		$startWeek = Carbon::now()->timezone('America/Denver')->startOfWeek();
		$endWeek = Carbon::now()->timezone('America/Denver')->endOfWeek()->subDays(2);
		$weekOf = $startWeek->format('Y-m-d');
		$data = Resource::all();
		Excel::create("TPS Week Of $weekOf", function($excel) use ($data, $export, $startWeek, $endWeek) {
			$excel->sheet('Weekly Spending', function($sheet) use ($data, $export, $startWeek, $endWeek) {
				$sheet->loadView('reports.spendweek')->with('data', $data)
					->with('export', $export)
					->with('startWeek', $startWeek)
					->with('endWeek');
			});
		})->download('xls');
	}

	public function roles() {
		if (Gate::denies('regular')) {
			abort(403, 'You cannot export reports.');
		}
		$export = true;
		$now = Carbon::now()->format('Y-m-d');
		$roleIdArray = Role::get()->lists('id')->toArray();
		Excel::create("Role Report $now", function($excel) use ($roleIdArray, $export) {
			$excel->sheet('Total Roles', function($sheet) use ($roleIdArray, $export) {
				$sheet->loadView('reports.roles')->with('roleIdArray', $roleIdArray)->with('export', $export);
			});
		})->download('xls');
	}

	public function unavailable() {
		if (Gate::denies('regular')) {
			abort(403, 'You cannot export reports.');
		}
		$export = true;
		$now = Carbon::now()->format('Y-m-d');
		$data = DB::table('resources')
		          ->select('name','project_assigned')
		          ->where('project_assigned' ,'=', '0')
		          ->get();

		Excel::create("Unassigned Report $now", function($excel) use ($data, $export) {
			$excel->sheet('Available People', function($sheet) use ($data, $export) {
				$sheet->loadView('reports.unavailable')->with('data', $data)->with('export', $export);
			});
		})->download('xls');
	}

//	public function upload() {
//		Model::unguard();
//		Excel::load(storage_path('excel') .'/converted.xls', function($reader) {
//			foreach ($reader->toArray() as $row) {
////			$first = $reader->first()->toArray();
//				foreach($row as $entry){
//					if(@isset($entry['email']) && @isset($entry['name']))
//					try {
//						Resource::create($entry);
//					} catch(\Exception $e) {}
//				}
////				Resource::create( $row );
//			}
//		});
//		Model::reguard();
//	}
}

        
      

Resource Controller

        
          
<?php

   namespace App\Http\Controllers;


   use DB;
   use Gate;
   use Request;
   use App\Role;
   use App\Resource;
   use App\Http\Requests;
   use App\Http\Requests\ResourceRequest;
   use Illuminate\Http\Request as HttpRequest;
   use Intervention\Image\ImageManagerStatic as Image;

   class ResourcesController extends Controller
   {
      /**
       * Display a listing of the resource.
       *
       * @return \Illuminate\Http\Response
       */
      public function index()
      {
         if (Gate::denies('viewer')) {
            abort(403, 'You cannot view resources.');
         }
         if ($search = Request::get('q')) {
            $searchArray = preg_split('!\s+!', $search);

            //            DB::listen(function($sql, $bindings, $time) { dd($sql, $bindings, $time); });
            $resources = Resource::with( 'roles' )
                                 ->where( function ( $query ) use ( $searchArray ) {
                                    foreach ( $searchArray as $search ) {
                                       $query->where( function ( $subQuery ) use ( $search ) {
                                          $subQuery->orWhere( 'name', 'LIKE', "%$search%" )
                                                   ->orWhere( 'email', 'LIKE', "%$search%" )
                                                   ->orWhere( 'phone', 'LIKE', "%$search%" )
                                                   ->orWhere( 'company', 'LIKE', "%$search%" )
                                                   ->orWhere( 'notes', 'LIKE', "%$search%" )
                                                   ->orWhere( 'skills', 'LIKE', "%$search%" )
                                                   ->orWhere( 'city', 'LIKE', "%$search%" )
                                                   ->orWhere( 'state', 'LIKE', "%$search%" )
                                                   ->orWhere( 'project_name', 'LIKE', "%$search%" )
                                                   ->orWhereHas( 'roles', function ( $rolesQuery ) use ( $search ) {
                                                      $rolesQuery->where( 'role_name', 'LIKE', "%$search%" );
                                                   } );
                                       } );
                                    }
                                 } )->get();

            $idArray = [];

            foreach($resources as $key => $item) {
               $idArray[] = $item->id;
            }

            if(!$idArray) {
               $stuff = "No search results for $search.";
               $resources = Resource::get()->sortBy('name');
               return view( 'resources.index', compact( 'resources', 'stuff' ));
            }

            array_unique($idArray);

            $resources = Resource::whereIn('id', $idArray)
                                 ->get()
                                 ->sortBy('name');

            return view( 'resources.index', compact( 'resources' ));

         } else {
            $resources = Resource::get()->sortBy('name');
            return view( 'resources.index', compact( 'resources' ));
         }
      }

      /**
       * Show the form for creating a new resource.
       *
       * @return \Illuminate\Http\Response
       */
      public function create()
      {
         if (Gate::denies('regular')) {
            abort(403, 'You cannot create resources.');
         }
         $roles = Role::lists('role_name', 'id')->toArray();
         return view('resources.create', compact('roles'));
      }


      public function store(ResourceRequest $request)
      {
         if (Gate::denies('regular')) {
            abort(403, 'You cannot store resources.');
         }
         $resource = Resource::create($request->all());

         $resource->roles()->attach( $request->input('role_list') );

         return redirect('resources/' . $resource->id);
      }

      public function show(Resource $resource)
      {
         if (Gate::denies('viewer')) {
            abort(403, 'You cannot view resources.');
         }

         return view('resources.show', compact('resource'));
      }

      public function edit(Resource $resource)
      {
         if (Gate::denies('regular')) {
            abort(403, 'You cannot edit resources.');
         }
         $roles = Role::lists('role_name', 'id')->toArray();

         return view('resources.edit', compact('resource', 'roles'));
      }


      public function update(Resource $resource, ResourceRequest $request)
      {
         if (Gate::denies('regular')) {
            abort(403, 'You cannot update resources.');
         }
         $resource->update($request->all());
         $roleList = $request->input('role_list') ? : [];
         $resource->roles()->sync( $roleList );
         return redirect('resources/' . $resource->id);
      }

      public function upload( $id, HttpRequest $request ) {
         if (Gate::denies('regular')) {
            abort(403, 'You cannot update resources.');
         }
         $this->validate($request, [
            'imageUpload' => 'required|mimes:jpg,jpeg,png,bmp'
         ]);

         $file = $request->file('imageUpload');
         $image = Image::make($file)->orientate();

         // make the original picture, save it
         $name = time() . $file->getClientOriginalName();

         $image->fit(500)
               ->save(public_path() . "/img/$name", 80)
               ->fit(200)
               ->save(public_path() . "/img/thumb-$name", 70);

         $resource = Resource::find($id);

         $resource->update(['profilepic' => "$name"]);
      }

      public function destroy(Resource $resource)
      {
         if (Gate::denies('admin')) {
            abort(403, 'You cannot delete resources.');
         }
         $resource->delete();
         return redirect('resources');
      }

   }