• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

benwbrum / fromthepage / 16626402560

30 Jul 2025 02:57PM UTC coverage: 64.038% (+0.1%) from 63.905%
16626402560

push

github

benwbrum
Fix timing issue in tests

1746 of 3271 branches covered (53.38%)

Branch coverage included in aggregate %.

7870 of 11745 relevant lines covered (67.01%)

87.3 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

38.14
/app/controllers/work_controller.rb
1
class WorkController < ApplicationController
1✔
2
  # require 'ftools'
3
  include ApplicationHelper
1✔
4
  include XmlSourceProcessor
1✔
5

6
  protect_from_forgery :except => [:set_work_title,
1✔
7
                                   :set_work_description,
8
                                   :set_work_physical_description,
9
                                   :set_work_document_history,
10
                                   :set_work_permission_description,
11
                                   :set_work_location_of_composition,
12
                                   :set_work_author,
13
                                   :set_work_transcription_conventions]
14
  # tested
15
  before_action :authorized?, only: [
1✔
16
    :edit,
17
    :pages_tab,
18
    :delete,
19
    :new,
20
    :create,
21
    :edit_scribes,
22
    :add_scribe,
23
    :remove_scribe,
24
    :search_scribes
25
  ]
26

27
  # no layout if xhr request
28
  layout Proc.new { |controller| controller.request.xhr? ? false : nil }, only: [:new, :create, :configurable_printout, :edit_scribes, :remove_scribe]
6!
29

30
  def metadata_overview_monitor
1✔
31
    @is_monitor_view = true
×
32
    render :template => "transcribe/monitor_view"
×
33
  end
34

35
  def configurable_printout
1✔
36
    @bulk_export = BulkExport.new
×
37
    @bulk_export.collection = @collection
×
38
    @bulk_export.work = @work
×
39
    @bulk_export.text_pdf_work = true
×
40
    @bulk_export.report_arguments['include_contributors'] = true
×
41
    @bulk_export.report_arguments['include_metadata'] = true
×
42
    @bulk_export.report_arguments['include_notes'] = true
×
43
    @bulk_export.report_arguments['preserve_linebreaks'] = false
×
44
  end
45

46
  def search
1✔
47
    @search_string = search_params[:term]
1✔
48

49
    @es_query = Elasticsearch::MultiQuery.new(
1✔
50
      query: @search_string,
51
      query_params: {
52
        mode: 'work',
53
        slug: @work.slug
54
      },
55
      page: params[:page] || 1,
56
      scope: search_params[:filter],
57
      user: current_user
58
    ).call
59

60
    @breadcrumb_scope = { work: true }
1✔
61
    @work_filter = @es_query.work_filter
1✔
62

63
    @search_results = @es_query.results
1✔
64
    @full_count = @es_query.total_count
1✔
65
    @type_counts = @es_query.type_counts
1✔
66
  end
67

68
  def describe
1✔
69
    @layout_mode = cookies[:transcribe_layout_mode] || @collection.default_orientation
×
70
    @metadata_array = JSON.parse(@work.metadata_description || '[]')
×
71
  end
72

73
  def needs_review_checkbox_checked
1✔
74
    params[:work] && params[:work]['needs_review'] == '1'
×
75
  end
76

77
  def save_description
1✔
78
    @field_cells = request.params[:fields]
×
79
    @metadata_array = @work.process_fields(@field_cells)
×
80
    @layout_mode = cookies[:transcribe_layout_mode] || @collection.default_orientation
×
81

82
    if params['save_to_incomplete'] && !needs_review_checkbox_checked
×
83
      @work.description_status = Work::DescriptionStatus::INCOMPLETE
×
84
    elsif params['save_to_needs_review'] || needs_review_checkbox_checked
×
85
      @work.description_status = Work::DescriptionStatus::NEEDS_REVIEW
×
86
    elsif (params['save_to_transcribed'] && !needs_review_checkbox_checked) || params['approve_to_transcribed']
×
87
      @work.description_status = Work::DescriptionStatus::DESCRIBED
×
88
    else
89
      # unexpected state
90
    end
91

92

93

94
    if @work.save
×
95
      # TODO record_description_deed(@work)
×
96
      if @work.saved_change_to_description_status?
×
97
        record_deed(@work, DeedType::DESCRIBED_METADATA, current_user)
