gallerist 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +2 -0
  3. data/CONTRIBUTING.md +53 -0
  4. data/Gemfile +8 -0
  5. data/LICENSE +25 -0
  6. data/README.md +57 -0
  7. data/Rakefile +16 -0
  8. data/assets/stylesheets/main.scss +17 -0
  9. data/bin/gallerist +59 -0
  10. data/config.ru +21 -0
  11. data/gallerist.gemspec +32 -0
  12. data/lib/gallerist.rb +46 -0
  13. data/lib/gallerist/app.rb +230 -0
  14. data/lib/gallerist/errors.rb +12 -0
  15. data/lib/gallerist/helpers.rb +72 -0
  16. data/lib/gallerist/library.rb +100 -0
  17. data/lib/gallerist/middleware/raise_warmup_exceptions.rb +24 -0
  18. data/lib/gallerist/middleware/show_exceptions.rb +40 -0
  19. data/lib/gallerist/models/admin_data.rb +10 -0
  20. data/lib/gallerist/models/album.rb +30 -0
  21. data/lib/gallerist/models/album_photo.rb +20 -0
  22. data/lib/gallerist/models/base_model.rb +32 -0
  23. data/lib/gallerist/models/image_proxies_model.rb +11 -0
  24. data/lib/gallerist/models/image_proxy_state.rb +22 -0
  25. data/lib/gallerist/models/master.rb +25 -0
  26. data/lib/gallerist/models/model_resource.rb +22 -0
  27. data/lib/gallerist/models/person.rb +46 -0
  28. data/lib/gallerist/models/person_model.rb +10 -0
  29. data/lib/gallerist/models/person_photo.rb +39 -0
  30. data/lib/gallerist/models/photo.rb +100 -0
  31. data/lib/gallerist/models/tag.rb +31 -0
  32. data/lib/gallerist/models/tag_photo.rb +20 -0
  33. data/lib/rack/handler/unicorn.rb +34 -0
  34. data/views/500.erb +5 -0
  35. data/views/album.erb +9 -0
  36. data/views/index.erb +24 -0
  37. data/views/layout.erb +34 -0
  38. data/views/partials/thumbnail.erb +13 -0
  39. data/views/person.erb +9 -0
  40. data/views/photos.erb +9 -0
  41. data/views/tag.erb +9 -0
  42. metadata +183 -0
