Wednesday 31 May 2017

FCC - twitch viewer V

09:21

This is the most apprehensive and downbeat I’ve been about the project so far. I’m concerned that as I try to fix the problems with my data structuring the whole thing will become unpicked.

I guess before I get into it I ought to make a list of what I need to achieve and make sure everything I do is consistent with that:

1) be able to construct the html template with the correct .png file indicator

This means each user object needs to have a binary property on which to select the image. At the moment I’m just constructing the image url around the property offline (pointing at offline.png and that’s a problem because there is no online just the name of the game in progress.

Maybe the best thing to do, given that I’ve chosen the template approach, is to update the broadcast icon along with the refresh function that makes an api call to the stream. That seems like the best approach as I write.

Ideally I’d like the background color to be red as well, but this is hardly vital.

2) placeholder display item for non-existent accounts

Off the top of my head, I’m going to say that the best thing to do here is have a placeholder user object. The for loop in the render function can check some property of the array it’s passed and point at the placeholder if appropriate.

Will that work? Don’t know.

3) initial call to render when the api call resolves on load

I’m assuming this can be achieved relatively easily. Not going to think too much about it now.

Again, this should be straightforward once I get the data sorted. Hyperlink to page will be a property of each user object that can be included in the template

NB One of my issues is that to constuct the user entries from the template the render function loops over an array. If everything I have is stored in objects that might be complexified, but I assume that I can make use of Object.keys.

To Do

  • user object property for path to broadcast icon which updates on refresh
  • write api responses to data.objects instead of pushing to data.accounts.array
  • create promise for initial api call -> view.render

Log

09:45 - 10:08

Straightforward to get objects from the API saved as data.objects, but it messes up my filter functions. I think I need to add them to a master accounts object so I can use array methods on it.

10:13

Easy enough to do, but can I work with it now?

11:15

