diff --git a/Gemfile b/Gemfile index 606c18a..2fbc318 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,7 @@ gem 'coffee-rails', '~> 4.2' # gem 'therubyracer', platforms: :ruby # Use jquery as the JavaScript library gem 'jquery-rails' +gem 'jquery-ui-rails' # Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks gem 'turbolinks', '~> 5' # Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder @@ -32,6 +33,7 @@ gem "mini_magick" gem 'rmagick' gem "animate-rails" gem 'best_in_place', '~> 3.0.1' +gem 'simple_form' # Use Capistrano for deployment # gem 'capistrano-rails', group: :development diff --git a/Gemfile.lock b/Gemfile.lock index 1a524aa..156d366 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -81,6 +81,8 @@ GEM rails-dom-testing (>= 1, < 3) railties (>= 4.2.0) thor (>= 0.14, < 2.0) + jquery-ui-rails (5.0.5) + railties (>= 3.2.16) json (2.0.2) listen (3.0.8) rb-fsevent (~> 0.9, >= 0.9.4) @@ -146,6 +148,9 @@ GEM sprockets (>= 2.8, < 4.0) sprockets-rails (>= 2.0, < 4.0) tilt (>= 1.1, < 3) + simple_form (3.3.1) + actionpack (> 4, < 5.1) + activemodel (> 4, < 5.1) spring (1.7.2) spring-watcher-listen (2.0.0) listen (>= 2.7, < 4.0) @@ -191,6 +196,7 @@ DEPENDENCIES devise jbuilder (~> 2.5) jquery-rails + jquery-ui-rails listen (~> 3.0.5) mini_magick pg @@ -198,6 +204,7 @@ DEPENDENCIES rails (~> 5.0.0) rmagick sass-rails (~> 5.0) + simple_form spring spring-watcher-listen (~> 2.0.0) sqlite3 diff --git a/app/assets/images/pen-grey.png b/app/assets/images/pen-grey.png new file mode 100644 index 0000000..0b21389 Binary files /dev/null and b/app/assets/images/pen-grey.png differ diff --git a/app/assets/images/white-pen.png b/app/assets/images/white-pen.png new file mode 100644 index 0000000..4f658a3 Binary files /dev/null and b/app/assets/images/white-pen.png differ diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 5da2447..2400da3 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -12,6 +12,7 @@ // //= require jquery //= require best_in_place +//= require jquery-ui //= require jquery_ujs //= require turbolinks //= require_tree . diff --git a/app/assets/javascripts/autosize.js b/app/assets/javascripts/autosize.js new file mode 100644 index 0000000..f33d0b6 --- /dev/null +++ b/app/assets/javascripts/autosize.js @@ -0,0 +1,55 @@ +/*! + * jQuery Textarea AutoSize plugin + * Author: Javier Julio + * Licensed under the MIT license + */ +;(function ($, window, document, undefined) { + + var pluginName = "textareaAutoSize"; + var pluginDataName = "plugin_" + pluginName; + + var containsText = function (value) { + return (value.replace(/\s/g, '').length > 0); + }; + + function Plugin(element, options) { + this.element = element; + this.$element = $(element); + this.init(); + } + + Plugin.prototype = { + init: function() { + var diff = parseInt(this.$element.css('paddingBottom')) + + parseInt(this.$element.css('paddingTop')) + + parseInt(this.$element.css('borderTopWidth')) + + parseInt(this.$element.css('borderBottomWidth')) || 0; + + if (containsText(this.element.value)) { + this.$element.height(this.element.scrollHeight - diff); + } + + // keyup is required for IE to properly reset height when deleting text + this.$element.on('input keyup', function(event) { + var $window = $(window); + var currentScrollPosition = $window.scrollTop(); + + $(this) + .height(0) + .height(this.scrollHeight - diff); + + $window.scrollTop(currentScrollPosition); + }); + } + }; + + $.fn[pluginName] = function (options) { + this.each(function() { + if (!$.data(this, pluginDataName)) { + $.data(this, pluginDataName, new Plugin(this, options)); + } + }); + return this; + }; + +})(jQuery, window, document); diff --git a/app/assets/stylesheets/mixins/introduction.sass b/app/assets/stylesheets/mixins/introduction.sass index 921d45a..6641953 100644 --- a/app/assets/stylesheets/mixins/introduction.sass +++ b/app/assets/stylesheets/mixins/introduction.sass @@ -2,5 +2,4 @@ height: 24px width: 24px background-repeat: no-repeat - background-size: auto content: '' diff --git a/app/assets/stylesheets/sections/_user-show.sass b/app/assets/stylesheets/sections/_user-show.sass index 493b189..ed84b49 100644 --- a/app/assets/stylesheets/sections/_user-show.sass +++ b/app/assets/stylesheets/sections/_user-show.sass @@ -114,26 +114,42 @@ margin: 0 .globe + +introduction + background-image: image-url('globe.png') + background-size: cover + display: inline-block height: 24px width: 24px margin-right: 0.5rem - .edit-user - text-align: right + a + height: 18px + width: 18px + position: relative + padding: 3px + border-radius: 3px + float: right + display: inline-block - &:before + &:hover + background-color: #3b5998 + + &:hover .edit-user + opacity: 1 + background-image: image-url('icons2.png') + background-size: 27px 219px + background-position: -13px -141px + + .edit-user + text-align: right +introduction background-image: image-url('icons2.png') - background-position: 0 -141px background-size: 27px 219px + background-position: 0 -141px height: 12px width: 12px - display: inline-block - opacity: .4 - - // &:hover - // background-color: #3b5998 - + display: block + opacity: .6 ul margin: 0 diff --git a/app/assets/stylesheets/sections/_wall.sass b/app/assets/stylesheets/sections/_wall.sass index 8a1db04..c0e5194 100644 --- a/app/assets/stylesheets/sections/_wall.sass +++ b/app/assets/stylesheets/sections/_wall.sass @@ -134,3 +134,13 @@ top: 0 right: 0 border-left: 1px solid #ccc + +.comments + display: block + width: 100% + max-width: 100% + min-height: 32px + word-wrap: break-word + border-radius: 0px + overflow: hidden + resize: none diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb index 7669955..b39faaf 100644 --- a/app/controllers/comments_controller.rb +++ b/app/controllers/comments_controller.rb @@ -1,2 +1,41 @@ class CommentsController < ApplicationController + before_action :find_post + before_action :find_post, only: [:show, :edit, :update, :destroy] + + def index + @comments = @post.comment + end + + def new + @comment = Comment.new + @comment = @post.comment.build + end + + def create + @comment = @post.comments.create(params[:comment].permit(:content)) + @comment.post_id = @post.id + @comment.user_id = current_user.id + # @comment = @post.comments.create(params[:comment].permit[:content]) + # @comment.post_id = @post.id + if @comment.save + redirect_to root_path + # format.json { render :show, status: :created, location: @post } + else + render 'new' + end + + end + + private + # Use callbacks to share common setup or constraints between actions. + # def comment_params + # params.require(:comment).permit(:content) + # end + + def find_post + @post = Post.find(params[:post_id]) + end + + + # Never trust parameters from the scary internet, only allow the white list through. end diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 2982b5f..ef40f80 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -2,16 +2,9 @@ class PostsController < ApplicationController before_action :set_post, only: [:show, :edit, :update, :destroy] before_action :authenticate_user! - # GET /posts - # GET /posts.json - - - # GET /posts/1 - # GET /posts/1.json - - # GET /posts/new def new @post = Post.new + @comment = Comment.new end # GET /posts/1/edit diff --git a/app/controllers/walls_controller.rb b/app/controllers/walls_controller.rb index c01a1d4..95e284a 100644 --- a/app/controllers/walls_controller.rb +++ b/app/controllers/walls_controller.rb @@ -1,12 +1,14 @@ class WallsController < ApplicationController respond_to :json, :html + + def index @posts = Post.order("created_at DESC") @post = Post.new - @walls = Wall.all.includes(:user, :post).to_json(:include => [{post: {only: %i(username image content youtube_url)}},{:user => {only: %i(id)}}]) + @walls = Wall.all.includes(:user, :post, :comment).to_json(:include => [{post: {only: %i(username image content youtube_url)}},{:user => {only: %i(id)}},{:comment => {only: %i(content)}}]) respond_with @wall @user = User.all + @comment = Comment.new + @comments = Comment.order("created_at DESC") end - - end diff --git a/app/helpers/variables/_colors.sass b/app/helpers/variables/_colors.sass new file mode 100644 index 0000000..77af6a5 --- /dev/null +++ b/app/helpers/variables/_colors.sass @@ -0,0 +1,5 @@ +$white: #fff +$dark-blue: #101b25 +$border-color: #ece8e8 +$black: #000 +$fb-blue: #1c4c77 diff --git a/app/helpers/variables/_vars.sass b/app/helpers/variables/_vars.sass new file mode 100644 index 0000000..fdf1c77 --- /dev/null +++ b/app/helpers/variables/_vars.sass @@ -0,0 +1,25 @@ +.m-top + margin-top: 3em + +.n-m + margin: 0 + +.card + background-color: #fff + padding: 0.75em + border: 1px solid #ece8e8 + border-radius: 4px + width: 100% + max-width: 100% + margin-bottom: 1em + position: relative + +.bold + font-weight: bold + +img + height: auto + max-width: 100% + +.table + display: table diff --git a/app/models/comment.rb b/app/models/comment.rb index 1d79d25..4a019df 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -1,2 +1,4 @@ class Comment < ApplicationRecord + belongs_to :post + belongs_to :user end diff --git a/app/models/post.rb b/app/models/post.rb index 8063faa..b97442f 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -1,5 +1,6 @@ class Post < ApplicationRecord - belongs_to :user, required: true + belongs_to :user + has_many :comments mount_uploader :image, AvatarUploader validates :content, presence: true, length: {minimum: 5} delegate :username, :username=, :email, :email=,:avatar, :avatar=, :to => :user, allow_nil: true diff --git a/app/models/user.rb b/app/models/user.rb index 23df477..ed6bd87 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,6 +10,7 @@ class User < ApplicationRecord # Setup accessible (or protected) attributes for your model has_many :posts, dependent: :delete_all + has_many :comments, dependent: :delete_all attr_accessor :login validates :username, diff --git a/app/models/wall.rb b/app/models/wall.rb index fc2dd47..ea7d11b 100644 --- a/app/models/wall.rb +++ b/app/models/wall.rb @@ -1,6 +1,8 @@ class Wall < ApplicationRecord - has_many :posts + has_many :post has_many :users + has_many :comments + delegate :username, :username=,:avatar, :avatar=, :email, :email=, :to => :user, allow_nil: true devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable diff --git a/app/views/comments/_comments.html.erb b/app/views/comments/_comments.html.erb new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/app/views/comments/_comments.html.erb @@ -0,0 +1 @@ + diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb new file mode 100644 index 0000000..d8a1bc2 --- /dev/null +++ b/app/views/comments/_form.html.erb @@ -0,0 +1,6 @@ +
+<%= form_for([@post, @post.comments.build]) do |f| %> + <%= f.text_area :content, class: 'comments js-auto-size', id: 'alex2' ,:rows => 1 %> + <%= f.submit "Submit", class: "btn btn-default" %> + <% end %> +
diff --git a/app/views/comments/index.html.erb b/app/views/comments/index.html.erb new file mode 100644 index 0000000..cac2c80 --- /dev/null +++ b/app/views/comments/index.html.erb @@ -0,0 +1,3 @@ +<%= @comments.each do |comment| %> +

