renalware-core 2.0.132 → 2.0.133

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/renalware/core.js.erb +1 -1
  3. data/app/assets/stylesheets/renalware/core.scss +1 -1
  4. data/app/assets/stylesheets/renalware/modules/_clinics.scss +1 -2
  5. data/app/assets/stylesheets/renalware/modules/_patients.scss +1 -1
  6. data/app/assets/stylesheets/renalware/partials/_dashboards.scss +15 -0
  7. data/app/components/renalware/application_component.rb +22 -0
  8. data/app/components/renalware/events/biopsies_component.html.slim +14 -0
  9. data/app/components/renalware/events/biopsies_component.rb +20 -0
  10. data/app/components/renalware/letters/letters_in_progress_component.html.slim +8 -0
  11. data/app/components/renalware/letters/letters_in_progress_component.rb +32 -0
  12. data/app/components/renalware/letters/unread_electronic_ccs_component.html.slim +7 -0
  13. data/app/components/renalware/letters/unread_electronic_ccs_component.rb +24 -0
  14. data/app/components/renalware/messaging/unread_messages_component.html.slim +11 -0
  15. data/app/components/renalware/messaging/unread_messages_component.rb +24 -0
  16. data/app/components/renalware/patients/bookmarks_component.html.slim +11 -0
  17. data/app/components/renalware/patients/bookmarks_component.rb +22 -0
  18. data/app/controllers/renalware/clinical/body_compositions_controller.rb +1 -1
  19. data/app/controllers/renalware/pathology/code_groups_controller.rb +44 -0
  20. data/app/controllers/renalware/transplants/wait_lists_controller.rb +17 -8
  21. data/app/models/renalware/clinical/body_composition.rb +7 -0
  22. data/app/models/renalware/hd/mdm_patients_query.rb +10 -1
  23. data/app/models/renalware/pathology/code_group.rb +10 -3
  24. data/app/models/renalware/pathology/code_group_membership.rb +2 -0
  25. data/app/models/renalware/pathology/current_observation_set.rb +16 -3
  26. data/app/models/renalware/pathology/observations_jsonb_serializer.rb +1 -1
  27. data/app/models/renalware/pathology/version.rb +11 -0
  28. data/app/models/renalware/system/component.rb +25 -0
  29. data/app/models/renalware/system/dashboard.rb +20 -0
  30. data/app/models/renalware/system/dashboard_component.rb +17 -0
  31. data/app/models/renalware/transplants.rb +8 -1
  32. data/app/models/renalware/transplants/registrations/wait_list_form.rb +16 -0
  33. data/app/models/renalware/transplants/registrations/wait_list_query.rb +17 -3
  34. data/app/models/renalware/ukrdc/incoming/file_list.rb +1 -1
  35. data/app/models/renalware/ukrdc/incoming/import_surveys.rb +16 -0
  36. data/app/models/renalware/ukrdc/outgoing/rendering/base.rb +22 -0
  37. data/app/models/renalware/ukrdc/outgoing/rendering/dialysis_session.rb +2 -2
  38. data/app/models/renalware/ukrdc/outgoing/rendering/hd_session_observations.rb +1 -1
  39. data/app/models/renalware/user.rb +9 -0
  40. data/app/policies/renalware/hd/closed_session_policy.rb +1 -1
  41. data/app/policies/renalware/pathology/code_group_policy.rb +23 -0
  42. data/app/presenters/renalware/hd/protocol_presenter.rb +8 -2
  43. data/app/views/renalware/clinical/body_compositions/_form.html.slim +6 -0
  44. data/app/views/renalware/clinical/body_compositions/_table.html.slim +4 -0
  45. data/app/views/renalware/dashboard/bookmarks/_bookmark.html.slim +5 -5
  46. data/app/views/renalware/dashboard/bookmarks/_table.html.slim +5 -5
  47. data/app/views/renalware/dashboard/dashboards/_content.html.slim +4 -41
  48. data/app/views/renalware/dashboard/letters/_letter.html.slim +2 -2
  49. data/app/views/renalware/hd/mdm_patients/_patient.html.slim +5 -1
  50. data/app/views/renalware/hd/mdm_patients/_table.html.slim +2 -1
  51. data/app/views/renalware/hd/protocols/_recent_pathology.html.slim +5 -12
  52. data/app/views/renalware/mdm/{_biopsies.html.slim → _biopsies.html.slim.dead} +0 -0
  53. data/app/views/renalware/mdm_patients/_patient.html.slim +5 -1
  54. data/app/views/renalware/mdm_patients/_table.html.slim +1 -1
  55. data/app/views/renalware/medications/prescriptions/_tables.html.slim +27 -23
  56. data/app/views/renalware/messaging/internal/receipts/_receipt.html.slim +1 -1
  57. data/app/views/renalware/modalities/modalities/index.html.slim +17 -16
  58. data/app/views/renalware/navigation/_super_admin.html.slim +1 -0
  59. data/app/views/renalware/pathology/code_groups/edit.html.slim +8 -0
  60. data/app/views/renalware/pathology/code_groups/index.html.slim +16 -0
  61. data/app/views/renalware/pathology/code_groups/show.html.slim +34 -0
  62. data/app/views/renalware/problems/problems/index.html.slim +9 -5
  63. data/app/views/renalware/surveys/_eq5d_summary_part.html.slim +17 -17
  64. data/app/views/renalware/surveys/_pos_s_summary_part.html.slim +61 -60
  65. data/app/views/renalware/transplants/mdm/_bottom.html.slim +1 -1
  66. data/app/views/renalware/transplants/mdm_patients/_patient.html.slim +5 -1
  67. data/app/views/renalware/transplants/mdm_patients/_table.html.slim +1 -1
  68. data/app/views/renalware/transplants/wait_lists/_registration.html.slim +1 -0
  69. data/app/views/renalware/transplants/wait_lists/show.html.slim +24 -1
  70. data/config/locales/renalware/clinical/body_composition.yml +4 -0
  71. data/config/routes/pathology.rb +1 -0
  72. data/db/migrate/20200114151225_add_clinical_body_composition_cols.rb +11 -0
  73. data/db/migrate/20200127165951_create_pathology_versions.rb +16 -0
  74. data/db/migrate/20200127170711_add_created_by_to_pathology_code_groups.rb +15 -0
  75. data/db/migrate/20200129093835_create_system_dashboards.rb +73 -0
  76. data/db/seeds/default/pathology/code_groups.rb +15 -0
  77. data/db/seeds/default/pathology/seeds.rb +2 -1
  78. data/lib/core_extensions/active_record/migration_helpers.rb +3 -2
  79. data/lib/renalware/engine.rb +1 -1
  80. data/lib/renalware/version.rb +1 -1
  81. data/lib/tasks/spec.rake +23 -21
  82. data/spec/factories/clinical/body_compositions.rb +3 -1
  83. data/spec/factories/pathology/code_group_memberships.rb +7 -0
  84. data/spec/factories/pathology/code_groups.rb +13 -0
  85. data/spec/factories/transplants/registration_status_descriptions.rb +5 -0
  86. data/spec/support/devise_spec_helper.rb +24 -8
  87. data/spec/support/ukrdc_helpers.rb +2 -1
  88. metadata +53 -24
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f670bf5df7603c7132365ac119ae9f6bdbb43dde12a24a04d3d015b5a694626c
4
- data.tar.gz: 0a8dde1dd0be593ee8483e01f8128e31f544a1c6eed362fe8fd263e78fd78684
3
+ metadata.gz: 958097e494920445885eb75809fb828e40462d27b0b65ed48e3aab2e0c0d8cc8
4
+ data.tar.gz: 935763fcf2fae4e1a76c2b2fca9e5f3b48b0a7d457b971a65b9c913864ef0024
5
5
  SHA512:
