mix-rails-albums 0.16.0 → 0.22.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.
@@ -3,7 +3,7 @@ class Application.Models.Photo extends Backbone.Model
3
3
  idAttribute: '_id'
4
4
  defaults:
5
5
  image: null
6
- description: null
6
+ description: ''
7
7
  progress: 0
8
8
 
9
9
  initialize: ->
@@ -1,16 +1,20 @@
1
1
  class Application.Routers.PhotosRouter extends Backbone.Router
2
2
  initialize: (options) ->
3
3
  @photos = new Application.Collections.PhotosCollection()
4
+ @upload_index()
5
+
4
6
  @photos.url = options.collectionUrl
5
7
  @photos.reset options.photos
6
8
 
9
+
7
10
  routes:
8
- "new" : "newPhoto"
9
- "index" : "index"
10
- "upload_index" : "upload_index"
11
- ":id/edit" : "edit"
12
- ":id" : "show"
13
- ".*" : "upload_index"
11
+ "new" : "newPhoto"
12
+ "index" : "index"
13
+ "upload_index" : "upload_index"
14
+ "photo_edited" : "photo_edited"
15
+ ":id/edit" : "edit"
16
+ ":id" : "show"
17
+ ".*" : "upload_index"
14
18
 
15
19
  newPhoto: ->
16
20
  @view = new Application.Views.Photos.NewView(collection: @photos)
@@ -32,6 +36,10 @@ class Application.Routers.PhotosRouter extends Backbone.Router
32
36
 
33
37
  edit: (id) ->
34
38
  photo = @photos.get(id)
35
- console.log 'Editando a foto!' + photo
39
+ console.log 'Editando a foto!', id
40
+ $("#photo-modal-#{id}").modal()
36
41
  #@view = new Application.Views.Photos.EditView(model: photo)
37
42
  #$("#upload-container").html(@view.render().el)
43
+
44
+ photo_edited: () ->
45
+
@@ -0,0 +1,14 @@
1
+ .modal.hide.fade.admix-photo-modal{id: "photo-modal-#{@_id}"}
2
+ .modal-header
3
+ %button.close{"aria-hidden" => "true", "data-dismiss" => "modal", :type => "button"} ×
4
+ %h3 Detalhes da foto
5
+ .modal-body
6
+ .edit-area.pull-right
7
+ %textarea.span5{id: "input_photo_description_#{@_id}",placeholder: 'Adicione uma descrição para esta foto.'}
8
+ #{@description}
9
+ .photo
10
+ %img{src: @image.medium.url}
11
+ %p One fine body…
12
+ .modal-footer
13
+ %a.btn{href:"#", "data-dismiss": "modal"} Cancelar
14
+ %a.btn.btn-primary.save{:href => "#", "data-dismiss": "modal"} Salvar mudanças
@@ -1,18 +1,21 @@
1
1
  .thumbnail
2
- .file-title
3
- = @title
4
2
  %a.link-popover{"data-content" => "<i class=icon-edit></i> Edit"}
5
3
  .loading-file
6
- - if @image.url
7
- %a.photo-link{href: "#"}
8
- %img{src: ROOT_PATH + @image.medium.url}
4
+ - if @get('image').url
5
+ %a.edit{href: "#"}
6
+ %img{src: ROOT_PATH + @get('image').medium.url}
9
7
  - else
10
8
  %img{src: "http://placehold.it/130x90&text=Carregando"}
11
9
  -if (@progress != null && @progress < 100)
12
10
  %div{class: (@progress < 100) ? 'progress progress-striped active' : 'progress'}
13
11
  .bar{style: "width:#{@progress}%;"}
12
+ %textarea.span12{style: 'margin-top:5px;', placeholder:'Adicione uma descrição'}
13
+ = @get('description')
14
14
  .caption
15
15
  %a.file-action.btn.destroy{href: "#", tooltip: 'Excluir'}
16
16
  <%= image_tag "admix/icons/delete.png" %>
17
- %a.file-action.btn.edit{href: "#", tooltip: 'Editar'}
18
- <%= image_tag "admix/icons/picture_edit.png" %>
17
+ -#%a.file-action.btn.edit{href: "#", tooltip: 'Editar'}
18
+ <%= image_tag "admix/icons/picture_edit.png" %>
19
+
20
+ %a.file-action.btn.btn-primary.save{style: 'display:none', href: "#", tooltip: 'Salvar mudanças'}
21
+ = 'Salvar mudanças'
@@ -0,0 +1,26 @@
1
+ Application.Views.Photos ||= {}
2
+
3
+ class Application.Views.Photos.PhotoModalEditView extends Backbone.View
4
+ template: JST["backbone/templates/photos/photo_modal_edit"]
5
+ tagName: "div"
6
+ #className: "span2"
7
+ events:
8
+ "click .save": "save_changes"
9
+
10
+ initialize: ->
11
+ @model.on "change", @render, this
12
+
13
+ render: ->
14
+ data = _.defaults(@model.attributes,
15
+ id: null
16
+ )
17
+ html = @template(@model.attributes)
18
+ $(@el).html html
19
+ this
20
+
21
+ save_changes: (e) ->
22
+ e.preventDefault()
23
+ description = $("#input_photo_description_#{@model.id}").val()
24
+ @model.set(description: description)
25
+ $.post @model.url() + '/update_description', @model.attributes, (data) ->
26
+ Backbone.history.navigate('photo_edited')
@@ -6,11 +6,14 @@ class Application.Views.Photos.PhotoView extends Backbone.View
6
6
  events:
7
7
  "click .destroy" : "destroy"
8
8
  "click .edit": "edit",
9
+ "keydown textarea": 'update_description'
10
+ "click .save": 'save_description'
9
11
 
10
12
  tagName: "li"
11
- className: 'span4'
13
+ className: 'span3'
12
14
 
13
15
  initialize: ->
16
+ @tmpDescription = null
14
17
  @model.on "change", @render, this
15
18
  @model.on "uploadCompleted", @removeProgressBar, this
16
19
  self = @
@@ -27,12 +30,32 @@ class Application.Views.Photos.PhotoView extends Backbone.View
27
30
  destroy: ->
28
31
  if confirm('Tem certeza que deseja deletar?')
29
32
  @model.destroy()
