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

Compare commits

...

4 Commits

Author SHA1 Message Date
71c7ba2acf Move tag handling over to turbo frames 2024-03-25 21:09:13 -05:00
6bbf9fcd73 Add albums 2024-03-25 20:26:50 -05:00
750db7cf55 Remove webpacker and update bundle 2024-03-25 20:26:25 -05:00
4d633efc03 Update some things 2024-03-23 19:50:54 -05:00
34 changed files with 412 additions and 289 deletions

View File

@ -24,7 +24,6 @@ gem "simple_form"
gem "stimulus-rails"
gem "turbo-rails"
gem "uglifier"
gem "webpacker"
group :development do
gem "web-console"

View File

@ -1,160 +1,167 @@
GEM
remote: https://rubygems.org/
specs:
actioncable (7.0.6)
actionpack (= 7.0.6)
activesupport (= 7.0.6)
actioncable (7.0.8.1)
actionpack (= 7.0.8.1)
activesupport (= 7.0.8.1)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (7.0.6)
actionpack (= 7.0.6)
activejob (= 7.0.6)
activerecord (= 7.0.6)
activestorage (= 7.0.6)
activesupport (= 7.0.6)
actionmailbox (7.0.8.1)
actionpack (= 7.0.8.1)
activejob (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
mail (>= 2.7.1)
net-imap
net-pop
net-smtp
actionmailer (7.0.6)
actionpack (= 7.0.6)
actionview (= 7.0.6)
activejob (= 7.0.6)
activesupport (= 7.0.6)
actionmailer (7.0.8.1)
actionpack (= 7.0.8.1)
actionview (= 7.0.8.1)
activejob (= 7.0.8.1)
activesupport (= 7.0.8.1)
mail (~> 2.5, >= 2.5.4)
net-imap
net-pop
net-smtp
rails-dom-testing (~> 2.0)
actionpack (7.0.6)
actionview (= 7.0.6)
activesupport (= 7.0.6)
actionpack (7.0.8.1)
actionview (= 7.0.8.1)
activesupport (= 7.0.8.1)
rack (~> 2.0, >= 2.2.4)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (7.0.6)
actionpack (= 7.0.6)
activerecord (= 7.0.6)
activestorage (= 7.0.6)
activesupport (= 7.0.6)
actiontext (7.0.8.1)
actionpack (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
globalid (>= 0.6.0)
nokogiri (>= 1.8.5)
actionview (7.0.6)
activesupport (= 7.0.6)
actionview (7.0.8.1)
activesupport (= 7.0.8.1)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (7.0.6)
activesupport (= 7.0.6)
activejob (7.0.8.1)
activesupport (= 7.0.8.1)
globalid (>= 0.3.6)
activemodel (7.0.6)
activesupport (= 7.0.6)
activerecord (7.0.6)
activemodel (= 7.0.6)
activesupport (= 7.0.6)
activestorage (7.0.6)
actionpack (= 7.0.6)
activejob (= 7.0.6)
activerecord (= 7.0.6)
activesupport (= 7.0.6)
activemodel (7.0.8.1)
activesupport (= 7.0.8.1)
activerecord (7.0.8.1)
activemodel (= 7.0.8.1)
activesupport (= 7.0.8.1)
activestorage (7.0.8.1)
actionpack (= 7.0.8.1)
activejob (= 7.0.8.1)
activerecord (= 7.0.8.1)
activesupport (= 7.0.8.1)
marcel (~> 1.0)
mini_mime (>= 1.1.0)
activesupport (7.0.6)
activesupport (7.0.8.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
addressable (2.8.4)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
archive-zip (0.12.0)
io-like (~> 0.3.0)
base64 (0.2.0)
better_errors (2.10.1)
erubi (>= 1.0.0)
rack (>= 0.9.0)
rouge (>= 1.0.0)
bigdecimal (3.1.7)
bindex (0.8.1)
binding_of_caller (1.0.0)
debug_inspector (>= 0.0.1)
bootsnap (1.16.0)
binding_of_caller (1.0.1)
debug_inspector (>= 1.2.0)
bootsnap (1.18.3)
msgpack (~> 1.2)
builder (3.2.4)
capybara (3.39.2)
capybara (3.40.0)
addressable
matrix
mini_mime (>= 0.1.3)
nokogiri (~> 1.8)
nokogiri (~> 1.11)
rack (>= 1.6.0)
rack-test (>= 0.6.3)
regexp_parser (>= 1.5, < 3.0)
xpath (~> 3.2)
childprocess (5.0.0)
coderay (1.1.3)
concurrent-ruby (1.2.2)
crack (0.4.5)
concurrent-ruby (1.2.3)
crack (1.0.0)
bigdecimal
rexml
crass (1.0.6)
date (3.3.3)
debug_inspector (1.1.0)
date (3.3.4)
debug_inspector (1.2.0)
delayed_job (4.1.11)
activesupport (>= 3.0, < 8.0)
delayed_job_active_record (4.1.7)
delayed_job_active_record (4.1.8)
activerecord (>= 3.0, < 8.0)
delayed_job (>= 3.0, < 5)
diff-lcs (1.5.0)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dotenv (2.8.1)
dotenv-rails (2.8.1)
dotenv (= 2.8.1)
railties (>= 3.2)
diff-lcs (1.5.1)
domain_name (0.6.20240107)
dotenv (3.1.0)
dotenv-rails (3.1.0)
dotenv (= 3.1.0)
railties (>= 6.1)
dragonfly (1.4.0)
addressable (~> 2.3)
multi_json (~> 1.0)
rack (>= 1.3)
erubi (1.12.0)
execjs (2.8.1)
faraday (2.7.9)
faraday-net_http (>= 2.0, < 3.1)
ruby2_keywords (>= 0.0.4)
faraday-net_http (3.0.2)
ffi (1.15.5)
ffi-compiler (1.0.1)
ffi (>= 1.0.0)
execjs (2.9.1)
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (3.1.0)
net-http
ffi (1.16.3)
ffi-compiler (1.3.2)
ffi (>= 1.15.5)
rake
geckodriver-helper (0.24.0)
archive-zip (~> 0.7)
globalid (1.1.0)
activesupport (>= 5.0)
hashdiff (1.0.1)
globalid (1.2.1)
activesupport (>= 6.1)
hashdiff (1.1.0)
hashie (5.0.0)
http (5.1.1)
http (5.2.0)
addressable (~> 2.8)
base64 (~> 0.1)
http-cookie (~> 1.0)
http-form_data (~> 2.2)
llhttp-ffi (~> 0.4.0)
llhttp-ffi (~> 0.5.0)
http-cookie (1.0.5)
domain_name (~> 0.5)
http-form_data (2.3.0)
i18n (1.14.1)
i18n (1.14.4)
concurrent-ruby (~> 1.0)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
importmap-rails (1.2.1)
importmap-rails (2.0.1)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
railties (>= 6.0.0)
io-like (0.3.1)
jbuilder (2.11.5)
actionview (>= 5.0.0)
activesupport (>= 5.0.0)
jwt (2.7.1)
launchy (2.5.2)
jwt (2.8.1)
base64
launchy (3.0.0)
addressable (~> 2.8)
llhttp-ffi (0.4.0)
childprocess (~> 5.0)
llhttp-ffi (0.5.0)
ffi-compiler (~> 1.0)
rake (~> 13.0)
loofah (2.21.3)
loofah (2.22.0)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@ -162,26 +169,28 @@ GEM
net-imap
net-pop
net-smtp
marcel (1.0.2)
marcel (1.0.4)
matrix (0.4.2)
method_source (1.0.0)
mini_magick (4.12.0)
mini_mime (1.1.2)
minitest (5.18.1)
msgpack (1.7.1)
mini_mime (1.1.5)
minitest (5.22.3)
msgpack (1.7.2)
multi_json (1.15.0)
multi_xml (0.6.0)
net-imap (0.3.6)
net-http (0.4.1)
uri
net-imap (0.4.10)
date
net-protocol
net-pop (0.1.2)
net-protocol
net-protocol (0.2.1)
net-protocol (0.2.2)
timeout
net-smtp (0.3.3)
net-smtp (0.4.0.1)
net-protocol
nio4r (2.5.9)
nokogiri (1.15.2-arm64-darwin)
nio4r (2.7.1)
nokogiri (1.16.3-arm64-darwin)
racc (~> 1.4)
oauth2 (2.0.9)
faraday (>= 0.17.3, < 3.0)
@ -190,7 +199,7 @@ GEM
rack (>= 1.2, < 4)
snaky_hash (~> 2.0)
version_gem (~> 1.1)
omniauth (2.1.1)
omniauth (2.1.2)
hashie (>= 3.4.6)
rack (>= 2.2.3)
rack-protection
@ -203,73 +212,71 @@ GEM
omniauth-rails_csrf_protection (1.0.1)
actionpack (>= 4.2)
omniauth (~> 2.0)
pg (1.5.3)
pg (1.5.6)
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
public_suffix (5.0.1)
puma (6.3.0)
public_suffix (5.0.4)
puma (6.4.2)
nio4r (~> 2.0)
racc (1.7.1)
rack (2.2.7)
rack-protection (3.0.6)
rack
rack-proxy (0.7.6)
rack
racc (1.7.3)
rack (2.2.9)
rack-protection (3.2.0)
base64 (>= 0.1.0)
rack (~> 2.2, >= 2.2.4)
rack-test (2.1.0)
rack (>= 1.3)
rails (7.0.6)
actioncable (= 7.0.6)
actionmailbox (= 7.0.6)
actionmailer (= 7.0.6)
actionpack (= 7.0.6)
actiontext (= 7.0.6)
actionview (= 7.0.6)
activejob (= 7.0.6)
activemodel (= 7.0.6)
activerecord (= 7.0.6)
activestorage (= 7.0.6)
activesupport (= 7.0.6)
rails (7.0.8.1)
actioncable (= 7.0.8.1)
actionmailbox (= 7.0.8.1)
actionmailer (= 7.0.8.1)
actionpack (= 7.0.8.1)
actiontext (= 7.0.8.1)
actionview (= 7.0.8.1)
activejob (= 7.0.8.1)
activemodel (= 7.0.8.1)
activerecord (= 7.0.8.1)
activestorage (= 7.0.8.1)
activesupport (= 7.0.8.1)
bundler (>= 1.15.0)
railties (= 7.0.6)
rails-dom-testing (2.1.1)
railties (= 7.0.8.1)
rails-dom-testing (2.2.0)
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.0)
loofah (~> 2.21)
nokogiri (~> 1.14)
railties (7.0.6)
actionpack (= 7.0.6)
activesupport (= 7.0.6)
railties (7.0.8.1)
actionpack (= 7.0.8.1)
activesupport (= 7.0.8.1)
method_source
rake (>= 12.2)
thor (~> 1.0)
zeitwerk (~> 2.5)
rake (13.0.6)
regexp_parser (2.8.1)
rexml (3.2.5)
rouge (4.1.2)
rspec-core (3.12.2)
rspec-support (~> 3.12.0)
rspec-expectations (3.12.3)
rake (13.1.0)
regexp_parser (2.9.0)
rexml (3.2.6)
rouge (4.2.1)
rspec-core (3.13.0)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-mocks (3.12.5)
rspec-support (~> 3.13.0)
rspec-mocks (3.13.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.12.0)
rspec-rails (6.0.3)
rspec-support (~> 3.13.0)
rspec-rails (6.1.2)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.12)
rspec-expectations (~> 3.12)
rspec-mocks (~> 3.12)
rspec-support (~> 3.12)
rspec-support (3.12.1)
ruby-vips (2.1.4)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-support (3.13.1)
ruby-vips (2.2.1)
ffi (~> 1.12)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
sassc (2.4.0)
ffi (~> 1.9)
@ -279,32 +286,32 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
selenium-webdriver (4.10.0)
selenium-webdriver (4.18.1)
base64 (~> 0.2)
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
semantic_range (3.0.0)
shoulda-matchers (5.3.0)
shoulda-matchers (6.2.0)
activesupport (>= 5.2.0)
simple_form (5.2.0)
simple_form (5.3.0)
actionpack (>= 5.2)
activemodel (>= 5.2)
snaky_hash (2.0.1)
hashie
version_gem (~> 1.1, >= 1.1.1)
sprockets (4.2.0)
sprockets (4.2.1)
concurrent-ruby (~> 1.0)
rack (>= 2.2.4, < 4)
sprockets-rails (3.4.2)
actionpack (>= 5.2)
activesupport (>= 5.2)
sprockets (>= 3.0.0)
stimulus-rails (1.2.1)
stimulus-rails (1.3.3)
railties (>= 6.0.0)
thor (1.2.2)
tilt (2.2.0)
timeout (0.4.0)
turbo-rails (1.4.0)
thor (1.3.1)
tilt (2.3.0)
timeout (0.4.1)
turbo-rails (2.0.5)
actionpack (>= 6.0.0)
activejob (>= 6.0.0)
railties (>= 6.0.0)
@ -312,31 +319,24 @@ GEM
concurrent-ruby (~> 1.0)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.8.2)
version_gem (1.1.3)
web-console (4.2.0)
uri (0.13.0)
version_gem (1.1.4)
web-console (4.2.1)
actionview (>= 6.0.0)
activemodel (>= 6.0.0)
bindex (>= 0.4.0)
railties (>= 6.0.0)
webmock (3.18.1)
webmock (3.23.0)
addressable (>= 2.8.0)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
webpacker (5.4.4)
activesupport (>= 5.2)
rack-proxy (>= 0.6.1)
railties (>= 5.2)
semantic_range (>= 2.3.0)
websocket (1.2.9)
websocket-driver (0.7.5)
websocket (1.2.10)
websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.8)
zeitwerk (2.6.13)
PLATFORMS
arm64-darwin-22
@ -372,7 +372,6 @@ DEPENDENCIES
uglifier
web-console
webmock
webpacker
RUBY VERSION
ruby 3.2.1p31

