metadata_presenter 1.0.8 → 1.3.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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/metadata_presenter/answers_controller.rb +36 -0
  3. data/app/controllers/metadata_presenter/engine_controller.rb +5 -0
  4. data/app/controllers/metadata_presenter/file_controller.rb +12 -0
  5. data/app/controllers/metadata_presenter/submissions_controller.rb +1 -1
  6. data/app/models/metadata_presenter/component.rb +4 -0
  7. data/app/models/metadata_presenter/file_uploader.rb +18 -0
  8. data/app/models/metadata_presenter/metadata.rb +4 -0
  9. data/app/models/metadata_presenter/offline_upload_adapter.rb +10 -0
  10. data/app/models/metadata_presenter/page.rb +4 -4
  11. data/app/models/metadata_presenter/page_answers.rb +20 -4
  12. data/app/models/metadata_presenter/uploaded_file.rb +14 -0
  13. data/app/presenters/metadata_presenter/page_answers_presenter.rb +4 -0
  14. data/app/validators/metadata_presenter/accept_validator.rb +7 -0
  15. data/app/validators/metadata_presenter/max_size_validator.rb +17 -0
  16. data/app/validators/metadata_presenter/upload_validator.rb +20 -0
  17. data/app/validators/metadata_presenter/virus_scan_validator.rb +7 -0
  18. data/app/views/metadata_presenter/component/_upload.html.erb +22 -0
  19. data/config/initializers/page_components.rb +1 -1
  20. data/config/routes.rb +4 -0
  21. data/default_metadata/component/upload.json +25 -0
  22. data/default_metadata/page/singlequestion.json +1 -1
  23. data/default_metadata/string/error.accept.json +6 -0
  24. data/default_metadata/string/error.max_size.json +6 -0
  25. data/default_metadata/string/error.virus_scan.json +7 -0
  26. data/default_text/content.json +2 -1
  27. data/fixtures/version.json +67 -1
  28. data/lib/metadata_presenter/version.rb +1 -1
  29. data/schemas/component/upload.json +40 -0
  30. data/schemas/validations/validations.json +68 -37
  31. metadata +18 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a9c2ec1af85d765a91dbf1e4558828cfa4e04698bc1a53c27753191644e14589
4
- data.tar.gz: cc258752398c51cde40f13cc94d0accc72f1fd0a2e7ef5e88a49dc54f847303b
3
+ metadata.gz: 8159601ef7b12c039633ef169437869d66abd193a70a72c6d3bd5bd83e8e43df
4
+ data.tar.gz: 117638aa22a6695d528a5c6f390526965dde81247706c9d203705ce85c0e62a4
5
5
  SHA512:
6
- metadata.gz: 61cafb1d8649b71d35ee3da5a9c6e404da5bed086628f3fa9e5b3c10dda963b6eb67d113e4a6a8bd60c6086d3e3ac06dfa4ad76e7236330513a1922faf8cdb7b
7
- data.tar.gz: e985eaf13f0729fa0f2a07a05d650e249435b03d1b13c1dfc2de961fbd385ecbcaafc2c8468e58748749f1a30f98c42b531d8285f99e2705cb46571a8933ae12
6
+ metadata.gz: f1e2a77178e1f0dba9d1e33562ce50fc1cc1e5f0ffd5c67393fcc9087dc00e703f07be00b23a9088b813fcae2a730c0690e767b1571ae5d56c45dd9ecf49591e
7
+ data.tar.gz: 27d472e2ad735d502477719935e6f099e6148930e6ecedd370f02211c593d4442ee20d33e481e6ecf583114a36f41289f5cd3840cefdf54bf71c6d3ef54119ab
@@ -5,6 +5,8 @@ module MetadataPresenter
5
5
  def create
6
6
  @page_answers = PageAnswers.new(page, answers_params)
7
7
 
8
+ upload_files if upload?
9
+
8
10
  if @page_answers.validate_answers
9
11
  save_user_data # method signature
10
12
  redirect_to_next_page
@@ -51,5 +53,39 @@ module MetadataPresenter
51
53
  def check_page_exists
52
54
  not_found if page.blank?
53
55
  end
56
+
57
+ def upload_files
58
+ user_data = load_user_data
59
+ @page_answers.page.upload_components.each do |component|
60
+ answer = user_data[component.id]
61
+
62
+ @page_answers.uploaded_files.push(uploaded_file(answer, component))
63
+ end
64
+ end
65
+
66
+ def uploaded_file(answer, component)
67
+ if answer.present?
68
+ @page_answers.answers[component.id] = answer
69
+ MetadataPresenter::UploadedFile.new(
70
+ file: @page_answers.send(component.id),
71
+ component: component
72
+ )
73
+ else
74
+ FileUploader.new(
75
+ session: session,
76
+ page_answers: @page_answers,
77
+ component: component,
78
+ adapter: upload_adapter
79
+ ).upload
80
+ end
81
+ end
82
+
83
+ def upload_adapter
84
+ super if defined?(super)
85
+ end
86
+
87
+ def upload?
88
+ Array(page.components).any?(&:upload?)
89
+ end
54
90
  end