30
- this.remove()
33
+ @$el.fadeOut 500, () =>
34
+ @remove()
31
35
  $(".qtip-#{@model.get('id')}").remove()
32
36
  false
33
37
  edit: () ->
34
38
  Backbone.history.navigate("#/#{@model.id}/edit")
35
39
  false
40
+ update_description: () ->
41
+ self = @
42
+ $(@el).find('textarea').livequery ->
43
+ new_description = $(this).val()
44
+ self.tmpDescription = new_description
45
+ $(self.el).find('.save').show()
46
+
47
+ save_description: (e) ->
48
+ e.preventDefault()
49
+ @doHighlighter = true
50
+ new_description = $(@el).find('textarea').val()
51
+ @model.set(description : new_description)
52
+ @tmpDescription = null
53
+ $.post @model.url() + '/update_description', @model.attributes, (data) =>
54
+ $(@el).find('.save').hide()
55
+
36
56
  render: ->
37
- @$el.html(@template(@model.toJSON() ))
57
+ @$el.html(@template(@model))
58
+ if @doHighlighter?
59
+ @$el.find('textarea').effect('highlight', {}, 3000)
60
+ @doHighlighter = undefined
38
61
  return this
@@ -9,9 +9,16 @@ class Admix::PhotosController < Admix::AdmixController
9
9
 
10
10
  polymorphic_belongs_to :album, param: :album_id
11
11
 
12
- # load_and_authorize_resource :album
13
- # load_and_authorize_resource :photo, :through => :album_id
14
- skip_load_and_authorize_resource
12
+ # TODO: Maybe we need to skip authorization here. But not authetication.
13
+
14
+ def update_description
15
+ @album = Album.find(params[:album_id])
16
+ @photo = @album.photos.find(params[:id])
17
+ @photo.description = params[:description]
18
+ @photo.save()
19
+ render :json => @photo
20
+ end
21
+
15
22
 
16
23
  def upload
17
24
  render inline: params.to_s
@@ -2,18 +2,10 @@ class AlbumsController < ApplicationController
2
2
 
3
3
  def index
4
4
  @albums = Album.published.paginate(:page => params[:page], :per_page => 12)
5
- # @albums.each do |a|
6
- # a.photos.each do |p|
7
- # p.image.recreate_versions!
8
- # end
9
- # end
10
-
11
5
  end
12
6
 
13
7
  def show
14
8
  @album = Album.find(params[:id])
15
9
  end
16
-
17
10
 
18
-
19
11
  end
@@ -0,0 +1,12 @@
1
+ class PhotosController < ApplicationController
2
+
3
+ def index
4
+ #@albums = Album.published.paginate(:page => params[:page], :per_page => 12)
5
+ end
6
+
7
+ def show
8
+ @album = Album.find(params[:album_id])
9
+ @photo = @album.photos.find(params[:id])
10
+ end
11
+
12
+ end
@@ -2,30 +2,28 @@ class Admix::AlbumsDatagrid
2
2
 
3
3
  include Datagrid
4
4
 
5
+ extend AdmixHelper
6
+
5
7
 
6
8
  scope do
7
9
  Album.desc(:date)
8
10
  end
9
11
 
10
- filter :name, :string
12
+ filter :title, :string
11
13
  filter :date do |value|
12
14
  value.to_s(:created_at)
13
15
  end
14
16
 
15
- column :name, header: I18n.t('albums.name')
16
- column :date, header: I18n.t('albums.date') do |album|
17
+ column :title, header: input_label(:albums, :title)
18
+ column :date, header: input_label(:albums, :date) do |album|
17
19
  album.date.strftime("%d/%m/%Y") #album.date.to_s(:created_at)
18
20
  end
19
- column :photos_quantity, header: I18n.t('albums.photos_quantity') do |album|
21
+ column :photos_quantity, header: input_label(:albums, :photos_quantity) do |album|
20
22
  album.photos.count
21
23
  end
22
24
 
23
- column :published, header: I18n.t('albums.published') do |album|
24
- if album.published
25
- I18n.t("albums.published_yes")
26
- else
27
- I18n.t("albums.published_no")
28
- end
25
+ column :published, header: input_label(:albums, :status) do |album|
26
+ album.status.text
29
27
  end
30
28
 
31
29
 
data/app/models/album.rb CHANGED
@@ -1,27 +1,3 @@
1
1
  class Album
2
-
3
- include Mongoid::Document
4
- include Mongoid::Timestamps
5
- include Mongoid::Slug
6
-
7
- field :name, type: String
8
- field :description, type: String
9
- field :date, type: Date
10
- field :published, type: Boolean, default: true
11
-
12
-
13
- validates_presence_of :name
14
- validates_presence_of :date
15
-
16
- #slug :name, history: true
17
-
18
- slug :name, history: true do |current_object|
19
- current_object.name.parameterize
20
- end
21
-
22
- embeds_many :photos, cascade_callbacks: true
23
-
24
- scope :published, where(published: true, :photos.ne => nil, :photos.exists => true)
25
-
26
-
2
+ include MixRailsAlbums::Concerns::Models::Album
27
3
  end
data/app/models/photo.rb CHANGED
@@ -2,8 +2,6 @@ class Photo
2
2
 
3
3
  include Mongoid::Document
4
4
  include Mongoid::Timestamps
5
-
6
- attr_accessible :description, :image, :image_cache
7
5
 
8
6
  field :description
9
7
 
@@ -1,5 +1,6 @@
1
1
  # encoding: utf-8
2
2
  require 'carrierwave/processing/mini_magick'
3
+ require 'mix-rails-core/gridfs'
3
4
 
4
5
  class Albums::ImageUploader < CarrierWave::Uploader::Base
5
6
 
@@ -22,7 +23,7 @@ class Albums::ImageUploader < CarrierWave::Uploader::Base
22
23
  end
23
24
 
24
25
  def cache_dir
25
- "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
26
+ "system/uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
26
27
  end
27
28
 
28
29
  # Provide a default URL as a default if there hasn't been a file uploaded:
@@ -45,8 +46,35 @@ class Albums::ImageUploader < CarrierWave::Uploader::Base
45
46
  # process :resize_to_fit => [80, 80]
46
47
  # end
47
48
 
