renalware-core 2.0.126 → 2.0.127

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/stylesheets/renalware/base/_variables.scss +2 -2
  3. data/app/assets/stylesheets/renalware/modules/_clinical.scss +3 -3
  4. data/app/assets/stylesheets/renalware/modules/_problems.scss +4 -1
  5. data/app/assets/stylesheets/renalware/modules/_rotated_tables_headings.scss +39 -0
  6. data/app/assets/stylesheets/renalware/modules/_surveys.scss +4 -0
  7. data/app/assets/stylesheets/renalware/partials/_forms.scss +1 -1
  8. data/app/assets/stylesheets/renalware/partials/_tables.scss +9 -3
  9. data/app/assets/stylesheets/renalware/partials/_tabs.scss +4 -4
  10. data/app/assets/stylesheets/renalware/partials/_toggling.scss +51 -1
  11. data/app/models/renalware/patients/ingestion/command_factory.rb +63 -51
  12. data/app/models/renalware/patients/ingestion/message_mappers/patient.rb +0 -17
  13. data/app/models/renalware/surveys/pos_s_summary_part.rb +9 -5
  14. data/app/models/renalware/ukrdc/incoming/import_survey.rb +6 -2
  15. data/app/models/renalware/ukrdc/incoming/xml_document.rb +11 -1
  16. data/app/presenters/renalware/hd/mdm_presenter.rb +6 -0
  17. data/app/presenters/renalware/problems/summary_part.rb +1 -1
  18. data/app/views/renalware/hd/mdm/_top.html.slim +12 -3
  19. data/app/views/renalware/hd/sessions/_row.html.slim +1 -1
  20. data/app/views/renalware/hd/sessions/dna/_row.html.slim +1 -1
  21. data/app/views/renalware/problems/problems/_current_table.html.slim +1 -1
  22. data/app/views/renalware/problems/problems/_summary_part.html.slim +21 -5
  23. data/app/views/renalware/surveys/_pos_s_summary_part.html.slim +43 -7
  24. data/db/migrate/20191205185835_update_survey_views.rb +12 -0
  25. data/db/migrate/20191209160151_add_patient_question_text_to_survey_responses.rb +7 -0
  26. data/db/migrate/20191209163151_update_survey_views_to_allow_free_text.rb +12 -0
  27. data/db/views/survey_pos_s_pivoted_responses_v02.sql +37 -0
  28. data/db/views/survey_pos_s_pivoted_responses_v03.sql +39 -0
  29. data/lib/renalware/version.rb +1 -1
  30. metadata +8 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c1b4b5e0615d605d093018e57c295da81fa8b2c7b51bd83b8ab02065ce357c91
4
- data.tar.gz: f78640822218ff8dfbae7ef9281d0cb9c5636791222fbb06a37cd36001b41ee8
3
+ metadata.gz: 334da5d5d7e32ed650c55379a33eedf5d4bba077a4480f987aece96dcb498ac9
4
+ data.tar.gz: 97f0bce7f1420f0d3f87b32e56bab92847c8f4efc61f7b2ba187a55749cd22fb
5
5
  SHA512:
6
- metadata.gz: a4074e24c734e3c38efb99687920d41ab1ac0e555dc6663a7cc356fc8035465b94ffa18be1ddcf8c2bbafd2e347a77caf0cf7806cd7d201980e699d8077bfcb6
7
- data.tar.gz: 680f524d251700a637fec7a8900a4c242cc691fad41d868254a773bd8de314859fbd7510bcb67fc01481cb300456b1bbebfee17aac0df95f0d86b63671ddd18e
6
+ metadata.gz: f83bf5d9b6e63e5ba23ba024b61aafc74bf92658bb9a80662d204bd1e5bd3cf75096ba5ebe7dc4ca58a988694d371b8b070cddf95298870dd21aa206f68c1525
7
+ data.tar.gz: 62f72f50326cb5275faa9205f0dff4e75c6f8efa7bd84b1a11047e6b3d9a495dc16049fd3e77544d64c93b8bb47cf59a3e8b4c379107a80f5eba88c7d67043af
@@ -61,7 +61,7 @@ $drug-type-default-colour: none;
61
61
  $drug-type-esa-colour: #ff9;
62
62
  $drug-type-immunosuppressant-colour: #ccfeff;
63
63
 
64
- $tab-border-color: $off-white;
64
+ $tab-border-color: #ddd;
65
65
 
66
66
  // Patient header/banner
67
67
  $patient-header-muted-color: #777;
@@ -102,7 +102,7 @@ $letter-preview-background-colour: #ddd;
102
102
 
103
103
  // tables
104
104
  $table-even-row-colour: #fcfcfc;
105
- $table-border-colour: #ccc;
105
+ $table-border-colour: #ddd;
106
106
  $table-toggled-content-colour: #fefff1;
107
107
  $table-urgent-colour: $nhs-yellow;
108
108
  $table-row-hover-colour: #f9f9f9;
@@ -51,7 +51,7 @@ article.clinical-allergies {
51
51
  }
52
52
 