View File

@ -1,2 +1,4 @@
//= link_tree ../images
//= link_directory ../stylesheets .css
//= link_tree ../../javascript .js
//= link_tree ../../../vendor/javascript .js

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,12 +1,20 @@
class ImagesController < ApplicationController
before_action :authenticate_user!
before_action :fetch_album
def index
@images = @current_user.images
@images = current_scope.images
end
def show
@image = @current_user.images.find(params[:id])
if turbo_frame_request?
render partial: "tags/tags", locals: {
image: @image,
tags: @image.tags
}
end
end
def create
@ -14,19 +22,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

@ -8,7 +8,7 @@ class TagsController < ApplicationController
if !image.tags.include?(tag)
image.tags << tag
image.save
render partial: "tags/tag", locals: { image: image, tag: tag }
redirect_to image, turbo_frame: "tags"
else
head :no_content, content_type: "text/html"
end
@ -20,6 +20,6 @@ class TagsController < ApplicationController
image.tags.delete(tag)
image.save
head :no_content
redirect_to image, turbo_frame: "tags"
end
end

View File

@ -0,0 +1,7 @@
// Configure your import map in config/importmap.rb. Read more: https://github.com/rails/importmap-rails
import "@hotwired/turbo-rails"
import Rails from "@rails/ujs";
import { Application } from "@hotwired/stimulus";
Rails.start();

