In the last episode, I pointed out that this wasn't CSS Sips. However, I'm kind of miffed that ElixirFriends looks ugly, so today we'll look at integrating Semantic UI into it and removing the CRUD actions that we don't really need. Let's get started.

NOTE: There's definitely stuff in this video that's not in the script; specifically, I add styles for pagination and support for active links at the end of the video.


Well, so it's not entirely CSS related. First off, we'll remove the CRUD bits from posts...

  scope "/", ElixirFriends do
    pipe_through :browser # Use the default browser stack

    get "/", PostController, :index
    resources "/posts", PostController, only: [:show]
      <td class="text-right">
        <%= link "Show", to: post_path(@conn, :show, post), class: "btn btn-default btn-xs" %>

Next we'll install Semantic UI.

npm install semantic-ui --save
cd semantic
gulp build

We'll copy the distribution into the vendor directory:

cp semantic/dist/semantic.js web/static/vendor/
cp semantic/dist/semantic.css web/static/vendor/

Semantic UI assumes we have jQuery:

cd web/static/vendor

Let's clear out the existing bootstrappy Phoenix CSS:

vim web/static/css/app.css

((( clear it out )))

Now we want to just show a card for each post:

<h2>Look at all these people!  They came together because of <%= link "Elixir!", to: "" %></h2>

<%= pagination_links(@posts_page) %>
<div class="ui grid">
  <%= for post <- @posts_page.entries do %>
    <div class="four wide column">
      <div class="ui card">
        <div class="image">
          <img src='<%= post.image_url %>' />
        <div class="content">
          <div class="header">
            elixirsips # here we want to show a username but we aren't storing this yet
          <div class="meta">
            <span class="date"><%= post.inserted_at %></span>
          <div class="description">
            <%= post.content %>
  <% end %>
<%= pagination_links(@posts_page) %>

We'll also tweak the application layout a bit...

<!DOCTYPE html>
<html lang="en">
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="">
    <meta name="author" content="">

    <link rel="stylesheet" href="<%= static_path(@conn, "/css/app.css") %>">

    <div class="ui container">
      <%= @inner %>
    <script src="<%= static_path(@conn, "/js/app.js") %>"></script>

OK now we actually need to do some elixir. We need to store the username on posts to show it, so we'll add a migration to store that:

mix ecto.gen.migration add_username_to_posts
defmodule ElixirFriends.Repo.Migrations.AddUsernameToPosts do
  use Ecto.Migration

  def change do
    alter table(:posts) do
      add :username, :string

Alright, so we've added username as a string to the database table. We also need to add it to the struct, so open up web/models/post.ex and we'll do that:

  schema "posts" do
    field :image_url, :string
    field :content, :string
    field :source_url, :string
    field :username, :string


Alright, now we'll modify the Streamer to store the username as well:

  defp store_tweet(%ExTwitter.Model.Tweet{}=tweet) do
    post = %ElixirFriends.Post{
      image_url: first_photo(tweet).media_url,
      content: tweet.text,
      source_url: first_photo(tweet).expanded_url,
      username: tweet.user.screen_name

Now that that's done, we're storing the usernames as well as the tweets now for display. We'll add it to the view and then check it out...

  <div class="header">
    <%= post.username %>
mix phoenix.server