1
0
mirror of https://github.com/danbee/my-images synced 2025-03-04 08:49:05 +00:00

Add albums

This commit is contained in:
Daniel Barber 2024-03-25 20:26:50 -05:00
parent 750db7cf55
commit 6bbf9fcd73
21 changed files with 218 additions and 29 deletions

View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="256"
height="256"
viewBox="0 0 67.733332 67.733333"
version="1.1"
id="svg1"
xml:space="preserve"
inkscape:version="1.3.2 (091e20e, 2023-11-25)"
sodipodi:docname="album.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1.8547559"
inkscape:cx="-1.8870408"
inkscape:cy="150.42411"
inkscape:window-width="2560"
inkscape:window-height="1387"
inkscape:window-x="0"
inkscape:window-y="25"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" /><defs
id="defs1" /><g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"><path
id="rect1"
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.272"
d="m 12.91127,6.6573004 c -3.3529062,0 -6.0523443,2.6994382 -6.0523443,6.0523446 v 34.194812 c 0,3.049461 2.235339,5.550874 5.1619593,5.979996 -0.01591,-0.17964 -0.02791,-0.360758 -0.02791,-0.544669 V 19.254539 c 0,-3.857255 3.607266,-7.161911 7.565389,-7.161911 h 32.681767 c 0.303632,0 0.59951,0.02959 0.890902,0.07235 C 52.856981,9.0695686 50.275077,6.6573004 47.106082,6.6573004 Z"
sodipodi:nodetypes="ssscsssscss" /><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.272"
id="rect2"
width="46.299191"
height="46.299191"
x="15.298862"
y="15.313577"
ry="6.0521822" /><circle
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.31967;stroke-opacity:1"
id="path3"
cx="29.99498"
cy="28.772318"
r="5.7495732" /><path
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 21.258978,55.737479 h 34.37896 c 0,0 -9.553836,-20.003863 -11.554753,-19.932004 -1.721418,0.06182 -4.850146,10.698848 -7.703169,10.698847 -2.14452,-1e-6 -3.066592,-3.138327 -5.706054,-2.995676 -2.639462,0.14265 -9.414984,12.228833 -9.414984,12.228833 z"
id="path4"
sodipodi:nodetypes="ccsszc" /></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1,27 @@
class AlbumsController < ApplicationController
before_action :authenticate_user!
def index
@albums = @current_user.albums
end
def create
@album = Album.create(permitted_params)
@current_user.albums << @album
redirect_to albums_path
end
def destroy
album = @current_user.albums.find(params[:id])
album.destroy
redirect_to user_albums_path
end
private
def permitted_params
params.require(:album).permit(:user_id, :title)
end
end

View File

@ -1,5 +1,5 @@
class HomeController < ApplicationController
def index
redirect_to user_images_path
redirect_to albums_path
end
end

View File

@ -1,8 +1,9 @@
class ImagesController < ApplicationController
before_action :authenticate_user!
before_action :fetch_album
def index
@images = @current_user.images
@images = current_scope.images
end
def show
@ -14,19 +15,37 @@ class ImagesController < ApplicationController
@current_user.images << @image
TagImageJob.perform_later(image_id: @image.id)
redirect_to user_images_path
redirect_for(@image)
end
def destroy
image = @current_user.images.find(params[:id])
image.destroy
redirect_to user_images_path
redirect_for(image)
end
private
def redirect_for(image)
if image.album.present?
redirect_to album_images_path(image.album)
else
redirect_to images_path
end
end
def current_scope
@album || @current_user
end
def fetch_album
if params[:album_id].present?
@album = @current_user.albums.find(params[:album_id])
end
end
def permitted_params
params.require(:image).permit(:user_id, :image)
params.require(:image).permit(:user_id, :album_id, :image)
end
end

View File