49
+ def watermark
50
+ manipulate! do |img|
51
+
52
+ albums_watermark = Setting.albums_watermark
53
+
54
+ watermark_image = if albums_watermark
55
+ gridfs_file = MixRailsCore::Gridfs::read_file(albums_watermark.image.url)
56
+ MiniMagick::Image.read(gridfs_file, "png")
57
+ else
58
+ # We can read a file from system too.
59
+ #MiniMagick::Image.open("#{Rails.root}/app/assets/images/watermarks/watermark.png", "png")
60
+ false
61
+ end
62
+
63
+ if watermark_image
64
+ result = img.composite(watermark_image) do |c|
65
+ c.gravity "SouthEast"
66
+ end
67
+ result
68
+ else
69
+ img
70
+ end
71
+
72
+ end
73
+ end
74
+
48
75
  version :medium do
49
76
  process :resize_to_fill => [640,420]
77
+ process :watermark
50
78
  end
51
79
 
52
80
  version :thumb do
@@ -1,4 +1,4 @@
1
- = f.input :name, as: 'string'
1
+ = f.input :title, as: 'string'
2
2
  = f.input :description, as: 'text'
3
3
  = f.input :date, as: 'datepicker'
4
- = f.input :published, as: 'boolean'
4
+ = f.input :status
@@ -1,7 +1,7 @@
1
1
  %dl
2
- %dt= t('albums.name')
3
- %dd= resource.name
4
- %dt= t('albums.date')
2
+ %dt= input_label(:albums, :title)
3
+ %dd= resource.title
4
+ %dt= input_label(:albums, :date)
5
5
  %dd= resource.date
6
6
 
7
7
  = render('admix/photos/upload')
@@ -0,0 +1,4 @@
1
+ - content_for(:photos_content) do
2
+ = render @photos
3
+ = will_paginate @photos
4
+ = render template: 'templates/photos/index'
@@ -0,0 +1,3 @@
1
+ - content_for(:photo_content) do
2
+ = render partial: 'photo_show', locals: {album: @album, photo: @photo}
3
+ = render template: 'templates/photos/show'
@@ -1,6 +1,7 @@
1
1
  pt-BR:
2
2
  resources:
3
- albums: 'fotos'
3
+ albums: 'albuns'
4
+ photos: 'fotos'
4
5
  will_paginate:
5
6
  previous_label: "<< admix"
6
7
  next_label: "próximo >>"
@@ -14,4 +15,15 @@ pt-BR:
14
15
  name: 'Nome'
15
16
  date: 'Data'
16
17
  published: 'Publicado?'
17
- photos_quantity: "Quantidade de fotos"
18
+ photos_quantity: "Quantidade de fotos"
19
+
20
+ photos:
21
+ photos: 'Fotos'
22
+ photo: 'Foto'
23
+ legend: 'Legenda'
24
+ or: 'ou'
25
+ upload:
26
+ explanation: 'Clique no botão abaixo para adicionar as fotos.'
27
+ btn:
28
+ upload_pictures: 'Enviar arquivos de imagem'
29
+ upload_zip: 'Enviar arquivo ZIP'
data/config/routes.rb CHANGED
@@ -1,7 +1,9 @@
1
1
  Rails.application.routes.draw do
2
2
 
3
3
  localized do
4
- resources :albums
4
+ resources :albums, :only => [:index, :show] do
5
+ resources :photos, :only => [:index, :show]
6
+ end
5
7
  end
6
8
 
7
9
  scope Admix::namespace_path, as: :admix, module: :admix do
@@ -9,6 +11,7 @@ Rails.application.routes.draw do
9
11
  resources :photos do
10
12
  member do
11
13
  get :edit_ajax
14
+ post :update_description
12
15
  end
13
16
  end
14
17
  end
@@ -0,0 +1,43 @@
1
+ module MixRailsAlbums::Concerns::Models::Album
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+
6
+ include Mongoid::Document
7
+ include Mongoid::Timestamps
8
+ include Mongoid::Slug
9
+
10
+ extend Enumerize
11
+
12
+ field :title, type: String
13
+ field :description, type: String
14
+ field :date, type: Date
15
+ field :status, type: String
16
+ enumerize :status, in: [:published, :unpublished], default: :published, predicates: true
17
+
18
+ validation_for_title
19
+ validation_for_date
20
+
21
+ slug :title, history: true do |current_object|
22
+ current_object.title.parameterize
23
+ end
24
+
25
+ embeds_many :photos, cascade_callbacks: true
26
+
27
+ scope :published, where(status: :published, :photos.ne => nil, :photos.exists => true)
28
+
29
+ end
30
+
31
+ module ClassMethods
32
+
33
+ def validation_for_title
34
+ validates_presence_of :title
35
+ end
36
+
37
+ def validation_for_date
38
+ validates_presence_of :date
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -7,7 +7,7 @@ module MixRailsAlbums
7
7
  Admix::Navigation::NavBar.find(:content) do |menu|
8
8
  menu.submenu do |submenu|
9
9
  submenu.key = :albums
10
- submenu.title = I18n.t 'albums.albums'
10
+ submenu.title = I18n.t('albums.albums')
11
11
  submenu.url = 'admix_albums_url'
12
12
  end
13
13
  end
@@ -1,7 +1,7 @@
1
1
  module MixRailsAlbums
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 0
4
- MINOR = 16
4
+ MINOR = 22
5
5
  TINY = 0
6
6
  PRE = nil
7
7
 
@@ -7,4 +7,10 @@ require "mini_magick"
7
7
  require "haml_coffee_assets"
8
8
 
9
9
  module MixRailsAlbums
10
- end
10
+ module Concerns
11
+ module Models
12
+ end
13
+ end
14
+ end
15
+
16
+ require 'concerns/models/album'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mix-rails-albums
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.22.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-27 00:00:00.000000000 Z
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -114,87 +114,89 @@ executables: []
114
114
  extensions: []
115
115
  extra_rdoc_files: []
116
116
  files:
117
- - app/assets/stylesheets/skins/tango/next-vertical.png
118
- - app/assets/stylesheets/skins/tango/skin.css
117
+ - app/uploaders/albums/image_uploader.rb
118
+ - app/controllers/admix/albums_controller.rb
119
+ - app/controllers/admix/photos_controller.rb
120
+ - app/controllers/albums_controller.rb
121
+ - app/controllers/photos_controller.rb
119
122
  - app/assets/stylesheets/skins/tango/next-horizontal.png