Progress has halted. Not because there’s an issue with the logic but - as is so often the case - there seems to be some sort of syntax error that I can’t debug. Here’s the code:

  filterUsers() { 
    if (data.currentFilter === 'all') {
      return data.accounts; // bypass any further processing
    }
    else {
      return (Object.keys(data.accounts).filter(function(userName) {
        debugger;
       return data.currentFilter === 'online' ? data.accounts[userName].stream.stream !== null : data.accounts[userName].stream.stream === null
      }))
  },

The problem is that data.accounts[userName].stream.stream is undefined. But th debugger shows userName and the data.accounts objects to have the right properties.

I’m going to spend 10 more minutes on this then try a less elegant approach and see if it works.

11:54

settled for:

 filterUsers() { 
    let all = Object.keys(data.accounts);
    if (data.currentFilter === 'all') {return all} // bypass any further processing
    else { // there's a more elegant way, but I haven't time to find it
      return data.currentFilter === 'online' ?
        all.filter(function(userName) {
          return (data.accounts[userName].stream.stream); })
        : 
        all.filter(function(userName) {
          return (!data.accounts[userName].stream.stream); })
    }
  }, 

Now need to get render to accept the results.

16:15

OK, I got the filter logic working fine, but couldn’t get view.render to parse it. I realised that in the case of all it was returning data.accounts - the whole object - while in the case of online and offline it was only giving back the names.

I ran into what I thought was a syntax problem but couldn’t figure out what was wrong since I seemed to get decent results from data.accounts[userName].stream.stream under some circumstances but not others.

It was frustrating me, but after going to the meetup and explaining it to someone (and working off a different internet connection, crucially) I think this is the issue:

The calls to getUserData() is not set up to deal with the results asyncronously. So the users query (which gets more data) sometimes hasn’t completed by the time the streams query does.

That’s why I’m getting cannot read property 'stream' of undefined - because at the time it tries to append the object, streams hasn’t been added.

### Lessons

  • don’t make assumptions about bugs
  • … or at least consider alternatives
  • be (even) more modular. TDD?
  • ask for help!
  • think about data model earlier, and in more detail
  • make sure you consider all the requirements from the start!

Tuesday 30 May 2017

FCC - twitch viewer IV

Day 5

Up at 05:30 to get on with this before the child is up. I think that says a lot about the power of knowing where you are and being in full flow.

So I have logo and whatnot pulling successfully from the API. I need to write another api call that checks whether the user is streaming. I guess actually I need to use that to update the data store then re-render the whole thing. So its should actually be called before the init render.

06:47

OK! generalised the api call to accept a second argument that goes toward formulating the API query url. This means I can call getUserData with a parameter as the second arg and get back whatever I want.

This is the first point when I’m not satisfied with my code cleanliness. I ought to compose separate functions for getting the initial user data and then the stream updates. Instead I’m relying on an if statement to update either the data.accounts array or write data[user] properties for offline/game-in-progress.

I’m also not happy about having the data in two different ‘domains’ in the data object, but cannot articulate exactly why.

Next to update the render method to show users by filter and display their game in progress if online.

07:08

Looking at my current implementation and thinking about approach, I reckon I need to make a new controller function which looks at data.currentFilter and generates a subset of the data.accounts object.

This is then passed to view.render(array) which can also access data.accounts to read the game in progress. Because the array will only consist of the filtered results it can consult this store from within the loop.

Does this violate the MVC by having the view.render method consult the model directly?

BREAK FOR CHILDCARE

15:55

I have hacked away for another hour or so this afternooon. It’s been pretty successful in terms of getting things to work: I have added an onclick handler applyFilter that updates data.currentFilter with the relevant online status, then calls view.render() to display iterate over the relevant subset of users and display the results.

Adding view.clear() as part of that process was trivial, and I got the _js template tweaked so it displays the appropriate status.

Where it’s gotten poor and unwieldy is that I didn’t trust my instincts earlier and store properties of user accounts in key-pair objects under data. This has made my filtering WET and, I fear, the whole edifice brittle.

AND I’ve realised I overlooked a user story at the outset that requires me to handle non-existent (or defunct) accounts. Bleh.

I also need to come up with a way to handle the icons I’ve chosen to represent streaming vs offline.

So, a bit of a re-write is in order. I’m thinking keep all user account data in an an object like:

accounts: {
    name : { 
        displayName: 'display_name',
        avatar: 'logo', // set to a default for non-existent or unpopulated
        bio: 'bio',
        status: 'online',

etc

Sunday 28 May 2017

FCC - twitch viewer II

Day 3

I should point out that I’m hardly working flat-out on this! Yesterday I was working on it at the code pod meetup, so my pace has been fairly leisurely. Today I’m grabbing an hour while the family’s out. Have completely lost track of the actual time spent. Maybe do pomodoros?

09:47

I’m probably at the point when I should start on the API, I’m going to revisit my pattern from the wiki viewer and try to complete some kind of call/response. Need to use the FCC workaround, it seems.

Day 4

Day 4 is actually several calendar days later, since I’ve had childcare and family days in between. So my flow is broken a bit and that’s something I need to watch. I can’t help these breaks in focus, but I need to plan for them better, maybe have specific notes to step into, and preferably have something fun and/or straightforward to do on resumption.

Right now I have neither of those things since I’m right at the beginning of a new section (the API) and I’m not clear how to proceed, and don’t have a decent run in terms of time, either. Well, at least I’ll try to get myself set up for next time.

Log

I’m going to generalise my API call/promise pattern into a github gist right now.

done

I’ve copied this into the twitch viewer and added the heroku proxy prefix to bypass CORS issues, and replaced the base twitch API url with the one provided by FCC.

It is returning something that looks like it has the data I need. I just need to parse it out and figure how to incorporate it into the app. Still don’t really get the CORS stuff or how promises are properly used.

Working in github pages.

Now the drill is charged, so I am obliged to resume my DIY chores.

Log

Evening now. Realised the query url I was using has a placeholder for callbacks in it. Took that out and looked again at the FCC workaround page. Looks like I have 3 calls I can make:

  • users
  • channels
  • streams

And I think I’ll have to make different calls at different times to fulfill these user stories.

Right now I’m thinking call one at init to get the avatar and whatnot (the ‘static’ user info) and then calls on the streams for subsequent updates/filter refreshes etc.

Maybe I should curry the basic query function to return variants on the string… but then do I need different ways of dealing with the responses?

need something like:

const userNameArray = ['medrybw', 'freecodecamp', 'femfreq', 'lootbndt', 'spitchell']; 
controller.init () {
    getAllUserData(userNameArray)

},

getAllUserData(array){
    array.forEach(user){
        submitQuery('https://cors-anywhere.herokuapp.com/wind-bow.gomix.me/twitch-api/streams/' + user).then(function(response) {
        localStorage.setItem(user, response));
    }
}

…Well anyway, decided not to use localStorage (yet), but I got this working pretty well!

I have real data from api responses pushing into an array of objects on the data property accounts and the view will render a chunk of HTML from an _js file for each. Current problem is to get view.render to run only when all the data is collected.

Another promise?

Then I need to write the refresh function and get stream-data and then add logic that acts on whether the stream is live or not.

FCC - twitch viewer II

13:00
Day two, and my clarity and resolve is already under assault!

I got a little bogged down into how to display an svg logo (abandoned now), and I find myself dithering over whether to have 2 cumulative filters for online status (on, off, both) or just 3 separate filters.

I guess this is appropriate since it’s part of the UI, which is the phase I’m working in. But at the moment I seem to be mocking up the mockup, still identifying which things I need to include for functional purposes and unsure how they fall out of the API responses.

Writing this helps. I’ll push on with bare-bones component placeholders and not worry about styling for now.

Next I’ll have a pass at the API call and see if I it feels like I’m on the right track.

13:37

Templated the userBox in html. In addition to the container box there are at least three subcomponents. I don’t really want to have to write all those createElement statements in the render function, so for the next 20 minutes I’m going to look into html templates.

13:56
Watched this.
Should I have a go?! Why not!

14:51

OK. This seems to work now:

  • copied the underscore.js dev file into my project folder
  • referenced it in the script
  • used the code under the video in the link above to create my template:
  render() {
    let userHTML = _.template(
      '<div class="userBox">' +
        '<img class="avatar" />' +
        '<div class="userText"><%= userName %></div>' +
        '<img class="statusIcon" />' +
      '</div>'
    );

  let toAppendString = '';

  for (i=0; i < data.accounts.length ; i++) {
  toAppendString += userHTML(data.accounts[i]);
}  document.getElementById('container').insertAdjacentHTML('beforeend', toAppendString);
  }

So, what it does is make a string then iterate over the data object appending variants on the template, then renders the whole block as HTML. Wonder if that’ll cause me problems later? Oh, well, for now it’s happy days!

Apart from using _js, the only new thing here is the insertAdjacentHTML method. I suppose I ought to look into the spec later.

15:20

So, feels pretty good. Major lessons include:

  • don’t be scared of new things (when’ll that sink in?)
  • timeboxing might help me not be scared to try but also not dive too deep on first attempt
  • (spec) have something I’m confident I can be successful at as a back up before trying something dodgy?

Now I’m going to polish up the UI a bit since I’m reasonably confident I can work with what I have so far.

Todo

  • check insertAdjacentHTML spec
  • read the _js source code please
  • figure out, if I’m using _js, I might as well make the most of it so what else can I do with it?

FCC Project - Twitch.tv

Hot on the heels of the Wikipedia viewer, the next exercise is twitch.tv stream.

I’m officially starting this today at 11:00, so I might even log the number of hours I spend on it.

In line with what I’ve learned in the last two projects, I’m going to design the UI first:

UI

  • User Story: I can see whether Free Code Camp is currently streaming on Twitch.tv.
  • User Story: I can click the status output and be sent directly to the Free Code Camp’s Twitch.tv channel.
  • User Story: I will see a placeholder notification if a streamer has closed their Twitch account (or the account never existed). You can verify this works by adding brunofin and comster404 to your array of Twitch streamers
  • Hint: See an example call to Twitch.tv’s JSONP API at http://forum.freecodecamp.com/t/use-the-twitchtv-json-api/19541.

1) Display list of twitch accounts

1.1) filterable by:

  • all
  • online
  • offline

1.2) online user listings should display further details of what they are playing
1.3) listings should include the user’s avatar
1.4) the user account/avatar/whole listing should link straight to the twitch page