@ -20,12 +20,12 @@ const config = () => ({
export default {
createTag: (tag) => {
return axios.post(`/user/images/${imageId()}/tags`, { tag }, config());
return axios.post(`/images/${imageId()}/tags`, { tag }, config());
},
deleteTag: (tag) => {
return axios.delete(
`/user/images/${imageId()}/tags/${encodeURIComponent(tag)}`,
`/images/${imageId()}/tags/${encodeURIComponent(tag)}`,
config()
);
}

7
app/models/album.rb Normal file
View File

@ -0,0 +1,7 @@
class Album < ApplicationRecord
validates :title, presence: true
belongs_to :user
has_many :images
end

View File

@ -4,4 +4,5 @@ class Image < ActiveRecord::Base
validates :image, presence: true
belongs_to :user
belongs_to :album
end

View File

@ -2,6 +2,7 @@ class User < ActiveRecord::Base
dragonfly_accessor :avatar
has_many :images
has_many :albums
def self.find_or_create_from_auth(auth)
find_by(auth.slice(:provider, :uid)) || create_from_auth(auth)

View File

@ -0,0 +1,29 @@
<% content_for :title do %>
<h1>My Albums</h1>
<% end %>
<h2>Albums</h2>
<ul class="images">
<% @albums.each do |album| %>
<li>
<%= link_to album_images_path(album), class: :album do %>
<% if album.images.any? %>
<%= image_tag(album.images.first.image.thumb('200x200#').url) %>
<% else %>
<%= image_tag(asset_path("album.svg")) %>
<% end %>
<%= album.title %>
<% end %>
</li>
<% end %>
</ul>
<h2>Create New Album</h2>
<%= simple_form_for @albums.new do |f| %>
<%= f.input :user_id, as: :hidden %>
<%= f.input :title %>
<%= f.submit %>
<% end %>

View File

@ -3,7 +3,7 @@
<%= render "tags/tags", image: image, tags: image.tags %>
<div class="new-tag-form">
<%= form_tag user_image_tags_path(image),
<%= form_tag image_tags_path(image),
method: :post,
data: { action: "tags#create" } do %>
<%= text_field_tag :tag, nil, data: { target: "tags.tag" } %>

View File

@ -3,7 +3,7 @@
data-controller="tag">
<span data-target="tag.name"><%= tag %></span>
<%= link_to "&times;".html_safe,
user_image_tag_path(@image, tag),
image_tag_path(@image, tag),
method: :delete,
data: { action: "click->tag#delete" },
class: "delete-tag" %>

View File

@ -1,13 +1,17 @@
<% content_for :title do %>
<h1>My Images</h1>
<h1><%= link_to "My Albums", albums_path %></h1>
<% end %>
<% if @album.present? %>
<h2><%= @album.title %></h2>
<% end %>
<ul class="images">
<% @images.each do |image| %>
<li>
<%= link_to image_tag(image.image.thumb('200x200#').url),
user_image_path(image), class: :image %><br>
<%= link_to 'Delete', user_image_path(image),
image_path(image), class: :image %><br>
<%= link_to 'Delete', image_path(image),
method: :delete, data: { confirm: 'Are you sure?' } %>
</li>
<% end %>
@ -15,8 +19,9 @@
<h2>Upload New Image</h2>
<%= simple_form_for [@current_user, @images.new] do |f| %>
<%= simple_form_for @images.new do |f| %>
<%= f.input :user_id, as: :hidden %>
<%= f.input :album_id, as: :hidden %>
<%= f.input :image, as: :file %>
<%= f.submit %>
<% end %>

View File

@ -1,5 +1,9 @@
<% content_for :title do %>
<h1><%= link_to "My Images", user_images_path %></h1>
<h1><%= link_to "My Albums", albums_path %></h1>
<% if @image.album.present? %>
&rarr;
<%= link_to @image.album.title, album_images_path(@image.album) %>
<% end %>
&rarr;
<%= @image.image.name %>
<% end %>

View File

@ -3,7 +3,7 @@
data-controller="tag">
<span data-target="tag.name"><%= tag %></span>
<%= link_to "&times;".html_safe,
user_image_tag_path(image, tag),
image_tag_path(image, tag),
data: { action: "click->tag#delete" },
class: "delete-tag" %>
</li>

View File

@ -4,9 +4,11 @@ Rails.application.routes.draw do
resource :session, only: %i[new destroy]
get "/auth/:provider/callback", to: "sessions#create", as: :create_session
resource :user, only: [] do
resources :images, only: %i[index show create destroy] do
resources :tags, only: %i[create destroy]
end
resources :images, only: %i[index show create destroy] do
resources :tags, only: %i[create destroy]
end
resources :albums, only: %i[index create destroy] do
resources :images, only: %i[index]
end
end

View File

@ -0,0 +1,11 @@
class CreateAlbums < ActiveRecord::Migration[7.0]
def change
create_table :albums do |t|
t.string :title
t.text :description
t.belongs_to :user
t.timestamps
end
end
end

View File

@ -0,0 +1,5 @@
class AddAlbumToImages < ActiveRecord::Migration[7.0]
def change
add_belongs_to :images, :album
end
end

31
db/schema.rb generated
View File

@ -10,22 +10,31 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2018_08_26_163510) do
ActiveRecord::Schema[7.0].define(version: 2024_03_24_010757) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
create_table "albums", force: :cascade do |t|
t.string "title"
t.text "description"
t.bigint "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_albums_on_user_id"
end
create_table "delayed_jobs", force: :cascade do |t|
t.integer "priority", default: 0, null: false
t.integer "attempts", default: 0, null: false
t.text "handler", null: false
t.text "last_error"
t.datetime "run_at"
t.datetime "locked_at"
t.datetime "failed_at"
t.datetime "run_at", precision: nil
t.datetime "locked_at", precision: nil
t.datetime "failed_at", precision: nil
t.string "locked_by"
t.string "queue"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", precision: nil
t.datetime "updated_at", precision: nil
t.index ["priority", "run_at"], name: "delayed_jobs_priority"
end
@ -33,9 +42,11 @@ ActiveRecord::Schema[7.0].define(version: 2018_08_26_163510) do
t.integer "user_id"
t.string "image_uid"
t.string "image_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "tags", default: [], array: true
t.bigint "album_id"
t.index ["album_id"], name: "index_images_on_album_id"
end
create_table "users", force: :cascade do |t|
@ -44,8 +55,8 @@ ActiveRecord::Schema[7.0].define(version: 2018_08_26_163510) do
t.string "name"
t.string "provider"
t.string "uid"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.datetime "created_at", precision: nil, null: false
t.datetime "updated_at", precision: nil, null: false
t.string "avatar_uid"
end

View File

@ -0,0 +1,7 @@
require "rails_helper"
describe Album do
it { is_expected.to validate_presence_of(:title) }
it { is_expected.to belong_to(:user) }
it { is_expected.to have_many(:images) }
end

View File

@ -3,6 +3,7 @@ require "rails_helper"
describe Image do
it { is_expected.to validate_presence_of(:image) }
it { is_expected.to belong_to(:user) }
it { is_expected.to belong_to(:album) }
it "should not be valid without an image" do
image = Image.new

View File

@ -2,4 +2,5 @@ require "rails_helper"
describe User do
it { is_expected.to have_many(:images) }
it { is_expected.to have_many(:albums) }
end