renalware-core 2.0.126 → 2.0.127
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.
- checksums.yaml +4 -4
- data/app/assets/stylesheets/renalware/base/_variables.scss +2 -2
- data/app/assets/stylesheets/renalware/modules/_clinical.scss +3 -3
- data/app/assets/stylesheets/renalware/modules/_problems.scss +4 -1
- data/app/assets/stylesheets/renalware/modules/_rotated_tables_headings.scss +39 -0
- data/app/assets/stylesheets/renalware/modules/_surveys.scss +4 -0
- data/app/assets/stylesheets/renalware/partials/_forms.scss +1 -1
- data/app/assets/stylesheets/renalware/partials/_tables.scss +9 -3
- data/app/assets/stylesheets/renalware/partials/_tabs.scss +4 -4
- data/app/assets/stylesheets/renalware/partials/_toggling.scss +51 -1
- data/app/models/renalware/patients/ingestion/command_factory.rb +63 -51
- data/app/models/renalware/patients/ingestion/message_mappers/patient.rb +0 -17
- data/app/models/renalware/surveys/pos_s_summary_part.rb +9 -5
- data/app/models/renalware/ukrdc/incoming/import_survey.rb +6 -2
- data/app/models/renalware/ukrdc/incoming/xml_document.rb +11 -1
- data/app/presenters/renalware/hd/mdm_presenter.rb +6 -0
- data/app/presenters/renalware/problems/summary_part.rb +1 -1
- data/app/views/renalware/hd/mdm/_top.html.slim +12 -3
- data/app/views/renalware/hd/sessions/_row.html.slim +1 -1
- data/app/views/renalware/hd/sessions/dna/_row.html.slim +1 -1
- data/app/views/renalware/problems/problems/_current_table.html.slim +1 -1
- data/app/views/renalware/problems/problems/_summary_part.html.slim +21 -5
- data/app/views/renalware/surveys/_pos_s_summary_part.html.slim +43 -7
- data/db/migrate/20191205185835_update_survey_views.rb +12 -0
- data/db/migrate/20191209160151_add_patient_question_text_to_survey_responses.rb +7 -0
- data/db/migrate/20191209163151_update_survey_views_to_allow_free_text.rb +12 -0
- data/db/views/survey_pos_s_pivoted_responses_v02.sql +37 -0
- data/db/views/survey_pos_s_pivoted_responses_v03.sql +39 -0
- data/lib/renalware/version.rb +1 -1
- metadata +8 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 334da5d5d7e32ed650c55379a33eedf5d4bba077a4480f987aece96dcb498ac9
|
|
4
|
+
data.tar.gz: 97f0bce7f1420f0d3f87b32e56bab92847c8f4efc61f7b2ba187a55749cd22fb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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:
|
|
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: #
|
|
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: $
|
|
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
|
|
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
|
|
185
|
+
border-bottom: 1px solid $white;;
|
|
186
186
|
color: $white
|
|
187
187
|
}
|
|
188
188
|
|
|
@@ -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
|
+
}
|
|
@@ -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:
|
|
9
|
-
padding: 0.
|
|
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
|
|
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: $
|
|
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 $
|
|
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: $
|
|
103
|
-
background-color: $
|
|
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
|
-
//
|
|
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
|
|
18
|
+
when :add_person_information then make_add_patient(message)
|
|
15
19
|
when :update_person_information then make_update_patient(message)
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# when :
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
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
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
-
|
|
88
|
-
|
|
89
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
|
@@ -1,13 +1,22 @@
|
|
|
1
|
-
.columns.small-12.medium-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
|
-
|
|
13
|
+
|
|
14
|
+
.columns.medium-6
|
|
7
15
|
= render "renalware/virology/profiles/summary",
|
|
8
16
|
patient: mdm.patient,
|
|
9
17
|
positive_results_only: true
|
|
10
|
-
|
|
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
|
|
@@ -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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
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.
|
|
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
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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
|
+
|
|
|
60
|
+
span= patient_question_text
|
|
61
|
+
|
|
|
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,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;
|
data/lib/renalware/version.rb
CHANGED
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.
|
|
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-
|
|
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
|