Turn an array of objects into a table

At work we use a number of javascript files that hold constants we can import to any of our builders or editors. The structure looks something like:

export const importantThing = [
    {
        id: 'slug',
        displayText: 'nice name',
        helpUrl: 'someurl.com/docs/nice-name'
        ...
    },
    ...etc
]

So a fairly large array of objects which makes it easy to work with. With this data structure I needed to export a whole bunch of these objects out and into a table. After a bit of searching there wasn’t anything I could drop in to the tiny project I created to build the tables.

I ended up with two functions that render first the table header and then the table rows:

function renderTableHeader(data) {
  const header = Object.keys(data[0]);
  return header.map((key, index) => <th key={index}>{key}</th>);
}

function renderTableRows(data) {
	const keys = Object.keys(data[0]);
	const table = data.map((row, index) => {
		return (
			<tr key={index}>
				{keys.map((key, index) => <td key={index}>{JSON.stringify(row[key])}</td>)}
			</tr>
		)
	});
	return table;
}

When implemented in the react component:

<table className="table table-sm">
  <tbody>
    <tr>{renderTableHeader(importantThing)}</tr> 
      {renderTableRows(importantThing)}
  </tbody>
</table>

Small and simple without any external libraries or extra bells and whistles. This gives a very plain table that I can easily copy and paste into a spreadsheet, print, or in this case share with another team so they have easy access to all of the underlying data from our production app.

I made a thing but not with code

I got into woodworking and general maker-y stuff shortly after my wife and I moved into our first house. Since then I have tackled decks, a big playset for my kids, a couple of desks because I kept messing with my own, and a bunch of other projects I wish I kept better track of.

That leads me to writing now since I finally got back into making things after a long break where work was way too busy.

So once again I made…a desk and some shelves. But this time it wasn’t for me! This was a private (but also taking up one whole wall of our living room) workspace for my wife. We decided on these sets of plans from Anna White for Ladder Shelves and a Ladder Desk. I tweaked the desk plans to be 36 inches wide instead of 31 inches but otherwise followed them just about exactly.

I really wasn’t sure if I would be able to pull the whole thing off considering I hadn’t been doing any major projects in a while and nothing so pretty and finished that someone else would be using. With that in mind I bought the cheapest whitewood 1x3s that Lowes had when I picked out the wood. The total for wood, nails, extra sandpaper and extra pocket hole screws was right around $150.

After looking over the big buy list and walking through the store a bit I definitely stood staring at a ladder shelf they had in the closet storage area for some minutes. But when I did the math a single ladder shelf would be $120 each and my wife still wouldn’t have a desk. So I got the wood and got to cutting.

I think I ended up starting everything on a Saturday and had everything cut and ready to sand some time Sunday. By Monday evening I was done sanding and ready to stain.

All of the shelf…shelves stacked on my work table after vacuuming an absurd amount of dust from everything

My wife picked out the stain and then I took a few lunches and evenings during the week to keep making progress.

The desk and two wide shelves for the center.

It wasn’t until Sunday that I was able to put together the desk against the wall. I did a single round of stain then lightly sanded a few spots where the grain got raised. For the desk I did two coats of polyurethane but the rest was a single coat with lite sanding at 220 and 320 in some spots.

Shelves in place aligned with the wall it will end up on.

One whole week later we finally had something to look at on the wall. Then it was only a matter of staining and sanding and coating everything else with the poly while trying to make sure the stain was matching. At least I had a good book to listen to.

You can see a couple of offcuts I used for testing out different finishes.

By that next weekend everything was finally done and put together. The one funky step was figuring out the angled cut for the legs and the part that touches the wall. The explanation that I came up with to actually get it done was make a 90 degree after making the 5 degree cut for both ends. I’m pretty sure that is exactly what the directions say from the plans but the wording gave me a few minutes of confusion.

It looks even better fully decorated but I have not taken a picture of that yet. I was happy and done at this point.

With all these words there is still so much of the process missing. I’ve learned so much from googling and watching others document their work and I have a running guilt meter for not returning the favor. This is step one in trying to give back.

I still have ongoing code projects and I’m definitely hooked on spending lots of time in the garage so I’m hoping to follow up with writing, video, and pictures as much as I can. Hopefully you enjoyed the read. If you have questions say hello and I’ll be glad to answer as best I can.

