New remote job

| Comments

For the last 10 years I've been firting with remote work on and off. In that time I've been fortunate enough to have great employers that have allowed me to work remote for a couple of months in winter so that we could go to somewhere pleasant in Latin America. We've spent winters working in Montevideo, Uruguay and in Oaxaca, Mexico. We both love it! My wife Addi has worked remote for over 13 years, and she has been on the first wave of fully distributed tech companies.

I've been curious to make the jump to a fully distributed company and when I saw that Automattic was hiring and that WordPress chops were not required (I have a whole bag of Drupal chops and no WordPress chops whatsoever), I applied for a job as a Code Wrangler. It sounded like a really cool place to work and while I was gathering some confidence to send an application, I read the book A Year Without Pants by Scott Berkun. That book gave me a pretty hard crush on Automattic, so I'm stoked to say: I got the job!

I'm going to miss my good collegues at Reload, but just like last time I moved on from there, I'll drop by for a Friday beer every now and then.

This year has been a pretty crazy year for just about anyone on the planet. When I applied for the job I had no idea that not much later we would be rushing home from Mexico and that I would be working remotely just like everybody else in Reload. It's safe to say that remote work has been trending this year. I'm excited to see what it's like to do it full time year round though. I start mid-July and just like everybody else we have no travel plans at the moment, but I'm excited to take advantage of the work-from-everywhere freedom that I'll have with Automattic.


Thunderbolt dock and Linux

| Comments

At work I have a Dell TB16 dock for my Dell XPS 13. It's pretty sweet. I plug in just one USB-C and everything works. The first time I plugged it in, Ubuntu popped up a window that wanted me to approve the access to the computer from the dock. A nice security feature when you think about it.

When I did a reinstall and installed Kubuntu instead of Ubuntu, I did not get the prompt to approve access. Apparently Kubuntu does not have packages for managing Thunderbolt by default, and no graphical interface for it. Luckily I knew that the authorization was necessary, because I could have easily just freaked out and believed that the dock would not work with Kubuntu

Here are the easy steps I did to make it work on Kubuntu:

