renalware-core 2.0.67 → 2.0.68

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 (44) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/renalware/partials/_forms.scss +33 -2
  3. data/app/assets/stylesheets/renalware/partials/_navigation.scss +4 -0
  4. data/app/controllers/renalware/hd/mdm_patients_controller.rb +19 -6
  5. data/app/controllers/renalware/pd/mdm_patients_controller.rb +9 -1
  6. data/app/controllers/renalware/research/studies_controller.rb +6 -1
  7. data/app/controllers/renalware/research/study_participants_controller.rb +13 -11
  8. data/app/models/renalware/hd/mdm_patients_form.rb +1 -0
  9. data/app/models/renalware/hd/mdm_patients_query.rb +20 -4
  10. data/app/models/renalware/patients/mdm_patients_query.rb +1 -1
  11. data/app/models/renalware/patients/search_query.rb +1 -1
  12. data/app/models/renalware/pd/mdm_patients_query.rb +18 -2
  13. data/app/models/renalware/transplants/mdm_patients_query.rb +1 -1
  14. data/app/views/renalware/clinics/appointments/new.html.slim +9 -8
  15. data/app/views/renalware/hd/mdm_patients/_filters.html.slim +3 -2
  16. data/app/views/renalware/hd/mdm_patients/_tabs.html.slim +8 -0
  17. data/app/views/renalware/hd/mdm_patients/index.html.slim +3 -0
  18. data/app/views/renalware/letters/printable_letters/_recipient_address_cover_sheet.html.slim +1 -1
  19. data/app/views/renalware/pd/mdm_patients/_tabs.html.slim +8 -0
  20. data/app/views/renalware/research/studies/_tabs.html.slim +12 -0
  21. data/app/views/renalware/research/studies/edit.html.slim +25 -1
  22. data/app/views/renalware/research/studies/index.html.slim +9 -15
  23. data/app/views/renalware/research/studies/show.html.slim +9 -13
  24. data/app/views/renalware/research/study_participants/_filters.html.slim +1 -1
  25. data/app/views/renalware/research/study_participants/_form.html.slim +18 -43
  26. data/app/views/renalware/research/study_participants/edit.html.slim +7 -1
  27. data/app/views/renalware/research/study_participants/index.html.slim +8 -22
  28. data/app/views/renalware/research/study_participants/new.html.slim +7 -1
  29. data/config/locales/renalware/hd/mdm_patients.yml +4 -0
  30. data/config/locales/renalware/pd/mdm.en.yml +4 -0
  31. data/config/routes.rb +8 -1
  32. data/db/migrate/20190104095254_create_active_storage_tables.active_storage.rb +27 -0
  33. data/lib/renalware/version.rb +1 -1
  34. data/spec/factories/hd/patients.rb +23 -1
  35. data/spec/factories/pd/modality_descriptions.rb +3 -0
  36. data/spec/factories/pd/patients.rb +23 -1
  37. data/spec/support/devise_spec_helper.rb +3 -0
  38. metadata +14 -16
  39. data/app/assets/javascripts/renalware/research.js +0 -18
  40. data/app/views/renalware/research/study_participants/create.js.erb +0 -3
  41. data/app/views/renalware/research/study_participants/new.js.erb +0 -4
  42. data/app/views/renalware/research/study_participants/update.js.erb +0 -3
  43. data/spec/support/capybara.rb +0 -23
  44. data/spec/support/select2_spec_helper.rb +0 -47
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf634cea697775671cc9b95511d93c3927bfaef385d14257daffa16ca86086bb
4
- data.tar.gz: da6403cbe24ea79e5690cb0e767bf83fd3931495950ad2135ffc9b08cad32ce6
3
+ metadata.gz: c551c17f27d4ce7093dcacaa92bb5936b9d9131ecc452fabb288b11a409c42e8
4
+ data.tar.gz: ce9f5588b3f29e82f900ac88d89ace8e11e0535c113b3479edf3d0745dd6d578
5
5
  SHA512:
6
- metadata.gz: d2d4668c9ce60c07e2d66bd2676270342c087292d32737a03a4a5db0f953b6f3339573f1815ba4e0efc939979c67b2de3e5f0192f5d3a4fd7250b9de10b95580
7
- data.tar.gz: 51c70c6a5b0d163669a13f5c3674afabb6dbdfd22093951521210b80d42d860c248a438c13c994b1f4a4cb103ea3969e1d856fd79c5631fb6f73557bb763b160
6
+ metadata.gz: f0e617fd1c72cd5162a23f853647d568296a3dbeb32a023daeadc3b517abee63bc7fe30adc06d8a2328ab0099526afc06a0b98f2a5cc74d942a6db570cf4bce3
7
+ data.tar.gz: 3b90fa1559317b7a89d94b879b147723b2aa47f87d46b84a0360025e49765934b6462ccfe6655fc5f52b22aee5c022555dfd81632126622aeb872751e1880fdb
@@ -3,8 +3,18 @@ textarea::placeholder {
3
3
  color: $form-hint-colour
4
4
  }
5
5
 
6
- .panel.compact {
7
- padding: 0.5rem 1rem;
6
+ .panel {
7
+ p {
8
+ padding-left: 0;
9
+ }
10
+
11
+ &.compact {
12
+ padding: 0.5rem 1rem;
13
+ }
14
+
15
+ .muted {
16
+ color: $dashboard-muted-color;
17
+ }
8
18
  }
9
19
 
10
20
  textarea.monospace {
@@ -434,3 +444,24 @@ fieldset {
434
444
  }
435
445
  }
436
446
  }