<%= comment.content %>

+<% end %> diff --git a/app/views/comments/new.html.erb b/app/views/comments/new.html.erb new file mode 100644 index 0000000..2ec8093 --- /dev/null +++ b/app/views/comments/new.html.erb @@ -0,0 +1,2 @@ +

New Comment

+<%= render 'form' %> diff --git a/app/views/comments/show.html.erb b/app/views/comments/show.html.erb new file mode 100644 index 0000000..43fa793 --- /dev/null +++ b/app/views/comments/show.html.erb @@ -0,0 +1 @@ +

<%= @comment.content %>

diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 0de7e56..2653374 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -17,5 +17,11 @@ <% end %> <%= render partial: "shared/navbar" %> <%= yield %> + + diff --git a/app/views/posts/index.html.erb b/app/views/posts/index.html.erb index 7008bc6..647ea65 100644 --- a/app/views/posts/index.html.erb +++ b/app/views/posts/index.html.erb @@ -25,5 +25,5 @@
- +<%= link_to "Comments", new_post_comment_path(@post) %> <%= link_to 'New Post', new_post_path %> diff --git a/app/views/posts/show.html.erb b/app/views/posts/show.html.erb index bddaad4..8d29604 100644 --- a/app/views/posts/show.html.erb +++ b/app/views/posts/show.html.erb @@ -10,5 +10,6 @@ <%= @post.image %>