6
- metadata.gz: dc8e11f2b13664bddaabdef7d8bede3f1e2a14bc63862b703a628ad3f8fd6019bcb6d285fd40a81bdd530417ce5c46cbfc8ba8f6a61d5901b7e8523ca783b6a6
7
- data.tar.gz: 5d77baac6abc4e238faa59e4147948315beed80cf363fac2b8c6cb88436b44ff8898a668ef71a3c81a5ccc3e8ca520f596a1919a242275c4540128431f7fa46d
6
+ metadata.gz: b0749b3a7697bcec528d027e5660f89992490fe516e981900bcdfd2560ccffafe08d27229b9ac46257a4de9a3547f90d4fd737091e53e8251adc8e328c63ae97
7
+ data.tar.gz: 95f5b2ab947a8d66e3e6072dda55aeba46bdb441fded424a7c7aaa09a2e6c5a4227f126edf32315270bba351d838e85c9a645740cc2fdde9a241a136cc7e1c75
@@ -32,7 +32,7 @@
32
32
  //= require underscore/underscore
33
33
  //= require select2/dist/js/select2
34
34
  //= require jquery_nested_form
35
- //= require foundation-datepicker
35
+ //= require foundation-datepicker/js/foundation-datepicker
36
36
  //= require renalware/double_scroll