55
91
  end
@@ -17,6 +17,11 @@ module MetadataPresenter
17
17
  end
18
18
  helper_method :back_link
19
19
 
20
+ def answered?(component_id)
21
+ @page_answers.send(component_id).present?
22
+ end
23
+ helper_method :answered?
24
+
20
25
  private
21
26
 
22
27
  def not_found
@@ -0,0 +1,12 @@
1
+ module MetadataPresenter
2
+ class FileController < EngineController
3
+ def destroy
4
+ remove_user_data(params[:component_id])
5
+ redirect_back(fallback_location: root_path)
6
+ end
7
+
8
+ def remove_user_data(component_id)
9
+ super(component_id) if defined?(super)
10
+ end
11
+ end
12
+ end
@@ -17,7 +17,7 @@ module MetadataPresenter
17
17
  # So in the Runner we defined the #create_submission in the parent
18
18
  # controller and in the Editor we don't.
19
19
  #
20
- if defined? super
20
+ if defined?(super)
21
21
  super
22
22
  end
23
23
  end
@@ -16,4 +16,8 @@ class MetadataPresenter::Component < MetadataPresenter::Metadata
16
16
  def content?
17
17
  type == 'content'
18
18
  end
19
+
20
+ def upload?
21
+ type == 'upload'
22
+ end
19
23
  end
@@ -0,0 +1,18 @@
1
+ module MetadataPresenter
2
+ class FileUploader
3
+ include ActiveModel::Model
4
+ attr_accessor :session, :page_answers, :component, :adapter
5
+
6
+ def upload
7
+ UploadedFile.new(file: upload_file, component: component)
8
+ end
9
+
10
+ def upload_file
11
+ adapter.new(
12
+ session: session,
13
+ file_details: page_answers.send(component.id),
14
+ allowed_file_types: component.validation['accept']
15
+ ).call
16
+ end
17
+ end
18
+ end
@@ -34,6 +34,10 @@ class MetadataPresenter::Metadata
34
34
  value.blank? && editor? ? MetadataPresenter::DefaultText[method_name] : value
35
35
  end
36
36
 
37
+ def ==(other)
38
+ id == other.id if other.respond_to? :id
39
+ end
40
+
37
41
  def editor?
38
42
  @editor.present?
39
43
  end
@@ -0,0 +1,10 @@
1
+ module MetadataPresenter
2
+ class OfflineUploadAdapter
3
+ include ActiveModel::Model
4
+ attr_accessor :session, :file_details, :allowed_file_types
5
+
6
+ def call
7
+ {}
8
+ end
9
+ end
10
+ end
@@ -14,10 +14,6 @@ module MetadataPresenter
14
14
  add_extra_component
15
15
  ].freeze
16
16
 
17
- def ==(other)
18
- id == other.id if other.respond_to? :id
19
- end
20
-
21
17
  def editable_attributes
22
18
  to_h.reject { |k, _| k.in?(NOT_EDITABLE) }
23
19
  end
@@ -58,6 +54,10 @@ module MetadataPresenter
58
54
  page_components(raw_type)[:content]
59
55
  end
60
56
 
57
+ def upload_components
58
+ components.select(&:upload?)
59
+ end
60
+
61
61
  private
62
62
 
63
63
  def to_components(node_components, collection:)
@@ -2,10 +2,12 @@ module MetadataPresenter
2
2
  class PageAnswers
3
3
  include ActiveModel::Model
4
4
  include ActiveModel::Validations
5
+ attr_reader :page, :answers, :uploaded_files
5
6
 
6
7
  def initialize(page, answers)
7
8
  @page = page
8
9
  @answers = answers
10
+ @uploaded_files = []
9
11
  end
10
12
 
11
13
  def validate_answers
@@ -23,11 +25,29 @@ module MetadataPresenter
23
25
 
24
26
  if component && component.type == 'date'
25
27
  date_answer(component.id)
28
+ elsif component && component.type == 'upload'
29
+ upload_answer(component.id)
26
30
  else
27
31
  answers[method_name.to_s]
28
32
  end
29
33
  end
30
34
 
35
+ def upload_answer(component_id)
36
+ file_details = answers[component_id.to_s]
37
+
38
+ return {} unless file_details
39
+
40
+ if file_details.is_a?(Hash) || file_details.is_a?(ActionController::Parameters)
41
+ file_details
42
+ else
43
+ {
44
+ 'original_filename' => file_details.original_filename,
45
+ 'content_type' => file_details.content_type,
46
+ 'tempfile' => file_details.tempfile.path.to_s
47
+ }
48
+ end
49
+ end
50
+
31
51
  def date_answer(component_id)