+ <%= link_to 'Edit', edit_post_path(@post) %> | <%= link_to 'Back', posts_path %> diff --git a/app/views/users/show.html.erb b/app/views/users/show.html.erb index 439b94e..c45f934 100644 --- a/app/views/users/show.html.erb +++ b/app/views/users/show.html.erb @@ -25,10 +25,12 @@
- <%= image_tag 'globe.png', class: 'two columns globe' %> -

Introduction -

- <%= link_to '', edit_user_path(@user), class: 'edit-user four columns' %> + +

Introduction

+ + <%= link_to edit_user_path(@user), class: '' do %> + + <% end %>

- - + <%= render 'form' %> +
diff --git a/config/initializers/simple_form.rb b/config/initializers/simple_form.rb new file mode 100644 index 0000000..934487a --- /dev/null +++ b/config/initializers/simple_form.rb @@ -0,0 +1,165 @@ +# Use this setup block to configure all options available in SimpleForm. +SimpleForm.setup do |config| + # Wrappers are used by the form builder to generate a + # complete input. You can remove any component from the + # wrapper, change the order or even add your own to the + # stack. The options given below are used to wrap the + # whole input. + config.wrappers :default, class: :input, + hint_class: :field_with_hint, error_class: :field_with_errors do |b| + ## Extensions enabled by default + # Any of these extensions can be disabled for a + # given input by passing: `f.input EXTENSION_NAME => false`. + # You can make any of these extensions optional by + # renaming `b.use` to `b.optional`. + + # Determines whether to use HTML5 (:email, :url, ...) + # and required attributes + b.use :html5 + + # Calculates placeholders automatically from I18n + # You can also pass a string as f.input placeholder: "Placeholder" + b.use :placeholder + + ## Optional extensions + # They are disabled unless you pass `f.input EXTENSION_NAME => true` + # to the input. If so, they will retrieve the values from the model + # if any exists. If you want to enable any of those + # extensions by default, you can change `b.optional` to `b.use`. + + # Calculates maxlength from length validations for string inputs + b.optional :maxlength + + # Calculates pattern from format validations for string inputs + b.optional :pattern + + # Calculates min and max from length validations for numeric inputs + b.optional :min_max + + # Calculates readonly automatically from readonly attributes + b.optional :readonly + + ## Inputs + b.use :label_input + b.use :hint, wrap_with: { tag: :span, class: :hint } + b.use :error, wrap_with: { tag: :span, class: :error } + + ## full_messages_for + # If you want to display the full error message for the attribute, you can + # use the component :full_error, like: + # + # b.use :full_error, wrap_with: { tag: :span, class: :error } + end + + # The default wrapper to be used by the FormBuilder. + config.default_wrapper = :default + + # Define the way to render check boxes / radio buttons with labels. + # Defaults to :nested for bootstrap config. + # inline: input + label + # nested: label > input + config.boolean_style = :nested + + # Default class for buttons + config.button_class = 'btn' + + # Method used to tidy up errors. Specify any Rails Array method. + # :first lists the first message for each field. + # Use :to_sentence to list all errors for each field. + # config.error_method = :first + + # Default tag used for error notification helper. + config.error_notification_tag = :div + + # CSS class to add for error notification helper. + config.error_notification_class = 'error_notification' + + # ID to add for error notification helper. + # config.error_notification_id = nil + + # Series of attempts to detect a default label method for collection. + # config.collection_label_methods = [ :to_label, :name, :title, :to_s ] + + # Series of attempts to detect a default value method for collection. + # config.collection_value_methods = [ :id, :to_s ] + + # You can wrap a collection of radio/check boxes in a pre-defined tag, defaulting to none. + # config.collection_wrapper_tag = nil + + # You can define the class to use on all collection wrappers. Defaulting to none. + # config.collection_wrapper_class = nil + + # You can wrap each item in a collection of radio/check boxes with a tag, + # defaulting to :span. + # config.item_wrapper_tag = :span + + # You can define a class to use in all item wrappers. Defaulting to none. + # config.item_wrapper_class = nil + + # How the label text should be generated altogether with the required text. + # config.label_text = lambda { |label, required, explicit_label| "#{required} #{label}" } + + # You can define the class to use on all labels. Default is nil. + # config.label_class = nil + + # You can define the default class to be used on forms. Can be overriden + # with `html: { :class }`. Defaulting to none. + # config.default_form_class = nil + + # You can define which elements should obtain additional classes + # config.generate_additional_classes_for = [:wrapper, :label, :input] + + # Whether attributes are required by default (or not). Default is true. + # config.required_by_default = true + + # Tell browsers whether to use the native HTML5 validations (novalidate form option). + # These validations are enabled in SimpleForm's internal config but disabled by default + # in this configuration, which is recommended due to some quirks from different browsers. + # To stop SimpleForm from generating the novalidate option, enabling the HTML5 validations, + # change this configuration to true. + config.browser_validations = false + + # Collection of methods to detect if a file type was given. + # config.file_methods = [ :mounted_as, :file?, :public_filename ] + + # Custom mappings for input types. This should be a hash containing a regexp + # to match as key, and the input type that will be used when the field name + # matches the regexp as value. + # config.input_mappings = { /count/ => :integer } + + # Custom wrappers for input types. This should be a hash containing an input + # type as key and the wrapper that will be used for all inputs with specified type. + # config.wrapper_mappings = { string: :prepend } + + # Namespaces where SimpleForm should look for custom input classes that + # override default inputs. + # config.custom_inputs_namespaces << "CustomInputs" + + # Default priority for time_zone inputs. + # config.time_zone_priority = nil + + # Default priority for country inputs. + # config.country_priority = nil + + # When false, do not use translations for labels. + # config.translate_labels = true + + # Automatically discover new inputs in Rails' autoload path. + # config.inputs_discovery = true + + # Cache SimpleForm inputs discovery + # config.cache_discovery = !Rails.env.development? + + # Default class for inputs + # config.input_class = nil + + # Define the default class of the input wrapper of the boolean input. + config.boolean_label_class = 'checkbox' + + # Defines if the default input wrapper class should be included in radio + # collection wrappers. + # config.include_default_input_wrapper_class = true + + # Defines which i18n scope will be used in Simple Form. + # config.i18n_scope = 'simple_form' +end diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml new file mode 100644 index 0000000..2374383 --- /dev/null +++ b/config/locales/simple_form.en.yml @@ -0,0 +1,31 @@ +en: + simple_form: + "yes": 'Yes' + "no": 'No' + required: + text: 'required' + mark: '*' + # You can uncomment the line below if you need to overwrite the whole required html. + # When using html, text and mark won't be used. + # html: '*' + error_notification: + default_message: "Please review the problems below:" + # Examples + # labels: + # defaults: + # password: 'Password' + # user: + # new: + # email: 'E-mail to sign in.' + # edit: + # email: 'E-mail.' + # hints: + # defaults: + # username: 'User name to sign in.' + # password: 'No special characters, please.' + # include_blanks: + # defaults: + # age: 'Rather not say' + # prompts: + # defaults: + # age: 'Select your age' diff --git a/config/routes.rb b/config/routes.rb index 7337e91..65e8d49 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -2,9 +2,9 @@ devise_for :users resources :uploads resources :users + resources :walls resources :posts resources :comments - resources :walls root 'walls#index' # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html end diff --git a/db/migrate/20160725155257_create_comments.rb b/db/migrate/20160829174913_create_comments.rb similarity index 55% rename from db/migrate/20160725155257_create_comments.rb rename to db/migrate/20160829174913_create_comments.rb index b932af0..87b7748 100644 --- a/db/migrate/20160725155257_create_comments.rb +++ b/db/migrate/20160829174913_create_comments.rb @@ -1,6 +1,9 @@ class CreateComments < ActiveRecord::Migration[5.0] def change create_table :comments do |t| + t.text :content + t.references :post, foreign_key: true + t.references :user, foreign_key: true t.timestamps end diff --git a/db/schema.rb b/db/schema.rb index e733209..05ce054 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,16 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160827130450) do +ActiveRecord::Schema.define(version: 20160829174913) do create_table "comments", force: :cascade do |t| + t.text "content" + t.integer "post_id" + t.integer "user_id" t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.index ["post_id"], name: "index_comments_on_post_id" + t.index ["user_id"], name: "index_comments_on_user_id" end create_table "friendships", force: :cascade do |t| diff --git a/lib/templates/erb/scaffold/_form.html.erb b/lib/templates/erb/scaffold/_form.html.erb new file mode 100644 index 0000000..201a069 --- /dev/null +++ b/lib/templates/erb/scaffold/_form.html.erb @@ -0,0 +1,13 @@ +<%%= simple_form_for(@<%= singular_table_name %>) do |f| %> + <%%= f.error_notification %> + +
+ <%- attributes.each do |attribute| -%> + <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %> + <%- end -%> +
+ +
+ <%%= f.button :submit %> +
+<%% end %> diff --git a/test/fixtures/comments.yml b/test/fixtures/comments.yml index 80aed36..0344159 100644 --- a/test/fixtures/comments.yml +++ b/test/fixtures/comments.yml @@ -1,11 +1,11 @@ # Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html -# This model initially had no columns defined. If you add columns to the -# model remove the '{}' from the fixture names and add the columns immediately -# below each fixture, per the syntax in the comments below -# -one: {} -# column: value -# -two: {} -# column: value +one: + content: MyText + post: one + user: one + +two: + content: MyText + post: two + user: two