37
37
  //= require cocoon
38
38
  //= require mousetrap/mousetrap
@@ -7,7 +7,7 @@
7
7
 
8
8
  @import "font-awesome-sprockets";
9
9
  @import "font-awesome";
10
- @import "foundation-datepicker";
10
+ @import "foundation-datepicker/css/foundation-datepicker";
11
11
  @import "dataTables/jquery.dataTables.foundation";
12
12
  @import "trix";
13
13
  @import "balloon-css/src/balloon";
@@ -1,5 +1,4 @@
1
- .page--visits {
2
-
1
+ .page--clinics-visits {
3
2
  .filters__output {
4
3
  display: none;
5
4
  }
@@ -353,7 +353,7 @@ form {
353
353
  }
354
354
  }
355
355
 
356
- .page--clinical_summaries {
356
+ .page--patients-clinical_summaries {
357
357
  .summary-part--letters {
358
358
  @include grid-column(12);
359
359
  }
@@ -0,0 +1,15 @@
1
+ @media only screen and (min-width: 830px) {
2
+ // Add body page--* classes to give them, the dashboard look.
3
+ body.page--dashboard-dashboards {
4
+ .main-content {
5
+ background-color: #E8EDEE;
6
+ }
7
+
8
+ article {
9
+ background-color: #fff;
10
+ padding: 0.3rem .5rem .5rem;
11
+ border-top-width: 2px;
12
+ border-top-color: $nhs-bright-blue;
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ class ApplicationComponent < ActionView::Component::Base
5
+ include Renalware::Engine.routes.url_helpers
6
+ include Pundit::Helper
7
+
8
+ # Not sure why include Renalware::Engine.routes.url_helpers does not make the
9
+ # engine urls visible in the views (seems to resolve alwatys to /assets?..)
10
+ # so we expose routes here so inside a component html file we can use
11
+ # e.g. renalware.bookmarks_path
12
+ def renalware
13
+ Renalware::Engine.routes.url_helpers
14
+ end
15
+
16
+ # Added this helper as I can't seem to get the Pundit #policy helper to be included
17
+ # in the context when renderingt a component template.
18
+ def policy(record)
19
+ current_user && Pundit.policy(current_user, record)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,14 @@
1
+ article.events
2
+ header
3
+ h2 Biopsies
4
+ .supplemental
5
+ span= "#{biopsies.length} of #{total_biopsies}"
6
+ span.noprint
7
+ = link_to "View All",
8
+ renalware.patient_events_path(patient),
9
+ class: "button secondary"
10
+
11
+ = render "renalware/events/events/table",
12
+ events: biopsies,
13
+ exclude_type_column: true,
14
+ toggle_prefix: "biopsy"
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ module Events
5
+ class BiopsiesComponent < ApplicationComponent
6
+ validates :patient, presence: true
7
+
8
+ def initialize(patient:, limit: 6)
9
+ @patient = patient
10
+ relation = Biopsy.for_patient(patient).includes(:created_by)
11
+ @biopsies = relation.limit(limit).ordered
12
+ @total_biopsies = relation.count
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :patient, :biopsies, :total_biopsies
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,8 @@
1
+ article.letters
2
+ header
3
+ h2 Letters in Progress
4
+ - if letters_in_progress.any?
5
+ #letters-in-progress
6
+ = render "renalware/dashboard/letters/table", letters: letters_in_progress
7
+ - else
8
+ p.empty-section Letters in Progress
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ module Letters
5
+ class LettersInProgressComponent < ApplicationComponent
6
+ attr_reader :current_user
7
+
8
+ def initialize(current_user:)
9
+ @current_user = current_user
10
+ end
11
+
12
+ # Note we want oldest letters ordered first here - elsewhere letters are newest first
13
+ def letters_in_progress
14
+ @letters_in_progress ||= begin
15
+ present_letters(
16
+ Letters::Letter
17
+ .reversed
18
+ .where("author_id = ? or created_by_id = ?", current_user.id, current_user.id)
19
+ .in_progress
20
+ .includes(:author, :patient, :letterhead)
21
+ )
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def present_letters(letters)
28
+ CollectionPresenter.new(letters, Letters::LetterPresenterFactory)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,7 @@
1
+ article.electonic_ccs
2
+ header
3
+ h2 Electronic CCs
4
+ - if unread_electronic_ccs.any?
5
+ = render "renalware/letters/electronic_receipts/table", receipts: unread_electronic_ccs
6
+ - else
7
+ p.empty-section You have no electronic CCs.
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ module Letters
5
+ class UnreadElectronicCCsComponent < ApplicationComponent
6
+ attr_reader :current_user
7
+
8
+ def initialize(current_user:)
9
+ @current_user = current_user
10
+ end
11
+
12
+ def unread_electronic_ccs
13
+ @unread_electronic_ccs ||= begin
14
+ receipts = Letters::ElectronicReceipt
15
+ .includes(letter: [:patient, :author, :letterhead])
16
+ .unread
17
+ .for_recipient(current_user.id)
18
+ .order(created_at: :asc)
19
+ CollectionPresenter.new(receipts, Letters::ElectronicReceiptPresenter)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ article.messages
2
+ header
3
+ h2 Messages
4
+ ul
5
+ li= render "renalware/messaging/shared/key"
6
+ - if unread_message_receipts.any?
7
+ .unread-messages
8
+ = render "renalware/messaging/internal/receipts/table",
9
+ receipts: unread_message_receipts
10
+ - else
11
+ p.empty-section You have no messages.
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ module Messaging
5
+ class UnreadMessagesComponent < ApplicationComponent
6
+ attr_reader :current_user
7
+
8
+ def initialize(current_user:)
9
+ @current_user = Messaging::Internal.cast_recipient(current_user)
10
+ end
11
+
12
+ def unread_message_receipts
13
+ @unread_message_receipts ||= begin
14
+ receipts = current_user
15
+ .receipts
16
+ .includes(message: [:author, :patient])
17
+ .order("messaging_messages.sent_at asc")
18
+ .unread
19
+ CollectionPresenter.new(receipts, Messaging::Internal::ReceiptPresenter)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,11 @@
1
+ article.bookmarks
2
+ header
3
+ h2.title= "Bookmarked Patients"
4
+ ul
5
+ li= link_to "View All", renalware.bookmarks_path, class: "button"
6
+
7
+ - if bookmarks.any?
8
+ #bookmarks
9
+ = render "renalware/dashboard/bookmarks/table", bookmarks: bookmarks
10
+ - else
11
+ p.empty-section= t(".bookmarks.none")
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Renalware
4
+ module Patients
5
+ class BookmarksComponent < ApplicationComponent
6
+ attr_reader :current_user
7
+
8
+ def initialize(current_user:)
9
+ @current_user = current_user
10
+ end
11
+
12
+ def bookmarks
13
+ @bookmarks ||= begin
14
+ Patients.cast_user(current_user)
15
+ .bookmarks
16
+ .ordered
17
+ .includes(patient: [current_modality: :description])
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -89,7 +89,7 @@ module Renalware
89
89
  :assessed_on, :overhydration, :volume_of_distribution, :total_body_water,
90
90
  :extracellular_water, :intracellular_water, :lean_tissue_index,
91
91
  :fat_tissue_index, :lean_tissue_mass, :fat_tissue_mass, :adipose_tissue_mass,
92
- :body_cell_mass, :quality_of_reading, :assessor_id, :notes
92
+ :body_cell_mass, :quality_of_reading, :assessor_id, :notes, :weight, :pre_post_hd
93
93
  ]
94
94
  end
95
95
  end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_dependency "renalware/pathology"
4
+
5
+ module Renalware
6
+ module Pathology
7
+ class CodeGroupsController < Pathology::BaseController
8
+ def index
9
+ groups = CodeGroup.order(:name)
10
+ authorize groups, :index?
11
+ render locals: { groups: groups }
12
+ end
13
+
14
+ def show
15
+ render locals: { group: find_authorize_group }
16
+ end
17
+
18
+ def edit
19
+ render locals: { group: find_authorize_group }
20
+ end
21
+
22
+ def update
23
+ group = find_authorize_group
24
+ if group.update_by(current_user, code_group_params)
25
+ redirect_to pathology_code_groups_path, notice: "Group saved"
26
+ else
27
+ render :edit, locals: { group: group }
28
+ end
29
+ end
30
+
31
+ private
32
+
33
+ def find_authorize_group
34
+ CodeGroup.find(params[:id]).tap { |group| authorize group }
35
+ end
36
+
37
+ def code_group_params
38
+ params
39
+ .require(:code_group)
40
+ .permit(:description)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -7,30 +7,39 @@ module Renalware
7
7
  class WaitListsController < BaseController
8
8
  include Renalware::Concerns::Pageable
9
9
 
10
+ # Here we display a named filter eg Active and query for patients based on registration
11
+ # status and also any search criteria entered in the search form which is backed by our
12
+ # ransack #search object.
10
13
  def show
14
+ form = Registrations::WaitListForm.new(form_params)
15
+ query = query_for(form)
11
16
  registrations = query.call.page(page).per(per_page || 50)
12
17
  authorize registrations
13
18
  render locals: {
14
19
  path_params: path_params,
15
20
  registrations: CollectionPresenter.new(registrations, WaitListRegistrationPresenter),
16
- q: query.search
21
+ q: query.search,
22
+ form: form
17
23
  }
18
24
  end
19
25
 
20
26
  private
21
27
 
22
- def query
23
- @query ||= begin
24
- Registrations::WaitListQuery.new(
25
- named_filter: params[:named_filter],
26
- q: params[:q]
27
- )
28
- end
28
+ def query_for(form)
29
+ Registrations::WaitListQuery.new(
30
+ named_filter: params[:named_filter],
31
+ ukt_recipient_number: form.ukt_recipient_number,
32
+ q: params[:q]
33
+ )
29
34
  end
30
35
 
31
36
  def path_params
32
37
  params.permit([:controller, :action, :named_filter])
33
38
  end
39
+
40
+ def form_params
41
+ params.fetch(:form, {}).permit(:ukt_recipient_number)
42
+ end
34
43
  end
35
44
  end
36
45
  end
@@ -9,6 +9,12 @@ module Renalware
9
9
  include PatientScope
10
10
  include Accountable
11
11
 
12
+ # This maps to a PG enum
13
+ enum pre_post_hd: {
14
+ pre: "pre",
15
+ post: "post"
16
+ }
17
+
12
18
  belongs_to :patient, class_name: "Renalware::Clinical::Patient", touch: true
13
19
  belongs_to :assessor, class_name: "User", foreign_key: "assessor_id"
14
20
  belongs_to :modality_description, class_name: "Modalities::Description"
@@ -32,6 +38,7 @@ module Renalware
32
38
  validates :body_cell_mass, presence: true, numeric_inclusion: { in: 0..150 }
33
39
  validates :quality_of_reading, presence: true, numeric_inclusion: { in: 50..100 }
34
40
  validates :assessed_on, presence: true, timeliness: { type: :date, allow_blank: false }
41
+ validates :weight, "renalware/patients/weight" => true
35
42
  end
36
43
  end
37
44
  end
@@ -23,6 +23,15 @@ module Renalware
23
23
  # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
24
24
  def search
25
25
  @search ||= begin
26
+ nasty_join_sql_to_get_around_a_kaminari_count_issue = <<-SQL
27
+ inner join modality_modalities X1
28
+ on patients.id = X1.patient_id
29
+ and X1.state = 'current'
30
+ and X1.ended_on IS NULL
31
+ inner join modality_descriptions MD1
32
+ on MD1.id = X1.description_id
33
+ and MD1.code = 'hd'
34
+ SQL
26
35
  HD::Patient
27
36
  .include(QueryablePatient)
28
37
  .extending(PatientTransplantScopes)
@@ -34,7 +43,7 @@ module Renalware
34
43
  .extending(NamedFilterScopes)
35
44
  .with_current_pathology
36
45
  .with_registration_statuses
37
- .with_current_modality_of_class(Renalware::HD::ModalityDescription)
46
+ .joins(nasty_join_sql_to_get_around_a_kaminari_count_issue)
38
47
  .public_send(named_filter.to_s)
39
48
  .ransack(params)
40
49
  end
@@ -28,9 +28,14 @@ module Renalware
28
28
  # G.name,
29
29
  # M.subgroup,
30
30
  # M.position_within_subgroup;
31
-
32
31
  class CodeGroup < ApplicationRecord
32
+ include Accountable
33
+ has_paper_trail(
34
+ class_name: "Renalware::Pathology::Version",
35
+ on: [:create, :update, :destroy]
36
+ )
33
37
  validates :name, presence: true, uniqueness: true
38
+ validates :description, presence: true
34
39
  has_many(
35
40
  :memberships,
36
41
  class_name: "CodeGroupMembership",
@@ -42,8 +47,10 @@ module Renalware
42
47
  )
43
48
 
44
49
  def self.descriptions_for_group(name)
45
- CodeGroup
46
- .find_by!(name: name)
50
+ group = CodeGroup.find_by(name: name)
51
+ return [] if group.nil?
52
+
53
+ group
47
54
  .observation_descriptions
48
55
  .order(subgroup: :asc, position_within_subgroup: :asc)
49
56
  end