53
53
  .clinical-header {
54
- background-color: $table-border-colour;
54
+ background-color: $disabled-colour;
55
55
  padding: 0 .2em .2em .6em;
56
56
 
57
57
  @media print {
@@ -85,7 +85,7 @@ article.clinical-allergies {
85
85
  padding: 0;
86
86
 
87
87
  li {
88
- border-bottom: 1px dotted $winter-sky;
88
+ border-bottom: 1px solid $winter-sky;
89
89
  display: inline-block;
90
90
  margin: 0.2rem .6rem .2rem 0;
91
91
  padding: 0
@@ -182,7 +182,7 @@ article.clinical-allergies {
182
182
  }
183
183
 
184
184
  a {
185
- border-bottom: 1px dotted $white;;
185
+ border-bottom: 1px solid $white;;
186
186
  color: $white
187
187
  }
188
188
 
@@ -2,7 +2,10 @@ table#problems,
2
2
  table#current_problems,
3
3
  table#archived_problems {
4
4
  td {
5
- vertical-align: top;
5
+ // vertical-align: top;
6
+ span {
7
+ line-height: 1.1rem;
8
+ }
6
9
 
7
10
  ol {
8
11
  font-size: 1em;
@@ -0,0 +1,39 @@
1
+ // Somewhat specialised for use in eg POS-S survey results table because
2
+ // the attributes are quite finicky to get it to look right.
3
+ // If you need to use these classes elsewhere and the look is not right,
4
+ // please make sure PROMS survey results still look OK.
5
+ .table-header-rotated {
6
+ width: auto;
7
+
8
+ th.rotate {
9
+ height: 138px;
10
+ white-space: nowrap;
11
+
12
+ // Firefox needs the extra DIV for some reason, otherwise the text disappears if you rotate
13
+ > div {
14
+ transform:
15
+ // Magic Numbers
16
+ translate(25px, 51px)
17
+ // 45 is really 360-45
18
+ rotate(315deg);
19
+ width: 2rem;
20
+ }
21
+
22
+ > div > span {
23
+ border-bottom: 1px solid #ccc ;
24
+ display: inline-block;
25
+ padding: .4rem .0rem;
26
+ margin: 0 0 1.1rem -0.5rem;
27
+ }
28
+ }
29
+
30
+ th.row-header {
31
+ padding: 0 10px;
32
+ border-bottom: 1px solid #ccc;
33
+ }
34
+
35
+ th {
36
+ overflow: visible;
37
+ vertical-align: inherit;
38
+ }
39
+ }
@@ -55,4 +55,8 @@ dl.pos-s-key {
55
55
  text-align: left;
56
56
  }
57
57
  }
58
+
59
+ .summary-part--pos_s-patient-question-text {
60
+ text-align: right;
61
+ }
58
62
  }
@@ -220,7 +220,7 @@ article {
220
220
  width: 100%;
221
221
 
222
222
  li {
223
- border-bottom: 1px dotted $iron;
223
+ border-bottom: 1px solid $table-border-color;
224
224
  // font-weight: bold;
225
225
  padding-bottom: 0.2rem;
226
226
 
@@ -5,8 +5,8 @@ table tbody tr th,
5
5
  table tbody tr td,
6
6
  table tr td {
7
7
  display: table-cell;
8
- line-height: 1rem;
9
- padding: 0.4rem 0.28571rem;
8
+ line-height: 1.3rem;
9
+ padding: 0.2rem 0.28571rem;
10
10
  }
11
11
 
12
12
  table thead th {
@@ -202,7 +202,7 @@ table {
202
202
 
203
203
  tr th,
204
204
  tr td {
205
- border-bottom: 1px dotted $disabled-colour;
205
+ border-bottom: 1px solid $table-border-colour;
206
206
  border-left-width: 0;
207
207
  border-right: solid 1px $white;
208
208
  font-size: 1rem;
@@ -498,3 +498,9 @@ table tr.alt,
498
498
  table tr:nth-of-type(even) {
499
499
  background: transparent;
500
500
  }
501
+
502
+ th, td {
503
+ &.valign-bottom {
504
+ vertical-align: bottom;
505
+ }
506
+ }
@@ -16,7 +16,7 @@
16
16
  .ui-tabs-tab.ui-tabs-active,
17
17
  .ui-tabs-tab.ui-state-active {
18
18
  background-color: $white;
19
- border-color: $table-border-colour;
19
+ border-color: $disabled-colour;
20
20
  }
21
21
 
22
22
  .ui-tabs-anchor {
@@ -66,7 +66,7 @@
66
66
 
67
67
  &.active {
68
68
  background-color: $smoke;
69
- border: solid 1px $table-border-colour;
69
+ border: solid 1px $disabled-colour;
70
70
  border-bottom: solid 1px $smoke;
71
71
  }
72
72
  }
@@ -99,8 +99,8 @@
99
99
  position: relative;
100
100
  display: block;
101
101
  z-index: 0;
102
- color: $table-border-colour;
103
- background-color: $table-border-colour;
102
+ color: $disabled-colour;
103
+ background-color: $disabled-colour;
104
104
  padding: 0;
105
105
  margin: 0;
106
106
  margin-bottom: 1rem;
@@ -16,6 +16,7 @@
16
16
  }
17
17
  }
18
18
 
19
+ // Toggle-all
19
20
  th.togglers .toggler {
20
21
  i:before {
21
22
  content: asset-data-url("renalware/icons/chevrons-down.svg");
@@ -37,7 +38,23 @@ th.togglers {
37
38
  width: 1rem;
38
39
  }
39
40
 
40
- // row-toggler-controller classes
41
+ // Classes to be used when toggling open an initially hidden tr.
42
+ // The expected structure
43
+ // table.toggleable
44
+ // thead
45
+ // th.togglers
46
+ // a.toggler (link to toggle all rows)
47
+ // th ...
48
+ // (for each thing)
49
+ // tbody
50
+ // tr (visible)
51
+ // td.toggleable--toggler-container
52
+ // a.toggler (link to toggle thos tobody's last row)
53
+ // td ...
54
+ // tr (will be initially hidden as its the last tr)
55
+ // td
56
+ // td Content to display when toggled
57
+ //
41
58
  .toggleable {
42
59
  .toggleable--open {
43
60
  td .toggler i:before {
@@ -57,5 +74,38 @@ th.togglers {
57
74
  &.toggleable--open tr:last-child {
58
75
  display: table-row;
59
76
  }
77
+
78
+ // Add this class to a toggleable tbody if there is nothing to toggle open to see.
79
+ // It prevents an empty row expanding down and taking up valuable space.
80
+ // An alternative could be to display 'No notes' or whatever, but that seems slightly odd.
81
+ &.toggleable--no-toggleable-content {
82
+ tr:last-child {
83
+ display: none;
84
+ }
85
+ }
86
+ }
87
+
88
+ &.toggleable--without-border-between-toggled-and-non-toggled-tr {
89
+ tbody.toggleable--open:not(.no-toggleable-content) {
90
+ td {
91
+ border-top: solid 1px $table-border-colour;
92
+ }
93
+
94
+ tr:first-child td {
95
+ border-bottom: none;
96
+ }
97
+
98
+ tr:last-child:not(.no-toggleable-content) td {
99
+ border-top: none;
100
+ padding-top: 0;
101
+ }
102
+ }
103
+ }
104
+
105
+ .toggleable--toggler-container {
106
+ padding: 0;
107
+ margin: 0;
108
+ text-align: center;
109
+ vertical-align: middle;
60
110
  }
61
111
  }
@@ -9,38 +9,29 @@ module Renalware
9
9
  # message type.
10
10
  #
11
11
  class CommandFactory
12
+ # rubocop:disable Metrics/CyclomaticComplexity
13
+ # Note that for now most of these mapped methods will only try and
14
+ # update the patient info and master patient index, and not actually
15
+ # try and create an admission/transfer etc
12
16
  def for(message)
13
17
  case message.action
14
- when :add_person_information then make_add_patient(message)
18
+ when :add_person_information then make_add_patient(message)
15
19
  when :update_person_information then make_update_patient(message)
16
- # when :admit_patient then make_admit_patient(message)
17
- # when :merge_patient then make_merge_patient(message)
18
- # when :update_admission then make_update_admission(message)
19
- # when :cancel_admission then make_cancel_admission(message)
20
- # when :transfer_patient then make_transfer_patient(message)
21
- # when :discharge_patient then make_discharge_patient(message)
22
- # when :cancel_discharge then make_cancel_discharge(message)
20
+ when :admit_patient then make_admit_patient(message)
21
+ when :update_admission then make_update_admission(message)
22
+ when :cancel_admission then make_cancel_admission(message)
23
+ when :transfer_patient then make_transfer_patient(message)
24
+ when :discharge_patient then make_discharge_patient(message)
25
+ when :cancel_discharge then make_cancel_discharge(message)
26
+ # when :merge_patient then make_merge_patient(message) # complex so ignore for now.
23
27
  # when :add_consultant then make_add_consultant(message)
24
28
  else noop
25
29
  end
26
30
  end
31
+ # rubocop:enable Metrics/CyclomaticComplexity
27
32
 
28
33
  private
29
34
 
30
- # def make_add_patient_with_finder(message)
31
- # CommandWithFinder.new(
32
- # make_add_patient(message),
33
- # message, finder: Finder::Patient.new
34
- # )
35
- # end
36
-
37
- # def make_add_patient_with_finder(message)
38
- # CommandWithFinder.new(
39
- # make_add_patient(message),
40
- # message, finder: Finder::Patient.new
41
- # )
42
- # end
43
-
44
35
  def make_add_patient(message)
45
36
  Commands::AddOrUpdatePatient.new(message)
46
37
  end
@@ -53,40 +44,40 @@ module Renalware
53
44
  NullObject.instance
54
45
  end
55
46
 
56
- # def make_merge_patient(message)
57
- # Commands::MergePatient.new(message,
58
- # major_patient_finder: make_patient_finder_with_add_if_missing,
59
- # minor_patient_finder: make_minor_patient_finder_with_add_if_missing)
60
- # end
61
-
62
- # def make_admit_patient(message)
63
- # Commands::AdmitPatient.new(message,
64
- # patient_finder: make_patient_finder_with_add_if_missing)
65
- # end
47
+ def make_admit_patient(message)
48
+ Commands::AddOrUpdatePatient.new(message)
49
+ # Commands::AdmitPatient.new(message,
50
+ # patient_finder: make_patient_finder_with_add_if_missing)
51
+ end
66
52
 
67
- # def make_update_admission(message)
68
- # Commands::UpdateAdmission.new(message,
69
- # admission_finder: make_admission_finder_with_logging_if_missing)
70
- # end
53
+ def make_update_admission(message)
54
+ Commands::AddOrUpdatePatient.new(message)
55
+ # Commands::UpdateAdmission.new(message,
56
+ # admission_finder: make_admission_finder_with_logging_if_missing)
57
+ end
71
58
 
72
- # def make_cancel_admission(message)
73
- # Commands::CancelAdmission.new(message,
74
- # admission_finder: make_admission_finder_with_logging_if_missing)
75
- # end
59
+ def make_cancel_admission(message)
60
+ Commands::AddOrUpdatePatient.new(message)
61
+ # Commands::CancelAdmission.new(message,
62
+ # admission_finder: make_admission_finder_with_logging_if_missing)
63
+ end
76
64
 
77
- # def make_transfer_patient(message)
78
- # Commands::TransferPatient.new(message,
79
- # admission_finder: make_admission_finder_with_admit_if_missing)
80
- # end
65
+ def make_transfer_patient(message)
66
+ Commands::AddOrUpdatePatient.new(message)
67
+ # Commands::TransferPatient.new(message,
68
+ # admission_finder: make_admission_finder_with_admit_if_missing)
69
+ end
81
70
 
82
- # def make_discharge_patient(message)
83
- # Commands::DischargePatient.new(message,
84
- # admission_finder: make_admission_finder_with_logging_if_missing)
85
- # end
71
+ def make_discharge_patient(message)
72
+ Commands::AddOrUpdatePatient.new(message)
73
+ # Commands::DischargePatient.new(message,
74
+ # admission_finder: make_admission_finder_with_logging_if_missing)
75
+ end
86
76
 
87
- # def make_cancel_discharge(message)
88
- # Commands::CancelDischarge.new(message)
89
- # end
77
+ def make_cancel_discharge(message)
78
+ Commands::AddOrUpdatePatient.new(message)
79
+ # Commands::CancelDischarge.new(message)
80
+ end
90
81
 
91
82
  # def make_add_consultant(message)
92
83
  # Commands::AddConsultant.new(message)
@@ -133,6 +124,27 @@ module Renalware
133
124
  # make_admit_patient(message).call
134
125
  # }
135
126
  # end
127
+ #
128
+ #
129
+ # def make_add_patient_with_finder(message)
130
+ # CommandWithFinder.new(
131
+ # make_add_patient(message),
132
+ # message, finder: Finder::Patient.new
133
+ # )
134
+ # end
135
+
136
+ # def make_add_patient_with_finder(message)
137
+ # CommandWithFinder.new(
138
+ # make_add_patient(message),
139
+ # message, finder: Finder::Patient.new
140
+ # )
141
+ # end
142
+ #
143
+ # def make_merge_patient(message)
144
+ # Commands::MergePatient.new(message,
145
+ # major_patient_finder: make_patient_finder_with_add_if_missing,
146
+ # minor_patient_finder: make_minor_patient_finder_with_add_if_missing)
147
+ # end
136
148
  end
137
149
  end
138
150
  end
@@ -48,23 +48,6 @@ module Renalware
48
48
  attrs.reject! { |_key, value| value.blank? }
49
49
  patient.attributes = attrs
50
50
 
51
- # patient.given_name = patient_identification.given_name
52
- # patient.family_name = patient_identification.family_name
53
- # patient.suffix = patient_identification.suffix
54
- # patient.title = patient_identification.title
55
- # patient.attributes = {
56
- # local_patient_id: patient_identification.internal_id,
57
- # nhs_number: patient_identification.nhs_number,
58
- # given_name: patient_identification.given_name,
59
- # family_name: patient_identification.family_name,
60
- # suffix: patient_identification.suffix,
61
- # title: patient_identification.title,
62
- # born_on: Time.zone.parse(patient_identification.dob)&.to_date,
63
- # died_on: Time.zone.parse(patient_identification.death_date)&.to_date,
64
- # sex: patient_identification.sex,
65
- # practice: find_practice(message.practice_code) || patient.practice,
66
- # primary_care_physician: find_primary_care_physician(message.gp_code)
67
- # }
68
51
  patient.build_current_address if patient.current_address.blank?
69
52
  patient.current_address.attributes = {
70
53
  street_1: address[0],
@@ -5,18 +5,22 @@ require_dependency "renalware/surveys"
5
5
  module Renalware
6
6
  module Surveys
7
7
  class POSSSummaryPart < Renalware::SummaryPart
8
+ # Backed by a SQL view
8
9
  def rows
9
10
  @rows ||= POSSPivotedResponse.where(patient_id: patient.id)
10
11
  end
11
12
 
12
13
  def question_labels
13
- survey
14
- .questions
15
- .order(:position)
16
- .select(:code, :label)
17
- .each_with_object({}) { |q, hash| hash[q.code] = q.label }
14
+ @question_labels ||= begin
15
+ survey
16
+ .questions
17
+ .order(:position)
18
+ .select(:code, :label)
19
+ .each_with_object({}) { |q, hash| hash[q.code] = q.label }
20
+ end
18
21
  end
19
22
 
23
+ # Return data for charting
20
24
  def data_for_question_code(_code)
21
25
  Renalware::Surveys::Response
22
26
  .where(patient_id: patient.id, question_id: 1)
@@ -9,14 +9,18 @@ module Renalware
9
9
  class ImportSurvey
10
10
  pattr_initialize [:patient, :survey_hash]
11
11
 
12
+ # Note that each question's answer may be a value like "1" or be an array where the second
13
+ # element is the user-entered question text e.g. ["1", "Paranoia"]
14
+ # This is used in POS-S so that a user can enter their own question text.
12
15
  def call
13
16
  responses.each do |question_code, answer|
14
17
  question = question_having_code(question_code)
15
-
18
+ answer = Array(answer)
16
19
  Surveys::Response.create!(
17
20
  patient_id: patient.id,
18
21
  question: question,
19
- value: answer,
22
+ value: answer[0],
23
+ patient_question_text: answer[1],
20
24
  answered_on: answered_on
21
25
  )
22
26
  end
@@ -54,12 +54,22 @@ module Renalware
54
54
  end
55
55
  end
56
56
 
57
+ # Note that if a response has a QuestionText this can be some text the user entered
58
+ # (presumably so they can then assign it a response value) so we need to store the
59
+ # question text (e.g. Paranoia) as well as the response (eg 4).
60
+ # If we find a QuestionText we store an array containing it and the response in the hash
61
+ # otherwise we just add the response.
57
62
  def question_hash_from(survey_node)
58
63
  question_nodes = survey_node.xpath("Questions/Question")
59
64
  question_nodes.each_with_object({}) do |question_node, responses|
60
65
  code = question_node.xpath("string(QuestionType/Code)")
61
66
  response = question_node.xpath("string(Response)")
62
- responses[code] = response
67
+ question_text = question_node.xpath("string(QuestionText)")
68
+ responses[code] = if question_text.present?
69
+ [response, question_text]
70
+ else
71
+ response
72
+ end
63
73
  end
64
74
  end
65
75
  end
@@ -33,6 +33,12 @@ module Renalware
33
33
  end
34
34
  end
35
35
 
36
+ def dry_weights
37
+ @dry_weights ||= begin
38
+ Clinical::DryWeight.for_patient(patient).ordered.includes(:assessor).limit(5)
39
+ end
40
+ end
41
+
36
42
  def preference_set
37
43
  @preference_set ||= PreferenceSet.for_patient(patient).first || NullObject.instance
38
44
  end
@@ -6,7 +6,7 @@ module Renalware
6
6
  module Problems
7
7
  class SummaryPart < Renalware::SummaryPart
8
8
  def problems
9
- @problems ||= patient.problems.ordered
9
+ @problems ||= patient.problems.with_notes
10
10
  end
11
11
 
12
12
  def cache_key
@@ -1,13 +1,22 @@
1
- .columns.small-12.medium-6.large-6
1
+ .columns.small-12.medium-6
2
2
  = render "renalware/hd/current_profile/summary", profile: mdm.hd_profile, patient: mdm.patient
3
+
4
+ .columns.medium-6
5
+ = render "renalware/clinical/dry_weights/list",
6
+ dry_weights: mdm.dry_weights,
7
+ patient: mdm.patient,
8
+ limit: true
9
+
3
10
  .columns.small-12.medium-6.large-3
4
11
  - if mdm.access.present?
5
12
  = render "renalware/hd/accesses/summary", access: mdm.access, patient: mdm.patient
6
- .columns.medium-6.large-6
13
+
14
+ .columns.medium-6
7
15
  = render "renalware/virology/profiles/summary",
8
16
  patient: mdm.patient,
9
17
  positive_results_only: true
10
- .columns.medium-6.large-6
18
+
19
+ .columns.medium-6
11
20
  = render "summary", mdm: mdm
12
21
  = render "worryboard", mdm: mdm
13
22
 
@@ -1,6 +1,6 @@
1
1
  tbody.hd-session-row(class=[session.state, stripe_class])
2
2
  tr
3
- td.noprint(rowspan=2)= row_toggler
3
+ td.toggleable--toggler-container.noprint(rowspan=2)= row_toggler
4
4
  td.noprint(rowspan=2)= session.edit_or_view_url
5
5
  td.col-width-date(rowspan=2)= session.performed_on
6
6
  td= session.hospital_unit_unit_code
@@ -1,6 +1,6 @@
1
1
  tbody(class=[session.state, stripe_class])
2
2
  tr
3
- td.noprint= row_toggler
3
+ td.toggleable--toggler-container.noprint= row_toggler
4
4
  td.noprint= session.edit_or_view_url
5
5
  td= session.performed_on
6
6
  td= session.hospital_unit_unit_code
@@ -4,7 +4,7 @@ table#current_problems.manual-stripes.auto-layout
4
4
  th.options.col-width-small
5
5
  th Description
6
6
  th.col-width-date Updated on
7
- td.nowrap Updated by
7
+ td.col-width-medium.nowrap Updated by
8
8
  th.col-width-tiny Reorder
9
9
  = content_tag(:tbody, class: "sortables", data: { rel: sort_patient_problems_path(@patient) }) do
10
10
  - problems.each do |problem|
@@ -20,8 +20,24 @@
20
20
  = link_to patient_problems_path(summary_part.patient), class: "button" do
21
21
  | Add
22
22
 
23
- ul.no-bullet
24
- - summary_part.problems.each do |problem|
25
- li
26
- = problem.full_description
27
- = " - #{l(problem.created_at.to_date)}"
23
+ table#problems.toggleable.toggleable--without-border-between-toggled-and-non-toggled-tr
24
+ thead.toggleable--open
25
+ th.togglers.noprint =rows_toggler
26
+ th Description
27
+ th.col-width-date Date
28
+
29
+ - summary_part.problems.each_with_index do |problem|
30
+ tbody.toggleable--open(class=("toggleable--no-toggleable-content" if problem.notes.none?))
31
+ tr
32
+ td.toggleable--toggler-container.noprint = row_toggler
33
+ td
34
+ span= problem.full_description
35
+ td= problem.created_at.to_date
36
+ tr
37
+ td
38
+ td
39
+ - if problem.notes.any?
40
+ ol
41
+ - problem.notes.each do |note|
42
+ li= note.description
43
+ td
@@ -1,3 +1,6 @@
1
+ /
2
+ / TODO: this could do with refactoring to move the formatting code into a helper or presenter.
3
+ /
1
4
  .summary-part--pos_s
2
5
  article
3
6
  header
@@ -10,22 +13,55 @@
10
13
  / br
11
14
 
12
15
  - return if pos_s_summary_part.rows.blank?
13
-
16
+ br
17
+ br
18
+ br
19
+ br
14
20
  .xsss
15
- table
21
+ table.table-header-rotated.toggleable
16
22
  thead
17
23
  tr
18
- th.col-width-date Date
24
+ th.togglers= rows_toggler
25
+ th.col-width-date.valign-bottom Date
26
+ th.col-width-tiny.valign-bottom Total
19
27
  - pos_s_summary_part.question_labels.each do |code, label|
20
- th= label
21
- tbody
22
- - pos_s_summary_part.rows.each do |row|
28
+ th.rotate
29
+ div
30
+ span= label
31
+
32
+ - superscript_char = 97
33
+ - pos_s_summary_part.rows.each do |row|
34
+ tbody
23
35
  tr
36
+ td= row_toggler
24
37
  td= row.answered_on
38
+ td= row.total_score
25
39
  - pos_s_summary_part.question_labels.each do |code, label|
26
40
  - value = row.send(code.to_sym)
27
- td(class="pos-s--#{value}") = value
41
+ - patient_question_text = row.try(:"#{code}_patient_question_text")
42
+ td(class="pos-s--#{value}")
43
+ - if patient_question_text
44
+ span(title="Toggle row for question text")= value
45
+ sup= superscript_char.chr
46
+ - superscript_char += 1
47
+ - else
48
+ = value
49
+ tr
50
+ td
51
+ td
52
+ td
53
+ td(class="summary-part--pos_s-patient-question-text" colspan=(pos_s_summary_part.question_labels.count ))
54
+ - superscript_char = 97
55
+ - pos_s_summary_part.question_labels.each do |code, label|
56
+ - patient_question_text = row.try(:"#{code}_patient_question_text")
57
+ - if patient_question_text
58
+ sup= superscript_char.chr
59
+ | &nbsp;
60
+ span= patient_question_text
61
+ | &nbsp;&nbsp;
62
+ - superscript_char += 1
28
63
 
64
+ / Colour-coded key
29
65
  dl.pos-s-key
30
66
  dt.pos-s--0 0
31
67
  dd Not at all
@@ -0,0 +1,12 @@
1
+ class UpdateSurveyViews < ActiveRecord::Migration[5.2]
2
+ def change
3
+ within_renalware_schema do
4
+ update_view(
5
+ :survey_pos_s_pivoted_responses,
6
+ version: 2,
7
+ revert_to_version: 1,
8
+ materialized: false
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ class AddPatientQuestionTextToSurveyResponses < ActiveRecord::Migration[5.2]
2
+ def change
3
+ within_renalware_schema do
4
+ add_column :survey_responses, :patient_question_text, :text
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,12 @@
1
+ class UpdateSurveyViewsToAllowFreeText < ActiveRecord::Migration[5.2]
2
+ def change
3
+ within_renalware_schema do
4
+ update_view(
5
+ :survey_pos_s_pivoted_responses,
6
+ version: 3,
7
+ revert_to_version: 2,
8
+ materialized: false
9
+ )
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,37 @@
1
+ /*
2
+ This is a pivoted crosstab view taking POS-S renal questionnaire responses from
3
+ patients and returning them with the question codes as the column headings.
4
+ See also the eq5d_5l for comments about alternative use of crosstab function.
5
+ */
6
+ SELECT r.answered_on,
7
+ r.patient_id,
8
+ sum(r.value::integer) as "total_score",
9
+ MAX(CASE WHEN q.code = 'YSQ1' THEN r.value ELSE NULL END) AS "YSQ1",
10
+ MAX(CASE WHEN q.code = 'YSQ2' THEN r.value ELSE NULL END) AS "YSQ2",
11
+ MAX(CASE WHEN q.code = 'YSQ3' THEN r.value ELSE NULL END) AS "YSQ3",
12
+ MAX(CASE WHEN q.code = 'YSQ4' THEN r.value ELSE NULL END) AS "YSQ4",
13
+ MAX(CASE WHEN q.code = 'YSQ5' THEN r.value ELSE NULL END) AS "YSQ5",
14
+ MAX(CASE WHEN q.code = 'YSQ6' THEN r.value ELSE NULL END) AS "YSQ6",
15
+ MAX(CASE WHEN q.code = 'YSQ7' THEN r.value ELSE NULL END) AS "YSQ7",
16
+ MAX(CASE WHEN q.code = 'YSQ8' THEN r.value ELSE NULL END) AS "YSQ8",
17
+ MAX(CASE WHEN q.code = 'YSQ9' THEN r.value ELSE NULL END) AS "YSQ9",
18
+ MAX(CASE WHEN q.code = 'YSQ10' THEN r.value ELSE NULL END) AS "YSQ10",
19
+ MAX(CASE WHEN q.code = 'YSQ11' THEN r.value ELSE NULL END) AS "YSQ11",
20
+ MAX(CASE WHEN q.code = 'YSQ12' THEN r.value ELSE NULL END) AS "YSQ12",
21
+ MAX(CASE WHEN q.code = 'YSQ13' THEN r.value ELSE NULL END) AS "YSQ13",
22
+ MAX(CASE WHEN q.code = 'YSQ14' THEN r.value ELSE NULL END) AS "YSQ14",
23
+ MAX(CASE WHEN q.code = 'YSQ15' THEN r.value ELSE NULL END) AS "YSQ15",
24
+ MAX(CASE WHEN q.code = 'YSQ16' THEN r.value ELSE NULL END) AS "YSQ16",
25
+ MAX(CASE WHEN q.code = 'YSQ17' THEN r.value ELSE NULL END) AS "YSQ17",
26
+ MAX(CASE WHEN q.code = 'YSQ18' THEN r.value ELSE NULL END) AS "YSQ18",
27
+ MAX(CASE WHEN q.code = 'YSQ19' THEN r.value ELSE NULL END) AS "YSQ19",
28
+ MAX(CASE WHEN q.code = 'YSQ20' THEN r.value ELSE NULL END) AS "YSQ20",
29
+ MAX(CASE WHEN q.code = 'YSQ21' THEN r.value ELSE NULL END) AS "YSQ21",
30
+ MAX(CASE WHEN q.code = 'YSQ22' THEN r.value ELSE NULL END) AS "YSQ22"
31
+
32
+ FROM survey_responses r
33
+ inner JOIN survey_questions q ON q.id = r.question_id
34
+ inner JOIN survey_surveys s ON s.id = q.survey_id
35
+ WHERE s.code = 'prom'
36
+ GROUP BY r.answered_on, r.patient_id
37
+ ORDER BY r.answered_on DESC;
@@ -0,0 +1,39 @@
1
+ /*
2
+ This is a pivoted crosstab view taking POS-S renal questionnaire responses from
3
+ patients and returning them with the question codes as the column headings.
4
+ See also the eq5d_5l for comments about alternative use of crosstab function.
5
+ */
6
+ SELECT r.answered_on,
7
+ r.patient_id,
8
+ sum(convert_to_float(r.value))::integer as "total_score",
9
+ MAX(CASE WHEN q.code = 'YSQ1' THEN r.value ELSE NULL END) AS "YSQ1",
10
+ MAX(CASE WHEN q.code = 'YSQ2' THEN r.value ELSE NULL END) AS "YSQ2",
11
+ MAX(CASE WHEN q.code = 'YSQ3' THEN r.value ELSE NULL END) AS "YSQ3",
12
+ MAX(CASE WHEN q.code = 'YSQ4' THEN r.value ELSE NULL END) AS "YSQ4",
13
+ MAX(CASE WHEN q.code = 'YSQ5' THEN r.value ELSE NULL END) AS "YSQ5",
14
+ MAX(CASE WHEN q.code = 'YSQ6' THEN r.value ELSE NULL END) AS "YSQ6",
15
+ MAX(CASE WHEN q.code = 'YSQ7' THEN r.value ELSE NULL END) AS "YSQ7",
16
+ MAX(CASE WHEN q.code = 'YSQ8' THEN r.value ELSE NULL END) AS "YSQ8",
17
+ MAX(CASE WHEN q.code = 'YSQ9' THEN r.value ELSE NULL END) AS "YSQ9",
18
+ MAX(CASE WHEN q.code = 'YSQ10' THEN r.value ELSE NULL END) AS "YSQ10",
19
+ MAX(CASE WHEN q.code = 'YSQ11' THEN r.value ELSE NULL END) AS "YSQ11",
20
+ MAX(CASE WHEN q.code = 'YSQ12' THEN r.value ELSE NULL END) AS "YSQ12",
21
+ MAX(CASE WHEN q.code = 'YSQ13' THEN r.value ELSE NULL END) AS "YSQ13",
22
+ MAX(CASE WHEN q.code = 'YSQ14' THEN r.value ELSE NULL END) AS "YSQ14",
23
+ MAX(CASE WHEN q.code = 'YSQ15' THEN r.value ELSE NULL END) AS "YSQ15",
24
+ MAX(CASE WHEN q.code = 'YSQ16' THEN r.value ELSE NULL END) AS "YSQ16",
25
+ MAX(CASE WHEN q.code = 'YSQ17' THEN r.value ELSE NULL END) AS "YSQ17",
26
+ MAX(CASE WHEN q.code = 'YSQ18' THEN r.value ELSE NULL END) AS "YSQ18",
27
+ MAX(CASE WHEN q.code = 'YSQ19' THEN r.value ELSE NULL END) AS "YSQ19",
28
+ MAX(CASE WHEN q.code = 'YSQ20' THEN r.value ELSE NULL END) AS "YSQ20",
29
+ MAX(CASE WHEN q.code = 'YSQ21' THEN r.value ELSE NULL END) AS "YSQ21",
30
+ MAX(CASE WHEN q.code = 'YSQ22' THEN r.value ELSE NULL END) AS "YSQ22",
31
+ MAX(CASE WHEN q.code = 'YSQ18' THEN r.patient_question_text ELSE NULL END) AS "YSQ18_patient_question_text",
32
+ MAX(CASE WHEN q.code = 'YSQ19' THEN r.patient_question_text ELSE NULL END) AS "YSQ19_patient_question_text",
33
+ MAX(CASE WHEN q.code = 'YSQ20' THEN r.patient_question_text ELSE NULL END) AS "YSQ20_patient_question_text"
34
+ FROM survey_responses r
35
+ inner JOIN survey_questions q ON q.id = r.question_id
36
+ inner JOIN survey_surveys s ON s.id = q.survey_id
37
+ WHERE s.code = 'prom'
38
+ GROUP BY r.answered_on, r.patient_id
39
+ ORDER BY r.answered_on DESC;
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Renalware
4
- VERSION = "2.0.126"
4
+ VERSION = "2.0.127"
5
5
  end
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.126
4
+ version: 2.0.127
5
5
  platform: ruby
6
6
  authors:
7
7
  - Airslie
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-12-04 00:00:00.000000000 Z
11
+ date: 2019-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview-component
@@ -1084,6 +1084,7 @@ files:
1084
1084
  - app/assets/stylesheets/renalware/modules/_problems.scss
1085
1085
  - app/assets/stylesheets/renalware/modules/_renal.scss
1086
1086
  - app/assets/stylesheets/renalware/modules/_reporting.scss
1087
+ - app/assets/stylesheets/renalware/modules/_rotated_tables_headings.scss
1087
1088
  - app/assets/stylesheets/renalware/modules/_snippets.scss
1088
1089
  - app/assets/stylesheets/renalware/modules/_surveys.scss
1089
1090
  - app/assets/stylesheets/renalware/modules/_system.scss
@@ -3719,6 +3720,9 @@ files:
3719
3720
  - db/migrate/20191105095304_update_views_to_exclude_deleted_sessions.rb
3720
3721
  - db/migrate/20191108105923_add_named_consultant_to_patients.rb
3721
3722
  - db/migrate/20191203112310_add_pg_stat_statements_extension.rb
3723
+ - db/migrate/20191205185835_update_survey_views.rb
3724
+ - db/migrate/20191209160151_add_patient_question_text_to_survey_responses.rb
3725
+ - db/migrate/20191209163151_update_survey_views_to_allow_free_text.rb
3722
3726
  - db/seeds.rb
3723
3727
  - db/seeds/default/accesses/access_pd_catheter_insertion_techniques.csv
3724
3728
  - db/seeds/default/accesses/access_pd_catheter_insertion_techniques.rb
@@ -3851,6 +3855,8 @@ files:
3851
3855
  - db/views/reporting_pd_audit_v01.sql
3852
3856
  - db/views/survey_eq5d_pivoted_responses_v01.sql
3853
3857
  - db/views/survey_pos_s_pivoted_responses_v01.sql
3858
+ - db/views/survey_pos_s_pivoted_responses_v02.sql
3859
+ - db/views/survey_pos_s_pivoted_responses_v03.sql
3854
3860
  - lib/age_calculator.rb
3855
3861
  - lib/array_stringifier.rb
3856
3862
  - lib/breadcrumb.rb