32
52
  date = raw_date_answer(component_id)
33
53
 
@@ -43,9 +63,5 @@ module MetadataPresenter
43
63
  answers["#{component_id}(#{segment})"]
44
64
  end
45
65
  end
46
-
47
- private
48
-
49
- attr_reader :page, :answers
50
66
  end
51
67
  end
@@ -0,0 +1,14 @@
1
+ module MetadataPresenter
2
+ class UploadedFile
3
+ include ActiveModel::Model
4
+ attr_accessor :file, :component
5
+
6
+ def ==(other)
7
+ file == other.file && component == other.component
8
+ end
9
+
10
+ def error_name
11
+ file.error_name if file.respond_to? :error_name
12
+ end
13
+ end
14
+ end
@@ -79,5 +79,9 @@ module MetadataPresenter
79
79
  def checkboxes(value)
80
80
  value.join('<br>').html_safe
81
81
  end
82
+
83
+ def upload(file_hash)
84
+ file_hash['original_filename']
85
+ end
82
86
  end
83
87
  end
@@ -0,0 +1,7 @@
1
+ module MetadataPresenter
2
+ class AcceptValidator < UploadValidator
3
+ def error_name
4
+ 'accept'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ module MetadataPresenter
2
+ class MaxSizeValidator < UploadValidator
3
+ def error_name
4
+ 'invalid.too-large'
5
+ end
6
+
7
+ def error_message_hash
8
+ super.merge(
9
+ { schema_key.to_sym => human_max_size }
10
+ )
11
+ end
12
+
13
+ def human_max_size
14
+ (component.validation[schema_key] / (1024.0 * 1024.0)).round
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module MetadataPresenter
2
+ class UploadValidator < BaseValidator
3
+ def invalid_answer?
4
+ user_answer.error_name == error_name
5
+ end
6
+
7
+ def user_answer
8
+ page_answers.uploaded_files.find do |uploaded_file|
9
+ component.id == uploaded_file.component.id
10
+ end
11
+ end
12
+
13
+ def error_message_hash
14
+ {
15
+ control: page_answers.send(component.id)['original_filename'],
16
+ schema_key.to_sym => component.validation[schema_key]
17
+ }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module MetadataPresenter
2
+ class VirusScanValidator < UploadValidator
3
+ def error_name
4
+ 'invalid.virus'
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ <% if answered?(component.id) %>
2
+ <h1 class="govuk-heading-xl"><%= input_title %></h1>
3
+ <span class="govuk-hint" id="answers-dog-picture-upload-1-hint" data-fb-default-text="<%= default_text('upload_hint') %>">
4
+ <%= component.hint.present? ? component.hint : default_text('upload_hint') %>
5
+ </span>
6
+
7
+ <p><%= @page_answers.send(component.id)['original_filename'] %></p>
8
+
9
+ <p>
10
+ <%= link_to 'Remove file', remove_file_path(component.id), class: 'govuk-link' %>
11
+ </p>
12
+ <% else %>
13
+ <%= f.govuk_file_field component.id.to_sym,
14
+ label: { text: input_title },
15
+ hint: {
16
+ data: { "fb-default-text" => default_text('upload_hint') },
17
+ text: component.hint.present? ? component.hint : default_text('upload_hint')
18
+ },
19
+ accept: component.validation['accept'],
20
+ disabled: editable?
21
+ %>
22
+ <% end %>
@@ -17,7 +17,7 @@ Rails.application.config.page_components =
17
17
  content: %w(content)
18
18
  },
19
19
  singlequestion: {
20
- input: %w(text textarea number date radios checkboxes),
20
+ input: %w(text textarea number date radios checkboxes upload),
21
21
  content: %w()
22
22
  }
23
23
  })
data/config/routes.rb CHANGED
@@ -4,6 +4,10 @@ MetadataPresenter::Engine.routes.draw do
4
4
  post '/reserved/submissions', to: 'submissions#create', as: :reserved_submissions
5
5
  get '/reserved/change-answer', to: 'change_answer#create', as: :change_answer
6
6
 
7
+ # We are not adding rails ujs to the editor app so we need to make it
8
+ # as get verb.
9
+ get '/reserved/file/:component_id', to: 'file#destroy', as: :remove_file
10
+
7
11
  post '/', to: 'answers#create'
8
12
  match '*path', to: 'answers#create', via: :post
9
13
  match '*path', to: 'pages#show',
