Thursday 1 June 2017

FCC - twitch viewer VI

After clawing back some territory yesterday, I’m back in the doldrums.

If I’m honest with myself, I think I’ve been trying to cut corners and do things fast. I figured I could just slap the api response objects into data and it’d all be there for access later.

Now I’m thinking I need to backpeddle and populate the data object in a much more methodical way.

I need to create an object class that has the specific properties I need and then populate that with the results of each API call, I think.

It might even be time to take a look at the Udacity OOP course before I continue.

What I was right about was doing the UI first! The thought of trying to hammer that out after going through all these logic hangups is just soul-destroying!

If I don’t make significant progress in the next hour or two I’m going to put this on hold and do the OOP course.


from users:
name
display_name
logo

from streams:
null ||

game
preview.medium

OK. Done all that. Works fine. Much more manageable. The user data is managed on api resolve, so it can construct user objects for null responses - these can now be rendered appropriately (I’ve yet to add all the logic).

That wasn’t so hard!

Now I need to update my filter functions and I should be pretty near the end.

Hyperlinks. I need to add those.

Day 6

05:42

Took a bit longer to rework the filter function than I thought. I was hungover, engaging in the code pod meetup and generally not focused.

Eventually realised that I was pushing my .filter output to an array when .filter already returns an array. D’Oh!.

Now I need to sort the scaling on the images I’m using when people are streaming or not.

DECISION: I am currently trying to use a “no broadcast” icon for not and a screengrab url from the API if the user is streaming. This is a random, last minute change I included ‘cause I thought it would be cool. I need to abandon that for my 2 identically-sized icons. It is not a functional requirement, whereas I have other features that are.

That is the correct thing to do!

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?