123
+ - app/assets/stylesheets/skins/tango/skin.css
120
124
  - app/assets/stylesheets/skins/tango/prev-vertical.png
125
+ - app/assets/stylesheets/skins/tango/next-vertical.png
121
126
  - app/assets/stylesheets/skins/tango/credits.txt
122
127
  - app/assets/stylesheets/skins/tango/prev-horizontal.png
123
- - app/assets/stylesheets/skins/ie7/loading-small.gif
124
- - app/assets/stylesheets/skins/ie7/skin.css
125
- - app/assets/stylesheets/skins/ie7/next-horizontal.gif
126
- - app/assets/stylesheets/skins/ie7/credits.txt
127
- - app/assets/stylesheets/skins/ie7/loading_small.gif
128
128
  - app/assets/stylesheets/skins/ie7/loading.gif
129
129
  - app/assets/stylesheets/skins/ie7/prev-horizontal.gif
130
+ - app/assets/stylesheets/skins/ie7/skin.css
131
+ - app/assets/stylesheets/skins/ie7/loading_small.gif
132
+ - app/assets/stylesheets/skins/ie7/credits.txt
133
+ - app/assets/stylesheets/skins/ie7/loading-small.gif
134
+ - app/assets/stylesheets/skins/ie7/next-horizontal.gif
130
135
  - app/assets/stylesheets/colorbox/colorbox.css.scss
131
- - app/assets/images/colorbox/ie6/borderMiddleLeft.png
132
- - app/assets/images/colorbox/ie6/borderTopRight.png
133
- - app/assets/images/colorbox/ie6/borderBottomLeft.png
134
- - app/assets/images/colorbox/ie6/borderTopLeft.png
135
- - app/assets/images/colorbox/ie6/borderBottomCenter.png
136
- - app/assets/images/colorbox/ie6/borderTopCenter.png
137
- - app/assets/images/colorbox/ie6/borderMiddleRight.png
138
- - app/assets/images/colorbox/ie6/borderBottomRight.png
136
+ - app/assets/images/albums/photos.png
137
+ - app/assets/images/albums/delete.png
138
+ - app/assets/images/albums/rotate_cw.png
139
+ - app/assets/images/albums/crop.png
140
+ - app/assets/images/albums/rotate_ccw.png
139
141
  - app/assets/images/colorbox/border.png
142
+ - app/assets/images/colorbox/loading.gif
140
143
  - app/assets/images/colorbox/loading_background.png
141
144
  - app/assets/images/colorbox/controls.png
142
- - app/assets/images/colorbox/loading.gif
145
+ - app/assets/images/colorbox/ie6/borderTopCenter.png
146
+ - app/assets/images/colorbox/ie6/borderMiddleRight.png
147
+ - app/assets/images/colorbox/ie6/borderBottomRight.png
148
+ - app/assets/images/colorbox/ie6/borderBottomCenter.png
149
+ - app/assets/images/colorbox/ie6/borderTopLeft.png
150
+ - app/assets/images/colorbox/ie6/borderTopRight.png
151
+ - app/assets/images/colorbox/ie6/borderBottomLeft.png
152
+ - app/assets/images/colorbox/ie6/borderMiddleLeft.png
143
153
  - app/assets/images/colorbox/overlay.png
144
- - app/assets/images/albums/delete.png
145
- - app/assets/images/albums/photos.png
146
- - app/assets/images/albums/rotate_cw.png
147
- - app/assets/images/albums/rotate_ccw.png
148
- - app/assets/images/albums/crop.png
149
- - app/assets/javascripts/application.js
150
- - app/assets/javascripts/backbone/views/photos/upload_index_view.js.coffee
151
- - app/assets/javascripts/backbone/views/photos/thumbnail_view.js.coffee
152
- - app/assets/javascripts/backbone/models/photo.js.coffee
153
- - app/assets/javascripts/backbone/templates/photos/thumbnail.hamlc.erb
154
+ - app/assets/javascripts/admix/photos.js.erb
155
+ - app/assets/javascripts/templates/photo_modal_edit.hamlc.erb
156
+ - app/assets/javascripts/templates/photo_view.hamlc.erb
157
+ - app/assets/javascripts/backbone/templates/photos/photo_modal_edit.hamlc.erb
154
158
  - app/assets/javascripts/backbone/templates/photos/upload_index.hamlc.erb
159
+ - app/assets/javascripts/backbone/templates/photos/thumbnail.hamlc.erb
155
160
  - app/assets/javascripts/backbone/application.js.coffee
156
161
  - app/assets/javascripts/backbone/routers/photos_router.js.coffee
157
- - app/assets/javascripts/admix/photos.js.erb
158
- - app/assets/javascripts/views/fileview.js
159
- - app/assets/javascripts/views/filezipview.js
160
- - app/assets/javascripts/views/photo_modal_view.js.coffee
161
- - app/assets/javascripts/views/filelistview.js
162
+ - app/assets/javascripts/backbone/models/photo.js.coffee
163
+ - app/assets/javascripts/backbone/views/photos/upload_index_view.js.coffee
164
+ - app/assets/javascripts/backbone/views/photos/photo_modal_view.js.coffee
165
+ - app/assets/javascripts/backbone/views/photos/thumbnail_view.js.coffee
162
166
  - app/assets/javascripts/photos/upload.js.coffee.erb
163
- - app/assets/javascripts/models/filezip.js
164
- - app/assets/javascripts/models/fileitem.js
165
167
  - app/assets/javascripts/collections/filelist.js
166
- - app/assets/javascripts/templates/photo_view.hamlc.erb
167
- - app/assets/javascripts/templates/photo_modal_edit.hamlc.erb
168
168
  - app/assets/javascripts/routers/photo_router.js.coffee.erb