Arrow function as class function in ES6

If you’ve been using create-react-app and tried to build things on your own you might have done/seen/used

handleClick = () => {
// do thing on click
}

This comes from the Class properties transform plugin from Babel: https://babeljs.io/docs/plugins/transform-class-properties/

So if you try to build a project on your own you’ll need to include it to use that syntax so babel knows what to do with it. Otherwise you can do:

onClick={(e) => this.handleClick(e)

In the jsx itself but it *can* have performance issues if you are passing that onClick down as a prop.

I’ve not gone deep enough down the big app building track with a bunch of things composited in a way where this was an issue so I’ve used both. With that said…after thinking about this and going through it manually over the weekend I’ll probably get in the habit of using the public class fields syntax unless I see it get a notice that it has been deprecated for some reason in babel or I stop using babel to transpile.

Simple Login Style plugin

does anyone have a simple little plugin for custom login styles. I dont need a nuclear bomb option, just trying to make a simple thing

I saw this question pop up in the Post Status slack earlier and immediately thought “that would be a quick plugin to make using the WordPress Plugin Boilerplate”.

So lets walk through the steps:

What do we need to style the WordPress login page? https://codex.wordpress.org/Customizing_the_Login_Form

Thanks codex! We hook onto login_enqueue_scripts and then write over the appropriate styles as needed. Since the boilerplate already comes with two classes that enqueue a css file and js file I only needed to figure out which this best fit into: Admin or Public.

For me, I see this as public facing. The styles aren’t behind the login and there is no actual admin functionality. Maybe you see it as an admin thing so you could go the opposite of the next steps.

After generating a custom named build of the boilerplate from http://wppb.me/ I had my plugin 90% done:

Screen-Shot-2015-07-31-at-10.22.19-PM

After removing the parts I didn’t need from the folder structure:

Screen-Shot-2015-07-31-at-10.34.48-PM

In the simple-login-styles.php file I removed the functions to call the deactivation/activation hooks and then opened up the class-simple-login-styles.php to remove the admin dependency.

Now, the actual coding of the plugin was just changing where the public css and public js files were being enqueued at. Since the boilerplate uses the loader class to manage hooks and filters I moved down to those lines in the class-simple-login-styles.php file and edited:

Screen-Shot-2015-07-31-at-10.38.56-PM

And done.

AAR on my Standards talk

I posted my rambled thoughts on writing out my slides/talk for WordCamp Miami last week and I thought a after action report would be a nice follow up.

I ended up editing my slides a bit after talking with Topher DeRosia who was speaking just before me as part of our mini-workshop. I left out referencing core and focused more on the PHP standards directly. I’m not sure if it was the best call or not but it felt like it.

I also left out deep diving into the code of the boilerplate since I didn’t want to go heavily into objects and turn anyone immediately off of the idea of writing their own plugin. Again, I think this was a good call since I explained enough about DocBlocks that anyone interested should be comfortable in opening up the boilerplate files to search then read the inline documentation.

Ultimately I feel good about how it went because at least now there is a short overview of applying core standards to writing plugins out there for anyone interested 🙂

Update: I was searching something unrelated this morning and came across the somewhat new Plugin Handbook. 🙁 I wish I would have found/known about this before my talk. It is amazing reference and covers some points I did not go over because I didn’t have a core/official reference point.

I’ll be updating wppb at least to reference them 🙂

 

Writing WordPress plugins with Standards

[Note: I wrote this in bits and pieces over the past week or so which has caused it to be a bit all over the place 😁 ]

On May 31st I will be speaking at WordCamp Miami about the WordPress coding standards, documentation standards, and showing how to apply those when writing your own plugins.

Although it isn’t an overly flashy or seemingly exciting topic, it gels nicely with my obsession with project organization so *I* am excited to talk about it. I have not completely nailed down my slides yet so I’m going to write things out and use this post as an organizational/focusing exercise.

Lets start with the big one: WordPress Coding Standards for contributing to core.

No, plugins are not core but in an effort to follow best practices we can use the standards when writing our own plugins. If you are new to writing code this should be easy for you. Coming from outside of the WordPress bubble is a bit harder.

This will be immediately after an intro to writing plugins so I need to keep that in mind. Still though, the easiest part of following the standards is making sure your code editor of choice is using the rules for css/php/js. I’ll mark that as “definitely tell people to do that”.

This is something I want to make sure to highlight as well: https://make.wordpress.org/core/handbook/coding-standards/php/#clever-code

Clever is great and all, but at least explain it with a nice big comment 😑

Since the handbook covers so much I don’t want to re-re-re-re-repeat things that everyone will be able to go digest later on. Moving on…

Plugins, with standards! Plugins as a whole topic are really all over the place. If you go off of the codex entry for “Writing a Plugin” there is no telling what you might end up with. [As an aside, that page needs to be updated. Ouch. Maybe I can help 😕 ]

Since the codex is kind of eh in this case, where should you go? These are both good: Plugin Resources – Reference, Plugin Resources – Special Topics . Still though, we are just touching the surface and spitting out a bunch of links. Since I happen to be leading a pretty fancy pants plugin boilerplate which strives to follow best practices and standards I’ll jump into that. Yea, code all up in there.

I’m tempted to go up an add this into my previous thought but that is rather disingenuous. I totally forgot the best place to look at best practices for WordPress….is WordPress. Thankfully there was this exchange to remind me core typically is #doingitright:

I joined an agency, it’s been pretty great

Up until the summer of 2014, I had been pretty much working alone for 8 years. With a rocky start in my early twenties, I eventually landed on a stable diet of sub-contracted agency work, graphic design, photography and finally concentrated fully on development. I did things right and incorporated early – which gave me an impressive list of titles, as well as get everything set up great for taxes, billing, and payroll.

On the personal side of things: I got married, became a first time home buyer, and then a dad twice over. While there was a new level of stress to deal with, ultimately life was stable and my wife and I had worked hard together to get there. I really had no intention of shaking things up.

Oddly enough, it was a series of big, well-paying projects that put me in search of something else. Instead of doing lots of small work over the summer, I decided to schedule just a couple of big projects.  They were challenging, fun, and I was working with some big names like ______ and _____.

The joy of an NDA means that even now I can’t say who I was working with or even what I was working on. All that code I could only loosely talk about for big names, I couldn’t say because I was working for an agency as a contractor and not an employee. While I don’t share much on social media, I do get overly excited and chatty in person about this kind of thing. Finishing up projects that I was proud of, but could not talk about at all those summer barbecues with friends and family was a struggle. I love what I do and it was that inability to talk about it that had me looking for another option.

Oh look, Range is hiring.

I spent more time than I’d like to admit looking at job requirements for being a developer at Range  and wondering if I was really qualified. Eventually I overcame the self-doubt, wrote up my email (after I got permission to include some of my NDA work) and hit send. I wanted a small team with some big clients and room to grow. I didn’t apply anywhere else; I really wanted that job.

The end of this story is really no surprise, it is in fact the point of this post. I heard back from Range, we talked, I did a short trial, they offered the job and I accepted. WOO! I was definitely worried about being able to make the transition from working alone to working in a team, but it turned out to be pretty easy. We talked daily on slack, I took on a few projects and got into a new routine with a lot less isolation.

The Great

The biggest and most immediate impact was on my mental health. I could actually relax in the evening. I had no idea how much of my time was spent thinking about work, until I no longer had to handle and plan every last detail.

With less stress came increased personal growth. I tackled ideas and projects that had been on my todo list for months. Eventually this lead to my current leadership of the WordPress Plugin Boilerplate, as I had so clearly showed Tom McFarlin I had too much free time for my own good.

I’ve discovered how amazing it is to have work funded travel. My first full month at Range ended at WordCamp San Francisco. Going there had been on my radar the year before, but the potential planning of it all alone (combined with the potential cost) made for too easy of an excuse. This time I was sent there to meet up with my team.

The next time we all got together was for an official Range Meetup. Our project manager Laura wrote about it on the Range blog. A few weeks after that I was back in California at The Carneros Inn for a WordPress VIP conference.

Lets get sappy

I’ve been planning this post in my head since getting back from the meetup last month and writing it all out has been a lot of fun. Hopefully this post is the first of many more. I want to help contribute to the community of blog posts that I learned from and continue to learn from daily.

I still love development. I still loving working at Range with all the awesome people there. Although I don’t know how long this stage of my life will last, I do know I’m extremely happy to be here.

Writing, I should do more of it

One of my goals for 2015 was to get a bit more active on my own site. It has taken me a few months to realize I have not actually been working on this at all.

Whoops!

So here we are mid April with a fresh start and a happy new year. I have a few projects I’ve been working on that I’m hoping to write about in an effort to finish them quicker. You, the potential reader, will be my rubber duck.

Codeable Contractor Reviews plugin

Edit: At some point in moving my site to a new server I did not copy over the plugin. I could probably dig it up from a backup if anyone ever requests it but otherwise I’ll leave the old post up for archival sake.

When Codeable updated their app to “2.0” they built it on a nice little api. I’ve been playing with WordPress and its api integration for a while now so I was quite excited to dig into another api.

Then again a new baby, summer, work, and generally life makes side projects….well side projects. Having said that I’ve got a very early version of the plugin available for any contractors who want to play with it below.

Notes

You need to add your contractor ID into the plugins file as the ID constant. Also its version .01 and powered by a nice bourbon so pardon the dust. It does work however 🙂

codeable-contractor-reviews

Usage
[codeable_reviews]
once installed. Some basic styling if you want:

 

.review-wrapper {
	border: 1px solid #ddd;
	border-radius: 3px;
	margin: 1%;
	padding: 15px;
	width: 48%;
	float: left;
	min-height: 210px;
}
.review-score {
    float: right;
}
img.review-avatar {
	border-radius: 2px;
	height: 60px;
	width: 60px;
	float: left;
	margin-right: 10px;
	}

 

Demo over on the project page here: http://devinvinson.com/codeable-contractor-reviews/

I’m going to push it to github after another revision as well.

[wpforms id="1992" title="false" description="false"]
<div class="wpforms-container wpforms-container-full" id="wpforms-1992"><form id="wpforms-form-1992" class="wpforms-validate wpforms-form" data-formid="1992" method="post" enctype="multipart/form-data" action="/"><noscript class="wpforms-error-noscript">Please enable JavaScript in your browser to complete this form.</noscript><div class="wpforms-field-container"><div id="wpforms-1992-field_0-container" class="wpforms-field wpforms-field-name" data-field-id="0"><label class="wpforms-field-label" for="wpforms-1992-field_0">Name <span class="wpforms-required-label">*</span></label><div class="wpforms-field-row wpforms-field-large"><div class="wpforms-field-row-block wpforms-first wpforms-one-half"><input type="text" id="wpforms-1992-field_0" class="wpforms-field-name-first wpforms-field-required" name="wpforms[fields][0][first]" required><label for="wpforms-1992-field_0" class="wpforms-field-sublabel after ">First</label></div><div class="wpforms-field-row-block wpforms-one-half"><input type="text" id="wpforms-1992-field_0-last" class="wpforms-field-name-last wpforms-field-required" name="wpforms[fields][0][last]" required><label for="wpforms-1992-field_0-last" class="wpforms-field-sublabel after ">Last</label></div></div></div><div id="wpforms-1992-field_1-container" class="wpforms-field wpforms-field-email" data-field-id="1"><label class="wpforms-field-label" for="wpforms-1992-field_1">Email <span class="wpforms-required-label">*</span></label><input type="email" id="wpforms-1992-field_1" class="wpforms-field-medium wpforms-field-required" name="wpforms[fields][1]" required></div><div id="wpforms-1992-field_2-container" class="wpforms-field wpforms-field-textarea" data-field-id="2"><label class="wpforms-field-label" for="wpforms-1992-field_2">Comment or Message <span class="wpforms-required-label">*</span></label><textarea id="wpforms-1992-field_2" class="wpforms-field-medium wpforms-field-required" name="wpforms[fields][2]" required></textarea></div></div><div class="wpforms-field wpforms-field-hp"><label for="wpforms-1992-field-hp" class="wpforms-field-label">Comment</label><input type="text" name="wpforms[hp]" id="wpforms-1992-field-hp" class="wpforms-field-medium"></div><div class="wpforms-submit-container" ><input type="hidden" name="wpforms[id]" value="1992"><input type="hidden" name="wpforms[author]" value="1"><button type="submit" name="wpforms[submit]" class="wpforms-submit " id="wpforms-submit-1992" value="wpforms-submit" aria-live="assertive" data-alt-text="Sending..." data-submit-text="Submit">Submit</button></div></form></div> <!-- .wpforms-container -->