initial commit

This commit is contained in:
Senad Uka
2017-09-24 10:12:44 +02:00
parent 05c9ffc3a3
commit 4a3349e500
125 changed files with 10992 additions and 0 deletions

View File

View File

@@ -0,0 +1,17 @@
// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
//= require bootstrap

View File

@@ -0,0 +1,15 @@
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require_self
*= require_tree .
*/
@import "bootstrap";
@import "bootstrap/theme"

View File

@@ -0,0 +1,12 @@
// Place all the styles related to the Recipes controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/
body {
padding-top: 60px;
}
@media (max-width: 979px) {
body {
padding-top: 0px;
}
}

View File

@@ -0,0 +1,5 @@
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
end

View File

@@ -0,0 +1,71 @@
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
# GET /recipes
# GET /recipes.json
def index
@recipes = Recipe.all
end
# GET /recipes/1
# GET /recipes/1.json
def show
end
# GET /recipes/new
def new
@recipe = Recipe.new
end
# GET /recipes/1/edit
def edit
@samplepis
end
# POST /recipes
def create
@recipe = Recipe.new(recipe_params)
@recipe.scrape!
respond_to do |format|
if @recipe.save
format.html { redirect_to edit_recipe_path(@recipe), notice: 'Recipe was successfully created.' }
else
format.html { render action: 'new' }
end
end
end
# PATCH/PUT /recipes/1
# PATCH/PUT /recipes/1.json
def update
respond_to do |format|
if @recipe.update(recipe_params)
format.html { render action: 'edit', notice: 'Recipe was successfully updated.' }
format.json { head :no_content }
format.html { render action: 'edit' }
end
end
end
# DELETE /recipes/1
# DELETE /recipes/1.json
def destroy
@recipe.destroy
respond_to do |format|
format.html { redirect_to recipes_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_recipe
@recipe = Recipe.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def recipe_params
params.require(:recipe).permit(:name, :duration, :ingredients, :process, :picture_url, :original_url)
end
end

View File

@@ -0,0 +1,2 @@
module ApplicationHelper
end

View File

@@ -0,0 +1,2 @@
module RecipesHelper
end

View File

View File

View File

@@ -0,0 +1,72 @@
# encoding: utf-8
class Recipe < ActiveRecord::Base
before_create :setup_ordinal
def scrape!
scrape_document Nokogiri::HTML(open(self.original_url))
end
def scrape_document(doc)
r = self
r.name = doc.css('h1')[0].text.to_s.strip
r.duration = doc.xpath('//*[@id="recipe_preparation"]/div[1]/dl/dd[1]/text()').text.to_s.strip
r.process = doc.css(".recipe_step_description").map { |el| el.text.to_s.strip }.join("\n")
r.ingredients = doc.xpath('//*[@id="recipe_ingredients"]/ul/li').map { |x|
if x.css('span').length == 2
x.css('span')[0].text.strip + " | " + x.css('span')[1].text.strip
else
nil
end
}.compact.join("\n")
end
def search_url
name = URI::escape(self.name)
return "https://www.google.com/search?q=#{name}&source=lnms&tbm=isch&sa=X"
end
def ingredients_fit?
ing = self.ingredients.to_s.split("\n")
return false if ing.length < 1
return false if ing.length > 20
return false unless ing.select { |x| x.length > 22 }.empty?
true
end
def process_fits?
pro = self.process.to_s
return false if pro.length < 1
return false if pro.length > 15 * 44
true
end
def picture_ok?
!picture_url.to_s.include?("coolinarika") and picture_url.to_s.length > 0
end
def is_it_valid?
ingredients_fit? and process_fits? and name.to_s.length <= 14 and duration.to_s.length <= 10 and picture_ok?
end
def ordinal_date
Date.ordinal(2014,self.ordinal)
end
def ingredients_safe
unless self.ingredients.nil?
ingred = self.ingredients.gsub("\r\n", "/").gsub("|"," ").gsub("/", "\n")
return ingred
end
""
end
private
def setup_ordinal
self.ordinal = Recipe.all.length + 1
end
end

View File

@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="bs_BA">
<head>
<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="">
<title>Theme Template for Bootstrap</title>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js" type="text/javascript"></script>
<![endif]-->
<%= stylesheet_link_tag "application", media: "all" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body role="document">
<!-- Fixed navbar -->
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" target="_blank" href="http://www.coolinarika.com">Šta za ručak?</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Recepti<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="<%= recipes_path %>">Lista</a></li>
<li><a href="<%= new_recipe_path %>">Novi recept</a></li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</div>
<div class="container" role="main">
<%= yield %>
</div> <!-- /container -->
</body>
</html>

View File

@@ -0,0 +1,41 @@
<%= form_for(@recipe) do |f| %>
<% if @recipe.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
<ul>
<% @recipe.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :name %><br>
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :duration %><br>
<%= f.text_field :duration %>
</div>
<div class="field">
<%= f.label :ingredients %><br>
<%= f.text_field :ingredients %>
</div>
<div class="field">
<%= f.label :process %><br>
<%= f.text_field :process %>
</div>
<div class="field">
<%= f.label :picture_url %><br>
<%= f.text_field :picture_url %>
</div>
<div class="field">
<%= f.label :original_url %><br>
<%= f.text_field :original_url %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>

View File

@@ -0,0 +1,98 @@
<h1>Promjena recepta</h1>
<%= form_for(@recipe, html: {role: "form"}) do |f| %>
<div class="form_group row">
<%= f.label :name, class: "col-md-1 control-label" %>
<div class="col-md-4">
<%= f.text_field :name, class: "form-control" %>
</div>
<% if @recipe.name.to_s.length > 14 %>
<div id="name" class="col-md-4 danger" >
Ime je predugo - skrati do 14 slova!
</div>
<% end %>
</div>
<div class="form_group row">
<%= f.label :duration, class: "col-md-1 control-label" %>
<div class="col-md-4">
<%= f.text_field :duration, class: "form-control" %>
</div>
<% if @recipe.duration.to_s.length > 10 %>
<div id="duration" class="col-md-4 danger">
Dužina je prevelika - skrati do 10 slova!
</div>
<% end %>
</div>
<div class="form_group row">
<%= f.label :ingredients, class: "col-md-1 control-label" %>
<div class="col-md-4">
<%= f.text_area :ingredients, class: "form-control", rows: "10" %>
</div>
<% unless @recipe.ingredients_fit? %>
<div id="ingredients" class="col-md-4 danger">
Ne smije biti više od 20 sastojaka i svaki sastojak ne smije imati više od 22 znaka (slova, broja, praznine itd.).
Skrati ili izbaci neke sastojke.
</div>
<% end %>
</div>
<div class="form_group row">
<%= f.label :process, class: "col-md-1 control-label" %>
<div class="col-md-4">
<%= f.text_area :process , class: "form-control" , rows: "15" %>
</div>
<% unless @recipe.process_fits? %>
<div id="process" class="col-md-4 danger">
Priprema mora imati najvise 15 redova a ni jedan red ne smije biti duzi od 44 slova.
Skrati malo.
</div>
<% end %>
</div>
<div class="form_group row ">
<div class="col-md-1">
Slika
</div>
<div class="col-md-4">
<%= link_to(@recipe.picture_url, class: "thumbnail") do %>
<%= image_tag(@recipe.picture_url) %>
<% end %>
<%= link_to(" Nađi drugu sliku", @recipe.search_url, target: "_blank" ) %>
</div>
</div>
<div class="form_group row">
<%= f.label :picture_url, class: "col-md-1 control-label" %>
<div class="col-md-4">
<%= f.text_field :picture_url, class: "form-control" %>
</div>
<% unless @recipe.picture_ok? %>
<div id="picture" class="col-md-4 danger">
Slika mora biti izabrana!
Slika ne smije biti sa stranice coolinarika. Nadji drugu.
</div>
<% end %>
</div>
<div class="form_group row">
<%= f.submit class: "btn btn-success" %>
</div>
<% end %>

View File

@@ -0,0 +1,34 @@
<div class="row">
<div class="col-md-8">
<h1>Recepti</h1>
<table class="table">
<thead>
<tr>
<th>Ime</th>
<th>Datum</th>
<th>Ispravan?</th>
<th></th>
</tr>
</thead>
<tbody>
<% @recipes.each do |recipe| %>
<tr>
<td><%= recipe.name %></td>
<td><%= recipe.ordinal_date %></td>
<td><%= (recipe.is_it_valid?) ? "DA" : "NE" %></td>
<td><%= link_to 'Popravi recept', edit_recipe_path(recipe) %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'Napravi novi recept', new_recipe_path %>
</div>
</div>

View File

@@ -0,0 +1,4 @@
json.array!(@recipes) do |recipe|
json.extract! recipe, :id, :name, :duration, :ingredients, :process, :picture_url, :original_url
json.url recipe_url(recipe, format: :json)
end

View File

@@ -0,0 +1,16 @@
<h1>Pravljenje Novog Recepta</h1>
<%= form_for(@recipe, html: {role: "form"}) do |f| %>
<div class="form_group row">
<%= f.label :original_url, class: "col-md-1 control-label" %>
<div class="col-md-6">
<%= f.url_field :original_url, class: "form-control" %>
</div>
<div class="col-md-1">
<%= f.submit class: "btn btn-success" %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,34 @@
<p id="notice"><%= notice %></p>
<p>
<strong>Name:</strong>
<%= @recipe.name %>
</p>
<p>
<strong>Duration:</strong>
<%= @recipe.duration %>
</p>
<p>
<strong>Ingredients:</strong>
<%= @recipe.ingredients %>
</p>
<p>
<strong>Process:</strong>
<%= @recipe.process %>
</p>
<p>
<strong>Picture url:</strong>
<%= @recipe.picture_url %>
</p>
<p>
<strong>Original url:</strong>
<%= @recipe.original_url %>
</p>
<%= link_to 'Edit', edit_recipe_path(@recipe) %> |
<%= link_to 'Back', recipes_path %>

View File

@@ -0,0 +1 @@
json.extract! @recipe, :id, :name, :duration, :ingredients, :process, :picture_url, :original_url, :created_at, :updated_at