That’s probably enough to get going.

Log

11:30 - account set up, couple of users followed
11:50 - some distractions… Plan approach:

1) mock up interface - attempt mobile first?
2) MVC shell
3) API interactions - this is going to be the hardest bit. Get promises working early on, I say.

12:05 - get distracted by thoughts of a whisky app. aaargh

12:19 - have created a directory and a github repo. added skeleton elements. Need to design my components now.

Wednesday 24 May 2017

Free Code Camp Project - Wikipedia Viewer

OK, I really enjoyed this one. The scope was nicely limited and I felt like I knew enough to chomp through it in a pretty workmanlike way.

The only point I got bogged down was in the construction of the api query, and that’s the real purpose of the exercise, so that’s fine. And even at that I wasn’t too phased by it.

So here’s how things went:

Having done the Design Patterns course on Udacity (well, the first part, anyway!), I was keen to apply the MVC model.

1) I mocked up the main elements of my viewer - title, search field, random button.

2) Made a shell MVC structure, sticking in placeholders for functions I knew I’d need and as they came up

3) Added the functionality to track user input and grab it with a Submit function

4) Figured out how to parse the user input into the API call

5) tinkered with the API until I was getting something back (though not what I wanted just yet!)

6) Worked on a preliminary approach to the render function

7) Figured out how to use a promise to call view.render on API resolve