@@ -0,0 +1,25 @@
1
+ {
2
+ "_id": "component.upload",
3
+ "_type": "upload",
4
+ "errors": {},
5
+ "label": "Question",
6
+ "hint": "Maximum file size is 7MB",
7
+ "name": "component-name",
8
+ "validation": {
9
+ "required": true,
10
+ "max_size": "7340032",
11
+ "virus_scan": true,
12
+ "accept": [
13
+ "text/csv",
14
+ "text/plain",
15
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
16
+ "application/msword",
17
+ "application/vnd.oasis.opendocument.text",
18
+ "application/pdf",
19
+ "application/rtf",
20
+ "image/jpeg",
21
+ "image/png",
22
+ "application/vnd.ms-excel"
23
+ ]
24
+ }
25
+ }
@@ -2,7 +2,7 @@
2
2
  "_id": "page.singlequestion",
3
3
  "_type": "page.singlequestion",
4
4
  "section_heading": "",
5
- "heading": "Question",
5
+ "heading": "",
6
6
  "lede": "",
7
7
  "body": "Body section",
8
8
  "components": [],
@@ -0,0 +1,6 @@
1
+ {
2
+ "_id": "error.accept",
3
+ "_type": "string.error",
4
+ "description": "File uploaded is wrong type",
5
+ "value": "%{control} was not uploaded successfully as it is the wrong type"
6
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "_id": "error.max_size",
3
+ "_type": "string.error",
4
+ "description": "File is too large",
5
+ "value": "The selected file must be smaller than %{max_size}MB."
6
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "_id": "error.virus_scan",
3
+ "_type": "string.error",
4
+ "description": "File uploaded contains virus",
5
+ "value": "%{control} was not uploaded successfully because it contains a virus"
6
+ }
7
+
@@ -5,5 +5,6 @@
5
5
  "content": "[Optional content]",
6
6
  "hint": "[Optional hint text]",
7
7
  "option": "Option",
8
- "option_hint": "[Optional hint text]"
8
+ "option_hint": "[Optional hint text]",
9
+ "upload_hint": "Maximum file size is 7MB"
9
10
  }
@@ -20,6 +20,7 @@
20
20
  "page.burgers",
21
21
  "page.star-wars-knowledge",
22
22
  "page.how-many-lights",
23
+ "page.dog-picture",
23
24
  "page.check-answers",
24
25
  "page.confirmation"
25
26
  ],
@@ -432,6 +433,71 @@
432
433
  "add_component": "content",
433
434
  "section_heading": "Chain of Command"
434
435
  },