×
98
      else
×
99
        record_deed(@work, DeedType::EDITED_METADATA, current_user)
×
100
      end
101

102
      flash[:notice] = t('.work_described')
×
103
      render :describe
×
104
    else
×
105
      render :describe
×
106
    end
107

108
  end
109

110
  def description_versions
1✔
111
    # @selected_version = @page_version.present? ? @page_version : @page.page_versions.first
112
    # @previous_version = params[:compare_version_id] ? PageVersion.find(params[:compare_version_id]) : @selected_version.prev
113
    selected_version_id = params[:metadata_description_version_id]
×
114
    if selected_version_id
×
115
      @selected_version= MetadataDescriptionVersion.find(selected_version_id)
×
116
    else
×
117
      @selected_version= @work.metadata_description_versions.first
×
118
    end
119
    # NB: Unlike in page versions (which are created when we first create the page), metadata description versions may be nil
120
    compare_version_id = params[:compare_version_id]
×
121
    if compare_version_id
×
122
      @previous_version = MetadataDescriptionVersion.find(compare_version_id)
×
123
    else
×
124
      if @selected_version.version_number > 1
×
125
        @previous_version = @work.metadata_description_versions.second
×
126
      else
×
127
        @previous_version = @selected_version
×
128
      end
129
    end
130
    # again, both may be blank here
131
  end
132

133
  def delete
1✔
134
    @work.destroy
2✔
135
    redirect_to dashboard_owner_path
2✔
136
  end
137

138
  def edit
1✔
139
    @collections = current_user.collections
27✔
140
    # set subjects to true if there are any articles/page_article_links
141
    @subjects = !@work.articles.blank?
27✔
142
    @scribes = @work.scribes
27✔
143
  end
144

145
  def edit_scribes
1✔
146
    @scribes = @work.scribes
5✔
147
    @nonscribes = User.where.not(id: @scribes.pluck(:id)).limit(100)
5✔
148
  end
149

150
  def search_scribes
1✔
151
    query = "%#{params[:term].to_s.downcase}%"
×
152
    excluded_ids = @work.scribes.pluck(:id) + [@work.owner.id]
×
153
    users = User.where('LOWER(real_name) LIKE :search OR LOWER(email) LIKE :search', search: query)
×
154
                .where.not(id: excluded_ids)
155
                .limit(100)
156

157
    render json: { results: users.map { |u| { text: "#{u.display_name} #{u.email}", id: u.id } } }
×
158
  end
159

160
  def add_scribe
1✔
161
    scribe = User.find_by(id: params[:scribe_id])
2✔
162
    @work.scribes << scribe
2✔
163

164
    if scribe.notification.add_as_collaborator && SMTP_ENABLED
2✔
165
      begin
166
        UserMailer.work_collaborator(scribe, @work).deliver!
1✔
167
      # :nocov:
168
      rescue StandardError => e
169
        print "SMTP Failed: Exception: #{e.message}"
170
      end
171
      # :cov:
172
    end
173

174
    redirect_to work_edit_scribes_path(@collection, @work)
175
  end
176

177
  def remove_scribe
178
    scribe = User.find_by(id: params[:scribe_id])
179
    @work.scribes.delete(scribe)
180

181
    redirect_to work_edit_scribes_path(@collection, @work)
182
  end
183

184
  def update_work
185
    @work.update(work_params)
186
    redirect_to work_edit_path(work_id: @work.id)
187
  end
188

189
  # tested
190
  def create
191
    @work = Work.new
192
    @work.title = params[:work][:title]
193
    @work.collection_id = params[:work][:collection_id]
194
    @work.description = params[:work][:description]
195
    @work.owner = current_user
196
    @collections = current_user.all_owner_collections
197

198
    if @work.save
199
      record_deed(@work, DeedType::WORK_ADDED, work.owner)
200
      flash[:notice] = t('.work_created')
201
      ajax_redirect_to(work_pages_tab_path(:work_id => @work.id, :anchor => 'create-page'))
202
    else
203
      render :new
204
    end
205
  end
206

207
  def update
208
    work = Work.find(params[:id])
209
    @collection ||= work.collection
210

211
    result = Work::Update.new(work: work, work_params: work_params).call
212

213
    @work = result.work
214
    if result.success?
