diff --git a/Gemfile b/Gemfile index bf629fa..61ea1c7 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,13 @@ gem 'rails', '~> 5.2.2' gem 'pg', '>= 0.18', '< 2.0' # Use Puma as the app server gem 'puma', '~> 3.11' +gem 'devise', '~> 4.6', '>= 4.6.1' + +gem 'carrierwave', '~> 0.10.0' +gem 'mini_magick', '~> 4.3' + +gem 'bootstrap' +gem 'jquery-rails' # Use SCSS for stylesheets gem 'sass-rails', '~> 5.0' # Use Uglifier as compressor for JavaScript assets diff --git a/Gemfile.lock b/Gemfile.lock index adbb6d4..d77806d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -47,9 +47,16 @@ GEM archive-zip (0.12.0) io-like (~> 0.3.0) arel (9.0.0) + autoprefixer-rails (9.4.10.2) + execjs + bcrypt (3.1.12) bindex (0.5.0) bootsnap (1.4.1) msgpack (~> 1.0) + bootstrap (4.3.1) + autoprefixer-rails (>= 9.1.0) + popper_js (>= 1.14.3, < 2) + sassc-rails (>= 2.0.0) builder (3.2.3) byebug (11.0.0) capybara (3.14.0) @@ -60,6 +67,11 @@ GEM rack-test (>= 0.6.3) regexp_parser (~> 1.2) xpath (~> 3.2) + carrierwave (0.10.0) + activemodel (>= 3.2.0) + activesupport (>= 3.2.0) + json (>= 1.7) + mime-types (>= 1.16) childprocess (0.9.0) ffi (~> 1.0, >= 1.0.11) chromedriver-helper (2.1.0) @@ -67,6 +79,12 @@ GEM nokogiri (~> 1.8) concurrent-ruby (1.1.4) crass (1.0.4) + devise (4.6.1) + bcrypt (~> 3.0) + orm_adapter (~> 0.1) + railties (>= 4.1.0, < 6.0) + responders + warden (~> 1.2.3) erubi (1.8.0) execjs (2.7.0) ffi (1.10.0) @@ -78,6 +96,11 @@ GEM jbuilder (2.8.0) activesupport (>= 4.2.0) multi_json (>= 1.2) + jquery-rails (4.3.3) + rails-dom-testing (>= 1, < 3) + railties (>= 4.2.0) + thor (>= 0.14, < 2.0) + json (2.2.0) listen (3.1.5) rb-fsevent (~> 0.9, >= 0.9.4) rb-inotify (~> 0.9, >= 0.9.7) @@ -90,7 +113,11 @@ GEM marcel (0.3.3) mimemagic (~> 0.3.2) method_source (0.9.2) + mime-types (3.2.2) + mime-types-data (~> 3.2015) + mime-types-data (3.2018.0812) mimemagic (0.3.3) + mini_magick (4.9.3) mini_mime (1.0.1) mini_portile2 (2.4.0) minitest (5.11.3) @@ -99,7 +126,9 @@ GEM nio4r (2.3.1) nokogiri (1.10.1) mini_portile2 (~> 2.4.0) + orm_adapter (0.5.0) pg (1.1.4) + popper_js (1.14.5) public_suffix (3.0.3) puma (3.12.0) rack (2.0.6) @@ -134,6 +163,9 @@ GEM rb-inotify (0.10.0) ffi (~> 1.0) regexp_parser (1.3.0) + responders (2.4.1) + actionpack (>= 4.2.0, < 6.0) + railties (>= 4.2.0, < 6.0) ruby_dep (1.5.0) rubyzip (1.2.2) sass (3.7.3) @@ -147,6 +179,15 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + sassc (2.0.1) + ffi (~> 1.9) + rake + sassc-rails (2.1.0) + railties (>= 4.0.0) + sassc (>= 2.0) + sprockets (> 3.0) + sprockets-rails + tilt selenium-webdriver (3.141.0) childprocess (~> 0.5) rubyzip (~> 1.2, >= 1.2.2) @@ -169,6 +210,8 @@ GEM thread_safe (~> 0.1) uglifier (4.1.20) execjs (>= 0.3.0, < 3) + warden (1.2.8) + rack (>= 2.0.6) web-console (3.7.0) actionview (>= 5.0) activemodel (>= 5.0) @@ -185,11 +228,16 @@ PLATFORMS DEPENDENCIES bootsnap (>= 1.1.0) + bootstrap byebug capybara (>= 2.15) + carrierwave (~> 0.10.0) chromedriver-helper + devise (~> 4.6, >= 4.6.1) jbuilder (~> 2.5) + jquery-rails listen (>= 3.0.5, < 3.2) + mini_magick (~> 4.3) pg (>= 0.18, < 2.0) puma (~> 3.11) rails (~> 5.2.2) diff --git a/app/assets/javascripts/books.js b/app/assets/javascripts/books.js new file mode 100644 index 0000000..dee720f --- /dev/null +++ b/app/assets/javascripts/books.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/comments.js b/app/assets/javascripts/comments.js new file mode 100644 index 0000000..dee720f --- /dev/null +++ b/app/assets/javascripts/comments.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/home.js b/app/assets/javascripts/home.js new file mode 100644 index 0000000..dee720f --- /dev/null +++ b/app/assets/javascripts/home.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.scss similarity index 91% rename from app/assets/stylesheets/application.css rename to app/assets/stylesheets/application.scss index d05ea0f..3ff9152 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.scss @@ -13,3 +13,7 @@ *= require_tree . *= require_self */ + + @import 'bootstrap'; + @import 'books.scss'; + @import 'home.scss'; diff --git a/app/assets/stylesheets/books.scss b/app/assets/stylesheets/books.scss new file mode 100644 index 0000000..42c3615 --- /dev/null +++ b/app/assets/stylesheets/books.scss @@ -0,0 +1,36 @@ +// Place all the styles related to the Books controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ +.header_table{ + background-color: rgb(192, 226, 245); + color: black; + font-size: 19px; + font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; +} + +.cell_table{ + background-color: rgba(241, 246, 248, 0.651); + font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; + font-size: 20px; + color: black; +} + +.My_book{ + font-family: 'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; + color: black; + font-size: 45px; + text-decoration: underline; +} +.operation_icon{ + background-color: rgb(109, 189, 236); +} +.operation{ + background-color: rgba(225, 240, 248, 0.74); + +} +.header{ + width: 180px; +} +.des{ + width: 730px; +} \ No newline at end of file diff --git a/app/assets/stylesheets/comments.scss b/app/assets/stylesheets/comments.scss new file mode 100644 index 0000000..e730912 --- /dev/null +++ b/app/assets/stylesheets/comments.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Comments controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/home.scss b/app/assets/stylesheets/home.scss new file mode 100644 index 0000000..7131aac --- /dev/null +++ b/app/assets/stylesheets/home.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the Home controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/assets/stylesheets/scaffolds.scss b/app/assets/stylesheets/scaffolds.scss new file mode 100644 index 0000000..6045188 --- /dev/null +++ b/app/assets/stylesheets/scaffolds.scss @@ -0,0 +1,84 @@ +body { + background-color: #fff; + color: #333; + margin: 33px; + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +p, ol, ul, td { + font-family: verdana, arial, helvetica, sans-serif; + font-size: 13px; + line-height: 18px; +} + +pre { + background-color: #eee; + padding: 10px; + font-size: 11px; +} + +a { + color: #000; + + &:visited { + color: #666; + } + + &:hover { + color: #fff; + background-color: #000; + } +} + +th { + padding-bottom: 5px; +} + +td { + padding: 0 5px 7px; +} + +div { + &.field, &.actions { + margin-bottom: 10px; + } +} + +#notice { + color: green; +} + +.field_with_errors { + padding: 2px; + background-color: red; + display: table; +} + +#error_explanation { + width: 450px; + border: 2px solid red; + padding: 7px 7px 0; + margin-bottom: 20px; + background-color: #f0f0f0; + + h2 { + text-align: left; + font-weight: bold; + padding: 5px 5px 5px 15px; + font-size: 12px; + margin: -7px -7px 0; + background-color: #c00; + color: #fff; + } + + ul li { + font-size: 12px; + list-style: square; + } +} + +label { + display: block; +} diff --git a/app/controllers/books_controller.rb b/app/controllers/books_controller.rb new file mode 100644 index 0000000..7803a79 --- /dev/null +++ b/app/controllers/books_controller.rb @@ -0,0 +1,90 @@ +class BooksController < ApplicationController + before_action :authenticate_user!,except: [:index, :show] + before_action :set_book, only: [:show, :edit, :update, :destroy] + # + + # GET /books + # GET /books.json + def index + if current_user + @books = current_user.books + else + redirect_to books_path(@book) + end + end + + # GET /books/1 + # GET /books/1.json + def show + user_edit + end + + # GET /books/new + def new + @book = Book.new + end + + # GET /books/1/edit + def edit + user_edit + end + + # POST /books + # POST /books.json + def create + @book = current_user.books.build(book_params) + respond_to do |format| + if @book.save + format.html { redirect_to @book, notice: 'Book was successfully created.' } + format.json { render :show, status: :created, location: @book } + else + format.html { render :new } + format.json { render json: @book.errors, status: :unprocessable_entity } + end + end + end + + # PATCH/PUT /books/1 + # PATCH/PUT /books/1.json + def update + respond_to do |format| + if @book.update(book_params) + format.html { redirect_to @book, notice: 'Book was successfully updated.' } + format.json { render :show, status: :ok, location: @book } + else + format.html { render :edit } + format.json { render json: @book.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /books/1 + # DELETE /books/1.json + def destroy + @book.destroy + respond_to do |format| + format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' } + format.json { head :no_content } + end + end + + private + # Use callbacks to share common setup or constraints between actions. + def set_book + @book = Book.find(params[:id]) + end + + # Never trust parameters from the scary internet, only allow the white list through. + def book_params + params.require(:book).permit(:title, :author, :description, :image, :category) + end + + def user_edit + if (user_signed_in? && (current_user.id == @book.user_id)) + @can_edit = true + else + @can_edit = false + end + end + +end \ No newline at end of file diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb new file mode 100644 index 0000000..5e2b169 --- /dev/null +++ b/app/controllers/comments_controller.rb @@ -0,0 +1,16 @@ +class CommentsController < ApplicationController + def create + @book = Book.find(params[:book_id]) + @comment = @book.comments.create(comment_params) + redirect_to books_id_path(@book) + end + + def index + end + + private + def comment_params + params.require(:comment).permit(:comment, :commenter) + end + +end diff --git a/app/controllers/home_controller.rb b/app/controllers/home_controller.rb new file mode 100644 index 0000000..0524087 --- /dev/null +++ b/app/controllers/home_controller.rb @@ -0,0 +1,13 @@ +class HomeController < ApplicationController + def index + @books = Book.all + my_book + end + def my_book + if (user_signed_in?) + @has_books = true + else + @has_books = false + end + end +end \ No newline at end of file diff --git a/app/helpers/books_helper.rb b/app/helpers/books_helper.rb new file mode 100644 index 0000000..4b9311e --- /dev/null +++ b/app/helpers/books_helper.rb @@ -0,0 +1,2 @@ +module BooksHelper +end diff --git a/app/helpers/comments_helper.rb b/app/helpers/comments_helper.rb new file mode 100644 index 0000000..0ec9ca5 --- /dev/null +++ b/app/helpers/comments_helper.rb @@ -0,0 +1,2 @@ +module CommentsHelper +end diff --git a/app/helpers/home_helper.rb b/app/helpers/home_helper.rb new file mode 100644 index 0000000..23de56a --- /dev/null +++ b/app/helpers/home_helper.rb @@ -0,0 +1,2 @@ +module HomeHelper +end diff --git a/app/models/book.rb b/app/models/book.rb new file mode 100644 index 0000000..879aa7d --- /dev/null +++ b/app/models/book.rb @@ -0,0 +1,5 @@ +class Book < ApplicationRecord + has_many :comments , dependent: :destroy + belongs_to :user + mount_uploader :image, ImageUploader +end diff --git a/app/models/comment.rb b/app/models/comment.rb new file mode 100644 index 0000000..7b1cda1 --- /dev/null +++ b/app/models/comment.rb @@ -0,0 +1,3 @@ +class Comment < ApplicationRecord + belongs_to :book +end diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..532194d --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,9 @@ +class User < ApplicationRecord + has_many :books, dependent: :destroy + # Include default devise modules. Others available are: + # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable + validates :email, presence: true, format: /\w+@\w+\.{1}[a-zA-Z]{2,}/ + + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :validatable +end diff --git a/app/uploaders/image_uploader.rb b/app/uploaders/image_uploader.rb new file mode 100644 index 0000000..4861131 --- /dev/null +++ b/app/uploaders/image_uploader.rb @@ -0,0 +1,51 @@ +# encoding: utf-8 + +class ImageUploader < CarrierWave::Uploader::Base + + # Include RMagick or MiniMagick support: + # include CarrierWave::RMagick + include CarrierWave::MiniMagick + + # Choose what kind of storage to use for this uploader: + storage :file + # storage :fog + + # Override the directory where uploaded files will be stored. + # This is a sensible default for uploaders that are meant to be mounted: + def store_dir + "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" + end + + # Provide a default URL as a default if there hasn't been a file uploaded: + # def default_url + # # For Rails 3.1+ asset pipeline compatibility: + # # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_')) + # + # "/images/fallback/" + [version_name, "default.png"].compact.join('_') + # end + + # Process files as they are uploaded: + # process :scale => [200, 300] + # + # def scale(width, height) + # # do something + # end + + # Create different versions of your uploaded files: + # version :thumb do + # process :resize_to_fit => [50, 50] + # end + + # Add a white list of extensions which are allowed to be uploaded. + # For images you might use something like this: + def extension_white_list + %w(jpg jpeg gif png) + end + + # Override the filename of the uploaded files: + # Avoid using model.id or version_name here, see uploader/store.rb for details. + # def filename + # "something.jpg" if original_filename + # end + +end diff --git a/app/views/books/_book.json.jbuilder b/app/views/books/_book.json.jbuilder new file mode 100644 index 0000000..b12aab1 --- /dev/null +++ b/app/views/books/_book.json.jbuilder @@ -0,0 +1,2 @@ +json.extract! book, :id, :title, :author, :description, :image, :category, :created_at, :updated_at +json.url book_url(book, format: :json) diff --git a/app/views/books/_form.html.erb b/app/views/books/_form.html.erb new file mode 100644 index 0000000..9843950 --- /dev/null +++ b/app/views/books/_form.html.erb @@ -0,0 +1,45 @@ +<%= form_with(model: book, local: true) do |form| %> + <% if book.errors.any? %> +
<%= notice %>
+ + +| Title | +Author | +Description | +Image | +Category | +👓 | +🖊 | +🗑 | +
|---|---|---|---|---|---|---|---|
| <%= book.title %> | +<%= book.author %> | +<%= book.description %> | +
+ |
+ <%= book.category %> | +<%= link_to 'Show', book %> | +<%= link_to 'Edit', edit_book_path(book) %> | +<%= link_to 'Destroy', book, method: :delete, data: { confirm: 'Are you sure?' } %> | +
<%= notice %>
+ ++ Title: + <%= @book.title %> +
+ ++ Author: + <%= @book.author %> +
+ ++ Description: + <%= @book.description %> +
+ ++Image: +<% if @book.image.url != nil %> + <%= image_tag @book.image.url %> +<%else%> +<%= image_tag 'http://insignia.sd23.bc.ca/Library/images/cover/book.png' %> +<%end%> +
+ ++ Category: + <%= @book.category %> +
+ + ++Commenter: +<%= comment.commenter %> +
+ ++Comment: +<%= comment.comment %> +
\ No newline at end of file diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb new file mode 100644 index 0000000..cc47475 --- /dev/null +++ b/app/views/comments/_form.html.erb @@ -0,0 +1,15 @@ +<%= form_with(model: [ @book, @book.comments.build ], local: true) do |form| %> +
+ <%= form.label :commenter %>
+ <%= form.text_field :commenter %>
+
+ <%= form.label :comment %>
+ <%= form.text_area :comment %>
+
+ <%= form.submit %> +
+ <% end %> \ No newline at end of file diff --git a/app/views/comments/create.html.erb b/app/views/comments/create.html.erb new file mode 100644 index 0000000..7990995 --- /dev/null +++ b/app/views/comments/create.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/comments/create.html.erb
diff --git a/app/views/comments/index.html.erb b/app/views/comments/index.html.erb new file mode 100644 index 0000000..d5edf6e --- /dev/null +++ b/app/views/comments/index.html.erb @@ -0,0 +1,2 @@ +Find me in app/views/comments/index.html.erb
diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb new file mode 100644 index 0000000..03d8c5a --- /dev/null +++ b/app/views/devise/confirmations/new.html.erb @@ -0,0 +1,17 @@ +Welcome <%= @email %>!
+ +You can confirm your account email through the link below:
+ +<%= link_to 'Confirm my account', confirmation_url(@resource, confirmation_token: @token) %>
diff --git a/app/views/devise/mailer/email_changed.html.erb b/app/views/devise/mailer/email_changed.html.erb new file mode 100644 index 0000000..32f4ba8 --- /dev/null +++ b/app/views/devise/mailer/email_changed.html.erb @@ -0,0 +1,7 @@ +Hello <%= @email %>!
+ +<% if @resource.try(:unconfirmed_email?) %> +We're contacting you to notify you that your email is being changed to <%= @resource.unconfirmed_email %>.
+<% else %> +We're contacting you to notify you that your email has been changed to <%= @resource.email %>.
+<% end %> diff --git a/app/views/devise/mailer/password_change.html.erb b/app/views/devise/mailer/password_change.html.erb new file mode 100644 index 0000000..b41daf4 --- /dev/null +++ b/app/views/devise/mailer/password_change.html.erb @@ -0,0 +1,3 @@ +Hello <%= @resource.email %>!
+ +We're contacting you to notify you that your password has been changed.
diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb new file mode 100644 index 0000000..f667dc1 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -0,0 +1,8 @@ +Hello <%= @resource.email %>!
+ +Someone has requested a link to change your password. You can do this through the link below.
+ +<%= link_to 'Change my password', edit_password_url(@resource, reset_password_token: @token) %>
+ +If you didn't request this, please ignore this email.
+Your password won't change until you access the link above and create a new one.
diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb new file mode 100644 index 0000000..41e148b --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -0,0 +1,7 @@ +Hello <%= @resource.email %>!
+ +Your account has been locked due to an excessive number of unsuccessful sign in attempts.
+ +Click the link below to unlock your account:
+ +<%= link_to 'Unlock my account', unlock_url(@resource, unlock_token: @token) %>
diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 0000000..cf3d281 --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb @@ -0,0 +1,25 @@ +Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), data: { confirm: "Are you sure?" }, method: :delete %>
+ +<%= link_to "Back", :back %> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb new file mode 100644 index 0000000..d655b66 --- /dev/null +++ b/app/views/devise/registrations/new.html.erb @@ -0,0 +1,29 @@ +<%= link_to book.description, book %>
+