436
+ {
437
+ "_id": "page.dog-picture",
438
+ "url": "dog-picture",
439
+ "_type": "page.singlequestion",
440
+ "_uuid": "2ef7d11e-0307-49e9-9fe2-345dc528dd66",
441
+ "heading": "Question",
442
+ "components": [
443
+ {
444
+ "_id": "dog-picture_upload_1",
445
+ "name": "dog-picture_upload_1",
446
+ "_type": "upload",
447
+ "_uuid": "f056a76e-ec3f-47ae-b625-1bba92220ad1",
448
+ "hint": "",
449
+ "legend": "Upload your best dog photo",
450
+ "max_files": 1,
451
+ "validation": {
452
+ "required": true,
453
+ "accept": [
454
+ "audio/*",
455
+ "image/bmp",
456
+ "text/csv",
457
+ "application/vnd.ms-excel",
458
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
459
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
460
+ "application/vnd.ms-excel.sheet.macroEnabled.12",
461
+ "application/vnd.ms-excel.template.macroEnabled.12",
462
+ "application/vnd.ms-excel.addin.macroEnabled.12",
463
+ "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
464
+ "image/gif",
465
+ "image/*",
466
+ "application/x-iwork-pages-sffpages",
467
+ "image/jpeg",
468
+ "application/pdf",
469
+ "text/plain",
470
+ "image/png",
471
+ "application/vnd.ms-powerpoint",
472
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
473
+ "application/vnd.openxmlformats-officedocument.presentationml.template",
474
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
475
+ "application/vnd.ms-powerpoint.addin.macroEnabled.12",
476
+ "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
477
+ "application/vnd.ms-powerpoint.template.macroEnabled.12",
478
+ "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
479
+ "text/rtf",
480
+ "excel",
481
+ "csv",
482
+ "image/svg+xml",
483
+ "pdf",
484
+ "word",
485
+ "rtf",
486
+ "plaintext",
487
+ "image/tiff",
488
+ "video/*",
489
+ "application/msword",
490
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
491
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
492
+ "application/vnd.ms-word.document.macroEnabled.12",
493
+ "application/vnd.ms-word.template.macroEnabled.12"
494
+ ],
495
+ "max_size": 7340032,
496
+ "virus_scan": true
497
+ }
498
+ }
499
+ ]
500
+ },
435
501
  {
436
502
  "_id": "page.check-answers",
437
503
  "url": "check-answers",
@@ -532,7 +598,7 @@
532
598
  {
533
599
  "_id": "page.accessibility",
534
600
  "url": "accessibility",
535
- "body": "This accessibility statement applies to [describe your form here - for example, the general enquiries form for the CICA]. There is a separate [accessibility statement for the main GOV.UK website](https://www.gov.uk/help/accessibility-statement).\r\n\r\n###Using this online form\r\n\r\nThis form was built using MoJ Forms, a tool developed by the Ministry of Justice, and uses components from the [GOV.UK Design System](https://design-system.service.gov.uk/).\r\n\r\n[insert your organisation here] is responsible for the content of this online form. The Ministry of Justice is responsible for its technical aspects.\r\n\r\nWe want as many people as possible to be able to use this online form. For example, that means you should be able to:\r\n\r\n- change colours, contrast levels and fonts\r\n- zoom in up to 300% without the text spilling off the screen\r\n- navigate the form using just a keyboard\r\n- navigate the form using speech recognition software\r\n- listen to the form using a screen reader (including recent versions of JAWS, NVDA and VoiceOver)\r\n\r\nWe’ve also made the text as simple as possible to understand.\r\n\r\n[AbilityNet](https://mcmw.abilitynet.org.uk/) has advice on making your device easier to use if you have a disability.\r\n\r\n###How accessible this form is\r\n\r\nWe know some parts of this form are not fully accessible:\r\n\r\n- pages have no skip links\r\n- the language attribute of the page has not been set in the HTML\r\n- some pages may contain empty headings\r\n- some content may be cut off or appear truncated when zooming in\r\n\r\n###Feedback and contact information\r\n\r\nIf you need information on this website in a different format:\r\n\r\n[insert your contact details for user requests here - add other channels, such as text phones or Relay UK, as required]\r\n\r\n- email: [your email address]\r\n- call: [your telephone number]\r\n- [Hours - e.g. Monday to Friday, 9am to 5pm]\r\n\r\n###Enforcement procedure\r\n\r\nThe Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the ‘accessibility regulations’). If you’re not happy with how we respond to your complaint, contact the [Equality Advisory and Support Service (EASS)](https://www.equalityadvisoryservice.com/).\r\n\r\n###Technical information about this online form’s accessibility\r\n\r\nWe are committed to making our online forms and services accessible, in accordance with the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018.\r\n\r\n####Compliance status\r\n\r\nThis online form is partially compliant with the [Web Content Accessibility Guidelines version 2.1 AA standard](https://www.w3.org/TR/WCAG21/), due to the non-compliances listed below.\r\n\r\n###Non-accessible content\r\n\r\nThe content listed below is non-accessible for the following reasons.\r\n\r\n####Non compliance with the accessibility regulations\r\n\r\n1. Pages have no skip links. This issue may affect screen reader and keyboard users who use skip links to bypass repeated content such as headers and navigation menus to skip directly to the main page content.\r\n2. The language attribute of the page has not been set in the HTML. This may cause confusion to screen reader users who may not be able to identify the primary language of the page in their journey.\r\n3. Some pages may contain empty headings, including on the check answers page. As a result, screen reader users may have difficulty navigating these pages.\n4. Some content may be cut off or appear truncated when zooming in. This issue may affect low-vision users navigating the form who use reflow settings to view web pages.\r\n\r\nWe plan to fix these issues by July 2021.\r\n\r\n###Preparation of this accessibility statement\r\n\r\nThis statement was prepared on [date when it was first published]. It was last reviewed on [date when it was last reviewed].\r\n\r\nThis form was last tested on [date when you performed your basic accessibility check].\r\n\r\nIn order to test the compliance of all forms built using the MoJ Forms tool, the Ministry of Justice commissioned The Digital Accessibility Centre (DAC) to carry out a WCAG 2.1 AA level audit of a sample form. This included extensive testing by users with a wide range of disabilities. The audit was performed on 8 April 2021.\r\n\r\nIn addition, this form was tested by [insert team or organisation here]. It was tested using the [WAVE Web Accessibility Evaluation Tool](https://wave.webaim.org/) following guidance from the Ministry of Justice and Government Digital Service (GDS).\r\n\r\n###What we’re doing to improve accessibility\r\n\r\nWe will monitor the accessibility of this website on an ongoing basis and fix any accessibility issues reported to us.",
601
+ "body": "This accessibility statement applies to [describe your form here - for example, the general enquiries form for the CICA]. There is a separate [accessibility statement for the main GOV.UK website](https://www.gov.uk/help/accessibility-statement).\r\n\r\n###Using this online form\r\n\r\nThis form was built using MoJ Forms, a tool developed by the Ministry of Justice, and uses components from the [GOV.UK Design System](https://design-system.service.gov.uk/).\r\n\r\n[insert your organisation here] is responsible for the content of this online form. The Ministry of Justice is responsible for its technical aspects.\r\n\r\nWe want as many people as possible to be able to use this online form. For example, that means you should be able to:\r\n\r\n- change colours, contrast levels and fonts\r\n- zoom in up to 300% without the text spilling off the screen\r\n- navigate the form using just a keyboard\r\n- navigate the form using speech recognition software\r\n- listen to the form using a screen reader (including recent versions of JAWS, NVDA and VoiceOver)\r\n\r\nWe’ve also made the text as simple as possible to understand.\r\n\r\n[AbilityNet](https://mcmw.abilitynet.org.uk/) has advice on making your device easier to use if you have a disability.\r\n\r\n###Feedback and contact information\r\n\r\nIf you need information on this website in a different format:\r\n\r\n[insert your contact details for user requests here - add other channels, such as text phones or Relay UK, as required]\r\n\r\n- email: [your email address]\r\n- call: [your telephone number]\r\n- [Hours - e.g. Monday to Friday, 9am to 5pm]\r\n\r\nWe'll consider your request and get back to you in [add your SLA - e.g. a week or 5 working days].\r\n\r\n###Reporting accessibility problems with this form\r\n\r\nWe’re always looking to improve the accessibility of this form. If you find any problems not listed on this page or think we’re not meeting accessibility requirements, contact:\r\n\r\n[insert your contact details for user feedback here - add other channels, such as text phones or Relay UK, as required]\r\n\r\n- email: [your email address]\r\n- call: [your telephone number]\r\n- [Hours - e.g. Monday to Friday, 9am to 5pm]\r\n\r\n###Enforcement procedure\r\n\r\nThe Equality and Human Rights Commission (EHRC) is responsible for enforcing the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018 (the ‘accessibility regulations’). If you’re not happy with how we respond to your complaint, contact the [Equality Advisory and Support Service (EASS)](https://www.equalityadvisoryservice.com/).\r\n\r\n###Technical information about this online form’s accessibility\r\n\r\nWe are committed to making our online forms and services accessible, in accordance with the Public Sector Bodies (Websites and Mobile Applications) (No. 2) Accessibility Regulations 2018.\r\n\r\n####Compliance status\r\n\r\nThis online form is fully compliant with the [Web Content Accessibility Guidelines version 2.1 AA standard](https://www.w3.org/TR/WCAG21/)\r\n\r\n###Preparation of this accessibility statement\r\n\r\nThis statement was prepared on [date when it was first published]. It was last reviewed on [date when it was last reviewed].\r\n\r\nThis form was last tested on [date when you performed your basic accessibility check].\r\n\r\nIn order to test the compliance of all forms built using the MoJ Forms tool, the Ministry of Justice commissioned The Digital Accessibility Centre (DAC) to carry out a WCAG 2.1 AA level audit of a sample form. This included extensive testing by users with a wide range of disabilities. The audit was performed on 8 April 2021. The audit highlighted a number of non-compliance issues which were fixed on 11 May 2021.\r\n\r\nIn addition, this form was tested by [insert team or organisation here]. It was tested using the [WAVE Web Accessibility Evaluation Tool](https://wave.webaim.org/) following guidance from the Ministry of Justice and the Government Digital Service (GDS).\r\n\r\n###What we’re doing to improve accessibility\r\n\r\nWe will monitor the accessibility of this website on an ongoing basis and fix any accessibility issues reported to us.",
536
602
  "_type": "page.standalone",
537
603
  "_uuid": "c439c7fd-f411-4e11-8598-4023934bac93",
538
604
  "heading": "Accessibility statement",
@@ -1,3 +1,3 @@
1
1
  module MetadataPresenter
2
- VERSION = '1.0.8'.freeze
2
+ VERSION = '1.3.0'.freeze
3
3
  end
@@ -0,0 +1,40 @@
1
+ {
2
+ "$id": "http://gov.uk/schema/v1.0.0/upload",
3
+ "_name": "component.upload",
4
+ "title": "Upload",
5
+ "description": "Let users select and upload one or more files",
6
+ "type": "object",
7
+ "properties": {
8
+ "_type": {
9
+ "const": "upload"
10
+ },
11
+ "max_files": {
12
+ "title": "Maximum number of files",
13
+ "description": "Maximum number of files a user can upload",
14
+ "type": "number",
15
+ "default": 1
16
+ },
17
+ "min_files": {
18
+ "title": "Minimum number of files",
19
+ "description": "Minimum number of files a user can upload - 1 if required, 0 if not required",
20
+ "type": "number"
21
+ }
22
+ },
23
+ "allOf": [
24
+ {
25
+ "$ref": "definition.field"
26
+ },
27
+ {
28
+ "$ref": "definition.width_class.input"
29
+ },
30
+ {
31
+ "$ref": "validations#/definitions/errors_accept"
32
+ },
33
+ {
34
+ "$ref": "validations#/definitions/errors_max_size"
35
+ },
36
+ {
37
+ "$ref": "validations#/definitions/errors_virus_scan"
38
+ }
39
+ ]
40
+ }
@@ -58,6 +58,14 @@
58
58
  }
59
59
  ]