sudo apt install bolt
  • Restart the machine (not sure if it is necessary, but can't hurt).
  • List the devices with:
boltctl

The output will look something like this:

 ● Dell Thunderbolt Cable
   ├─ type:          peripheral
   ├─ name:          Dell Thunderbolt Cable
   ├─ vendor:        Dell
   ├─ uuid:          xxxxxxxx-7a0f-d400-ffff-ffffffffffff
   ├─ status:        authorized
   │  ├─ authflags:  none
   │  ├─ authorized: Wed 14 Nov 2018 03:01:12 PM UTC
   │  └─ connected:  Wed 14 Nov 2018 03:01:09 PM UTC
   └─ stored:        yes
      ├─ when:       Wed 31 Oct 2018 04:11:14 PM UTC
      ├─ policy:     auto
      └─ key:        no

 ● Dell Thunderbolt Dock
   ├─ type:          peripheral
   ├─ name:          Dell Thunderbolt Dock
   ├─ vendor:        Dell
   ├─ uuid:          xxxxxxxx-3b05-8680-ffff-ffffffffffff
   ├─ status:        authorized
   │  ├─ authflags:  none
   │  ├─ authorized: Wed 14 Nov 2018 03:01:18 PM UTC
   │  └─ connected:  Wed 14 Nov 2018 03:01:15 PM UTC
   └─ stored:        yes
      ├─ when:       Wed 31 Oct 2018 04:11:45 PM UTC
      ├─ policy:     auto
      └─ key:        no


  • Copy the uuid and authorize the device with: boltctl enroll [uuid]

If you only want to give permission for the current session, use boltctl authorize instead of enroll.

Wired internet can be flaky

On Kubuntu I have a couple of times every day where the machine looses the ethernet connection through the dock. I have no idea what does it - it never happened on Ubuntu. If you have any idea what that is please leave a comment.


Switching from Mac to Linux

| Comments

I've made the switch from a mac to Linux this fall. It's something I've been wanting to do for many years, but I haven't really had the courage before now. I used Linux when I was in the IT-University and a little bit at my first couple of jobs, but that is so long ago that it would be fair to call me a many years Mac user.

The reason I wanted to switch was that I really don't like where Apple is going. The touch bar on the newer macs are gimmicky and the new keyboards are almost offensively horrible to me. Also - as a Vim user I get quite angry when a computer does not have an escape key. So bye, bye, Apple. I haven't had an iPhone since 2010 and I've never had an iPad. This should go pretty smooth. It should be said that I am a shit photographer that never edits photos. I never play games and sadly I don't ever do graphical design. I mostly just write code and look at tapirs and kittens on YouTube.

It was pretty easy

I got a Dell XPS 13 (9370 Rose Gold edition), installed Ubuntu, and I was up and running really easily. I did not have any horrible problems or withdrawal symptoms at all. The thing I spent the most time tinkering with was probably my keyboard layout, but I spent ages on that on Mac too. Some time I'll write a blog post about mapping keys for opinionated people.

OK, I did have a serious problem when the kernel did a minor upgrade and the computer suddenly disagreed with me on what the password for the encrypted hard drive was (I was right about the password). I decided to re-install the computer after the password-incident and the second time around I chose to give Kubuntu a try after some loving and quite insisting group pressure in a chat channel.

Did it kill my productivity?

Surprisingly little I would say. I got the computer when I switched jobs, so I had to install a lot of new stuff anyway. Maybe if I had been in an existing job it would have felt a little more like a slowdown. I'm also lucky to have quite a few colleagues at Reload that use Linux and they have been really helpful when I've run into problems.

What I miss from the Mac

What I miss the most is 1Password. I migrated to LastPass and I am less than overwhelmed with that. It turned out that 1Password is not just a Mac app and that there is an awesome browser plugin that also works in Firefox (which I prefer). There is even a 1Password CLI tool! So I'm back to using 1Password.

Other than that there isn't an app that I really miss, but there are definitely small things that MacOs does better. Well maybe Sourcetree. I only ever used it for pretty diffs - I use CLI for all commands, so no biggie.

I miss being able to type in the help menu and have an arrow pointing to what i can't find. And I really miss the keyboard shortcuts I spent years learning in PhpStorm - they are all different on Linux so that feels like starting from scratch.

Oh, and the mouse/trackpad situation. I had no idea there was such a big difference between Mac and PC with that. It's not really Linux' fault since it's hardware, but it is so hard to get the mouse to be responsive without it flying off to hyperspace.

It's still early

I'm only a month and a half into using Linux again. In a year I'll have more experience, scars, and hopefully successes. I'm not going to say Ubuntu is better than Kubuntu or vice versa. I like both, but I think I'm sticking with Kubuntu because I used KDE back in university and it's what I'm more used to.

I've had some help from Sally's Kubuntu 18.04 on Dell XPS 13" gist and after I realized that the the Albert launcher integrates with CopyQ I was a lot less sad to loose the clipboard-rememberer in Alfred for Mac.


Navigate in Twig namespaces in PhpStorm

| Comments

I've gotten so used to have everything be clickable or navigable in PhpStorm. "I wonder what that function deep in the vendor folder looks like?" - I command click on Mac or ctrl click on Linux (or command+b/ctrl+b), and boom I go to the function definition. I don't know how I lived without it in the past.

But when I was writing a lot of Twig this spring I was sad that the file in Twig was not navigable like this: Add Twig namespace in PhpStorm

It took me forever to find out how to set it up. You need to install the Symfony plugin and either manually add the namespace under "Languages & Frameworks" -> "PHP" -> "Symfony" -> "Twig/Template": Add Twig namespace in PhpStorm - or even better, you can add a file called ide-twig.json where you tell the editor where to find files from a namespace. If you namespace was called "mynamespace" your file could look like this:

{
  "namespaces": [
    {
      "namespace": "mynamespace",
      "path": "templates/stuff"
    }
  ]
}

where the path is relative to your Twig templates.

The feature with the ide-twig.json file was added in the Symfony Plugin in version 0.11.110 years ago, but I've not come across much documentation for it. So now it's in this blog post.


Going back to a new job

| Comments

It seems I'm one to like going back and forth between jobs, so now I'm going back to work for Reload. I've loved working for Information and I'm going to miss the people there a lot, but I decided it was time to try something new (and old I guess) again.

Like last time I changed jobs I know some people already where I'm going, but a lot has also happened in the almost 4 years I've been away, so I'm looking forward to getting to know new people, do more drupal, and learn some shiny new technologies too.


Mexican street art as pixel art

| Comments

I'm slowly working my way through ES6 for Everyone by Wes Bos. It's been almost 6 months since I did the #javascript30 thing and I have been trying to do little projects every now and then to keep what I learned a little current.

The ES6 course has a lot of things that I already know now - and that feels great actually. I understand it much better when I get it explained again and when I get to play with it a little.

Today I had the perfect combination of no plans all day, dreary weather, and acute lazyness, so I stayed on the couch all day playing around with arrays in ES6 and some pixel art. I have loved geometric art since I was a kid, so when I stubmled upon this photo I took of some street art in Oaxaca in the spring, I decided to recreate it for the browser with JavaScript. I am aware that there are libraries out there that lets you do this — or even editors, but I wanted to make sure I played with some good ole vanilla JS.

So here is a pen with my browser version of the street art frieze from Oaxaca that inspired me. The street artist was likely inspiered by the unique friezes at the Zapotec archaeological site Mitla.

See the Pen Copying street art frieze in pixel art by Camilla Krag Jensen (@naxoc) on CodePen.

It was good fun to write code for the fun of it and doing "art". I might stick with pixel art and friezes from Mitla for a while. This one just begs to be done with box shadows:

12-05oaxaca077.jpgBy en:User:Bobak Ha'Eri - English Wikipedia, CC BY 2.0, Link


JavaScript30 - Day 30

| Comments

The final day of #javascript30 is a whack a mole game. I'm not going to write about that, but just do a little bit of evaluation on the #javascript30 month.

For whatever reason, it took me forever to get to doing the last day of #javascript30. I have really enjoyed the course and I was going on 25 days streaks of publishing a blog post with it, and then suddenly it took me over 2 weeks to write the last blog post.

#javascript30 was really great. I learned at ton that I might have known already to some degree, but I had never used to make something where I got to put the things together. It felt great to admit that while I have been making a living as a (backend) programmer for well over 10 years, I was bad at Javascript. Admitting that made it easier for me to choose to follow a "simpler" course on JS instead of tripping myself up with trying to use a framework while pretending that I understood ES6, Webpack, and tons of other things at once. The course is really well put together and I enjoyed the tasks very much. It seems trivial, but I find that it can be really hard to come up with ideas for small projects to work on when learning, but the projects in the course were really useful and fun.

My favorites things about the course were:

  • The array workouts
  • The speech recognition stuff
  • Learning ES6 syntax (wow, I really like that).
  • Really understanding the events the browser fires.
  • Doing cool shit that looks cool.
  • Felling like I have something to blog about again.

So thank you very, very much for an awesome free course, @wesbos. I would recommend it to everybody that is either learning Javascript or someone like me who has been using frameworks that kinda hid the real understanding of the language. Doge recommends


JavaScript30 - Day 29

| Comments

Day 29 of #javascript30 creates a countdown timer in the browser.

setInterval()

This exercise has some clever use of setInterval(). Understanding timers is a little more tricky than it seems, so take a good look at the examples in the docs too.

Select with Element.name

This one is so cool! I did not know you could do that. If you have an element that has a name like an input element, a link anchor, or even an image, you can "select" it by it's name. The name is a property on the document and will give you the same as if you used a querySelector:

document.myFormElement;

Is the same as:

const myForm = document.querySelector('.form-class');

Pretty cool!

string.padStart()

It the exercise, the minutes in the timer are padded with zero using a small ternary if. That might be the tersest way to do it, but I just wanted to mention string.padStart(). It doesn't have great browser support yet, but I like functions like this. Just give it the length you are shooting for and what you want the string padded with. It needs to be called on a string, so I had to "cast" to string first like this:

const minutes = Math.floor(seconds / 60);
const remainderSecs = (seconds % 60).toString().padStart(2, '0');
const display = `${minutes}:${remainderSecs}`;
endTime.textContent = `Be back at ${hour}:${minutes}`;

Where Wes' solution is like this:

const end = new Date(timestamp);
const hour = end.getHours();
const adjustedHour = hour > 12 ? hour - 12 : hour;
const minutes = end.getMinutes();
endTime.textContent = `Be Back At ${adjustedHour}:${minutes < 10 ? '0' : ''}${minutes}`;

Both are perfectly readable, but I do like the pad functions. There is a padEnd() too.


JavaScript30 - Day 28

| Comments

Day 28 of #javascript30 is a UI for controlling the playback speed on a video.

There is a bit of math to calculate where the mouse is moved over a bar that will control the video speed. It is a good idea to practice lots of things that use this recording of where the mouse is or where something is clicked. The math is not rocket science, but understanding the tools that are needed to get positions are important. I have read the docs for MouseEvent.pageY, Element.offsetTop, and Element.offsetHeight quite a number of times now and while they are also not complicated, I feel like I can do with even more practice with this. I'll cook up some codepen at some point where I illustrate what they do so I can use that as reference.


JavaScript30 - Day 27

| Comments

Day 27 of #javascript30 makes a neat horizontal scroll click and drag accordion or carousel.

There are a number of event listeners in use to achieve this. mousedown, mouseleave, mouseup, and mousemove. They keep a boolean that keeps track of whether the mouse is down or up, and they set the Element.scrollLeft property to the number of pixels the user dragged the element.

let vs var

I understand const completely now, but I was fuzzy on let vs var. They are quite similar, but they differ in scope. Once again, MDN's docs has a great explanation and example:

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // same variable!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // different variable
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

So var has scope in the entire function, while let has function in the block it is in (and all sub-blocks in that block).