8) Did more research on the API to get the right query.

9) Added logic to parse the right API results to the render function and styled it

10) worked back over secondary functionality and todo items I’d come up with along the way.

and

There was a fair amount of interplay between steps 4-8, but I tried to be methodical and avoid work that might need to be replaced by a change in other parts of the program.

I used git obsessively for this, making branches for all kinds of trivial stuff that really didn’t need it - but it was an exercise in discipline and avoiding my own errors.

A few times I managed to catch myself on the the master branch, randomly tweaking things in dangerous fashion. When I did I got things back to a stable condition, branched, resolved the matter, merged and deleted.

Here’s the finished result

It’s nothing special, but I think it’s reasonably solid and I’m proud that I didn’t crib code to any significant extent (there’s one thing I think I need to double check).

There’s outstanding issues on my todo, most important of which is adding breakpoints for mobile use, but TBH I’m probably going to do that on future projects intsead.

Be realistic, right?

Weather App - conclusion

I’ve not really kept up on documenting my progress on this - got distracted with one thing and another. But for continuity, here’s how things ended up:

The app is finished (under some definition of ‘done’); it meets the requirements as laid out and superficially has the right functionality.

Here’s a link

It’s pretty crappy. But TBH I’ve extracted the lessons I need to from the project and I’ve moved on and done better work. I don’t think there’s much value in making this one better, though it’s painfully sloppy!

Here’s my main lessons:

Do

UI requirements first

  • gives structure to the project and is easier and more exciting at the beginning when energy and optimism are high.
  • creating placeholder values starts you thinking about what functional structure is needed
  • slotting real functions into an existing framework is easier than building a framework around functional components
  • adding real functionality to a pretty mockup feels like turning pinnochio into a real boy
  • good looking mock up IS a definition of done, right? right?
  • trying to polish a turd at the end of an exhausting mental process is dispiriting

Use MVC

  • I need structure.
  • Once the UI is mocked up, how is it kept separate from all the other junk I want to layer on top?
  • It just makes sense

Don’t

  • start working on other projects before this one is finished
  • use codepen for work that requires significant coding work
  • … or at least, don’t work directly in codepen. frustrating
  • leave big boring bits of straightforward logic to the end. doing conditionals for the backgrounds and icons was a chore

Conclusion

Pretty basic stuff, but useful to really know it from experience. I applied much better discipline in my next project, for which, see next post.

Tuesday 2 May 2017

Weather App - code execution

State of Play

I made good progress yesterday - really pleased I started with the presentational aspect and got an adequate level of responsiveness in at an early stage, along with the layout. My codepen got picked for the front page almost as soon as I had these in place - I don’t know if that was a mistake or just because I’d laid it out reasonably well and used decent placeholder styling.

I also think being very systematic about the the presentational components is good practice because you end up with a very modular framework. Because I wasn’t sure exactly what the subsequent implementation would look like, I couldn’t make any assumptions about where and how I needed to manipulate values, so I ended up defining variables for:

  • each DOM element
  • each component value to extract from API object
  • each subcomponent of the composite value to be displayed (eg tempand temp-unit)
  • each weather type before an image is selected

All of which means I have very granular control of how the data will be combined functionally - it just becomes a matter of plugging things together.

Because it was all being done in abstract rather than ad hoc it can be reasonably clearly structured.

So the app has a solid foundation. I struggled for ages to get navigator.geolocation.getCurrentPosition to work, but the lesson there is to read the API. The key for me was this stackoverflow answer:

What you want and what you can have are two different things. Almost everything in Cordova/Phonegap is asynchronous, which means you cannot do var p = navigator.geolocation.getCurrentPosition(onSuccess, onError);. You have to use the onSuccess function to return the value.

If there is no error and you are in onSuccess, this is where your code continues, and will use the position returned. Which means you probably have to refactor your code and/or rethink your workflow.

Once I understood that, I got back on track.

Current Problem

When the page loads all the functions and values get hoisted and I end up with my coordinates variable undefined. I need to figure out how to execute the code in the right order so that the page defers creating the DOM until the ajax request returns, or executes an update function once to insert the values after the page loads.

  • promises?
  • .then statement? (is that the same as a promise?)
  • some sort of chained or bound execution sequence, where the update function is created following the API call>

Log

Not making any progress with that so I turn my attention to some other features until someone arrives whose advice I can ask.

Temp conversion