447
+
448
+ .panel.danger-zone {
449
+ background-color: $white;
450
+ color: $nhs-red;
451
+
452
+ h4 {
453
+ color: inherit;
454
+ }
455
+
456
+ a {
457
+ color: inherit;
458
+ font-weight: bold;
459
+ background-color: $table-border-color;
460
+
461
+ &:hover,
462
+ &:active {
463
+ background-color: $nhs-red;
464
+ color: $white;
465
+ }
466
+ }
467
+ }
@@ -20,6 +20,10 @@
20
20
  dd {
21
21
  margin: 0;
22
22
  padding: 0;
23
+
24
+ i {
25
+ margin-right: .7rem;
26
+ }
23
27
  }
24
28
  }
25
29
 
@@ -6,12 +6,6 @@ module Renalware
6
6
  module HD
7
7
  class MDMPatientsController < Renalware::MDMPatientsController
8
8
  def index
9
- filter_form = form_object_class.new(filter_form_params)
10
-
11
- query = HD::MDMPatientsQuery.new(
12
- params: filter_form.ransacked_parameters.merge(query_params).with_indifferent_access
13
- )
14
-
15
9
  render_index(filter_form: filter_form,
16
10
  query: query,
17
11
  page_title: t(".page_title"),
@@ -21,6 +15,21 @@ module Renalware
21
15
 
22
16
  private
23
17
 
18
+ def query
19
+ @query ||= begin
20
+ MDMPatientsQuery.new(
21
+ params: filter_form.ransacked_parameters.merge(query_params).with_indifferent_access,
22
+ named_filter: named_filter
23
+ )
24
+ end
25
+ end
26
+
27
+ # Pass in the current path to the filter form so it can render the correct URI in form and
28
+ # reset links.
29
+ def filter_form
30
+ @filter_form ||= form_object_class.new(filter_form_params.merge(url: request.path))
31
+ end
32
+
24
33
  # Permit all attributes on the filter form object. Slightly messy
25
34
  def filter_form_params
26
35
  params.fetch(:filter, {}).permit(form_object_class.permittable_attributes)
@@ -35,6 +44,10 @@ module Renalware
35
44
  params.fetch(:q, {}).permit(:s)
36
45
  end
37
46
 
47
+ def named_filter
48
+ params[:named_filter]
49
+ end
50
+
38
51
  def render_index(filter_form:, **args)
39
52
  presenter = build_presenter(params: params, **args)
40
53
  authorize presenter.patients
@@ -6,10 +6,18 @@ module Renalware
6
6
  module PD
7
7
  class MDMPatientsController < Renalware::MDMPatientsController
8
8
  def index
9
- render_index(query: MDMPatientsQuery.new(q: params[:q]),
9
+ render_index(query: query,
10
10
  page_title: t(".page_title"),
11
11
  view_proc: ->(patient) { patient_pd_mdm_path(patient) })
12
12
  end
13
+
14
+ def query
15
+ @query ||= MDMPatientsQuery.new(q: params[:q], named_filter: named_filter)
16
+ end
17
+
18
+ def named_filter
19
+ params[:named_filter]
20
+ end
13
21
  end
14
22
  end
15
23
  end
@@ -14,6 +14,11 @@ module Renalware
14
14
  render locals: { studies: studies, query: query }
15
15
  end
16
16
 
17
+ def show
18
+ study = find_and_authorize_study
19
+ render locals: { study: study }
20
+ end
21
+
17
22
  def new
18
23
  study = Study.new
19
24
  authorize study
@@ -38,7 +43,7 @@ module Renalware
38
43
  def update
39
44
  study = find_and_authorize_study
40
45
  if study.update_by(current_user, study_params)
41
- redirect_to research_studies_path, notice: success_msg_for("clinical study")
46
+ redirect_to research_study_path(study), notice: success_msg_for("clinical study")
42
47
  else
43
48
  render_edit(study)
44
49
  end
@@ -9,7 +9,9 @@ module Renalware
9
9
 
10
10
  def index
11
11
  authorize StudyParticipant, :index?
12
- render_current_action_with_locals
12
+ query = StudyParticipantsQuery.new(study: study, options: params[:q])
13
+ participants = query.call.page(page).per(per_page)
14
+ render locals: { study: study, participants: participants, query: query.search }
13
15
  end
14
16
 
15
17
  def show
@@ -23,7 +25,10 @@ module Renalware
23
25
  authorize participant
24
26
 
25
27
  if participant.save
26
- render_current_action_with_locals
28
+ redirect_to(
29
+ research_study_participants_path(study),
30
+ notice: success_msg_for("participant")
31
+ )
27
32
  else
28
33
  render_new(participant)
29
34
  end
@@ -50,7 +55,10 @@ module Renalware
50
55
  def update
51
56
  participant = find_and_authorise_participant
52
57
  if participant.update(participant_params_for_update)
53
- render_current_action_with_locals
58
+ redirect_to(
59
+ research_study_participants_path(study),
60
+ notice: success_msg_for("participant")
61
+ )
54
62
  else
55
63
  render_edit(participant)
56
64
  end
@@ -63,17 +71,11 @@ module Renalware
63
71
  end
64
72
 
65
73
  def render_edit(participant)
66
- render :new, locals: { participant: participant }, layout: false
74
+ render :edit, locals: { participant: participant }
67
75
  end
68
76
 
69
77
  def render_new(participant)
70
- render :new, locals: { participant: participant }, layout: false
71
- end
72
-
73
- def render_current_action_with_locals
74
- query = StudyParticipantsQuery.new(study: study, options: params[:q])
75
- participants = query.call.page(page).per(per_page)
76
- render locals: { study: study, participants: participants, query: query.search }
78
+ render :new, locals: { participant: participant }
77
79
  end
78
80
 
79
81
  def study
@@ -14,6 +14,7 @@ module Renalware
14
14
  attribute :hospital_unit_id, Integer
15
15
  attribute :named_nurse_id, Integer
16
16
  attribute :schedule_definition_ids, String # an Integer array in string form e.g. "[1 ,2]"
17
+ attribute :url
17
18
 
18
19
  # The hash returned here is passed into the Ransack #search method later i the ouery object.
19
20
  def ransacked_parameters
@@ -9,18 +9,19 @@ module Renalware
9
9
  include PatientPathologyScopes
10
10
  MODALITY_NAMES = "HD"
11
11
  DEFAULT_SEARCH_PREDICATE = "hgb_date desc"
12
- attr_reader :params
12
+ attr_reader :params, :named_filter
13
13
 
14
- def initialize(params:)
14
+ def initialize(params:, named_filter:)
15
15
  @params = params || {}
16
16
  @params[:s] = DEFAULT_SEARCH_PREDICATE if @params[:s].blank?
17
+ @named_filter = named_filter || :none
17
18
  end
18
19
 
19
20
  def call
20
21
  search.result
21
22
  end
22
23
 
23
- # rubocop:disable Metrics/MethodLength
24
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
24
25
  def search
25
26
  @search ||= begin
26
27
  HD::Patient
@@ -31,13 +32,15 @@ module Renalware
31
32
  .eager_load(hd_profile: [:hospital_unit])
32
33
  .extending(ModalityScopes)
33
34
  .extending(PatientPathologyScopes)
35
+ .extending(NamedFilterScopes)
34
36
  .with_current_pathology
35
37
  .with_registration_statuses
36
38
  .with_current_modality_matching(MODALITY_NAMES)
39
+ .public_send(named_filter.to_s)
37
40
  .ransack(params)
38
41
  end
39
42
  end
40
- # rubocop:enable Metrics/MethodLength
43
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
41
44
 
42
45
  # Module to allow us to mixin ransackers
43
46
  module QueryablePatient
@@ -63,5 +66,18 @@ module Renalware
63
66
  end
64
67
  end
65
68
  end
69
+
70
+ # Module to allow us to mixin named filters like on_worryboard which correspond to tabs
71
+ # on the UI for example.
72
+ module NamedFilterScopes
73
+ def none
74
+ self # NOOP - aka 'all'
75
+ end
76
+
77
+ def patients_on_the_worry_board
78
+ joins("RIGHT OUTER JOIN patient_worries ON patient_worries.patient_id = patients.id")
79
+ end
80
+ alias_method :on_worryboard, :patients_on_the_worry_board
81
+ end
66
82
  end
67
83
  end
@@ -25,7 +25,7 @@ module Renalware
25
25
  .extending(PatientPathologyScopes)
26
26
  .with_current_pathology
27
27
  .with_current_modality_matching(modality_names)
28
- .search(q)
28
+ .ransack(q)
29
29
  end
30
30
  end
31
31
  end
@@ -31,7 +31,7 @@ module Renalware
31
31
  def search
32
32
  @search ||= begin
33
33
  scope
34
- .search(identity_match: term).tap do |search|
34
+ .ransack(identity_match: term).tap do |search|
35
35
  search.sorts = %w(family_name given_name)
36
36
  end
37
37
  end
@@ -7,31 +7,47 @@ module Renalware
7
7
  include PatientPathologyScopes
8
8
  MODALITY_NAMES = "PD"
9
9
  DEFAULT_SEARCH_PREDICATE = "hgb_date desc"
10
- attr_reader :q, :relation
10
+ attr_reader :q, :relation, :named_filter
11
11
 
12
- def initialize(relation: PD::Patient.all, q:)
12
+ def initialize(relation: PD::Patient.all, q:, named_filter: nil)
13
13
  @q = q || {}
14
14
  @q[:s] = DEFAULT_SEARCH_PREDICATE if @q[:s].blank?
15
15
  @relation = relation
16
+ @named_filter = named_filter || :none
16
17
  end
17
18
 
18
19
  def call
19
20
  search.result
20
21
  end
21
22
 
23
+ # rubocop:disable Metrics/MethodLength
22
24
  def search
23
25
  @search ||= begin
24
26
  relation
25
27
  .extending(PatientTransplantScopes)
26
28
  .extending(ModalityScopes)
27
29
  .extending(PatientPathologyScopes)
30
+ .extending(NamedFilterScopes)
28
31
  .with_current_modality_matching(MODALITY_NAMES)
29
32
  .with_current_pathology
30
33
  .with_registration_statuses
31
34
  .left_outer_joins(:current_observation_set)
35
+ .public_send(named_filter.to_s)
32
36
  .ransack(q)
33
37
  end
34
38
  end
39
+ # rubocop:enable Metrics/MethodLength
40
+ end
41
+
42
+ module NamedFilterScopes
43
+ def none
44
+ self # NOOP
45
+ end
46
+
47
+ def patients_on_the_worry_board
48
+ joins("RIGHT OUTER JOIN patient_worries ON patient_worries.patient_id = patients.id")
49
+ end
50
+ alias_method :on_worryboard, :patients_on_the_worry_board
35
51
  end
36
52
  end
37
53
  end
@@ -9,7 +9,7 @@ module Renalware
9
9
  class MDMPatientsQuery
10
10
  include ModalityScopes
11
11
  include PatientPathologyScopes
12
- MODALITY_NAMES = ["Transplant"].freeze
12
+ MODALITY_NAMES = "Transplant"
13
13
  DEFAULT_SEARCH_PREDICATE = "hgb_date DESC"
14
14
  attr_reader :q, :relation, :named_filter
15
15
 
@@ -12,14 +12,15 @@
12
12
  / the blank option. Selecting index 1 fails silently if there is nothing there (no patient
13
13
  / selected yet) otherwise it will display the selected patient who will always be
14
14
  / at option index 1.
15
- = f.input :patient_id,
16
- wrapper: :horizontal_medium,
17
- collection: [[appointment.patient&.to_s(:long), appointment.patient&.id]],
18
- selected: 1,
19
- input_html: { \
20
- class: "patient-id-select2 patient-ajax-search",
21
- data: { "ajax--url" => search_patients_path(format: :json),
22
- placeholder: "Search by patient name or hospital/NHS no." } \
15
+ #patient-select2
16
+ = f.input :patient_id,
17
+ wrapper: :horizontal_medium,
18
+ collection: [[appointment.patient&.to_s(:long), appointment.patient&.id]],
19
+ selected: 1,
20
+ input_html: { \
21
+ class: "patient-id-select2 patient-ajax-search",
22
+ data: { "ajax--url" => search_patients_path(format: :json),
23
+ placeholder: "Search by patient name or hospital/NHS no." } \
23
24
  }
24
25
 
25
26
  = f.input :clinic_id,
@@ -1,6 +1,7 @@
1
+
1
2
  = simple_form_for filter_form,
2
3
  as: :filter,
3
- url: hd_mdm_patients_path,
4
+ url: filter_form.url,
4
5
  method: :get,
5
6
  html: { autocomplete: "off" },
6
7
  wrapper: :horizontal_form do |f|
@@ -27,4 +28,4 @@
27
28
  .medium-2.columns.actions
28
29
  = f.submit t("helpers.submit.filter"), class: "button", name: nil
29
30
  span= " or "
30
- = link_to t("helpers.reset"), hd_mdm_patients_path
31
+ = link_to t("helpers.reset"), filter_form.url
@@ -0,0 +1,8 @@
1
+ - named_filter_param = params[:named_filter]
2
+
3
+ dl.sub-nav
4
+ dd(class=("active" unless named_filter_param.present?))
5
+ = link_to t(".tab.all"), hd_mdm_patients_path
6
+ - %i(on_worryboard).each do |filter|
7
+ dd(class=("active" if named_filter_param == filter.to_s))
8
+ = link_to t(".tab.#{filter}"), hd_filtered_mdm_patients_path(named_filter: filter)
@@ -1,6 +1,9 @@
1
1
  = content_for(:filters) do
2
2
  = render_if_exists "filters", presenter: presenter, filter_form: filter_form
3
3
 
4
+ = content_for(:tabs) do
5
+ = render_if_exists "tabs", presenter: presenter
6
+
4
7
  = within_admin_layout(title: presenter.page_title)
5
8
  = render "table", presenter: presenter
6
9
  = paginate presenter.patients
@@ -20,7 +20,7 @@ scss:
20
20
  .address-in-window {
21
21
  position: absolute;
22
22
  left: 60px;
23
- top: 75px;
23
+ top: 130px;
24
24
  width: 50%;
25
25
  height: 50%;
26
26
  line-height: 1.2em;
@@ -0,0 +1,8 @@
1
+ - named_filter_param = params[:named_filter]
2
+
3
+ dl.sub-nav
4
+ dd(class=("active" unless named_filter_param.present?))
5
+ = link_to t(".tab.all"), pd_mdm_patients_path
6
+ - %i(on_worryboard).each do |filter|
7
+ dd(class=("active" if named_filter_param == filter.to_s))
8
+ = link_to t(".tab.#{filter}"), pd_filtered_mdm_patients_path(named_filter: filter)
@@ -0,0 +1,12 @@
1
+ dl.sub-nav
2
+ dd= link_to "Summary", research_study_path(study)
3
+ dd
4
+ = link_to edit_research_study_path(study) do
5
+ i.fas.fa-cogs
6
+ | Settings
7
+ dd
8
+ = link_to research_study_participants_path(study) do
9
+ i.fas.fa-users
10
+ | Participants
11
+ / dd(class=("active" if params.fetch(:q, {})[:expired]))
12
+ / = link_to "Members", admin_expired_users_path
@@ -1,5 +1,29 @@
1
- = within_admin_layout(title: "Edit",
1
+ = content_for(:tabs) do
2
+ = render "tabs", study: study
3
+
4
+ = within_admin_layout(title: study.code,
2
5
  breadcrumbs: breadcrumb_for("Clinical Studies",
3
6
  research_studies_path)) do
4
7
 
5
8
  = render "form", study: study
9
+
10
+ br
11
+ hr
12
+ br
13
+ .panel.danger-zone
14
+ h4 Danger zone
15
+ br
16
+ - super_admin = current_user.has_role?(:super_admin)
17
+ - if super_admin
18
+ p= link_to "Delete this study",
19
+ research_study_path(study),
20
+ method: :delete,
21
+ data: { confirm: "Are you sure you want to delete this study?", disable: true },
22
+ class: "button"
23
+ - else
24
+ p= link_to "Delete this study",
25
+ "#",
26
+ class: "button",
27
+ disabled: true
28
+ p
29
+ i You need to have the super_admin role to delete a study
@@ -8,30 +8,24 @@
8
8
  table
9
9
  thead
10
10
  tr
11
- th.col-width-date= sort_link(query, :started_on, "Started")
12
- th.col-width-date= sort_link(query, :terminated_on, "Terminated")
11
+ th
13
12
  th.col-width-small= sort_link(query, :code, "Code")
14
13
  th Description
15
14
  th= sort_link(query, :code, "Leader")
16
15
  th Participants
17
- th
16
+ th.col-width-date= sort_link(query, :started_on, "Started")
17
+ th.col-width-date= sort_link(query, :terminated_on, "Terminated")
18
+
18
19
  tbody
19
20
  - studies.each do |study|
20
21
  tr
21
- td= l(study.started_on)
22
- td= l(study.terminated_on)
22
+ td.actions.left
23
+ = link_to "View", research_study_path(study)
23
24
  td= study.code
24
- td= study.description
25
+ td= study.description.truncate(60)
25
26
  td= study.leader
26
27
  td= study.participants.count
27
- td.actions
28
- = link_to "Delete",
29
- research_study_path(study),
30
- method: :delete,
31
- data: { confirm: "Are you sure you want to delete this study?" }
32
- = " | "
33
- = link_to "Edit", edit_research_study_path(study)
34
- = " | "
35
- = link_to "View Participants", research_study_participants_path(study)
28
+ td= l(study.started_on)
29
+ td= l(study.terminated_on)
36
30
 
37
31
  = paginate studies
@@ -1,18 +1,14 @@
1
- = content_for(:actions) do
2
- = link_to("Add Participant", new_research_study_participant_path(study), class: :button)
1
+ = content_for(:tabs) do
2
+ = render "tabs", study: study
3
3
 
4
4
  = within_admin_layout(title: study.code,
5
5
  breadcrumbs: breadcrumb_for("Clinical Studies",
6
6
  research_studies_path)) do
7
7
 
8
- p= study.description
9
-
10
- table
11
- thead
12
- tr
13
- th Patient
14
- th
15
- tbody
16
- - study.participants.each do |participant|
17
- tr
18
- td= participant
8
+ - if study.description.present?
9
+ p.panel.radius.compact
10
+ = "Description: #{study.description}"
11
+ br
12
+ = "Started on: #{l(study.started_on)}"
13
+ br
14
+ = "Leader: #{study.leader}"
@@ -8,6 +8,6 @@
8
8
  = f.input :identity_match, label: "Search by Hosp/NHS no or name"
9
9
 
10
10
  .columns.medium-4.actions.end
11
- = f.submit t("helpers.submit.filter"), class: "button", name: nil
11
+ = f.submit t("helpers.submit.filter"), class: "button secondary", name: nil
12
12
  span= " or "
13
13
  = link_to t("helpers.reset"), research_study_participants_path(study)
@@ -1,44 +1,19 @@
1
- ruby:
2
- url = if participant.new_record?
3
- research_study_participants_path(participant.study)
4
- else
5
- research_study_participant_path(participant.study, participant)
6
- end
7
- .modal
8
- .modal__header
9
- h2= participant.persisted? ? "Edit Patient" : "Add Patient"
10
- = render "renalware/shared/modal_close_link"
1
+ = simple_form_for(participant,
2
+ url: url,
3
+ html: { autocomplete: "off" },
4
+ wrapper: :horizontal_form) do |f|
5
+ - if participant.persisted?
6
+ h5= participant.patient.to_s(:long)
7
+ - else
8
+ #patient-select2
9
+ = f.input :participant_id,
10
+ collection: [],
11
+ input_html: { \
12
+ class: "patient-id-select2 patient-ajax-search",
13
+ data: { "ajax--url" => search_patients_path(format: :json),
14
+ placeholder: "Search by patient name or hospital/NHS no." } \
15
+ }
11
16
 
12
- .modal__body
13
- = render "renalware/shared/errors", model: participant
14
-
15
- = simple_form_for(participant,
16
- url: url,
17
- remote: true,
18
- html: { autocomplete: "off" },
19
- wrapper: :horizontal_form) do |f|
20
- - if participant.persisted?
21
- h5= participant.patient.to_s(:long)
22
- - else
23
- = f.input :participant_id,
24
- collection: [],
25
- input_html: { \
26
- class: "patient-id-select2 patient-ajax-search",
27
- data: { "ajax--url" => search_patients_path(format: :json),
28
- placeholder: "Search by patient name or hospital/NHS no." } \
29
- }
30
-
31
- = f.input :joined_on, as: :date_picker
32
- = f.input :left_on, as: :date_picker
33
-
34
- = f.submit "Add", class: :button
35
- span= " or "
36
- = link_to "Cancel",
37
- "#",
38
- "aria-label" => "Close",
39
- class: "reveal-modal-close"
40
-
41
- .modal__footer
42
-
43
- javascript:
44
- $(document).ready(Renalware.Research.init);
17
+ = f.input :joined_on, as: :date_picker
18
+ = f.input :left_on, as: :date_picker
19
+ = save_or_cancel(form: f, back_path: research_study_participants_path(participant.study))
@@ -1 +1,7 @@
1
- = render "form", participant: participant
1
+ = within_admin_layout(title: "Edit",
2
+ breadcrumbs: breadcrumb_for("Clinical Studies",
3
+ research_studies_path)) do
4
+
5
+ = render "form",
6
+ participant: participant,
7
+ url: research_study_participant_path(participant.study, participant)
@@ -1,28 +1,14 @@
1
- = content_for(:actions) do
2
- = link_to("Add",
3
- new_research_study_participant_path,
4
- id: "add-study-participants",
5
- class: :button,
6
- data: { "reveal-id" => "study-participant-modal", "reveal-ajax" => "true" })
7
-
8
1
  = content_for(:filters) do
2
+ = link_to(new_research_study_participant_path, class: :button) do
3
+ i.fas.fa-plus
4
+ | Add
9
5
  = render "filters", study: study, query: query
10
6
 
11
- = within_admin_layout(\
12
- title: "Participants",
13
- breadcrumbs: [\
14
- breadcrumb_for("Clinical Studies", research_studies_path),
15
- breadcrumb_for(study.code, edit_research_study_path(study))\
16
- ]) do
7
+ = content_for(:tabs) do
8
+ = render "renalware/research/studies/tabs", study: study
17
9
 
18
- - if study.description.present?
19
- p.panel.radius.compact
20
- = "Description: #{study.description}"
21
- br
22
- = "Started on: #{l(study.started_on)}"
23
- br
24
- = "Leader: #{study.leader}"
10
+ = within_admin_layout(\
11
+ title: study.code,
12
+ breadcrumbs: breadcrumb_for("Clinical Studies", research_studies_path)) do
25
13
 
26
14
  = render "table", study: study, participants: participants, query: query
27
-
28
- #study-participant-modal.reveal-modal.small(data-reveal)
@@ -1 +1,7 @@
1
- = render "form", participant: participant
1
+ = within_admin_layout(title: "Add Participant",
2
+ breadcrumbs: breadcrumb_for("Clinical Studies",
3
+ research_studies_path)) do
4
+
5
+ = render "form",
6
+ participant: participant,
7
+ url: research_study_participants_path(participant.study)
@@ -37,3 +37,7 @@ en:
37
37
  cre: CRE
38
38
  cre_date: CRE Date
39
39
  egfr: EGFR
40
+ tabs:
41
+ tab:
42
+ all: All
43
+ on_worryboard: On Worryboard
@@ -4,3 +4,7 @@ en:
4
4
  mdm_patients:
5
5
  index:
6
6
  page_title: PD MDM Patients
7
+ tabs:
8
+ tab:
9
+ all: All
10
+ on_worryboard: On Worryboard
@@ -95,7 +95,7 @@ Renalware::Engine.routes.draw do
95
95
  end
96
96
 
97
97
  namespace :research do
98
- resources :studies, except: :show do
98
+ resources :studies do
99
99
  resources :participants, controller: :study_participants
100
100
  end
101
101
  end
@@ -162,6 +162,10 @@ Renalware::Engine.routes.draw do
162
162
  resources :dialysates, except: :show
163
163
  resource :ongoing_sessions, only: :show
164
164
  resources :mdm_patients, only: :index
165
+ resources :mdm_patients, only: :index
166
+ constraints(named_filter: /(on_worryboard)/) do
167
+ get "mdm_patients/:named_filter", to: "mdm_patients#index", as: :filtered_mdm_patients
168
+ end
165
169
  resources :unmet_preferences, only: :index
166
170
  resources :units, only: [] do
167
171
  resources :stations do
@@ -240,6 +244,9 @@ Renalware::Engine.routes.draw do
240
244
  resources :bag_types, except: [:show]
241
245
  resources :infection_organisms
242
246
  resources :mdm_patients, only: :index
247
+ constraints(named_filter: /(on_worryboard)/) do
248
+ get "mdm_patients/:named_filter", to: "mdm_patients#index", as: :filtered_mdm_patients
249
+ end
243
250
  end
244
251
 
245
252
  namespace :renal do
@@ -0,0 +1,27 @@
1
+ # This migration comes from active_storage (originally 20170806125915)
2
+ class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
3
+ def change
4
+ create_table :active_storage_blobs do |t|
5
+ t.string :key, null: false
6
+ t.string :filename, null: false
7
+ t.string :content_type
8
+ t.text :metadata
9
+ t.bigint :byte_size, null: false
10
+ t.string :checksum, null: false
11
+ t.datetime :created_at, null: false
12
+
13
+ t.index [:key], unique: true
14
+ end
15
+
16
+ create_table :active_storage_attachments do |t|
17
+ t.string :name, null: false
18
+ t.references :record, null: false, polymorphic: true, index: false
19
+ t.references :blob, null: false
20
+
21
+ t.datetime :created_at, null: false
22
+
23
+ t.index [:record_type, :record_id, :name, :blob_id], name: "index_active_storage_attachments_uniqueness", unique: true
24
+ t.foreign_key :active_storage_blobs, column: :blob_id
25
+ end
26
+ end
27
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Renalware
4
- VERSION = "2.0.67"
4
+ VERSION = "2.0.68"
5
5
  end
@@ -1,5 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  FactoryBot.define do
4
- factory :hd_patient, class: "Renalware::HD::Patient", parent: :patient
4
+ factory :hd_patient, class: "Renalware::HD::Patient", parent: :patient do
5
+ trait :with_hd_modality do
6
+ after(:create) do |instance|
7
+ # This a rather clumsy approach to trying to re-use the set_modality helper
8
+ # in PatientsSpecHelper; we can't include the module here so I am creating
9
+ # a contrived class so I can mix in PatientsSpecHelper.
10
+ # Other options here
11
+ # https://github.com/thoughtbot/factory_bot/issues/564#issuecomment-157669866
12
+ class ModalityMaker
13
+ include PatientsSpecHelper
14
+
15
+ def call(patient)
16
+ set_modality(
17
+ patient: patient,
18
+ modality_description: FactoryBot.create(:hd_modality_description),
19
+ by: patient.created_by
20
+ )
21
+ end
22
+ end
23
+ ModalityMaker.new.call(instance)
24
+ end
25
+ end
26
+ end
5
27
  end
@@ -2,6 +2,9 @@
2
2
 
3
3
  FactoryBot.define do
4
4
  factory :pd_modality_description, class: "Renalware::PD::ModalityDescription" do
5
+ initialize_with do
6
+ Renalware::PD::ModalityDescription.find_or_create_by!(name: name)
7
+ end
5
8
  name { "PD" }
6
9
  end
7
10
  end
@@ -1,5 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  FactoryBot.define do
4
- factory :pd_patient, class: "Renalware::PD::Patient", parent: :patient
4
+ factory :pd_patient, class: "Renalware::PD::Patient", parent: :patient do
5
+ trait :with_pd_modality do
6
+ after(:create) do |instance|
7
+ # This a rather clumsy approach to trying to re-use the set_modality helper
8
+ # in PatientsSpecHelper; we can't include the module here so I am creating
9
+ # a contrived class so I can mix in PatientsSpecHelper.
10
+ # Other options here
11
+ # https://github.com/thoughtbot/factory_bot/issues/564#issuecomment-157669866
12
+ class ModalityMaker
13
+ include PatientsSpecHelper
14
+
15
+ def call(patient)
16
+ set_modality(
17
+ patient: patient,
18
+ modality_description: FactoryBot.create(:pd_modality_description),
19
+ by: patient.created_by
20
+ )
21
+ end
22
+ end
23
+ ModalityMaker.new.call(instance)
24
+ end
25
+ end
26
+ end
5
27
  end
@@ -8,6 +8,9 @@ RSpec.configure do |config|
8
8
  config.include LoginMacros, type: :controller
9
9
 
10
10
  config.include Warden::Test::Helpers, type: :feature
11
+ config.include Warden::Test::Helpers, type: :system
12
+ config.include Devise::Test::IntegrationHelpers, type: :system
13
+ config.include LoginMacros, type: :system
11
14
  config.include LoginMacros, type: :feature
12
15
 
13
16
  config.include Warden::Test::Helpers, type: :request
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: renalware-core
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.67
4
+ version: 2.0.68
5
5
  platform: ruby
6
6
  authors:
7
7
  - Airslie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-02 00:00:00.000000000 Z
11
+ date: 2019-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_type
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.27.0
33
+ version: 0.28.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.27.0
40
+ version: 0.28.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: ahoy_matey
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -282,14 +282,14 @@ dependencies:
282
282
  requirements:
283
283
  - - "~>"
284
284
  - !ruby/object:Gem::Version
285
- version: 5.3.1
285
+ version: 5.6.1
286
286
  type: :runtime
287
287
  prerelease: false
288
288
  version_requirements: !ruby/object:Gem::Requirement
289
289
  requirements:
290
290
  - - "~>"
291
291
  - !ruby/object:Gem::Version
292
- version: 5.3.1
292
+ version: 5.6.1
293
293
  - !ruby/object:Gem::Dependency
294
294
  name: foundation-rails
295
295
  requirement: !ruby/object:Gem::Requirement
@@ -310,14 +310,14 @@ dependencies:
310
310
  requirements:
311
311
  - - "~>"
312
312
  - !ruby/object:Gem::Version
313
- version: 5.2.3
313
+ version: 5.2.5
314
314
  type: :runtime
315
315
  prerelease: false
316
316
  version_requirements: !ruby/object:Gem::Requirement
317
317
  requirements:
318
318
  - - "~>"
319
319
  - !ruby/object:Gem::Version
320
- version: 5.2.3
320
+ version: 5.2.5
321
321
  - !ruby/object:Gem::Dependency
322
322
  name: hashdiff
323
323
  requirement: !ruby/object:Gem::Requirement
@@ -758,14 +758,14 @@ dependencies:
758
758
  requirements:
759
759
  - - "~>"
760
760
  - !ruby/object:Gem::Version
761
- version: 2.0.1
761
+ version: 2.0.5
762
762
  type: :runtime
763
763
  prerelease: false
764
764
  version_requirements: !ruby/object:Gem::Requirement
765
765
  requirements:
766
766
  - - "~>"
767
767
  - !ruby/object:Gem::Version
768
- version: 2.0.1
768
+ version: 2.0.5
769
769
  - !ruby/object:Gem::Dependency
770
770
  name: slim-rails
771
771
  requirement: !ruby/object:Gem::Requirement
@@ -986,7 +986,6 @@ files:
986
986
  - app/assets/javascripts/renalware/problems.js
987
987
  - app/assets/javascripts/renalware/renal.js
988
988
  - app/assets/javascripts/renalware/reporting.js.erb
989
- - app/assets/javascripts/renalware/research.js
990
989
  - app/assets/javascripts/renalware/searchables.js
991
990
  - app/assets/javascripts/renalware/select2-ajax-search.js
992
991
  - app/assets/javascripts/renalware/session_timeout_redirect.js.erb
@@ -2240,6 +2239,7 @@ files:
2240
2239
  - app/views/renalware/hd/mdm_patients/_filters.html.slim
2241
2240
  - app/views/renalware/hd/mdm_patients/_patient.html.slim
2242
2241
  - app/views/renalware/hd/mdm_patients/_table.html.slim
2242
+ - app/views/renalware/hd/mdm_patients/_tabs.html.slim
2243
2243
  - app/views/renalware/hd/mdm_patients/index.html.slim
2244
2244
  - app/views/renalware/hd/ongoing_sessions/_filters.html.slim
2245
2245
  - app/views/renalware/hd/ongoing_sessions/_session.html.slim
@@ -2587,6 +2587,7 @@ files:
2587
2587
  - app/views/renalware/pd/infection_organisms/update.js.erb
2588
2588
  - app/views/renalware/pd/mdm/_summary.html.slim
2589
2589
  - app/views/renalware/pd/mdm/_top.html.slim
2590
+ - app/views/renalware/pd/mdm_patients/_tabs.html.slim
2590
2591
  - app/views/renalware/pd/peritonitis_episodes/_details.html.slim
2591
2592
  - app/views/renalware/pd/peritonitis_episodes/_fields.html.slim
2592
2593
  - app/views/renalware/pd/peritonitis_episodes/_form.html.slim
@@ -2663,6 +2664,7 @@ files:
2663
2664
  - app/views/renalware/research/_alerts.html.slim
2664
2665
  - app/views/renalware/research/studies/_filters.html.slim
2665
2666
  - app/views/renalware/research/studies/_form.html.slim
2667
+ - app/views/renalware/research/studies/_tabs.html.slim
2666
2668
  - app/views/renalware/research/studies/edit.html.slim
2667
2669
  - app/views/renalware/research/studies/index.html.slim
2668
2670
  - app/views/renalware/research/studies/new.html.slim
@@ -2670,12 +2672,9 @@ files:
2670
2672
  - app/views/renalware/research/study_participants/_filters.html.slim
2671
2673
  - app/views/renalware/research/study_participants/_form.html.slim
2672
2674
  - app/views/renalware/research/study_participants/_table.html.slim
2673
- - app/views/renalware/research/study_participants/create.js.erb
2674
2675
  - app/views/renalware/research/study_participants/edit.html.slim
2675
2676
  - app/views/renalware/research/study_participants/index.html.slim
2676
2677
  - app/views/renalware/research/study_participants/new.html.slim
2677
- - app/views/renalware/research/study_participants/new.js.erb
2678
- - app/views/renalware/research/study_participants/update.js.erb
2679
2678
  - app/views/renalware/shared/_attributes_group.html.slim
2680
2679
  - app/views/renalware/shared/_attributes_list.html.slim
2681
2680
  - app/views/renalware/shared/_error_messages.html.slim
@@ -3384,6 +3383,7 @@ files:
3384
3383
  - db/migrate/20181126090401_add_warnings_to_hd_transmission_logs.rb
3385
3384
  - db/migrate/20181126123745_refresh_hd_grouped_transmission_logs_view.rb
3386
3385
  - db/migrate/20181217124025_change_ukrdc_transmission_log_error_type.rb
3386
+ - db/migrate/20190104095254_create_active_storage_tables.active_storage.rb
3387
3387
  - db/seeds.rb
3388
3388
  - db/seeds/default/accesses/access_pd_catheter_insertion_techniques.csv
3389
3389
  - db/seeds/default/accesses/access_pd_catheter_insertion_techniques.rb
@@ -3705,7 +3705,6 @@ files:
3705
3705
  - spec/factories/transplants/registrations.rb
3706
3706
  - spec/factories/virology/patients.rb
3707
3707
  - spec/factories/virology/vaccinations.rb
3708
- - spec/support/capybara.rb
3709
3708
  - spec/support/capybara_helper.rb
3710
3709
  - spec/support/database_functions_spec_helper.rb
3711
3710
  - spec/support/date_helpers.rb
@@ -3726,7 +3725,6 @@ files:
3726
3725
  - spec/support/patients_spec_helper.rb
3727
3726
  - spec/support/pundit_matcher.rb
3728
3727
  - spec/support/roles_spec_helper.rb
3729
- - spec/support/select2_spec_helper.rb
3730
3728
  - spec/support/select_date_spec_helper.rb
3731
3729
  - spec/support/shared_contexts/a_global_rule_set.rb
3732
3730
  - spec/support/shared_examples/accountable_examples.rb
@@ -1,18 +0,0 @@
1
- var Renalware = typeof Renalware === 'undefined' ? {} : Renalware;
2
-
3
- Renalware.Research = (function() {
4
- var focusPatientInput = function() {
5
- $('.patient-ajax-search').select2('open');
6
- $('select2-patient-ajax-search-container .select2-search__field').focus();
7
- };
8
-
9
- return {
10
- init: function () {
11
- initDatepickersIn(".modal");
12
- Renalware.PatientSearch.init();
13
- focusPatientInput();
14
- }
15
- };
16
- }());
17
-
18
- $(document).on('opened.fndtn.reveal', '#study-participant-modal', Renalware.Research.init);
@@ -1,3 +0,0 @@
1
- <%= refresh(".flash-message", partial: "renalware/shared/flash_messages", locals: local_assigns) %>
2
- $(".study-participants-table").replaceWith("<%= j(render 'table', **local_assigns) %>");
3
- $("#study-participant-modal").foundation('reveal', 'close');
@@ -1,4 +0,0 @@
1
- // We render this view if there was a validation error submitting the foundation reveal modal.
2
- // Replace the original content so that error messages are displayed.
3
- var modal = $("#study-participant-modal")
4
- $(modal).html("<%= j(render 'form', participant: participant) %>");
@@ -1,3 +0,0 @@
1
- <%= refresh(".flash-message", partial: "renalware/shared/flash_messages", locals: local_assigns) %>
2
- $(".study-participants-table").replaceWith("<%= j(render 'table', **local_assigns) %>");
3
- $("#study-participant-modal").foundation('reveal', 'close');
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # # frozen_string_literal: true
4
- if defined?(Capybara)
5
- Capybara.register_driver(:headless_chrome) do |app|
6
- capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
7
- chromeOptions: { args: %w(headless disable-gpu window-size=1366,1768) }
8
- )
9
-
10
- Capybara::Selenium::Driver.new(
11
- app,
12
- browser: :chrome,
13
- desired_capabilities: capabilities
14
- )
15
- end
16
-
17
- if RUBY_PLATFORM.match?(/darwin/)
18
- Capybara::Screenshot.register_driver(:headless_chrome) do |driver, path|
19
- driver.browser.save_screenshot(path)
20
- end
21
- end
22
- Capybara.javascript_driver = :headless_chrome
23
- end
@@ -1,47 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Select2SpecHelper
4
- def select2(value, opts)
5
- scope = opts[:from]
6
- select2_container = first("#{scope} + .select2-container")
7
- select2_container.first(".select2-selection").click
8
-
9
- first("input.select2-search__field").set(value)
10
- page.execute_script(%|$("#{scope} ~ input.select2-search__field:visible").keyup();|)
11
- body = find(:xpath, "//body")
12
- matches = body.find_all(".select2-results li", text: value)
13
- matches.last.click
14
- end
15
-
16
- # select2_ajax helper to make capybara work with ajax-enabled Select2 elements
17
- # assumes 'placeholder' option is used in Select2 (if it is using ajax, it should be)
18
- #
19
- # usage:
20
- #
21
- # it "should have a select2 field for searching by team name" do
22
- # @team = Factory :team
23
- # select2_ajax @team.name, from: "Select a Team", minlength: 4
24
- # click_button "Join"
25
- # page.should have_content "You are now on '#{@team.name}'."
26
- # end
27
- # Thx to https://gist.github.com/sbeam/3849340
28
- def select2_ajax(value, options = {})
29
- if !options.is_a?(Hash) || !options.key?(:from)
30
- raise "Must pass a hash containing 'from'"
31
- end
32
-
33
- placeholder = options[:from]
34
- minlength = options[:minlength] || 4
35
-
36
- # click_link placeholder
37
-
38
- page.find(:xpath, "//*[text()='#{placeholder}']").click
39
-
40
- js = %Q|container = $('.select2-container:contains("#{placeholder}")');
41
- $('input[type=text]', container).val('#{value[0, minlength]}').trigger('keyup');
42
- window.setTimeout( function() {
43
- $('li:contains("#{value}")', container).click();
44
- }, 5000);|
45
- page.execute_script(js)
46
- end
47
- end