@@ -0,0 +1,10 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2015, Sebastian Staudt
5
+
6
+ class Gallerist::PersonModel < Gallerist::BaseModel
7
+
8
+ self.abstract_class = true
9
+
10
+ end
@@ -0,0 +1,39 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2015, Sebastian Staudt
5
+
6
+ class Gallerist::PersonPhoto < Gallerist::PersonModel
7
+
8
+ iphoto do
9
+ self.table_name = 'RKDetectedFace'
10
+
11
+ has_one :person, primary_key: 'faceKey', foreign_key: 'faceKey'
12
+
13
+ alias_attribute :master_uuid, :masterUuid
14
+ alias_attribute :person_id, :faceKey
15
+
16
+ def photo
17
+ Gallerist::Photo.find_by master_uuid: master_uuid
18
+ end
19
+
20
+ def photo_id
21
+ photo.id
22
+ end
23
+ end
24
+
25
+ photos do
26
+ self.table_name = 'RKPersonVersion'
27
+
28
+ has_one :person, primary_key: 'personId', foreign_key: 'modelId'
29
+ has_one :photo, primary_key: 'versionId', foreign_key: 'modelId'
30
+
31
+ alias_attribute :person_id, :personId
32
+ alias_attribute :photo_id, :versionId
33
+ end
34
+
35
+ def inspect
36
+ '#<%s person_id=%d photo_id=%s>' % [ self.class, person_id, photo_id ]
37
+ end
38
+
39
+ end
@@ -0,0 +1,100 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2015, Sebastian Staudt
5
+
6
+ class Gallerist::Photo < Gallerist::BaseModel
7
+
8
+ self.table_name = 'RKVersion'
9
+
10
+ has_one :image_proxy_state, foreign_key: 'versionId'
11
+ has_one :master, primary_key: 'masterId', foreign_key: 'modelId'
12
+ has_one :model_resource, -> { where model_type: 2 }, foreign_key: 'attachedModelId'
13
+ has_many :album_photos, primary_key: 'modelId', foreign_key: 'versionId'
14
+ has_many :albums, through: :album_photos
15
+ has_many :tag_photos, primary_key: 'modelId', foreign_key: 'versionId'
16
+ has_many :tags, -> { distinct }, through: :tag_photos
17
+
18
+ iphoto do
19
+ alias_attribute :master_uuid, :masterUuid
20
+
21
+ def person_photos
22
+ Gallerist::PersonPhoto.where master_uuid: master.uuid
23
+ end
24
+ end
25
+
26
+ photos do
27
+ has_many :person_photos, primary_key: 'modelId', foreign_key: 'versionId'
28
+ end
29
+
30
+ alias_attribute :date, :imageDate
31
+ alias_attribute :file_name, :fileName
32
+ alias_attribute :is_favorite, :isFavorite
33
+ alias_attribute :show_in_library, :showInLibrary
34
+
35
+ delegate :thumbnail_available?, to: :image_proxy_state, allow_nil: true
36
+
37
+ scope :favorites, -> { where(is_favorite: true) }
38
+
39
+ photos do
40
+ default_scope do
41
+ select(:masterId, :modelId, :fileName, :imageDate, :type, :uuid).
42
+ where(show_in_library: true)
43
+ end
44
+ end
45
+
46
+ iphoto do
47
+ default_scope do
48
+ select(:masterId, :modelId, :fileName, :imageDate, :uuid).
49
+ where(show_in_library: true)
50
+ end
51
+ end
52
+
53
+ def image_path
54
+ if model_resource && !video?
55
+ uuid = model_resource.uuid
56
+ first, second = uuid[0].ord.to_s, uuid[1].ord.to_s
57
+
58
+ File.join 'resources', 'modelresources', first, second, uuid, model_resource.file_name
59
+ else
60
+ File.join 'Masters', master.path
61
+ end
62
+ end
63
+
64
+ def inspect
65
+ "#<%s id=%d uuid=%s file_name='%s'>" % [ self.class, id, uuid, file_name ]
66
+ end
67
+
68
+ def path
69
+ File.dirname master.path
70
+ end
71
+
72
+ # ActiveRecord does not support has_many-through associations across
73
+ # different databases, so we have to query the persons manually
74
+ photos do
75
+ def persons
76
+ Gallerist::Person.where modelId: person_photos.map(&:person_id)
77
+ end
78
+ end
79
+
80
+ iphoto do
81
+ def persons
82
+ Gallerist::Person.where faceKey: person_photos.map(&:person_id)
83
+ end
84
+ end
85
+
86
+ def preview_path
87
+ dir_name = File.dirname master.path
88
+ image_name = File.basename(master.path, '.*') + '.jpg'
89
+ File.join 'Previews', dir_name, image_name
90
+ end
91
+
92
+ def small_thumbnail_path
93
+ File.join 'Thumbnails', image_proxy_state.small_thumbnail_path
94
+ end
95
+
96
+ def video?
97
+ type == 8
98
+ end
99
+
100
+ end
@@ -0,0 +1,31 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2015, Sebastian Staudt
5
+
6
+ class Gallerist::Tag < Gallerist::BaseModel
7
+
8
+ self.table_name = 'RKKeyword'
9
+
10
+ has_many :tag_photos, primary_key: 'modelId', foreign_key: 'keywordId'
11
+ has_many :photos, -> { distinct }, through: :tag_photos
12
+
13
+ alias_attribute :simple_name, :searchName
14
+
15
+ default_scope { select(:modelId, :name, :searchName) }
16
+ scope :nonempty, -> {
17
+ joins(:tag_photos).
18
+ select('count(RKKeywordForVersion.keywordId) as photos_count').
19
+ group('RKKeywordForVersion.keywordId').
20
+ having('photos_count > 0')
21
+ }
22
+
23
+ def inspect
24
+ "#<%s id=%d name='%s'>" % [ self.class, id, name ]
25
+ end
26
+
27
+ def to_s
28
+ name
29
+ end
30
+
31
+ end
@@ -0,0 +1,20 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2015, Sebastian Staudt
5
+
6
+ class Gallerist::TagPhoto < Gallerist::BaseModel
7
+
8
+ self.table_name = 'RKKeywordForVersion'
9
+
10
+ has_one :tag, primary_key: 'keywordId', foreign_key: 'modelId'
11
+ has_one :photo, primary_key: 'versionId', foreign_key: 'modelId'
12
+
13
+ alias_attribute :tag_id, :keywordId
14
+ alias_attribute :photo_id, :versionId
15
+
16
+ def inspect
17
+ '#<%s tag_id=%d photo_id=%d>' % [ self.class, tag_id, photo_id ]
18
+ end
19
+
20
+ end
@@ -0,0 +1,34 @@
1
+ # This code is free software; you can redistribute it and/or modify it under
2
+ # the terms of the new BSD License.
3
+ #
4
+ # Copyright (c) 2015, Sebastian Staudt
5
+
6
+ require 'unicorn'
7
+
8
+ module Rack::Handler::Unicorn
9
+
10
+ class << self
11
+
12
+ def run(app, options = {})
13
+ environment = ENV['RACK_ENV'] || 'development'
14
+ default_host = (environment == 'development') ? 'localhost' : '0.0.0.0'
15
+ options[:Host] ||= default_host
16
+
17
+ unicorn_options = {
18
+ listeners: [ '%s:%d' % [ options[:Host], options[:Port] ] ],
19
+ worker_processes: options[:worker_processes] || 1
20
+ }
21
+
22
+ ::Unicorn::Launcher.daemonize!(unicorn_options) if options[:daemonize]
23
+ ::Unicorn::HttpServer.new(app, unicorn_options).start.join
24
+ end
25
+
26
+ def environment
27
+ ENV['RACK_ENV']
28
+ end
29
+
30
+ end
31
+
32
+ end
33
+
34
+ Rack::Handler.register :unicorn, Rack::Handler::Unicorn
@@ -0,0 +1,5 @@
1
+ <div class="jumbotron">
2
+ <h2><span class="text-danger">Internal Server Error</span></h2>
3
+
4
+ Something went wrong while processing this request.
5
+ </div>
@@ -0,0 +1,9 @@
1
+ <h1><%= @album.name %></h1>
2
+
3
+ <div class="row">
4
+ <% @album.photos.order(:date).each do |photo| %>
5
+ <div class="col-md-3">
6
+ <%= partial :thumbnail, locals: { photo: photo } %>
7
+ </div>
8
+ <% end %>
9
+ </div>
@@ -0,0 +1,24 @@
1
+ <div class="list-group">
2
+ <a class="list-group-item" href="/photos">All photos</a>
3
+ <a class="list-group-item" href="/favorites">Favorites</a>
4
+ </div>
5
+
6
+ <h2>Albums</h2>
7
+
8
+ <div class="list-group">
9
+ <% @albums.each do |album| %>
10
+ <%= link_to album, 'list-group-item' %>
11
+ <% end %>
12
+ </div>
13
+
14
+ <h2>Tags</h2>
15
+
16
+ <h3>
17
+ <%= @tags.map { |tag| link_to tag }.join %>
18
+ </h3>
19
+
20
+ <h2>Persons</h2>
21
+
22
+ <h3>
23
+ <%= @persons.map { |person| link_to person }.join %>
24
+ </h3>
@@ -0,0 +1,34 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <title><%= title %></title>
5
+
6
+ <link href="<%= stylesheet_path 'main' %>" rel="stylesheet">
7
+
8
+ <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
9
+ </head>
10
+ <body>
11
+ <nav class="navbar navbar-default navbar-inverse navbar-static-top">
12
+ <div class="container-fluid">
13
+ <div class="navbar-header">
14
+ <span class="navbar-brand"><strong>Gallerist</strong></span>
15
+ </div>
16
+ <ul class="nav navbar-nav">
17
+ <% (navbar || []).each_with_index do |item, idx| %>
18
+ <li<%= ' class="active"' if idx == navbar.size - 1 %>>
19
+ <% if route_exists item.first %>
20
+ <a href="<%= item.first %>" ><%= item.last %></a>
21
+ <% else %>
22
+ <span class="navbar-text"><%= item.last %></span>
23
+ <% end %>
24
+ </li>
25
+ <% end %>
26
+ </ul>
27
+ </div>
28
+ </nav>
29
+
30
+ <div class="container-fluid">
31
+ <%= yield %>
32
+ </div>
33
+ </body>
34
+ </html>
@@ -0,0 +1,13 @@
1
+ <div class="thumbnail">
2
+ <a href="<%= url_for(photo) %>">
3
+ <img src="/thumbs/<%= photo.id %>">
4
+ </a>
5
+ <div class="caption">
6
+ <% unless photo.tags.to_a.empty? %>
7
+ <p>Tags: <%= photo.tags.map { |t| link_to t }.join('') %></p>
8
+ <% end %>
9
+ <% unless photo.persons.to_a.empty? %>
10
+ <p>Persons: <%= photo.persons.map { |t| link_to t }.join('') %></p>
11
+ <% end %>
12
+ </div>
13
+ </div>
@@ -0,0 +1,9 @@
1
+ <h1><%= @person.name %></h1>
2
+
3
+ <div class="row">
4
+ <% @person.photos.order(:date).each do |photo| %>
5
+ <div class="col-md-3">
6
+ <%= partial :thumbnail, locals: { photo: photo } %>
7
+ </div>
8
+ <% end %>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <h1><%= @title %></h1>
2
+
3
+ <div class="row">
4
+ <% @photos.order(:date).each do |photo| %>
5
+ <div class="col-md-3">
6
+ <%= partial :thumbnail, locals: { photo: photo } %>
7
+ </div>
8
+ <% end %>
9
+ </div>
@@ -0,0 +1,9 @@
1
+ <h1><%= @tag.name %></h1>
2
+
3
+ <div class="row">
4
+ <% @tag.photos.order(:date).each do |photo| %>
5
+ <div class="col-md-3">
6
+ <%= partial :thumbnail, locals: { photo: photo } %>
7
+ </div>
8
+ <% end %>
9
+ </div>
metadata ADDED
@@ -0,0 +1,183 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gallerist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Sebastian Staudt
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '4.2'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '4.2'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bootstrap-sass
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.3'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '3.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rack
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.6'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.6'
55
+ - !ruby/object:Gem::Dependency
56
+ name: sinatra
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.4'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sprockets-helpers
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '1.1'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '1.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sqlite3
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: unicorn
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: '4.8'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: '4.8'
111
+ description: View Photos and iPhoto libraries in your browser
112
+ email:
113
+ - koraktor@gmail.com
114
+ executables:
115
+ - gallerist
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - .gitignore
120
+ - CONTRIBUTING.md
121
+ - Gemfile
122
+ - LICENSE
123
+ - README.md
124
+ - Rakefile
125
+ - assets/stylesheets/main.scss
126
+ - bin/gallerist
127
+ - config.ru
128
+ - gallerist.gemspec
129
+ - lib/gallerist.rb
130
+ - lib/gallerist/app.rb
131
+ - lib/gallerist/errors.rb
132
+ - lib/gallerist/helpers.rb
133
+ - lib/gallerist/library.rb
134
+ - lib/gallerist/middleware/raise_warmup_exceptions.rb
135
+ - lib/gallerist/middleware/show_exceptions.rb
136
+ - lib/gallerist/models/admin_data.rb
137
+ - lib/gallerist/models/album.rb
138
+ - lib/gallerist/models/album_photo.rb
139
+ - lib/gallerist/models/base_model.rb
140
+ - lib/gallerist/models/image_proxies_model.rb
141
+ - lib/gallerist/models/image_proxy_state.rb
142
+ - lib/gallerist/models/master.rb
143
+ - lib/gallerist/models/model_resource.rb
144
+ - lib/gallerist/models/person.rb
145
+ - lib/gallerist/models/person_model.rb
146
+ - lib/gallerist/models/person_photo.rb
147
+ - lib/gallerist/models/photo.rb
148
+ - lib/gallerist/models/tag.rb
149
+ - lib/gallerist/models/tag_photo.rb
150
+ - lib/rack/handler/unicorn.rb
151
+ - views/500.erb
152
+ - views/album.erb
153
+ - views/index.erb
154
+ - views/layout.erb
155
+ - views/partials/thumbnail.erb
156
+ - views/person.erb
157
+ - views/photos.erb
158
+ - views/tag.erb
159
+ homepage: https://github.com/koraktor/gallerist
160
+ licenses:
161
+ - BSD
162
+ metadata: {}
163
+ post_install_message:
164
+ rdoc_options: []
165
+ require_paths:
166
+ - lib
167
+ required_ruby_version: !ruby/object:Gem::Requirement
168
+ requirements:
169
+ - - '>='
170
+ - !ruby/object:Gem::Version
171
+ version: '0'
172
+ required_rubygems_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - '>='
175
+ - !ruby/object:Gem::Version
176
+ version: '0'
177
+ requirements: []
178
+ rubyforge_project:
179
+ rubygems_version: 2.4.6
180
+ signing_key:
181
+ specification_version: 4
182
+ summary: A web application to browse Apple Photos and iPhoto libraries
183
+ test_files: []