View File

@ -1,22 +0,0 @@
import { Controller } from "stimulus";
import ajaxService from "../services/ajax_service";
export default class extends Controller {
static targets = ["name"];
delete(event) {
const tag = this.nameTarget.innerText;
event.preventDefault();
this.element.classList.add("hidden");
ajaxService.deleteTag(tag)
.then(response => {
this.element.parentElement.removeChild(this.element);
})
.catch(error => {
this.element.classList.remove("hidden")
});
}
}

View File

@ -1,20 +0,0 @@
import { Controller } from "stimulus";
import ajaxService from "../services/ajax_service";
export default class extends Controller {
static targets = ["tag", "tagList"]
create(event) {
const tag = this.tagTarget.value;
event.preventDefault();
ajaxService.createTag(tag)
.then(response => {
if (response.status == 200) {
this.tagListTarget.innerHTML += response.data;
this.tagTarget.value = "";
};
})
}
}

View File

@ -1,18 +0,0 @@
/* eslint no-console:0 */
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
//
// To reference this file, add <%= javascript_pack_tag 'application' %> to the appropriate
// layout file, like app/views/layouts/application.html.erb
import Rails from "rails-ujs";
import { Application } from "stimulus";
import { definitionsFromContext } from "stimulus/webpack-helpers";
Rails.start();
const application = Application.start();
const context = require.context("controllers", true, /.js$/);
application.load(definitionsFromContext(context));

