rdcms_publication 0.0.1

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3599ff268d4061a0a4f23ea2479ec622fb8127d0
4
+ data.tar.gz: 659bf82ea367711ec7d0db972ba2b5d04a37501d
5
+ SHA512:
6
+ metadata.gz: fc5b456a0432d7b68fa5cfcf9c8e49d669cdca9280c9b05f43b08a95c743943bfde6388c5c6f727bbcff5a970e6086bd994e8cc26903280f3cebf61e1c414c08
7
+ data.tar.gz: 3cff408d4e82e01d6e33b840398bccb6fb7e6bc7d9d0937b426a0e4fde6a482c91ab354df2e8563be830955e852d0cfd5b637d4aa1d0396fa5cf174007026fe8
data/.gitignore ADDED
@@ -0,0 +1,41 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+
13
+ *.sublime*
14
+ .DS_Store
15
+ db/.DS_Store
16
+ test/.DS_Store
17
+ test/dummy/.DS_Store
18
+ .sass-cache/
19
+ .rvmrc
20
+ *.rbc
21
+ .config
22
+ .yardoc
23
+ Gemfile.lock
24
+ InstalledFiles
25
+ _yardoc
26
+ coverage
27
+ doc/
28
+ lib/bundler/man
29
+ pkg
30
+ rdoc
31
+ spec/reports
32
+ test/tmp
33
+ test/version_tmp
34
+ tmp
35
+ log
36
+
37
+ # Gem
38
+ *.gem
39
+
40
+ # RubyMine IDE
41
+ .idea/
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Gullit Miranda
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Rdcms Publications
2
+
3
+ O Rdcms Publications é o módulo para publicações de cartilhas, revistas, catálogos dentro outros materiais do gênero utilizando a api do [issuu.com](http://issuu.com/)
4
+
5
+ ## Instalação
6
+
7
+ Adicione esta linha ao Gemfile da sua aplicação:
8
+
9
+ gem "rdcms_publication"
10
+
11
+ e execulte o:
12
+
13
+ bundle install
14
+
15
+ ou instale-a diretamente execultando:
16
+
17
+ gem install rdcms_publication
18
+
19
+ ## Como utilizar
20
+
21
+ Definir os parâmetros de autenticação do issuu.com
22
+ para gerar sua chave de acesso acesse [Get an API Key](http://issuu.com/user/settings?services=true#services)
23
+ linux:
24
+ export ISSUU_API_KEY=
25
+ export ISSUU_SECRET=
26
+
27
+ heroku:
28
+ heroku config:add ISSUU_API_KEY=
29
+ heroku config:add ISSUU_SECRET=
30
+
31
+ ## Author
32
+ Gullit Miranda (https://github.com/gullitmiranda)
data/Rakefile ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require "bundler/gem_tasks"
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+ begin
8
+ require 'rdoc/task'
9
+ rescue LoadError
10
+ require 'rdoc/rdoc'
11
+ require 'rake/rdoctask'
12
+ RDoc::Task = Rake::RDocTask
13
+ end
14
+
15
+ RDoc::Task.new(:rdoc) do |rdoc|
16
+ rdoc.rdoc_dir = 'rdoc'
17
+ rdoc.title = "Rdcms Publications #{RdcmsPublication::VERSION}"
18
+ rdoc.options << '--line-numbers'
19
+ rdoc.rdoc_files.include('README.rdoc')
20
+ rdoc.rdoc_files.include('lib/**/*.rb')
21
+ end
@@ -0,0 +1,62 @@
1
+ ActiveAdmin.register Publication do
2
+ menu priority: 7,
3
+ parent: I18n.t('activerecord.models.content_management'),
4
+ if: proc{can?(:update, Publication)}
5
+ # menu false
6
+
7
+ batch_action :destroy, false
8
+ config.paginate = false
9
+ config.clear_action_items!
10
+ config.clear_sidebar_sections!
11
+
12
+ index :download_links => false do
13
+ render :partial => "index"
14
+ end
15
+
16
+ controller do
17
+ def index
18
+ index! do |format|
19
+ format.html # index.html.erb
20
+ format.json { render json: { files: @publications.map{|publication| publication.to_jq_upload } } }
21
+ end
22
+ end
23
+
24
+ def create
25
+ if params["reorder_positions"]
26
+ Publication.reorder_positions params['ids_order']
27
+
28
+ respond_to do |format|
29
+ format.json { render json: {
30
+ success: true,
31
+ message: I18n.t("notices.ordered.success")
32
+ }.to_json }
33
+ end
34
+ else
35
+ unless params["publication"]["file"].blank?
36
+ file = params["publication"]["file"]
37
+
38
+ params["publication"].merge!({
39
+ title: file.original_filename,
40
+ content_type: file.content_type
41
+ })
42
+ end
43
+
44
+ create! do |format|
45
+
46
+ if @publication.save
47
+ format.html { redirect_to admin_publication_path @publication }
48
+ format.json { render json: { files: [@publication].map{|publication| publication.to_jq_upload } }, status: :created }
49
+ else
50
+ format.html { render action: "new" }
51
+ format.json { render json: @publication.errors, status: :unprocessable_entity }
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ def edit
58
+ @publication = Publication.find(params[:id])
59
+ render :layout => false, :partial => "form"
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,126 @@
1
+ # Função para validar campos utilizando o x-editable
2
+ window.required = (value) ->
3
+ return 'Este campo é obrigatório' if $.trim(value) == ""
4
+
5
+ jQuery ->
6
+ #### Selectores
7
+ publications_container = $('.fileuploads-container')
8
+ file_selector = $('#file_selector', publications_container)
9
+ auto_save = $('#auto_save', file_selector)
10
+ auto_save_checkbox = $(':checkbox', auto_save)
11
+ fileupload_form = $('#fileupload:first' , publications_container)
12
+ files_container = $('#upload_container .files' , publications_container)
13
+ action = file_selector.prop('action') || file_selector.prop('href')
14
+ #### end Selectores
15
+
16
+ # Core Functions
17
+ # renderFiles - Renderiza os itens
18
+ renderFiles = (data = {}, container = $(), offset, onload = false) ->
19
+ template = tmpl "template-download", files: data
20
+ temp_itens = $("<div />").append(template).children()
21
+
22
+ if temp_itens.length
23
+ temp_itens.each (o, ix) ->
24
+ _t = $(this)
25
+ _r = container.find("##{this.id}")
26
+
27
+ if _r.length
28
+ _r.replaceWith _t
29
+ else
30
+ container.append _t
31
+ unless (onload)
32
+ _savePositions()
33
+ else
34
+ container.append template
35
+
36
+ container.children().addClass('in')
37
+ _sortable(container).data()
38
+
39
+ # Renderiza o formulário de edição.
40
+ _renderEdit = (ev) ->
41
+ ev.preventDefault()
42
+ currentTarget = $(ev.currentTarget)
43
+ delegateTarget = $(ev.delegateTarget)
44
+ viewPort = _checkOrCreateViewPort()
45
+ container = $('.container:first', viewPort)
46
+ overlayItem = $('<div class="row overlay-item"></div>')
47
+
48
+ overlayItem.load currentTarget.prop('href'), () ->
49
+ _t = $(this)
50
+
51
+ # overlay_form = $('form', _t).data("remote", true)
52
+ overlay_form = $('form', _t)
53
+ .bind "submit", (ev) ->
54
+ ev.preventDefault()
55
+ .bind "ajax:complete", (ev, data) ->
56
+ jData = eval("(#{data.responseText})")
57
+ renderFiles jData.files, files_container
58
+ _checkAndDestroyViewPort($(this))
59
+
60
+ cancel = $('.btn.cancel', overlay_form).bind "click", (ev) ->
61
+ ev.preventDefault()
62
+ _checkAndDestroyViewPort($(this))
63
+
64
+ .appendTo(container)
65
+
66
+ # caso a viewPort não exista cria
67
+ _checkOrCreateViewPort = ->
68
+ viewPort = $('body .publication_edit_viewport')
69
+ viewPort = if viewPort.length then viewPort else $("""
70
+ <div class="publication_edit_viewport fade in overlay-viewport">
71
+ <div class="overlay-block overlay-white"></div>
72
+ <div class="publication_edit_container overlay-container"><div class="container"></div></div>
73
+ </div>
74
+ """).appendTo($("body").css("overflow", "hidden"))
75
+
76
+ _checkAndDestroyViewPort = (_4remove)->
77
+ _4remove = $(_4remove)
78
+ _4remove.closest('.overlay-item').remove() if _4remove.length
79
+
80
+ viewPort = $('body .publication_edit_viewport')
81
+ containerItens = $('.overlay-item', viewPort)
82
+ if viewPort.length and !containerItens.length
83
+ viewPort.removeClass('in').remove()
84
+ $('body').css("overflow", "")
85
+
86
+ # _sortable - Jquery UI para ordenação de itens
87
+ _sortable = (container) ->
88
+ container.sortable('destroy') if container.data("sortable")
89
+
90
+ container
91
+ .sortable
92
+ handle: ".checkbox-container"
93
+ # placeholder: "ui-state-highlight ui-sortable-placeholder template-download span3 fade in"
94
+ opacity: 0.6
95
+ revert: true
96
+ stop: (ev, ui) ->
97
+ _savePositions()
98
+ .disableSelection()
99
+
100
+ # Grava a ordenação no DB
101
+ _savePositions = () ->
102
+ $(".ids_order", file_selector).remove()
103
+ ids_order = $(".ids_order", fileupload_form).clone().appendTo(file_selector)
104
+ file_selector.submit()
105
+
106
+ #### end Core Functions
107
+
108
+ # Renderiza os itens carregados do Banco de dados
109
+ selectedData = files_container.data('load')
110
+ if selectedData && $.isArray(selectedData.files)
111
+ renderFiles selectedData.files, files_container, 0, true
112
+ else
113
+ _sortable files_container
114
+ publications_itens = $('tr', files_container)
115
+
116
+ # Callbacks
117
+ fileupload_form
118
+ .bind "fileuploadcompleted", (e, data) ->
119
+ _savePositions()
120
+
121
+ publications_itens.on "click", ".edit, .save", (event) ->
122
+ target = $(event.delegateTarget)
123
+ buttons = $(".edit, .save", target).toggleClass("hidden")
124
+
125
+ $('.enable-editable', target).editable('toggleDisabled')
126
+ # end Callbacks
@@ -0,0 +1,23 @@
1
+ class PublicationsController < InheritedResources::Base
2
+ load_and_authorize_resource
3
+
4
+ respond_to :html, :json
5
+ def index
6
+ if params[:tag]
7
+ @search = Publication.tagged_with(params[:tag]).list_all.search(params[:search])
8
+ @publications = @search.all
9
+ else
10
+ @search = Publication.list_all.search(params[:search])
11
+ @publications = @search.all
12
+ end
13
+
14
+ respond_with @publications
15
+ end
16
+
17
+ def show
18
+ @publication = Publication.find(params[:id])
19
+ @publication.visit! :by => request.try(:remote_ip)
20
+
21
+ respond_with(@publication)
22
+ end
23
+ end
@@ -0,0 +1,116 @@
1
+ class Publication < ActiveRecord::Base
2
+ include Rails.application.routes.url_helpers
3
+ include ActionView::Helpers::NumberHelper
4
+
5
+ # Taggings
6
+ acts_as_taggable
7
+
8
+ # Contador de visitas
9
+ is_visitable accept_ip: true
10
+
11
+ # URL amigáveis através do :name
12
+ extend FriendlyId
13
+ friendly_id :title, use: [:slugged, :history]
14
+
15
+ # Escopos
16
+ scope :with_locale, lambda{ |locale = I18n.locale| where("language = ?", locale) }
17
+ scope :active , lambda{ where(:published => true) }
18
+ scope :inactive , lambda{ where(:published => false) }
19
+ scope :ordained , lambda{ order("position asc").order("updated_at desc") }
20
+
21
+ scope :list_all , lambda{ with_locale.active.ordained }
22
+ scope :recents , lambda{ |limit = 10| active.ordained.limit(limit) }
23
+
24
+ # Callbacks
25
+ before_save :issuu_upload
26
+ before_destroy :issuu_delete
27
+
28
+ attr_accessor :file
29
+
30
+ def thumb_path
31
+ if self.document?
32
+ "http://image.issuu.com/#{self.document}/jpg/page_1_thumb_medium.jpg"
33
+ else
34
+ "/assets/missing/thumb.png"
35
+ end
36
+ end
37
+
38
+ #Jquery File Uploads
39
+ def to_jq_upload
40
+ {
41
+ "id" => read_attribute(:id),
42
+ "name" => read_attribute(:title),
43
+ "description" => read_attribute(:description),
44
+ "language" => read_attribute(:language),
45
+ "document" => read_attribute(:document),
46
+ "content_type" => read_attribute(:content_type),
47
+ "size" => read_attribute(:file_size),
48
+ "published" => read_attribute(:published),
49
+ "tag_list" => read_attribute(:tag_list),
50
+ "updated_at" => read_attribute(:updated_at),
51
+ "created_at" => read_attribute(:created_at),
52
+ "thumb" => self.thumb_path,
53
+ "view_url" => publication_path(self),
54
+ "edit_url" => admin_publication_path(self),
55
+ "delete_url" => admin_publication_path(self),
56
+ "delete_type" => "DELETE",
57
+ "i18n" => {
58
+ "updated_at" => I18n.l(read_attribute(:updated_at), format: :long),
59
+ "created_at" => I18n.l(read_attribute(:created_at), format: :long),
60
+ }
61
+ }
62
+ end
63
+
64
+ private
65
+
66
+ # Refaz a ordenação dos uploads
67
+ def self.reorder_positions(ids = nil)
68
+ [] if ids.blank?
69
+ counter = 1
70
+ ActiveRecord::Base.establish_connection
71
+ ids.each do |id|
72
+ ActiveRecord::Base.connection.execute("UPDATE publications SET position=#{counter} WHERE id='#{id}';\n")
73
+ counter += 1
74
+ end
75
+ return true
76
+ end
77
+
78
+ def issuu_upload
79
+ if defined?(self.file) and !defined?(self.document_name)
80
+ self.language = I18n.locale.to_s if self.language.nil?
81
+ self.document_name = self.slug[/^(.{0,50})/]
82
+
83
+ language = case self.language
84
+ when "br" then "pt"
85
+ else self.language
86
+ end
87
+
88
+ params = {
89
+ name: self.document_name,
90
+ title: self.title,
91
+ tags: self.tag_list,
92
+ description: self.description,
93
+ language: language,
94
+ downloadable: true
95
+ }
96
+ begin
97
+ document = Issuu::Document.upload self.file.tempfile, self.file.content_type, params
98
+
99
+ self.attributes= {
100
+ document: document.documentId,
101
+ username: document.username
102
+ }
103
+ rescue Issuu::IssuuException, Timeout::Error => msg
104
+ document = { error: true, msg: msg }
105
+ end
106
+ end
107
+ end
108
+
109
+ def issuu_delete
110
+ begin
111
+ Issuu::Document.delete [self.document_name]
112
+ rescue Issuu::IssuuException, Timeout::Error => msg
113
+ { error: true, msg: msg }
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,142 @@
1
+ <% if defined?(f) %>
2
+ <!-- The template to display files available for upload -->
3
+ <script id="template-upload" type="text/x-tmpl">
4
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
5
+ <tr class="template-upload fade">
6
+ <td class="checkbox-container">
7
+ <!-- <input type="checkbox" name="selected" value="{%=file.id%}" class="toggle" title="<%= t('.select') %>" > -->
8
+ </td>
9
+ <td class="preview-container">
10
+ <span class="preview"></span>
11
+ <div class="label size">{%=o.formatFileSize(file.size)%}</div>
12
+ </td>
13
+ <td class="body">
14
+ {% if (file.error) { %}
15
+ <h4 title="{%=file.name%}" > {%=file.name %} </h4>
16
+ <div class="alert alert-error "> <strong>{%=locale.fileupload.error%}</strong> {%=locale.fileupload.errors[file.error] || file.error%} </div>
17
+ {% } else { %}
18
+ <div class="row">
19
+ <div class="span4">
20
+ <div class="control-group">
21
+ <%= f.text_field :title, :class => 'text_field span4', placeholder: t(".title_placeholder"), value: "{%=file.name %}" %>
22
+ </div>
23
+ <div class="control-group description">
24
+ <%= f.text_area :description, :class => 'text_area span4', placeholder: t(".description_placeholder") %>
25
+ </div>
26
+ <div class="control-group">
27
+ <div class="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="bar" style="width:0%;"></div></div>
28
+ </div>
29
+ </div>
30
+ <div class="span4">
31
+ <div class="control-group language">
32
+ <%= f.label :language, :class => 'control-label' %>
33
+ <div class="controls">
34
+ <%= f.select :language, I18n.available_locales.map { |locale| [ I18n.t("translation.#{locale}"), locale ] },
35
+ :selected => I18n.locale, class: 'select select2', title: t(".language") %>
36
+ </div>
37
+ </div>
38
+ <div class="control-group tag_list">
39
+ <%= f.label :tag_list, :class => 'control-label' %>
40
+ <div class="controls">
41
+ <%= f.text_field :tag_list, class: "select2-tag" %>
42
+ </div>
43
+ <em class="controls"><%= t(".separated_by_commas") %></em>
44
+ </div>
45
+ <div class="control-group published">
46
+ <%= f.label :published, :class => 'control-label' do %>
47
+ <%= "#{t(".published")}: #{f.check_box(:published, :class => 'checkbox')}".html_safe %>
48
+ <% end %>
49
+ </div>
50
+ </div>
51
+ </div>
52
+ {% } %}
53
+ </td>
54
+ <td class="actions">
55
+ <div class="btn-group btn-group-vertical">
56
+ {% if (!file.error) { %}
57
+ <div class="start">
58
+ <%= button_tag type:"submit", :class => 'btn btn-primary start', title: "#{t('.send')}" do %>
59
+ <i class="icon-upload icon-white"></i> <span class="string"><%= t('.send') %></span>
60
+ <% end %>
61
+ </div>
62
+ {% } %}
63
+
64
+ {% if (!i) { %}
65
+ <div class="cancel">
66
+ <button class="btn btn-warning" title="<%= t(".cancel") %>" > <i class="icon-denied"></i> <span class="string"><%= t('.cancel') %></span> </button>
67
+ </div>
68
+ {% } %}
69
+ </div>
70
+ </td>
71
+ </tr>
72
+ {% } %}
73
+ </script>
74
+ <!-- The template to display files available for download -->
75
+ <script id="template-download" type="text/x-tmpl">
76
+ {% for (var i=0, file; file=o.files[i]; i++) { %}
77
+ <tr id="publication_{%=file.id%}" class="template-download fade" data-url="{%=file.edit_url%}" data-pk="{%=file.id%}">
78
+ <td class="checkbox-container" title="<%= t('.move') %>" >
79
+ <!-- <input type="checkbox" name="selected" value="{%=file.id%}" class="toggle" title="<%= t('.select') %>" > -->
80
+ <input type="input" value="{%=file.id%}" name="ids_order[]" class="ids_order hidden" >
81
+ </td>
82
+ <td class="preview-container">
83
+ {% if (file.thumb) { %}
84
+ <a href="{%=file.url%}" title="{%=file.name%}" class="thumb preview preview-button" target="_blank" data-gallery="gallery" download="{%=file.download_path || "" %}" title="<%= t('.preview') %>" >
85
+ <img class="media-object" src="{%= file.thumb || '/assets/missing/thumb.png' %}" />
86
+ </a>
87
+ {% } %}
88
+ </td>
89
+ <td class="body">
90
+ <h4 class="enable-editable" title="{%=file.name%}" id="publication_title" data-url="{%=file.edit_url%}" data-pk="{%=file.id%}" data-value="{%=file.name%}" data-display="truncate(75)" data-placeholder="<%= t(".required") %>" data-validate="required" >
91
+ {%=file.name && file.name.truncate(75) %}
92
+ </h4>
93
+
94
+ {% if (file.error) { %}
95
+ <div class="alert alert-error "> <strong>{%=locale.fileupload.error%}</strong> {%=locale.fileupload.errors[file.error] || file.error%} </div>
96
+ {% } else { %}
97
+ <div class="media-description enable-editable" id="publication_description" data-url="{%=file.edit_url%}" data-pk="{%=file.id%}" data-type="textarea" data-value="{%=file.description%}" data-display="truncate(250)"
98
+ data-mode="popup" data-original-title="<%= t(".description_placeholder") %>" data-showbuttons="bottom" >
99
+ {%=file.description && file.description.truncate(250) %}
100
+ </div>
101
+
102
+ <div class="enable-editable" id="publication_tag_list" data-url="{%=file.edit_url%}" data-pk="{%=file.id%}" data-value="{%= file.tag_list %}"
103
+ >
104
+ {%= file.tag_list %}
105
+ </div>
106
+ <div class="enable-editable" id="publication_published" data-url="{%=file.edit_url%}" data-pk="{%=file.id%}" data-type="select" data-value="{%= file.published || "false"%}"
107
+ data-source="{'true': '<%= t(".published") %>','false': '<%= t(".private") %>'}">
108
+ {%= file.published ? "<%= t(".published") %>" : "<%= t(".private") %>" %}
109
+ </div>
110
+ {% } %}
111
+ </td>
112
+ <td class="actions">
113
+ <div class="btn-group btn-group-vertical">
114
+ {% if (!file.error) { %}
115
+ <div class="preview"></div>
116
+ <a href="{%=file.view_url%}" class="btn preview" title="<%= t('.preview') %>" target="_blank" >
117
+ <i class="icon-share-2"></i><span class="string"><%= t('.preview') %></span>
118
+ </a>
119
+ </div>
120
+ <div class="edit">
121
+ <a class="btn btn-primary" title="<%= t('.edit') %>" >
122
+ <i class="icon-pencil-2"></i><span class="string"><%= t('.edit') %></span>
123
+ </a>
124
+ </div>
125
+ <div class="save hidden">
126
+ <a class="btn btn-success" title="<%= t('.save') %>" >
127
+ <i class="icon-checkmark"></i><span class="string"><%= t('.save') %></span>
128
+ </a>
129
+ </div>
130
+ {% } %}
131
+
132
+ <div class="delete">
133
+ <button class="btn btn-danger" title="<%= t('.delete') %>" data-type="{%=file.delete_type%}" data-url="{%=file.delete_url%}">
134
+ <i class="icon-trashcan"></i><span class="string"><%= t('.delete') %></span>
135
+ </button>
136
+ </div>
137
+ </div>
138
+ </td>
139
+ </tr>
140
+ {% } %}
141
+ </script>
142
+ <% end %>