60
60
  },
61
+ "errors_virus_scan": {
62
+ "title": "Error messages for 'Virus Scan'",
63
+ "allOf": [
64
+ {
65
+ "$ref": "#/definitions/error_strings"
66
+ }
67
+ ]
68
+ },
61
69
  "min_length": {
62
70
  "title": "Minimum length",
63
71
  "description": "The minimum characters users must enter",
@@ -270,6 +278,66 @@
270
278
  }
271
279
  ]
272
280
  },
281
+ "accept": {
282
+ "title": "Accepted types",
283
+ "description": "Which file types to accept",
284
+ "type": "array",
285
+ "items": {
286
+ "type": "string",
287
+ "enum": [
288
+ "audio/*",
289
+ "image/bmp",
290
+ "text/csv",
291
+ "application/vnd.ms-excel",
292
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
293
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.template",
294
+ "application/vnd.ms-excel.sheet.macroEnabled.12",
295
+ "application/vnd.ms-excel.template.macroEnabled.12",
296
+ "application/vnd.ms-excel.addin.macroEnabled.12",
297
+ "application/vnd.ms-excel.sheet.binary.macroEnabled.12",
298
+ "image/gif",
299
+ "image/*",
300
+ "application/x-iwork-pages-sffpages",
301
+ "image/jpeg",
302
+ "applicattion/pdf",
303
+ "text/plain",
304
+ "image/png",
305
+ "application/vnd.ms-powerpoint",
306
+ "application/vnd.openxmlformats-officedocument.presentationml.presentation",
307
+ "application/vnd.openxmlformats-officedocument.presentationml.template",
308
+ "application/vnd.openxmlformats-officedocument.presentationml.slideshow",
309
+ "application/vnd.ms-powerpoint.addin.macroEnabled.12",
310
+ "application/vnd.ms-powerpoint.presentation.macroEnabled.12",
311
+ "application/vnd.ms-powerpoint.template.macroEnabled.12",
312
+ "application/vnd.ms-powerpoint.slideshow.macroEnabled.12",
313
+ "text/rtf",
314
+ "excel",
315
+ "csv",
316
+ "image/svg+xml",
317
+ "pdf",
318
+ "word",
319
+ "rtf",
320
+ "plaintext",
321
+ "image/tiff",
322
+ "video/*",
323
+ "application/msword",
324
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
325
+ "application/vnd.openxmlformats-officedocument.wordprocessingml.template",
326
+ "application/vnd.ms-word.document.macroEnabled.12",
327
+ "application/vnd.ms-word.template.macroEnabled.12"
328
+ ]
329
+ }
330
+ },
331
+ "max_size": {
332
+ "title": "Maximum size",
333
+ "description": "Maximum file size as human readable string or bytes",
334
+ "type": "string"
335
+ },
336
+ "virus_scan": {
337
+ "title": "Virus scan",
338
+ "description": "Scanning of files for viruses",
339
+ "type": "boolean"
340
+ },
273
341
  "required_bundle": {
274
342
  "properties": {
275
343
  "validation": {
@@ -294,43 +362,6 @@
294
362
  }
295
363
  }
296
364
  },