169
- - app/assets/javascripts/albums/show.js.coffee
170
- - app/assets/javascripts/albums/jquery.jcarousel.min.js
169
+ - app/assets/javascripts/models/fileitem.js
170
+ - app/assets/javascripts/models/filezip.js
171
+ - app/assets/javascripts/application.js
172
+ - app/assets/javascripts/views/filelistview.js
173
+ - app/assets/javascripts/views/photo_modal_view.js.coffee
174
+ - app/assets/javascripts/views/filezipview.js
175
+ - app/assets/javascripts/views/fileview.js
176
+ - app/helpers/admix/albums_helper.rb
177
+ - app/models/admix/photos_datagrid.rb
178
+ - app/models/admix/albums_datagrid.rb
179
+ - app/models/album.rb
180
+ - app/models/photo.rb
181
+ - app/views/admix/albums/_show.html.haml
182
+ - app/views/admix/albums/_table_actions.html.haml
183
+ - app/views/admix/albums/_form_fields.html.haml
171
184
  - app/views/admix/photos/index.html.haml
172
185
  - app/views/admix/photos/_upload.html.haml
173
- - app/views/admix/albums/_form_fields.html.haml
174
- - app/views/admix/albums/_table_actions.html.haml
175
- - app/views/admix/albums/_show.html.haml
176
186
  - app/views/albums/index.html.haml
177
187
  - app/views/albums/show.html.haml
178
- - app/controllers/albums_controller.rb
179
- - app/controllers/admix/albums_controller.rb
180
- - app/controllers/admix/photos_controller.rb
181
- - app/models/album.rb
182
- - app/models/admix/photos_datagrid.rb
183
- - app/models/admix/albums_datagrid.rb
184
- - app/models/photo.rb
185
- - app/helpers/admix/albums_helper.rb
186
- - app/uploaders/albums/image_uploader.rb
187
- - config/initializers/carrierwave.rb
188
+ - app/views/photos/index.html.haml
189
+ - app/views/photos/show.html.haml
190
+ - config/locales/albums.pt-BR.yml
191
+ - config/locales/albums.en.yml
188
192
  - config/initializers/albums.rb
189
193
  - config/routes.rb
190
194
  - config/application.rb
191
- - config/locales/photos.pt-BR.yml
192
- - config/locales/albums.pt-BR.yml
193
- - config/locales/albums.en.yml
194
195
  - lib/tasks/albums_tasks.rake
196
+ - lib/mix-rails-albums.rb
197
+ - lib/concerns/models/album.rb
195
198
  - lib/mix-rails-albums/version.rb
196
199
  - lib/mix-rails-albums/engine.rb
197
- - lib/mix-rails-albums.rb
198
200
  - MIT-LICENSE
199
201
  - Rakefile
200
202
  - README.rdoc
@@ -212,7 +214,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
212
214
  version: '0'
213
215
  segments:
214
216
  - 0
215
- hash: -3421642337988709305
217
+ hash: -3474028709906897679
216
218
  required_rubygems_version: !ruby/object:Gem::Requirement
217
219
  none: false
218
220
  requirements:
@@ -221,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
221
223
  version: '0'
222
224
  segments:
223
225
  - 0
224
- hash: -3421642337988709305
226
+ hash: -3474028709906897679
225
227
  requirements: []
226
228
  rubyforge_project:
227
229
  rubygems_version: 1.8.24