View File

@ -1,32 +0,0 @@
import axios from "axios";
const csrfToken = () => {
return document
.getElementsByName("csrf-token")[0]
.attributes["content"]
.value;
}
const imageId = () => {
return document
.getElementsByClassName("show-image")[0]
.attributes["data-image-id"]
.value;
}
const config = () => ({
headers: { "X-CSRF-Token": csrfToken() }
});
export default {
createTag: (tag) => {
return axios.post(`/user/images/${imageId()}/tags`, { tag }, config());
},
deleteTag: (tag) => {
return axios.delete(
`/user/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,11 +3,13 @@
<%= 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" } %>
<%= submit_tag "Add Tag", data: { disable_with: false } %>
data: {"turbo-frame": "tags"}
) do %>
<%= text_field_tag :tag, nil %>
<%= submit_tag "Add Tag" %>
<% end %>
</div>
</div>

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

@ -4,8 +4,8 @@
<title>My Images</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<%= stylesheet_link_tag "application", media: "all" %>
<%= javascript_pack_tag "application" %>
<%= csrf_meta_tags %>
<%= javascript_importmap_tags %>
</head>
<body>

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),
data: { action: "click->tag#delete" },
image_tag_path(image, id: tag),
data: {method: "delete", "turbo-frame": "tags"},
class: "delete-tag" %>
</li>

View File

@ -1,5 +1,7 @@
<ul class="image-tags-list" id="image-tags" data-target="tags.tagList">
<% tags.each do |tag| %>
<%= render "tags/tag", image: image, tag: tag %>
<% end %>
</ul>
<%= turbo_frame_tag "tags" do %>
<ul class="image-tags-list" id="image-tags" data-target="tags.tagList">
<% tags.each do |tag| %>
<%= render "tags/tag", image: image, tag: tag %>
<% end %>
</ul>
<% end %>

View File

@ -1,4 +0,0 @@
document.getElementById("tag").value = "";
document.getElementById("image-tags")
.outerHTML = `<%= render "tags", image: image, tags: tags %>`;

4
bin/importmap Executable file
View File

@ -0,0 +1,4 @@
#!/usr/bin/env ruby
require_relative "../config/application"
require "importmap/commands"

8
config/importmap.rb Normal file
View File

@ -0,0 +1,8 @@
# Pin npm packages by running ./bin/importmap
pin "application"
pin "@rails/ujs", to: "@rails--ujs.js" # @7.1.3
pin "@hotwired/stimulus", to: "@hotwired--stimulus.js" # @3.2.2
pin "@hotwired/turbo-rails", to: "@hotwired--turbo-rails.js" # @8.0.4
pin "@hotwired/turbo", to: "@hotwired--turbo.js" # @8.0.4
pin "@rails/actioncable/src", to: "@rails--actioncable--src.js" # @7.1.3

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