The temp is given in kelvin, so I apply some conversions I found.

Used a couple of unfamiliar methods - .toFixed(1) so I don’t lose the decimal place (I think I can live without rounding it) and parseFloat because I want it to be a number and not a string like toFixed returns.

That was easy!

Main Issue Update

B came and helped me look at the code and (we think) identify the problem, which is this:

 function getWeather(address) {
      var jhr = new XMLHttpRequest();
      jhr.open("GET", proxyCORS + address, false);
      jhr.send();
      console.log(jhr.status);
      console.log(jhr.response);
      response = jhr.response;
      update();
   } 

jhr the new XMLHttpRequest object has an onLoad property that determines the consequences of the call being answered. At the moment I’m doing nothing with this, so when jhr.send is invoked it does, indeed, send the http request, but then immediately executes the subsequent code without waiting for a response. Looking at it like that, response is undefined because at the time it’s assigned jhr.response is undefined.

I’m going to hack my way through this for the purposes of the project, but I should come back and look at using promises at some point.

Log (resumed)

Long hours and many mis-steps later, I finally got it so the app is updating from the API’s response message. I had some help, too in verying degrees.

The key points are:

  • set an onload method for the https object - it fires automatically on receiving response
  • if successful, pass the object to the update function but not before it’s JSON.parsed
  • make sure the local and global variables are in the right places

I also stopped messing around with functions that convert the temperature on the fly and just put both variants into an object with a toggle function that switches between them.

ToDo

  • background images change in response to weather category
  • improve the UI - two lines for location? flag?
  • weather icon?

There’s an MVP to be had here - tick off the user stories and call it a day.

I”m also tempted to rewrite it as a react app because all a lot of the problems I’ve had have fel like react would solve them: component lifecycles for API requests, state for temperature variants and api data, structural clarity etc.

Hmmm.

Starting Weather App

Prep

Started with a Trello board listing user stories.
Broke down each one into as many considerations as necessary at this stage.

Decide ‘weather’ to use React.

Against

  • clearly overkill
  • very little state to manage
  • smallest scale app imaginable!
  • no frequent re-renders
  • overly complex

For

  • extensibility of app
  • better example for portfolio
  • I want to learn React!
  • I’m probably as good with it as vanilla web-dev
  • I want to

Decision

No. I will go for the simplest implementation possible at first. But I will think about how it would work with React, make notes relevant to that conversion, and consider a flashy show-off portfolio version at a later date.

Start

Presentation was my weak point in the quotes project. I plan to get my presentation defined first for this, with the assumption that the logical components will slot into it more easily than trying to design around functionality.

This is also consistent with a react-style approach.

Create a layout on codepen

Make a basic responsive framework by copying the settings from that earlier pen Piotr helped me with.

Basic frame

Uses a full screen solution from Stack Overflow. No idea if it’s ‘good’.

Key to maximise bg image was 100vh as the height of the div to which it was set:

.background {
   height: 100vh ;
   background-image: url('https://static.pexels.com/photos/38928/pexels-photo-38928.jpeg');
   background-size: cover;
}

Add placeholder boxes

Now at the point when I need to add placeholder boxes, values, it’s probably time to investigate the API to see what data I’ll have to play with. At minimum, I need:

-location
- prose description
- icon
- temperature display
- temperature button

temp display and button should be two components composed (keyboard shortcut for change unit as well as button? Two buttons - F and C? How to communicate best via the UI?)

conclude this section

  • Responsive background image is set via CSS and is injected by js. Ready to be acted upon by a function.
  • mobile-first approach stacks the info boxes vertically.
  • text size is responsive to the screen width.
  • values of location, weather and temperature are derived from a dummy JSON object - ready to receive actual API responses.

Start App Logic

I have already separated my values out into (what seems to me) well-defined variables.
I ought to be able to manipulate all the relevant aspects relatively easily once I am able to retrieve real data.

The current challenges are:

  • get the user’s location from their IP address (need to handle errors on this - add manual input via dropdown on fail? react starting to look good!)
  • parse location info and make API call

get location from IP

var x = document.getElementById("demo");

function getLocation() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(showPosition);
    } 
   else {
        x.innerHTML = "Geolocation is not supported by this browser.";
    }
}

function showPosition(position) {
    x.innerHTML = "Latitude: " + position.coords.latitude + 
    "<br>Longitude: " + position.coords.longitude; 
}

END OF DAY 1

Notes & follow-up actions

  • look up the inherit CSS property
  • use class or id for things like app and background? clearly unique elements
  • preferences for unicode display formats