@@ -1,16 +0,0 @@
1
- /*!
2
- * jCarousel - Riding carousels with jQuery
3
- * http://sorgalla.com/jcarousel/
4
- *
5
- * Copyright (c) 2006 Jan Sorgalla (http://sorgalla.com)
6
- * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
7
- * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
8
- *
9
- * Built on top of the jQuery library
10
- * http://jquery.com
11
- *
12
- * Inspired by the "Carousel Component" by Bill Scott
13
- * http://billwscott.com/carousel/
14
- */
15
-
16
- (function(g){var q={vertical:!1,rtl:!1,start:1,offset:1,size:null,scroll:3,visible:null,animation:"normal",easing:"swing",auto:0,wrap:null,initCallback:null,setupCallback:null,reloadCallback:null,itemLoadCallback:null,itemFirstInCallback:null,itemFirstOutCallback:null,itemLastInCallback:null,itemLastOutCallback:null,itemVisibleInCallback:null,itemVisibleOutCallback:null,animationStepCallback:null,buttonNextHTML:"<div></div>",buttonPrevHTML:"<div></div>",buttonNextEvent:"click",buttonPrevEvent:"click", buttonNextCallback:null,buttonPrevCallback:null,itemFallbackDimension:null},m=!1;g(window).bind("load.jcarousel",function(){m=!0});g.jcarousel=function(a,c){this.options=g.extend({},q,c||{});this.autoStopped=this.locked=!1;this.buttonPrevState=this.buttonNextState=this.buttonPrev=this.buttonNext=this.list=this.clip=this.container=null;if(!c||c.rtl===void 0)this.options.rtl=(g(a).attr("dir")||g("html").attr("dir")||"").toLowerCase()=="rtl";this.wh=!this.options.vertical?"width":"height";this.lt=!this.options.vertical? this.options.rtl?"right":"left":"top";for(var b="",d=a.className.split(" "),f=0;f<d.length;f++)if(d[f].indexOf("jcarousel-skin")!=-1){g(a).removeClass(d[f]);b=d[f];break}a.nodeName.toUpperCase()=="UL"||a.nodeName.toUpperCase()=="OL"?(this.list=g(a),this.clip=this.list.parents(".jcarousel-clip"),this.container=this.list.parents(".jcarousel-container")):(this.container=g(a),this.list=this.container.find("ul,ol").eq(0),this.clip=this.container.find(".jcarousel-clip"));if(this.clip.size()===0)this.clip= this.list.wrap("<div></div>").parent();if(this.container.size()===0)this.container=this.clip.wrap("<div></div>").parent();b!==""&&this.container.parent()[0].className.indexOf("jcarousel-skin")==-1&&this.container.wrap('<div class=" '+b+'"></div>');this.buttonPrev=g(".jcarousel-prev",this.container);if(this.buttonPrev.size()===0&&this.options.buttonPrevHTML!==null)this.buttonPrev=g(this.options.buttonPrevHTML).appendTo(this.container);this.buttonPrev.addClass(this.className("jcarousel-prev"));this.buttonNext= g(".jcarousel-next",this.container);if(this.buttonNext.size()===0&&this.options.buttonNextHTML!==null)this.buttonNext=g(this.options.buttonNextHTML).appendTo(this.container);this.buttonNext.addClass(this.className("jcarousel-next"));this.clip.addClass(this.className("jcarousel-clip")).css({position:"relative"});this.list.addClass(this.className("jcarousel-list")).css({overflow:"hidden",position:"relative",top:0,margin:0,padding:0}).css(this.options.rtl?"right":"left",0);this.container.addClass(this.className("jcarousel-container")).css({position:"relative"}); !this.options.vertical&&this.options.rtl&&this.container.addClass("jcarousel-direction-rtl").attr("dir","rtl");var j=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible):null,b=this.list.children("li"),e=this;if(b.size()>0){var h=0,i=this.options.offset;b.each(function(){e.format(this,i++);h+=e.dimension(this,j)});this.list.css(this.wh,h+100+"px");if(!c||c.size===void 0)this.options.size=b.size()}this.container.css("display","block");this.buttonNext.css("display","block");this.buttonPrev.css("display", "block");this.funcNext=function(){e.next()};this.funcPrev=function(){e.prev()};this.funcResize=function(){e.resizeTimer&&clearTimeout(e.resizeTimer);e.resizeTimer=setTimeout(function(){e.reload()},100)};this.options.initCallback!==null&&this.options.initCallback(this,"init");!m&&g.browser.safari?(this.buttons(!1,!1),g(window).bind("load.jcarousel",function(){e.setup()})):this.setup()};var f=g.jcarousel;f.fn=f.prototype={jcarousel:"0.2.8"};f.fn.extend=f.extend=g.extend;f.fn.extend({setup:function(){this.prevLast= this.prevFirst=this.last=this.first=null;this.animating=!1;this.tail=this.resizeTimer=this.timer=null;this.inTail=!1;if(!this.locked){this.list.css(this.lt,this.pos(this.options.offset)+"px");var a=this.pos(this.options.start,!0);this.prevFirst=this.prevLast=null;this.animate(a,!1);g(window).unbind("resize.jcarousel",this.funcResize).bind("resize.jcarousel",this.funcResize);this.options.setupCallback!==null&&this.options.setupCallback(this)}},reset:function(){this.list.empty();this.list.css(this.lt, "0px");this.list.css(this.wh,"10px");this.options.initCallback!==null&&this.options.initCallback(this,"reset");this.setup()},reload:function(){this.tail!==null&&this.inTail&&this.list.css(this.lt,f.intval(this.list.css(this.lt))+this.tail);this.tail=null;this.inTail=!1;this.options.reloadCallback!==null&&this.options.reloadCallback(this);if(this.options.visible!==null){var a=this,c=Math.ceil(this.clipping()/this.options.visible),b=0,d=0;this.list.children("li").each(function(f){b+=a.dimension(this, c);f+1<a.first&&(d=b)});this.list.css(this.wh,b+"px");this.list.css(this.lt,-d+"px")}this.scroll(this.first,!1)},lock:function(){this.locked=!0;this.buttons()},unlock:function(){this.locked=!1;this.buttons()},size:function(a){if(a!==void 0)this.options.size=a,this.locked||this.buttons();return this.options.size},has:function(a,c){if(c===void 0||!c)c=a;if(this.options.size!==null&&c>this.options.size)c=this.options.size;for(var b=a;b<=c;b++){var d=this.get(b);if(!d.length||d.hasClass("jcarousel-item-placeholder"))return!1}return!0}, get:function(a){return g(">.jcarousel-item-"+a,this.list)},add:function(a,c){var b=this.get(a),d=0,p=g(c);if(b.length===0)for(var j,e=f.intval(a),b=this.create(a);;){if(j=this.get(--e),e<=0||j.length){e<=0?this.list.prepend(b):j.after(b);break}}else d=this.dimension(b);p.get(0).nodeName.toUpperCase()=="LI"?(b.replaceWith(p),b=p):b.empty().append(c);this.format(b.removeClass(this.className("jcarousel-item-placeholder")),a);p=this.options.visible!==null?Math.ceil(this.clipping()/this.options.visible): null;d=this.dimension(b,p)-d;a>0&&a<this.first&&this.list.css(this.lt,f.intval(this.list.css(this.lt))-d+"px");this.list.css(this.wh,f.intval(this.list.css(this.wh))+d+"px");return b},remove:function(a){var c=this.get(a);if(c.length&&!(a>=this.first&&a<=this.last)){var b=this.dimension(c);a<this.first&&this.list.css(this.lt,f.intval(this.list.css(this.lt))+b+"px");c.remove();this.list.css(this.wh,f.intval(this.list.css(this.wh))-b+"px")}},next:function(){this.tail!==null&&!this.inTail?this.scrollTail(!1): this.scroll((this.options.wrap=="both"||this.options.wrap=="last")&&this.options.size!==null&&this.last==this.options.size?1:this.first+this.options.scroll)},prev:function(){this.tail!==null&&this.inTail?this.scrollTail(!0):this.scroll((this.options.wrap=="both"||this.options.wrap=="first")&&this.options.size!==null&&this.first==1?this.options.size:this.first-this.options.scroll)},scrollTail:function(a){if(!this.locked&&!this.animating&&this.tail){this.pauseAuto();var c=f.intval(this.list.css(this.lt)), c=!a?c-this.tail:c+this.tail;this.inTail=!a;this.prevFirst=this.first;this.prevLast=this.last;this.animate(c)}},scroll:function(a,c){!this.locked&&!this.animating&&(this.pauseAuto(),this.animate(this.pos(a),c))},pos:function(a,c){var b=f.intval(this.list.css(this.lt));if(this.locked||this.animating)return b;this.options.wrap!="circular"&&(a=a<1?1:this.options.size&&a>this.options.size?this.options.size:a);for(var d=this.first>a,g=this.options.wrap!="circular"&&this.first<=1?1:this.first,j=d?this.get(g): this.get(this.last),e=d?g:g-1,h=null,i=0,k=!1,l=0;d?--e>=a:++e<a;){h=this.get(e);k=!h.length;if(h.length===0&&(h=this.create(e).addClass(this.className("jcarousel-item-placeholder")),j[d?"before":"after"](h),this.first!==null&&this.options.wrap=="circular"&&this.options.size!==null&&(e<=0||e>this.options.size)))j=this.get(this.index(e)),j.length&&(h=this.add(e,j.clone(!0)));j=h;l=this.dimension(h);k&&(i+=l);if(this.first!==null&&(this.options.wrap=="circular"||e>=1&&(this.options.size===null||e<= this.options.size)))b=d?b+l:b-l}for(var g=this.clipping(),m=[],o=0,n=0,j=this.get(a-1),e=a;++o;){h=this.get(e);k=!h.length;if(h.length===0){h=this.create(e).addClass(this.className("jcarousel-item-placeholder"));if(j.length===0)this.list.prepend(h);else j[d?"before":"after"](h);if(this.first!==null&&this.options.wrap=="circular"&&this.options.size!==null&&(e<=0||e>this.options.size))j=this.get(this.index(e)),j.length&&(h=this.add(e,j.clone(!0)))}j=h;l=this.dimension(h);if(l===0)throw Error("jCarousel: No width/height set for items. This will cause an infinite loop. Aborting..."); this.options.wrap!="circular"&&this.options.size!==null&&e>this.options.size?m.push(h):k&&(i+=l);n+=l;if(n>=g)break;e++}for(h=0;h<m.length;h++)m[h].remove();i>0&&(this.list.css(this.wh,this.dimension(this.list)+i+"px"),d&&(b-=i,this.list.css(this.lt,f.intval(this.list.css(this.lt))-i+"px")));i=a+o-1;if(this.options.wrap!="circular"&&this.options.size&&i>this.options.size)i=this.options.size;if(e>i){o=0;e=i;for(n=0;++o;){h=this.get(e--);if(!h.length)break;n+=this.dimension(h);if(n>=g)break}}e=i-o+ 1;this.options.wrap!="circular"&&e<1&&(e=1);if(this.inTail&&d)b+=this.tail,this.inTail=!1;this.tail=null;if(this.options.wrap!="circular"&&i==this.options.size&&i-o+1>=1&&(d=f.intval(this.get(i).css(!this.options.vertical?"marginRight":"marginBottom")),n-d>g))this.tail=n-g-d;if(c&&a===this.options.size&&this.tail)b-=this.tail,this.inTail=!0;for(;a-- >e;)b+=this.dimension(this.get(a));this.prevFirst=this.first;this.prevLast=this.last;this.first=e;this.last=i;return b},animate:function(a,c){if(!this.locked&& !this.animating){this.animating=!0;var b=this,d=function(){b.animating=!1;a===0&&b.list.css(b.lt,0);!b.autoStopped&&(b.options.wrap=="circular"||b.options.wrap=="both"||b.options.wrap=="last"||b.options.size===null||b.last<b.options.size||b.last==b.options.size&&b.tail!==null&&!b.inTail)&&b.startAuto();b.buttons();b.notify("onAfterAnimation");if(b.options.wrap=="circular"&&b.options.size!==null)for(var c=b.prevFirst;c<=b.prevLast;c++)c!==null&&!(c>=b.first&&c<=b.last)&&(c<1||c>b.options.size)&&b.remove(c)}; this.notify("onBeforeAnimation");if(!this.options.animation||c===!1)this.list.css(this.lt,a+"px"),d();else{var f=!this.options.vertical?this.options.rtl?{right:a}:{left:a}:{top:a},d={duration:this.options.animation,easing:this.options.easing,complete:d};if(g.isFunction(this.options.animationStepCallback))d.step=this.options.animationStepCallback;this.list.animate(f,d)}}},startAuto:function(a){if(a!==void 0)this.options.auto=a;if(this.options.auto===0)return this.stopAuto();if(this.timer===null){this.autoStopped= !1;var c=this;this.timer=window.setTimeout(function(){c.next()},this.options.auto*1E3)}},stopAuto:function(){this.pauseAuto();this.autoStopped=!0},pauseAuto:function(){if(this.timer!==null)window.clearTimeout(this.timer),this.timer=null},buttons:function(a,c){if(a==null&&(a=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="first"||this.options.size===null||this.last<this.options.size),!this.locked&&(!this.options.wrap||this.options.wrap=="first")&&this.options.size!==null&& this.last>=this.options.size))a=this.tail!==null&&!this.inTail;if(c==null&&(c=!this.locked&&this.options.size!==0&&(this.options.wrap&&this.options.wrap!="last"||this.first>1),!this.locked&&(!this.options.wrap||this.options.wrap=="last")&&this.options.size!==null&&this.first==1))c=this.tail!==null&&this.inTail;var b=this;this.buttonNext.size()>0?(this.buttonNext.unbind(this.options.buttonNextEvent+".jcarousel",this.funcNext),a&&this.buttonNext.bind(this.options.buttonNextEvent+".jcarousel",this.funcNext), this.buttonNext[a?"removeClass":"addClass"](this.className("jcarousel-next-disabled")).attr("disabled",a?!1:!0),this.options.buttonNextCallback!==null&&this.buttonNext.data("jcarouselstate")!=a&&this.buttonNext.each(function(){b.options.buttonNextCallback(b,this,a)}).data("jcarouselstate",a)):this.options.buttonNextCallback!==null&&this.buttonNextState!=a&&this.options.buttonNextCallback(b,null,a);this.buttonPrev.size()>0?(this.buttonPrev.unbind(this.options.buttonPrevEvent+".jcarousel",this.funcPrev), c&&this.buttonPrev.bind(this.options.buttonPrevEvent+".jcarousel",this.funcPrev),this.buttonPrev[c?"removeClass":"addClass"](this.className("jcarousel-prev-disabled")).attr("disabled",c?!1:!0),this.options.buttonPrevCallback!==null&&this.buttonPrev.data("jcarouselstate")!=c&&this.buttonPrev.each(function(){b.options.buttonPrevCallback(b,this,c)}).data("jcarouselstate",c)):this.options.buttonPrevCallback!==null&&this.buttonPrevState!=c&&this.options.buttonPrevCallback(b,null,c);this.buttonNextState= a;this.buttonPrevState=c},notify:function(a){var c=this.prevFirst===null?"init":this.prevFirst<this.first?"next":"prev";this.callback("itemLoadCallback",a,c);this.prevFirst!==this.first&&(this.callback("itemFirstInCallback",a,c,this.first),this.callback("itemFirstOutCallback",a,c,this.prevFirst));this.prevLast!==this.last&&(this.callback("itemLastInCallback",a,c,this.last),this.callback("itemLastOutCallback",a,c,this.prevLast));this.callback("itemVisibleInCallback",a,c,this.first,this.last,this.prevFirst, this.prevLast);this.callback("itemVisibleOutCallback",a,c,this.prevFirst,this.prevLast,this.first,this.last)},callback:function(a,c,b,d,f,j,e){if(!(this.options[a]==null||typeof this.options[a]!="object"&&c!="onAfterAnimation")){var h=typeof this.options[a]=="object"?this.options[a][c]:this.options[a];if(g.isFunction(h)){var i=this;if(d===void 0)h(i,b,c);else if(f===void 0)this.get(d).each(function(){h(i,this,d,b,c)});else for(var a=function(a){i.get(a).each(function(){h(i,this,a,b,c)})},k=d;k<=f;k++)k!== null&&!(k>=j&&k<=e)&&a(k)}}},create:function(a){return this.format("<li></li>",a)},format:function(a,c){for(var a=g(a),b=a.get(0).className.split(" "),d=0;d<b.length;d++)b[d].indexOf("jcarousel-")!=-1&&a.removeClass(b[d]);a.addClass(this.className("jcarousel-item")).addClass(this.className("jcarousel-item-"+c)).css({"float":this.options.rtl?"right":"left","list-style":"none"}).attr("jcarouselindex",c);return a},className:function(a){return a+" "+a+(!this.options.vertical?"-horizontal":"-vertical")}, dimension:function(a,c){var b=g(a);if(c==null)return!this.options.vertical?b.outerWidth(!0)||f.intval(this.options.itemFallbackDimension):b.outerHeight(!0)||f.intval(this.options.itemFallbackDimension);else{var d=!this.options.vertical?c-f.intval(b.css("marginLeft"))-f.intval(b.css("marginRight")):c-f.intval(b.css("marginTop"))-f.intval(b.css("marginBottom"));g(b).css(this.wh,d+"px");return this.dimension(b)}},clipping:function(){return!this.options.vertical?this.clip[0].offsetWidth-f.intval(this.clip.css("borderLeftWidth"))- f.intval(this.clip.css("borderRightWidth")):this.clip[0].offsetHeight-f.intval(this.clip.css("borderTopWidth"))-f.intval(this.clip.css("borderBottomWidth"))},index:function(a,c){if(c==null)c=this.options.size;return Math.round(((a-1)/c-Math.floor((a-1)/c))*c)+1}});f.extend({defaults:function(a){return g.extend(q,a||{})},intval:function(a){a=parseInt(a,10);return isNaN(a)?0:a},windowLoaded:function(){m=!0}});g.fn.jcarousel=function(a){if(typeof a=="string"){var c=g(this).data("jcarousel"),b=Array.prototype.slice.call(arguments, 1);return c[a].apply(c,b)}else return this.each(function(){var b=g(this).data("jcarousel");b?(a&&g.extend(b.options,a),b.reload()):g(this).data("jcarousel",new f(this,a))})}})(jQuery);
@@ -1,62 +0,0 @@
1
- photos_initCallback = (carousel) ->
2
- jQuery(".jcarousel-control a").bind "click", ->
3
- carousel.scroll jQuery.jcarousel.intval(jQuery(this).text())
4
- false
5
-
6
- jQuery(".jcarousel-scroll select").bind "change", ->
7
- carousel.options.scroll = jQuery.jcarousel.intval(@options[@selectedIndex].value)
8
- false
9
-
10
- jQuery(".s-next").bind "click", (e) ->
11
- e.preventDefault()
12
- carousel.next()
13
- false
14
-
15
- jQuery(".s-prev").bind "click", (e)->
16
- e.preventDefault()
17
- carousel.prev()
18
- false
19
-
20
- $("a.trigger").click (e)->
21
- e.preventDefault()
22
- index = jQuery(this).attr('href').replace('#', "")
23
- carousel.scroll jQuery.jcarousel.intval(index)
24
-
25
-
26
- mycarousel_initCallback = (carousel) ->
27
- jQuery(".jcarousel-control a").bind "click", ->
28
- carousel.scroll jQuery.jcarousel.intval(jQuery(this).text())
29
- false
30
-
31
- jQuery(".jcarousel-scroll select").bind "change", ->
32
- carousel.options.scroll = jQuery.jcarousel.intval(@options[@selectedIndex].value)
33
- false
34
-
35
- jQuery(".next-thumbs").bind "click", (e) ->
36
- e.preventDefault()
37
- carousel.next()
38
- false
39
-
40
- jQuery(".prev-thumbs").bind "click", (e) ->
41
- e.preventDefault()
42
- carousel.prev()
43
- false
44
-
45
- $ ->
46
-
47
- photos = $("#photos-carousel").jcarousel
48
- visible: 1
49
- scroll: 1
50
- initCallback: photos_initCallback
51
- # This tells jCarousel NOT to autobuild prev/next buttons
52
- buttonNextHTML: null
53
- buttonPrevHTML: null
54
-
55
-
56
- $(".mycarousel").jcarousel
57
- visible: 6
58
- initCallback: mycarousel_initCallback
59
- # This tells jCarousel NOT to autobuild prev/next buttons
60
- buttonNextHTML: null
61
- buttonPrevHTML: null
62
-
@@ -1,9 +0,0 @@
1
- require 'mongoid/railtie'
2
-
3
- CarrierWave.configure do |config|
4
-
5
- config.storage = :grid_fs
6
- config.grid_fs_access_url = "/files"
7
- config.cache_dir = "uploads"
8
- config.root = Rails.root.join('public')
9
- end
@@ -1,11 +0,0 @@
1
- pt-BR:
2
- photos:
3
- photos: 'Fotos'
4
- photo: 'Foto'
5
- legend: 'Legenda'
6
- or: 'ou'
7
- upload:
8
- explanation: 'Clique no botão abaixo para adicionar as fotos.'
9
- btn:
10
- upload_pictures: 'Enviar arquivos de imagem'
11
- upload_zip: 'Enviar arquivo ZIP'