297
- "upload_bundle": {
298
- "properties": {
299
- "validation": {
300
- "title": "Validation",
301
- "description": "Values for default validation",
302
- "role": "validation",
303
- "properties": {
304
- "accept": {
305
- "title": "Accepted types",
306
- "description": "Which file types to accept",
307
- "type": "array",
308
- "items": {
309
- "type": "string"
310
- }
311
- },
312
- "max_size": {
313
- "title": "Maximum size",
314
- "description": "Maximum file size as human readable string or bytes",
315
- "type": "string"
316
- }
317
- }
318
- },
319
- "errors": {
320
- "title": "Errors",
321
- "description": "Strings to override for default error messages",
322
- "role": "error_strings",
323
- "properties": {
324
- "accept": {
325
- "$ref": "#/definitions/errors_accept"
326
- },
327
- "maxSize": {
328
- "$ref": "#/definitions/errors_max_size"
329
- }
330
- }
331
- }
332
- }
333
- },
334
365
  "string_bundle": {
335
366
  "properties": {
336
367
  "validation": {
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metadata_presenter
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.8
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - MoJ Online
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-06 00:00:00.000000000 Z
11
+ date: 2021-06-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: govuk_design_system_formbuilder
@@ -148,14 +148,14 @@ dependencies:
148
148
  requirements:
149
149
  - - "~>"
150
150
  - !ruby/object:Gem::Version
151
- version: 1.10.0
151
+ version: 1.15.0
152
152
  type: :development
153
153
  prerelease: false
154
154
  version_requirements: !ruby/object:Gem::Requirement
155
155
  requirements:
156
156
  - - "~>"
157
157
  - !ruby/object:Gem::Version
158
- version: 1.10.0
158
+ version: 1.15.0
159
159
  - !ruby/object:Gem::Dependency
160
160
  name: rubocop-govuk
161
161
  requirement: !ruby/object:Gem::Requirement
@@ -255,6 +255,7 @@ files:
255
255
  - app/controllers/metadata_presenter/answers_controller.rb
256
256
  - app/controllers/metadata_presenter/change_answer_controller.rb
257
257
  - app/controllers/metadata_presenter/engine_controller.rb
258
+ - app/controllers/metadata_presenter/file_controller.rb
258
259
  - app/controllers/metadata_presenter/pages_controller.rb
259
260
  - app/controllers/metadata_presenter/service_controller.rb
260
261
  - app/controllers/metadata_presenter/submissions_controller.rb
@@ -263,23 +264,30 @@ files:
263
264
  - app/jobs/metadata_presenter/application_job.rb
264
265
  - app/models/metadata_presenter/component.rb
265
266
  - app/models/metadata_presenter/date_field.rb
267
+ - app/models/metadata_presenter/file_uploader.rb
266
268
  - app/models/metadata_presenter/item.rb
267
269
  - app/models/metadata_presenter/meta.rb
268
270
  - app/models/metadata_presenter/meta_item.rb
269
271
  - app/models/metadata_presenter/metadata.rb
270
272
  - app/models/metadata_presenter/next_page.rb
273
+ - app/models/metadata_presenter/offline_upload_adapter.rb
271
274
  - app/models/metadata_presenter/page.rb
272
275
  - app/models/metadata_presenter/page_answers.rb
273
276
  - app/models/metadata_presenter/service.rb
277
+ - app/models/metadata_presenter/uploaded_file.rb
274
278
  - app/presenters/metadata_presenter/page_answers_presenter.rb
279
+ - app/validators/metadata_presenter/accept_validator.rb
275
280
  - app/validators/metadata_presenter/base_validator.rb
276
281
  - app/validators/metadata_presenter/date_validator.rb
277
282
  - app/validators/metadata_presenter/max_length_validator.rb
283
+ - app/validators/metadata_presenter/max_size_validator.rb
278
284
  - app/validators/metadata_presenter/min_length_validator.rb
279
285
  - app/validators/metadata_presenter/number_validator.rb
280
286
  - app/validators/metadata_presenter/required_validator.rb
287
+ - app/validators/metadata_presenter/upload_validator.rb
281
288
  - app/validators/metadata_presenter/validate_answers.rb
282
289
  - app/validators/metadata_presenter/validate_schema.rb
290
+ - app/validators/metadata_presenter/virus_scan_validator.rb
283
291
  - app/views/errors/404.html
284
292
  - app/views/layouts/metadata_presenter/application.html.erb
285
293
  - app/views/metadata_presenter/attribute/_body.html.erb
@@ -294,6 +302,7 @@ files:
294
302
  - app/views/metadata_presenter/component/_radios.html.erb
295
303
  - app/views/metadata_presenter/component/_text.html.erb
296
304
  - app/views/metadata_presenter/component/_textarea.html.erb
305
+ - app/views/metadata_presenter/component/_upload.html.erb
297
306
  - app/views/metadata_presenter/footer/_meta.html.erb
298
307
  - app/views/metadata_presenter/footer/footer.html.erb
299
308
  - app/views/metadata_presenter/header/show.html.erb
@@ -317,6 +326,7 @@ files:
317
326
  - default_metadata/component/radios.json
318
327
  - default_metadata/component/text.json
319
328
  - default_metadata/component/textarea.json
329
+ - default_metadata/component/upload.json
320
330
  - default_metadata/config/meta.json
321
331
  - default_metadata/config/service.json
322
332
  - default_metadata/definition/checkbox.json
@@ -329,11 +339,14 @@ files:
329
339
  - default_metadata/page/standalone.json
330
340
  - default_metadata/page/start.json
331
341
  - default_metadata/service/base.json
342
+ - default_metadata/string/error.accept.json
332
343
  - default_metadata/string/error.date.json
333
344
  - default_metadata/string/error.max_length.json
345
+ - default_metadata/string/error.max_size.json
334
346
  - default_metadata/string/error.min_length.json
335
347
  - default_metadata/string/error.number.json
336
348
  - default_metadata/string/error.required.json
349
+ - default_metadata/string/error.virus_scan.json
337
350
  - default_text/content.json
338
351
  - fixtures/invalid_content_page.json
339
352
  - fixtures/no_component_page.json
@@ -352,6 +365,7 @@ files:
352
365
  - schemas/component/radios.json
353
366
  - schemas/component/text.json
354
367
  - schemas/component/textarea.json
368
+ - schemas/component/upload.json
355
369
  - schemas/condition/condition.json
356
370
  - schemas/config/meta.json
357
371
  - schemas/config/service.json