215
      if result.original_collection_id != result.collection.id
216
        record_deed(@work, DeedType::WORK_ADDED, @work.owner)
217
        @collection = @work.collection
218
      end
219

220
      flash[:notice] = t('.work_updated')
221
      redirect_to edit_collection_work_path(@work.collection.owner, @collection, @work)
222
    else
223
      @scribes = @work.scribes
224
      @nonscribes = User.where.not(id: @scribes.select(:id))
225
      @collections = current_user.collections
226
      @subjects = @work.articles.any?
227

228
      render :edit, status: :unprocessable_entity
229
    end
230
  end
231

232
  def revert
233
    work = Work.find_by(id: params[:work_id])
234
    work.update_attribute(:transcription_conventions, nil)
235
    render :plain => work.collection.transcription_conventions
236
  end
237

238
  def update_featured_page
239
    @work.update(featured_page: params[:page_id])
240
    redirect_back fallback_location: @work
241
  end
242

243
  def document_sets_select
244
    document_sets = current_user.document_sets.where(collection_id: params[:collection_id])
245

246
    render partial: 'document_sets_select', locals: { document_sets: document_sets }
247
  end
248

249
  protected
250

251
  def record_deed(work, deed_type, user)
252
    deed = Deed.new
253
    deed.work = work
254
    deed.deed_type = deed_type
255
    deed.collection = work.collection
256
    deed.user = user
257
    deed.save!
258
    update_search_attempt_contributions
259
  end
260

261
  def show
262
    # Set meta information for work pages for better archival
263
    @page_title = "#{@work.title} - #{@collection.title}"
264
    @meta_description = "Historical document: #{@work.title}#{@work.author.present? ? " by #{@work.author}" : ""} in the #{@collection.title} collection. #{@work.description}".truncate(160)
265
    @meta_keywords = [@work.title, @work.author, @collection.title, "historical document", "digital archive"].compact.join(", ")
266
    
267
    # Generate structured data for work
268
    @structured_data = {
269
      "@context" => "https://schema.org",
270
      "@type" => "DigitalDocument",
271
      "name" => @work.title,
272
      "description" => @work.description,
273
      "inLanguage" => @collection.text_language || "en",
274
      "isPartOf" => {
275
        "@type" => "Collection",
276
        "name" => @collection.title,
277
        "description" => to_snippet(@collection.intro_block)
278
      },
279
      "url" => request.original_url,
280
      "dateModified" => @work.most_recent_deed_created_at&.iso8601,
281
      "publisher" => {
282
        "@type" => "Organization",
283
        "name" => @collection.owner&.display_name || "FromThePage"
284
      }
285
    }
286
    
287
    # Add optional fields conditionally
288
    @structured_data["author"] = @work.author if @work.author.present?
289
    @structured_data["dateCreated"] = @work.document_date if @work.document_date.present?
290

291
    # Add archival-friendly headers
292
    respond_to do |format|
293
      format.html do
294
        response.headers['X-Robots-Tag'] = 'index, follow, archive'
295
      end
296
    end
297
  end
298

299
  private
300

301
  def authorized?
302
    if !user_signed_in? || !current_user.owner
303
      ajax_redirect_to dashboard_path
304
    elsif @work && !current_user.like_owner?(@work)
305
      ajax_redirect_to dashboard_path
306
    end
307
  end
308

309
  def search_params
310
    params.permit(:term, :page, :filter, :work_id, :collection_id, :user_id)
311
  end
312

313
  def work_params
314
    params.require(:work).permit(
315
      :title,
316
      :description,
317
      :collection_id,
318
      :supports_translation,
319
      :slug,
320
      :ocr_correction,
321
      :transcription_conventions,
322
      :author,
323
      :recipient,
324
      :location_of_composition,
325
      :identifier,
326
      :pages_are_meaningful,
327
      :physical_description,
328
      :document_history,
329
      :permission_description,
330
      :translation_instructions,
331
      :scribes_can_edit_titles,
332
      :restrict_scribes,
333
      :picture,
334
      :genre,
335
      :source_location,
336
      :source_collection_name,
337
      :source_box_folder,
338
      :in_scope,
339
      :editorial_notes,
340
      :document_date,
341
      :term,
342
      document_set_ids: []
343
    )
344
  end
345

346
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc