sufia 0.0.2 → 0.0.3
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.
- data/README.md +3 -0
- data/app/assets/javascripts/sufia.js +11 -0
- data/app/assets/stylesheets/sufia.css +1 -0
- data/app/controllers/batch_edits_controller.rb +1 -1
- data/app/controllers/downloads_controller.rb +1 -65
- data/app/controllers/generic_files_controller.rb +1 -296
- data/app/models/datastreams/generic_file_rdf_datastream.rb +0 -4
- data/app/views/_ga.html.erb +2 -2
- data/app/views/batch/edit.html.erb +1 -13
- data/app/views/batch_edits/edit.html.erb +0 -8
- data/app/views/catalog/index.html.erb +1 -1
- data/app/views/dashboard/index.html.erb +0 -19
- data/app/views/generic_files/_media_display.html.erb +6 -6
- data/app/views/generic_files/_show_actions.html.erb +37 -0
- data/app/views/generic_files/_show_descriptions.html.erb +118 -0
- data/app/views/generic_files/_show_details.html.erb +67 -0
- data/app/views/generic_files/edit.html.erb +6 -19
- data/app/views/generic_files/show.html.erb +3 -236
- data/app/views/users/edit.html.erb +0 -6
- data/lib/generators/sufia/templates/catalog_controller.rb +2 -2
- data/lib/generators/sufia/templates/config/sufia.rb +3 -0
- data/lib/sufia.rb +10 -8
- data/lib/sufia/downloads_controller_behavior.rb +77 -0
- data/lib/sufia/files_controller_behavior.rb +245 -0
- data/lib/sufia/generic_file.rb +9 -15
- data/lib/sufia/version.rb +1 -1
- data/spec/controllers/generic_files_controller_spec.rb +9 -19
- data/spec/models/generic_file_spec.rb +2 -3
- metadata +7 -7
- data/app/assets/javascripts/batch.js +0 -26
- data/app/assets/javascripts/bootstrap-button.js +0 -96
- data/app/assets/javascripts/bootstrap-dropdown.js +0 -100
- data/app/assets/javascripts/bootstrap-modal.js +0 -218
- data/app/assets/javascripts/dashboard.js +0 -40
data/README.md
CHANGED
@@ -37,6 +37,9 @@ You'll want to ensure you're not loading the blacklight.css, so remove this line
|
|
37
37
|
//= require sufia
|
38
38
|
```
|
39
39
|
|
40
|
+
### Install Fits.sh
|
41
|
+
http://code.google.com/p/fits/downloads/list
|
42
|
+
|
40
43
|
### Start background workers
|
41
44
|
```
|
42
45
|
COUNT=4 QUEUE=* rake environment resque:work
|
@@ -18,9 +18,20 @@ limitations under the License.
|
|
18
18
|
//= require jquery-ui-1.9.2/jquery.ui.widget
|
19
19
|
//= require jquery-ui-1.9.2/jquery.ui.menu
|
20
20
|
//= require jquery-ui-1.9.2/jquery.ui.autocomplete
|
21
|
+
|
21
22
|
//= require bootstrap-dropdown
|
22
23
|
//= require bootstrap-button
|
24
|
+
//= require bootstrap-modal
|
23
25
|
//= require bootstrap-collapse
|
26
|
+
//= require bootstrap-tooltip
|
27
|
+
//= require bootstrap-popover
|
28
|
+
|
29
|
+
//= require video
|
30
|
+
//= require audio.min
|
31
|
+
//= require jquery.validate
|
32
|
+
//= require swfobject
|
33
|
+
//= require jquery.zclip.min
|
34
|
+
|
24
35
|
//= require batch_edit
|
25
36
|
//= require terms_of_service
|
26
37
|
//= require fileupload
|
@@ -7,7 +7,7 @@ class BatchEditsController < ApplicationController
|
|
7
7
|
@generic_file = GenericFile.new
|
8
8
|
@generic_file.depositor = current_user.login
|
9
9
|
@groups = current_user.groups
|
10
|
-
@terms = @generic_file.get_terms.reject{|k,v| (k=='
|
10
|
+
@terms = @generic_file.get_terms.reject{|k,v| (k=='generic_file__title')|| (k == 'generic_file__part_of')|| (k == 'generic_file__date_uploaded') || (k == 'generic_file__date_modified')}
|
11
11
|
|
12
12
|
# do we want to show the original values for anything...
|
13
13
|
@show_file = GenericFile.new
|
@@ -14,69 +14,5 @@
|
|
14
14
|
|
15
15
|
class DownloadsController < ApplicationController
|
16
16
|
# module mixes in normalize_identifier method
|
17
|
-
include Sufia::
|
18
|
-
|
19
|
-
# moved check into the routine so we can handle the user with no access
|
20
|
-
#before_filter :deny_access_if_not_reader, :only=>[:show]
|
21
|
-
prepend_before_filter :normalize_identifier, :only=>[:audit, :edit, :show, :update, :destroy]
|
22
|
-
|
23
|
-
def show
|
24
|
-
if can? :read, permissions_solr_doc_for_id(params["id"])
|
25
|
-
logger.info "Can read #{params['id']}"
|
26
|
-
|
27
|
-
send_content (params["id"])
|
28
|
-
return
|
29
|
-
else
|
30
|
-
logger.info "Can not read #{params['id']}"
|
31
|
-
redirect_to "/assets/NoAccess.png"
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
protected
|
36
|
-
|
37
|
-
def send_content (id)
|
38
|
-
@asset = ActiveFedora::Base.find(id)
|
39
|
-
opts = {}
|
40
|
-
ds = nil
|
41
|
-
opts[:filename] = params["filename"] || @asset.label
|
42
|
-
#opts[:disposition] = params["disposition"] if params.has_key?("disposition")
|
43
|
-
opts[:disposition] = 'inline'
|
44
|
-
if params.has_key?(:datastream_id)
|
45
|
-
opts[:filename] = params[:datastream_id]
|
46
|
-
ds = @asset.datastreams[params[:datastream_id]]
|
47
|
-
end
|
48
|
-
ds = default_content_ds(@asset) if ds.nil?
|
49
|
-
data = ds.content
|
50
|
-
opts[:type] = ds.mimeType
|
51
|
-
send_data data, opts
|
52
|
-
return
|
53
|
-
end
|
54
|
-
|
55
|
-
|
56
|
-
private
|
57
|
-
|
58
|
-
def default_content_ds(asset)
|
59
|
-
ActiveFedora::ContentModel.known_models_for(asset).each do |model_class|
|
60
|
-
return model_class.default_content_ds if model_class.respond_to?(:default_content_ds)
|
61
|
-
end
|
62
|
-
if asset.datastreams.keys.include?(DownloadsController.default_content_dsid)
|
63
|
-
return asset.datastreams[DownloadsController.default_content_dsid]
|
64
|
-
else
|
65
|
-
return asset.inner_object.profile.to_xml
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
def self.default_content_dsid
|
70
|
-
"content"
|
71
|
-
end
|
72
|
-
|
73
|
-
# Custom enforcement for show requests -- redirects to catalog_path if not reader.
|
74
|
-
def deny_access_if_not_reader
|
75
|
-
authenticate_user!
|
76
|
-
load_permissions_from_solr
|
77
|
-
unless can? :read, @permissions_solr_document
|
78
|
-
redirect_to catalog_path
|
79
|
-
return
|
80
|
-
end
|
81
|
-
end
|
17
|
+
include Sufia::DownloadsControllerBehavior
|
82
18
|
end
|
@@ -14,300 +14,5 @@
|
|
14
14
|
# limitations under the License.
|
15
15
|
|
16
16
|
class GenericFilesController < ApplicationController
|
17
|
-
include
|
18
|
-
include Hydra::Controller::UploadBehavior # for add_posted_blob_to_asset method
|
19
|
-
include Blacklight::Configurable # comply with BL 3.7
|
20
|
-
include Sufia::Noid # for normalize_identifier method
|
21
|
-
|
22
|
-
# This is needed as of BL 3.7
|
23
|
-
self.copy_blacklight_config_from(CatalogController)
|
24
|
-
|
25
|
-
# Catch permission errors
|
26
|
-
rescue_from Hydra::AccessDenied do |exception|
|
27
|
-
if (exception.action == :edit)
|
28
|
-
redirect_to(sufia.url_for({:action=>'show'}), :alert => exception.message)
|
29
|
-
elsif current_user and current_user.persisted?
|
30
|
-
redirect_to root_url, :alert => exception.message
|
31
|
-
else
|
32
|
-
session["user_return_to"] = request.url
|
33
|
-
redirect_to new_user_session_url, :alert => exception.message
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# actions: audit, index, create, new, edit, show, update, destroy, permissions, citation
|
38
|
-
before_filter :authenticate_user!, :except => [:show, :citation]
|
39
|
-
before_filter :has_access?, :except => [:show]
|
40
|
-
before_filter :enforce_access_controls
|
41
|
-
before_filter :find_by_id, :except => [:index, :create, :new]
|
42
|
-
prepend_before_filter :normalize_identifier, :except => [:index, :create, :new]
|
43
|
-
|
44
|
-
# routed to /files/new
|
45
|
-
def new
|
46
|
-
@generic_file = GenericFile.new
|
47
|
-
@batch_noid = Sufia::Noid.noidify(Sufia::IdService.mint)
|
48
|
-
end
|
49
|
-
|
50
|
-
# routed to /files/:id/edit
|
51
|
-
def edit
|
52
|
-
@terms = @generic_file.get_terms
|
53
|
-
@groups = current_user.groups
|
54
|
-
end
|
55
|
-
|
56
|
-
# routed to /files/:id
|
57
|
-
def index
|
58
|
-
@generic_files = GenericFile.find(:all, :rows => GenericFile.count)
|
59
|
-
render :json => @generic_files.map(&:to_jq_upload).to_json
|
60
|
-
end
|
61
|
-
|
62
|
-
# routed to /files/:id (DELETE)
|
63
|
-
def destroy
|
64
|
-
pid = @generic_file.noid
|
65
|
-
@generic_file.delete
|
66
|
-
Sufia.queue.push(ContentDeleteEventJob.new(pid, current_user.user_key))
|
67
|
-
redirect_to sufia.dashboard_index_path, :notice => render_to_string(:partial=>'generic_files/asset_deleted_flash', :locals => { :generic_file => @generic_file })
|
68
|
-
end
|
69
|
-
|
70
|
-
# routed to /files (POST)
|
71
|
-
def create
|
72
|
-
begin
|
73
|
-
retval = " "
|
74
|
-
# check error condition No files
|
75
|
-
if !params.has_key?(:files)
|
76
|
-
retval = render :json => [{:error => "Error! No file to save"}].to_json
|
77
|
-
|
78
|
-
# check error condition empty file
|
79
|
-
elsif ((params[:files][0].respond_to?(:tempfile)) && (params[:files][0].tempfile.size == 0))
|
80
|
-
retval = render :json => [{ :name => params[:files][0].original_filename, :error => "Error! Zero Length File!"}].to_json
|
81
|
-
|
82
|
-
elsif ((params[:files][0].respond_to?(:size)) && (params[:files][0].size == 0))
|
83
|
-
retval = render :json => [{ :name => params[:files][0].original_filename, :error => "Error! Zero Length File!"}].to_json
|
84
|
-
|
85
|
-
elsif (params[:terms_of_service] != '1')
|
86
|
-
retval = render :json => [{ :name => params[:files][0].original_filename, :error => "You must accept the terms of service!"}].to_json
|
87
|
-
|
88
|
-
# process file
|
89
|
-
else
|
90
|
-
create_and_save_generic_file
|
91
|
-
if @generic_file
|
92
|
-
Sufia.queue.push(ContentDepositEventJob.new(@generic_file.pid, current_user.user_key))
|
93
|
-
respond_to do |format|
|
94
|
-
format.html {
|
95
|
-
retval = render :json => [@generic_file.to_jq_upload].to_json,
|
96
|
-
:content_type => 'text/html',
|
97
|
-
:layout => false
|
98
|
-
}
|
99
|
-
format.json {
|
100
|
-
retval = render :json => [@generic_file.to_jq_upload].to_json
|
101
|
-
}
|
102
|
-
end
|
103
|
-
else
|
104
|
-
retval = render :json => [{:error => "Error creating generic file."}].to_json
|
105
|
-
end
|
106
|
-
end
|
107
|
-
rescue => error
|
108
|
-
logger.warn "GenericFilesController::create rescued error #{error.backtrace}"
|
109
|
-
retval = render :json => [{:error => "Error occurred while creating generic file."}].to_json
|
110
|
-
ensure
|
111
|
-
# remove the tempfile (only if it is a temp file)
|
112
|
-
params[:files][0].tempfile.delete if params[:files][0].respond_to?(:tempfile)
|
113
|
-
end
|
114
|
-
|
115
|
-
return retval
|
116
|
-
end
|
117
|
-
|
118
|
-
# routed to /files/:id/citation
|
119
|
-
def citation
|
120
|
-
end
|
121
|
-
|
122
|
-
# routed to /files/:id
|
123
|
-
def show
|
124
|
-
perms = permissions_solr_doc_for_id(@generic_file.pid)
|
125
|
-
@can_read = can? :read, perms
|
126
|
-
@can_edit = can? :edit, perms
|
127
|
-
@events = @generic_file.events(100)
|
128
|
-
|
129
|
-
respond_to do |format|
|
130
|
-
format.html
|
131
|
-
format.endnote { render :text => @generic_file.export_as_endnote }
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
# routed to /files/:id/audit (POST)
|
136
|
-
def audit
|
137
|
-
render :json=>@generic_file.audit
|
138
|
-
end
|
139
|
-
|
140
|
-
# routed to /files/:id (PUT)
|
141
|
-
def update
|
142
|
-
version_event = false
|
143
|
-
|
144
|
-
if params.has_key?(:revision) and params[:revision] != @generic_file.content.latest_version.versionID
|
145
|
-
revision = @generic_file.content.get_version(params[:revision])
|
146
|
-
@generic_file.add_file_datastream(revision.content, :dsid => 'content')
|
147
|
-
version_event = true
|
148
|
-
Sufia.queue.push(ContentRestoredVersionEventJob.new(@generic_file.pid, current_user.user_key, params[:revision]))
|
149
|
-
end
|
150
|
-
|
151
|
-
if params.has_key?(:filedata)
|
152
|
-
return unless virus_check(params[:filedata]) == 0
|
153
|
-
add_posted_blob_to_asset(@generic_file, params[:filedata])
|
154
|
-
version_event = true
|
155
|
-
Sufia.queue.push(ContentNewVersionEventJob.new(@generic_file.pid, current_user.user_key))
|
156
|
-
end
|
157
|
-
@generic_file.attributes = params[:generic_file].reject { |k,v| %w{ Filedata Filename revision part_of date_modified date_uploaded format }.include? k}
|
158
|
-
@generic_file.set_visibility(params[:visibility])
|
159
|
-
@generic_file.date_modified = Time.now.ctime
|
160
|
-
@generic_file.save!
|
161
|
-
# do not trigger an update event if a version event has already been triggered
|
162
|
-
Sufia.queue.push(ContentUpdateEventJob.new(@generic_file.pid, current_user.user_key)) unless version_event
|
163
|
-
record_version_committer(@generic_file, current_user)
|
164
|
-
redirect_to sufia.edit_generic_file_path(:tab => params[:redirect_tab]), :notice => render_to_string(:partial=>'generic_files/asset_updated_flash', :locals => { :generic_file => @generic_file })
|
165
|
-
|
166
|
-
end
|
167
|
-
|
168
|
-
protected
|
169
|
-
def record_version_committer(generic_file, user)
|
170
|
-
version = generic_file.content.latest_version
|
171
|
-
# content datastream not (yet?) present
|
172
|
-
return if version.nil?
|
173
|
-
VersionCommitter.create(:obj_id => version.pid,
|
174
|
-
:datastream_id => version.dsid,
|
175
|
-
:version_id => version.versionID,
|
176
|
-
:committer_login => user.user_key)
|
177
|
-
end
|
178
|
-
|
179
|
-
def find_by_id
|
180
|
-
@generic_file = GenericFile.find(params[:id])
|
181
|
-
end
|
182
|
-
|
183
|
-
def virus_check( file)
|
184
|
-
if defined? ClamAV
|
185
|
-
stat = ClamAV.instance.scanfile(file.path)
|
186
|
-
flash[:error] = "Virus checking did not pass for #{file.original_filename} status = #{stat}" unless stat == 0
|
187
|
-
logger.warn "Virus checking did not pass for #{file.inspect} status = #{stat}" unless stat == 0
|
188
|
-
stat
|
189
|
-
else
|
190
|
-
logger.warn "Virus checking disabled for #{file.inspect}"
|
191
|
-
0
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def create_and_save_generic_file
|
196
|
-
unless params.has_key?(:files)
|
197
|
-
logger.warn "!!!! No Files !!!!"
|
198
|
-
return
|
199
|
-
end
|
200
|
-
file = params[:files][0]
|
201
|
-
return nil unless virus_check(file) == 0
|
202
|
-
|
203
|
-
@generic_file = GenericFile.new
|
204
|
-
@generic_file.terms_of_service = params[:terms_of_service]
|
205
|
-
# if we want to be able to save zero length files then we can use this to make the file 1 byte instead of zero length and fedora will take it
|
206
|
-
#if (file.tempfile.size == 0)
|
207
|
-
# logger.warn "Encountered an empty file... Creating a new temp file with on space."
|
208
|
-
# f = Tempfile.new ("emptyfile")
|
209
|
-
# f.write " "
|
210
|
-
# f.rewind
|
211
|
-
# file.tempfile = f
|
212
|
-
#end
|
213
|
-
add_posted_blob_to_asset(@generic_file,file)
|
214
|
-
|
215
|
-
@generic_file.apply_depositor_metadata(user_key)
|
216
|
-
@generic_file.date_uploaded = Time.now.ctime
|
217
|
-
@generic_file.date_modified = Time.now.ctime
|
218
|
-
@generic_file.relative_path = params[:relative_path] if params.has_key?(:relative_path)
|
219
|
-
@generic_file.creator = current_user.name
|
220
|
-
|
221
|
-
if params.has_key?(:batch_id)
|
222
|
-
batch_id = Sufia::Noid.namespaceize(params[:batch_id])
|
223
|
-
@generic_file.add_relationship("isPartOf", "info:fedora/#{batch_id}")
|
224
|
-
else
|
225
|
-
logger.warn "unable to find batch to attach to"
|
226
|
-
end
|
227
|
-
|
228
|
-
save_tries = 0
|
229
|
-
begin
|
230
|
-
@generic_file.save
|
231
|
-
rescue RSolr::Error::Http => error
|
232
|
-
logger.warn "GenericFilesController::create_and_save_generic_file Caught RSOLR error #{error.inspect}"
|
233
|
-
save_tries+=1
|
234
|
-
# fail for good if the tries is greater than 3
|
235
|
-
rescue_action_without_handler(error) if save_tries >=3
|
236
|
-
sleep 0.01
|
237
|
-
retry
|
238
|
-
end
|
239
|
-
|
240
|
-
record_version_committer(@generic_file, current_user)
|
241
|
-
Sufia.queue.push(UnzipJob.new(@generic_file.pid)) if file.content_type == 'application/zip'
|
242
|
-
return @generic_file
|
243
|
-
end
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
############################ to get rid of deprication warnings. Need to fix #################
|
248
|
-
# Controller "before" filter that delegates enforcement based on the controller action
|
249
|
-
# Action-specific implementations are enforce_index_permissions, enforce_show_permissions, etc.
|
250
|
-
# @param [Hash] opts (optional, not currently used)
|
251
|
-
#
|
252
|
-
# @example
|
253
|
-
# class CatalogController < ApplicationController
|
254
|
-
# before_filter :enforce_access_controls
|
255
|
-
# end
|
256
|
-
#
|
257
|
-
# @deprecated HYDRA-886 Blacklight is now using Catalog#update to store pagination info, so we don't want to enforce_edit_permissions on it. Instead just call before_filter :enforce_show_permissions, :only=>:show. Move all Edit/Update/Delete methods into non-catalog backed controllers.
|
258
|
-
def enforce_access_controls(opts={})
|
259
|
-
controller_action = params[:action].to_s
|
260
|
-
delegate_method = "enforce_#{controller_action}_permissions"
|
261
|
-
if self.respond_to?(delegate_method.to_sym, true)
|
262
|
-
self.send(delegate_method.to_sym)
|
263
|
-
else
|
264
|
-
true
|
265
|
-
end
|
266
|
-
end
|
267
|
-
|
268
|
-
|
269
|
-
# Controller "before" filter for enforcing access controls on edit actions
|
270
|
-
# @param [Hash] opts (optional, not currently used)
|
271
|
-
def enforce_edit_permissions(opts={})
|
272
|
-
logger.debug("Enforcing edit permissions")
|
273
|
-
load_permissions_from_solr
|
274
|
-
if !can? :edit, params[:id]
|
275
|
-
session[:viewing_context] = "browse"
|
276
|
-
raise Hydra::AccessDenied.new("You do not have sufficient privileges to edit this document. You have been redirected to the read-only view.", :edit, params[:id])
|
277
|
-
else
|
278
|
-
session[:viewing_context] = "edit"
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
|
-
## This method is here for you to override
|
283
|
-
def enforce_create_permissions(opts={})
|
284
|
-
logger.debug("Enforcing create permissions")
|
285
|
-
if !can? :create, ActiveFedora::Base.new
|
286
|
-
raise Hydra::AccessDenied.new "You do not have sufficient privileges to create a new document."
|
287
|
-
end
|
288
|
-
end
|
289
|
-
|
290
|
-
## proxies to enforce_edit_permssions. This method is here for you to override
|
291
|
-
def enforce_update_permissions(opts={})
|
292
|
-
enforce_edit_permissions(opts)
|
293
|
-
end
|
294
|
-
|
295
|
-
## proxies to enforce_edit_permssions. This method is here for you to override
|
296
|
-
def enforce_destroy_permissions(opts={})
|
297
|
-
enforce_edit_permissions(opts)
|
298
|
-
end
|
299
|
-
|
300
|
-
## proxies to enforce_edit_permssions. This method is here for you to override
|
301
|
-
def enforce_new_permissions(opts={})
|
302
|
-
enforce_create_permissions(opts)
|
303
|
-
end
|
304
|
-
|
305
|
-
# Controller "before" filter for enforcing access controls on index actions
|
306
|
-
# Currently does nothing, instead relies on
|
307
|
-
# @param [Hash] opts (optional, not currently used)
|
308
|
-
def enforce_index_permissions(opts={})
|
309
|
-
# Do nothing. Relies on enforce_search_permissions being included in the Controller's solr_search_params_logic
|
310
|
-
return true
|
311
|
-
end
|
312
|
-
|
17
|
+
include Sufia::FilesControllerBehavior
|
313
18
|
end
|
@@ -17,7 +17,6 @@ class GenericFileRdfDatastream < ActiveFedora::NtriplesRDFDatastream
|
|
17
17
|
map_predicates do |map|
|
18
18
|
map.part_of(:to => "isPartOf", :in => RDF::DC)
|
19
19
|
map.contributor(:in => RDF::DC) do |index|
|
20
|
-
#index.as :searchable, :facetable, :displayable
|
21
20
|
index.as :searchable, :displayable
|
22
21
|
end
|
23
22
|
map.creator(:in => RDF::DC) do |index|
|
@@ -56,9 +55,6 @@ class GenericFileRdfDatastream < ActiveFedora::NtriplesRDFDatastream
|
|
56
55
|
map.resource_type(:to => "type", :in => RDF::DC) do |index|
|
57
56
|
index.as :searchable, :facetable, :displayable
|
58
57
|
end
|
59
|
-
map.format(:in => RDF::DC) do |index|
|
60
|
-
index.as :searchable, :facetable, :displayable
|
61
|
-
end
|
62
58
|
map.identifier(:in => RDF::DC) do |index|
|
63
59
|
index.as :searchable, :displayable
|
64
60
|
end
|
data/app/views/_ga.html.erb
CHANGED
@@ -15,8 +15,8 @@ limitations under the License.
|
|
15
15
|
%>
|
16
16
|
|
17
17
|
<%
|
18
|
-
|
19
|
-
|
18
|
+
if Sufia::Engine.config.respond_to? :google_analytics_id
|
19
|
+
tracking_id = Sufia::Engine.config.google_analytics_id
|
20
20
|
%>
|
21
21
|
<script type="text/javascript">
|
22
22
|
var _gaq = _gaq || [];
|