rdcms_publication 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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 %>