**View concepts we will cover: **
- more practice with the Foundation CSS framework and writing minimal layout css
- using partials to encapsulate parts of your layout
- using partials and passing in
local
variables for repeating elements - using font-awesome icon set for rapid prototyping
Now it's time to turn all that great data into something more "web-appy".
Lets start with the main application layout.erb
file in your views
directory. It will start with a few CDN files for Foundation, Font Awesome for icons, and jQuery. We will talk more throughout the course about why the javascript files should always go at the bottom.
Also we will link in a couple of local files stored in the public
directory for custom CSS and javascript. Sinatra serves files and folders it finds in the public folder (You will find that Rails also does this).
Lastly, lets make a basic Foundation structure. We are going after this layout for the getfeed/:username/:reponame
route.
Lets liberally steal a common social feed design pattern from the web:
First let's be clear. We are not taking their code. We can make this same structure with partials and Foundation pretty fast with minimal CSS. **Often when you take code from the web it is more trouble than it's worth.** And it is inherently not broken up into partials well.Add this to your layout.erb
file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>The Repo Feeder</title>
<link rel="shortcut icon" href="/images/feedIcon.png" type="image/x-icon" />
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/foundation/5.1.1/css/foundation.min.css">
<link href="//netdna.bootstrapcdn.com/font-awesome/4.0.3/css/font-awesome.css" rel="stylesheet">
<link rel="stylesheet" href="/application.css" type="text/css" />
</head>
<body>
<header class="row">
<%%= erb :_header %>
</header>
<section class="row">
<div class="large-3 columns">
<%%= erb :_user_info %>
</div>
<div class="large-6 columns activity-feed">
<%%= yield %>
</div>
<div class="large-3 columns">
<%%= erb :_ads_left_column %>
</div>
</section>
<footer class="row">
<%%= erb :_footer %>
</footer>
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery/2.0.3/jquery-2.0.3.js"></script>
<script type="text/javascript" src="/application.js"></script>
<%%# possibly add in foundation js here - not necessary %>
</body>
</html>
In the <body>
tags, we put in a <header>
and <footer>
tag that merely create Foundation "row" and set up a place for us to put in the erb partials to the other files. We can go ahead and create those files (_header.erb
and _footer.erb
) in the view
folder. The underscore is merely a file naming convention for partials. (This should also keep those partials from ever being loaded in the browser by themselves.)
Next, focus on the vertical middle section between the <header>
and the <footer>
. The meat of the layout.
Again we will start by making a 12-column foundation class="row"
on the middle <section>
tag. We want 3 columns for the two sidebars with the bigger middle of 6 columns. So to say it another way we need to add 3 columns on the left for the profile, 6 columns in the middle for the feed and for any parts of the app that I want to pull in, and 3 columns on the right side for the ads.
Also go ahead and create the files for those partials in your view
folder: _user_info.erb
and _ads_left_column.erb
. We will start filling in all these partials in a second, but notice that we are leaving the middle column open for whatever erb
the main server.rb
file gives us for the given route we are on, such as erb :feed
with the <%= yield %>
code. So we can use this for other routes like creating a post route so we can search for another repo.
Lets visit the header and footer partials and put in some code.
Header:
<div class="large-8 columns">
<h1><i class="fa fa-rss-square"></i> The Repo Feeder</h1>
</div>
<div class="large-4 columns">
<p class="repo-name">
<i class="fa fa-github"></i> <strong>Repo:</strong> <a href="http://github.com/<%%= params[:username] %>/<%%= params[:reponame] %>" target="_blank">
<%%= params[:username] %> / <%= params[:reponame] %>
</a>
</p>
</div>
<hr />
And the Footer:
<hr />
<h1>Thanks for feeding!</h1>
Then let's put in some code for those sidebars, and lastly we can focus on the feed:
Here is the profile sidebar
<%%# if the user info is empty put in the dummy sidebar to impress the UI team %>
<%% if @user_info.empty? %>
<img src="http://placekitten.com/g/200/300" />
<h3>Dummy User</h3>
<p>
<strong><i class="fa fa-envelope"></i> Email</strong>
<a href="mailto:[email protected]">[email protected]</a>
</p>
<%% else %>
<%%# implement your own code to pull in a user's profile data here %>
<%% end %>
And here is some dummy ads (bonus points for DRYing up this code! ... any repeating code should really start to scare you):
<div class="ad-wrapper">
<h5>
<i class="fa fa-tags"></i> Buy This!
<a href="#" class="closer"><i class="fa fa-power-off"></i></a>
</h5>
<img src="http://placehold.it/220x240&text=[ad]" />
<br clear="all" />
</div>
<div class="ad-wrapper">
<h5>
<i class="fa fa-tags"></i> Also Buy This!
<a href="#" class="closer"><i class="fa fa-power-off"></i></a>
</h5>
<img src="http://placehold.it/220x240&text=[ad]" />
<br clear="all" />
</div>
<div class="ad-wrapper">
<h5>
<i class="fa fa-tags"></i> Don't forget about this!
<a href="#" class="closer"><i class="fa fa-power-off"></i></a>
</h5>
<img src="http://placehold.it/220x240&text=[ad]" />
</div>
Here is some code for the feed:
<%% @commits_hash.each do |c| %>
<%%= erb :_feed_item, locals: {commit: c} %>
<%% end %>
Since the server.rb
file passes to feed.erb
, we won't consider it a partial in the views
folder (and not use the partial _partialname.erb
naming scheme ). This is certainly debatable - remember with partials and CSS: you are creating your own craziness
to have to maintain.
We are doing something neat here. We are essentially using partials to template inside of an erb each
loop. So each time it loops through the @commits_hash
array, it passes in a local variable called commit
to the _feed_item.erb
partial. The local key commit
takes in the commit object that is assigned to the value of c
.
So now we just need 1 of those feed items as a template for all of them.
Code for _feed_item.erb
:
<div class="row feed-item">
<div class="large-3 columns">
<a href="http://github.com/<%%= commit["author"]["login"] %>" target="_blank">
<img src="https://secure.gravatar.com/avatar/<%%= commit["author"]["gravatar_id"] %>" />
</a>
</div>
<div class="large-9 columns">
<div>
<strong>Author:</strong>
<a href="http://github.com/<%%= commit["author"]["login"] %>" target="_blank">
<%%= commit["commit"]["author"]["name"] %>
</a>
<br />
</div>
<div>
<strong>Commit Message:</strong> <%%= commit["commit"]["message"] %>
<br /><br />
</div>
<div>
<i class="fa fa-code"></i><a href="<%%= commit["html_url"] %>" target="_blank">View Commit Diff</a>
<span style="float:right;"><strong><small><i class="fa fa-clock-o"></i> <%%= DateTime.iso8601(commit["commit"]["author"]["date"]).strftime("%m/%d/%Y at %I:%M%p") %></small></strong></span>
</div>
</div>
</div>
This is still using many foundation column layout principals, by creating a new 12 column row inside of the 6 columns in the middle. Then we create 3 and 9 columns so the profile picture is held on the left and we can pull in items like the user's name, commit message, link to the git diff, and time-stamp on the left side. (Bonus points for fixing the inline style on the timestamp. Also look at the ruby docs for what you can do with string of time.)
Lastly, lets add some styles to pretty it up.
In application.css
in the public folder, add in these styles one at a time and think about what they are doing. Also feel free to give this your own twist.
/* Application specific CSS */
/* make the background grey */
body { background: #eee; }
/* move the repo name down from the top - move over vertical-align! */
header p.repo-name { margin-top: 30px; }
/* make the main logo mks blue */
header h1 {
color: #1189d9;
text-shadow: 2px 2px 2px #FFFFFF;
}
/* nice little feed boxes in the middle column */
.feed-item {
background: #fff;
padding: 20px 0;
/* make the border pretty */
box-shadow: 0 1px 1px rgba(0,0,0,0.2);
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
border-radius: 2px;
}
/* spread out the feed boxes */
.row.feed-item { margin-bottom: 10px; }
/* put some space between the code icon and the link to diff */
.feed-item i.fa-code { margin-right: 10px; }
/* put the closer X in the top right of the ad */
.closer { float: right; }
/* center the text in the footer */
footer h1 { text-align: center; }
And for good measure make sure you have a favicon in the public/images
folder, so that the link in the <head>
tag has something to grab. It an really be any png that is around 32 by 32. If you call it feedIcon.png
, then you don't have to adjust the file name in the <head>
tag.
Also this site doesn't move yet. Let's at least sprinkle on one jQuery event.
Go to application.js
file and add:
// Application specific JS
// set up an ad closer click handler
// that slides up the add on click
$(".ad-wrapper").on("click", ".closer", function(e){
e.preventDefault();
$(this).parents(".ad-wrapper").slideUp();
});
This will allow the user to hide the ads on the left side by clicking the on/off icon.
That is about it for the layout at this point. Especially in the extensions start to make this site your own.
By adding in a couple input boxes and a submit button at the top of the feed 6 columns, you can post to another route with the same structure post '/feed/:username/:reponame'
, you can then have another erb file like post_feed.erb
. Then you can use the same partials you already have to print out a brand new repo that is sent through the <form>
. Happy view script hacking!