My web development group uses a spreadsheet to track weekly time allocations for a couple of dozen web developers, designers, project managers and other specialists.  This is useful in several ways, including

  • letting project managers know how committed each professional is, and who might have some available time
  • projecting vacation and holiday time
  • allowing projects to be scheduled out over several weeks
  • allowing time to be reallocated as urgent needs crop up
  • letting professionals to look at just their time and the list of projects they have been assigned to

As great as this is, there are some pitfalls with the current system: 

  • picky macros that sometimes fail
  • downloaded files go out of date
  • two managers can’t update the files at the same time
  • a lot of us don’t work with spreadsheets open all day, so this is unfamiliar technology.

In sum, this is just calling out to anyone looking for a project on which to try out new tech!

I’ve tried smaller things in GraphQL and React, but trying to craft a Resource Tracker will push me on both fronts, so here I go.

Getting Started

First, let’s flesh out some first steps.  It sounds like we’ll need to store some data:

  • projects — each will have at least a name, and a note containing what technology the project uses, to help managers assign the right resources. An active flag would be good if we have projects we want to archive or suspend.
  • resources — the people that will work on the projects.  For each, we’ll store their name and title (designer, project manager, etc.).  Our spreadsheet solution uses a different color to highlight data for each person, so, we’ll adopt that feature and add a color field to each resource, too.
  • assignments — I’m thinking of a pivot table attaching resources to projects. 
  • allocations — these are the number of hours a particular resource is allocated to work on a specific project in a specific week.  So we will need fields for hours, resource_id,  project_id, and a date field for the start of a specific week.  The project managers like to be able to add a note to a specific allocation, so we’ll add a note text field, too.    Allocations will be created on demand… if there is no allocation, there is no data.

We want a GraphQL server for all of this.  Since we are a Laravel shop, I’ll give the folkloreatelier/laravel-graphql library a try.  This is a Laravel wrapper around the popular webonyx/graphql-php GraphQL server code.

Following the laravel-graphql installation instructions (which I won’t repeat here) on a fresh Laravel 5.7 install, I required the package via Composer and ran a composer install.  I found I needed to add the service provider to the config/app.php file and add the facade to the config/app.php file before I could publish the graphql configuration file via the Laravel artisan command.

Add a model

Anxious to get started, I added a projects table to my MySQL database with a name and note field, and added a Projects model.  I then added an App\GraphQL\Type\ProjectType class:

<?PHP 

namespace App\GraphQL\Type;

use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Type as GraphQLType;
use GraphQL;

class ProjectType extends GraphQLType
{
    protected $attributes = [
        'name' => 'Name',
        'active' => 'Active',
	    'technology' => 'Technology'
    ];

    /*
    * Uncomment following line to make the type input object.
    * http://graphql.org/learn/schema/#input-types
    */
    // protected $inputObject = true;

    public function fields()
    {
        return [
            'id' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The id of the project',
            ],
            'name' => [
                'type' => Type::nonNull(Type::string()),
                'description' => 'The name of the project',
            ],
            'active' => [
                'type' => Type::nonNull(Type::int()),
                'description' => 'Flag indicating whether the project is active',
            ],
            'technology' => [
                'type' => Type::string(),
                'description' => 'The technology the project is built in',
            ],
        ];
    }
}

and an App\GraphQL\Query\ProjectsQuery class:

<?PHP 

namespace App\GraphQL\Query;

use GraphQL;
use GraphQL\Type\Definition\Type;
use Folklore\GraphQL\Support\Query;
use App\Project;

class ProjectsQuery extends Query
{
    protected $attributes = [
        'name' => 'projects'
    ];

    public function type()
    {
        return Type::listOf(GraphQL::type('Project'));
    }

    public function args()
    {
        return [
            'id' => [
                'name' => 'id', 
                'type' => Type::string(),
            ],
            'name' => [
                'name' => 'name', 
                'type' => Type::string()
            ],
            'active' => ['name' => 'active', 'type' => Type::int()],
            'technology' => ['name' => 'active', 'type' => Type::string()]
        ];
    }

    public function resolve($root, $args)
    {
        
        if (isset($args['id'])) {
            return Project::where('id' , $args['id'])->get();
        } else if(isset($args['name'])) {
            return Project::where('name', $args['name'])->get();
        } else if(isset($args['active'])) {
            return Project::where('active', $args['active'])->get();
        } else {
            return Project::all();
        }
    }
}

After adding the new class names to the graphql.php configuration file, and with a few records in my database table, I could now go to my local server and bring up graphiql at the /graphiql route.

Sweet! Now that we have some behavior, we can work on adding the other models to the server in Part 2.