caruby-scat 1.2.1
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.
- data/.gitignore +17 -0
- data/Gemfile +25 -0
- data/Gemfile.lock +158 -0
- data/History.md +9 -0
- data/LEGAL +4 -0
- data/LICENSE +22 -0
- data/README.md +131 -0
- data/Rakefile +41 -0
- data/bin/scat +7 -0
- data/bin/scatseed +10 -0
- data/caruby-scat.gemspec +30 -0
- data/conf/fields.yaml +22 -0
- data/conf/redis.conf +492 -0
- data/config.ru +15 -0
- data/features/edit.feature +29 -0
- data/features/step_definitions/scat_steps.rb +50 -0
- data/features/support/env.rb +18 -0
- data/features/support/seed.rb +2 -0
- data/lib/scat.rb +56 -0
- data/lib/scat/autocomplete.rb +74 -0
- data/lib/scat/cache.rb +90 -0
- data/lib/scat/configuration.rb +79 -0
- data/lib/scat/edit.rb +160 -0
- data/lib/scat/field.rb +99 -0
- data/lib/scat/version.rb +3 -0
- data/public/images/apple-touch-icon-114x114.png +0 -0
- data/public/images/apple-touch-icon-72x72.png +0 -0
- data/public/images/apple-touch-icon.png +0 -0
- data/public/images/favicon.ico +0 -0
- data/public/images/help.png +0 -0
- data/public/javascripts/tabs.js +29 -0
- data/public/robots.txt +5 -0
- data/public/stylesheets/base.css +342 -0
- data/public/stylesheets/layout.css +58 -0
- data/public/stylesheets/scat.css +64 -0
- data/public/stylesheets/skeleton.css +242 -0
- data/redis.rdb +0 -0
- data/spec/autocomplete_spec.rb +17 -0
- data/spec/edit_spec.rb +60 -0
- data/spec/spec_helper.rb +13 -0
- data/test/fixtures/seed.rb +25 -0
- data/views/edit.haml +12 -0
- data/views/layout.haml +40 -0
- metadata +216 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
/*
|
2
|
+
* Skeleton V1.1
|
3
|
+
* Copyright 2011, Dave Gamache
|
4
|
+
* www.getskeleton.com
|
5
|
+
* Free to use under the MIT license.
|
6
|
+
* http://www.opensource.org/licenses/mit-license.php
|
7
|
+
* 8/17/2011
|
8
|
+
*/
|
9
|
+
|
10
|
+
/* Table of Content
|
11
|
+
==================================================
|
12
|
+
#Site Styles
|
13
|
+
#Page Styles
|
14
|
+
#Media Queries
|
15
|
+
#Font-Face */
|
16
|
+
|
17
|
+
/* #Site Styles
|
18
|
+
================================================== */
|
19
|
+
|
20
|
+
/* #Page Styles
|
21
|
+
================================================== */
|
22
|
+
|
23
|
+
/* #Media Queries
|
24
|
+
================================================== */
|
25
|
+
|
26
|
+
/* Smaller than standard 960 (devices and browsers) */
|
27
|
+
@media only screen and (max-width: 959px) {}
|
28
|
+
|
29
|
+
/* Tablet Portrait size to standard 960 (devices and browsers) */
|
30
|
+
@media only screen and (min-width: 768px) and (max-width: 959px) {}
|
31
|
+
|
32
|
+
/* All Mobile Sizes (devices and browser) */
|
33
|
+
@media only screen and (max-width: 767px) {}
|
34
|
+
|
35
|
+
/* Mobile Landscape Size to Tablet Portrait (devices and browsers) */
|
36
|
+
@media only screen and (min-width: 480px) and (max-width: 767px) {}
|
37
|
+
|
38
|
+
/* Mobile Portrait Size to Mobile Landscape Size (devices and browsers) */
|
39
|
+
@media only screen and (max-width: 479px) {}
|
40
|
+
|
41
|
+
|
42
|
+
/* #Font-Face
|
43
|
+
================================================== */
|
44
|
+
/* This is the proper syntax for an @font-face file
|
45
|
+
Just create a "fonts" folder at the root,
|
46
|
+
copy your FontName into code below and remove
|
47
|
+
comment brackets */
|
48
|
+
|
49
|
+
/* @font-face {
|
50
|
+
font-family: 'FontName';
|
51
|
+
src: url('../fonts/FontName.eot');
|
52
|
+
src: url('../fonts/FontName.eot?iefix') format('eot'),
|
53
|
+
url('../fonts/FontName.woff') format('woff'),
|
54
|
+
url('../fonts/FontName.ttf') format('truetype'),
|
55
|
+
url('../fonts/FontName.svg#webfontZam02nTh') format('svg');
|
56
|
+
font-weight: normal;
|
57
|
+
font-style: normal; }
|
58
|
+
*/
|
@@ -0,0 +1,64 @@
|
|
1
|
+
body {
|
2
|
+
background: #FAFFF6
|
3
|
+
}
|
4
|
+
|
5
|
+
h1.application {
|
6
|
+
font-family: "Handwriting - Dakota", Pristina, "Rage Italic", "Comic Sans MS", Georgia, serif;
|
7
|
+
font-weight: bold;
|
8
|
+
color: DarkBlue;
|
9
|
+
}
|
10
|
+
|
11
|
+
a.help {
|
12
|
+
display: block;
|
13
|
+
float: left;
|
14
|
+
left: -20px;
|
15
|
+
top: 4px;
|
16
|
+
text-decoration: none;
|
17
|
+
position: relative;
|
18
|
+
}
|
19
|
+
|
20
|
+
a.help img {
|
21
|
+
width: 15px;
|
22
|
+
height: 15px;
|
23
|
+
}
|
24
|
+
|
25
|
+
a.help span {
|
26
|
+
display: none;
|
27
|
+
}
|
28
|
+
|
29
|
+
a.help:hover span {
|
30
|
+
display: block;
|
31
|
+
position: absolute;
|
32
|
+
width: 180px;
|
33
|
+
padding: 5px 5px;
|
34
|
+
margin: 0 0 1px;
|
35
|
+
border: 1px solid black;
|
36
|
+
z-index: 100;
|
37
|
+
background-color: #eeeeee;
|
38
|
+
font: 10px sans-serif;
|
39
|
+
}
|
40
|
+
|
41
|
+
label {
|
42
|
+
left: -15px;
|
43
|
+
position: relative;
|
44
|
+
}
|
45
|
+
|
46
|
+
.ui-menu .ui-menu-item a {
|
47
|
+
font-size: smaller;
|
48
|
+
line-height: 1;
|
49
|
+
}
|
50
|
+
|
51
|
+
input[type='checkbox'] {
|
52
|
+
position: relative;
|
53
|
+
left: -1em;
|
54
|
+
margin-bottom: 20px;
|
55
|
+
}
|
56
|
+
|
57
|
+
#malignant label {
|
58
|
+
float: left;
|
59
|
+
}
|
60
|
+
|
61
|
+
#quantity input {
|
62
|
+
max-width: 8em;
|
63
|
+
}
|
64
|
+
|
@@ -0,0 +1,242 @@
|
|
1
|
+
/*
|
2
|
+
* Skeleton V1.1
|
3
|
+
* Copyright 2011, Dave Gamache
|
4
|
+
* www.getskeleton.com
|
5
|
+
* Free to use under the MIT license.
|
6
|
+
* http://www.opensource.org/licenses/mit-license.php
|
7
|
+
* 8/17/2011
|
8
|
+
*/
|
9
|
+
|
10
|
+
|
11
|
+
/* Table of Contents
|
12
|
+
==================================================
|
13
|
+
#Base 960 Grid
|
14
|
+
#Tablet (Portrait)
|
15
|
+
#Mobile (Portrait)
|
16
|
+
#Mobile (Landscape)
|
17
|
+
#Clearing */
|
18
|
+
|
19
|
+
|
20
|
+
|
21
|
+
/* #Base 960 Grid
|
22
|
+
================================================== */
|
23
|
+
|
24
|
+
.container { position: relative; width: 960px; margin: 0 auto; padding: 0; }
|
25
|
+
.container .column,
|
26
|
+
.container .columns { float: left; display: inline; margin-left: 10px; margin-right: 10px; }
|
27
|
+
.row { margin-bottom: 20px; }
|
28
|
+
|
29
|
+
/* Nested Column Classes */
|
30
|
+
.column.alpha, .columns.alpha { margin-left: 0; }
|
31
|
+
.column.omega, .columns.omega { margin-right: 0; }
|
32
|
+
|
33
|
+
/* Base Grid */
|
34
|
+
.container .one.column,
|
35
|
+
.container .one.columns { width: 40px; }
|
36
|
+
.container .two.columns { width: 100px; }
|
37
|
+
.container .three.columns { width: 160px; }
|
38
|
+
.container .four.columns { width: 220px; }
|
39
|
+
.container .five.columns { width: 280px; }
|
40
|
+
.container .six.columns { width: 340px; }
|
41
|
+
.container .seven.columns { width: 400px; }
|
42
|
+
.container .eight.columns { width: 460px; }
|
43
|
+
.container .nine.columns { width: 520px; }
|
44
|
+
.container .ten.columns { width: 580px; }
|
45
|
+
.container .eleven.columns { width: 640px; }
|
46
|
+
.container .twelve.columns { width: 700px; }
|
47
|
+
.container .thirteen.columns { width: 760px; }
|
48
|
+
.container .fourteen.columns { width: 820px; }
|
49
|
+
.container .fifteen.columns { width: 880px; }
|
50
|
+
.container .sixteen.columns { width: 940px; }
|
51
|
+
|
52
|
+
.container .one-third.column { width: 300px; }
|
53
|
+
.container .two-thirds.column { width: 620px; }
|
54
|
+
|
55
|
+
/* Offsets */
|
56
|
+
.container .offset-by-one { padding-left: 60px; }
|
57
|
+
.container .offset-by-two { padding-left: 120px; }
|
58
|
+
.container .offset-by-three { padding-left: 180px; }
|
59
|
+
.container .offset-by-four { padding-left: 240px; }
|
60
|
+
.container .offset-by-five { padding-left: 300px; }
|
61
|
+
.container .offset-by-six { padding-left: 360px; }
|
62
|
+
.container .offset-by-seven { padding-left: 420px; }
|
63
|
+
.container .offset-by-eight { padding-left: 480px; }
|
64
|
+
.container .offset-by-nine { padding-left: 540px; }
|
65
|
+
.container .offset-by-ten { padding-left: 600px; }
|
66
|
+
.container .offset-by-eleven { padding-left: 660px; }
|
67
|
+
.container .offset-by-twelve { padding-left: 720px; }
|
68
|
+
.container .offset-by-thirteen { padding-left: 780px; }
|
69
|
+
.container .offset-by-fourteen { padding-left: 840px; }
|
70
|
+
.container .offset-by-fifteen { padding-left: 900px; }
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
/* #Tablet (Portrait)
|
75
|
+
================================================== */
|
76
|
+
|
77
|
+
/* Note: Design for a width of 768px */
|
78
|
+
|
79
|
+
@media only screen and (min-width: 768px) and (max-width: 959px) {
|
80
|
+
.container { width: 768px; }
|
81
|
+
.container .column,
|
82
|
+
.container .columns { margin-left: 10px; margin-right: 10px; }
|
83
|
+
.column.alpha, .columns.alpha { margin-left: 0; margin-right: 10px; }
|
84
|
+
.column.omega, .columns.omega { margin-right: 0; margin-left: 10px; }
|
85
|
+
.alpha.omega { margin-left: 0; margin-right: 0; }
|
86
|
+
|
87
|
+
.container .one.column,
|
88
|
+
.container .one.columns { width: 28px; }
|
89
|
+
.container .two.columns { width: 76px; }
|
90
|
+
.container .three.columns { width: 124px; }
|
91
|
+
.container .four.columns { width: 172px; }
|
92
|
+
.container .five.columns { width: 220px; }
|
93
|
+
.container .six.columns { width: 268px; }
|
94
|
+
.container .seven.columns { width: 316px; }
|
95
|
+
.container .eight.columns { width: 364px; }
|
96
|
+
.container .nine.columns { width: 412px; }
|
97
|
+
.container .ten.columns { width: 460px; }
|
98
|
+
.container .eleven.columns { width: 508px; }
|
99
|
+
.container .twelve.columns { width: 556px; }
|
100
|
+
.container .thirteen.columns { width: 604px; }
|
101
|
+
.container .fourteen.columns { width: 652px; }
|
102
|
+
.container .fifteen.columns { width: 700px; }
|
103
|
+
.container .sixteen.columns { width: 748px; }
|
104
|
+
|
105
|
+
.container .one-third.column { width: 236px; }
|
106
|
+
.container .two-thirds.column { width: 492px; }
|
107
|
+
|
108
|
+
/* Offsets */
|
109
|
+
.container .offset-by-one { padding-left: 48px; }
|
110
|
+
.container .offset-by-two { padding-left: 96px; }
|
111
|
+
.container .offset-by-three { padding-left: 144px; }
|
112
|
+
.container .offset-by-four { padding-left: 192px; }
|
113
|
+
.container .offset-by-five { padding-left: 240px; }
|
114
|
+
.container .offset-by-six { padding-left: 288px; }
|
115
|
+
.container .offset-by-seven { padding-left: 336px; }
|
116
|
+
.container .offset-by-eight { padding-left: 384px; }
|
117
|
+
.container .offset-by-nine { padding-left: 432px; }
|
118
|
+
.container .offset-by-ten { padding-left: 480px; }
|
119
|
+
.container .offset-by-eleven { padding-left: 528px; }
|
120
|
+
.container .offset-by-twelve { padding-left: 576px; }
|
121
|
+
.container .offset-by-thirteen { padding-left: 624px; }
|
122
|
+
.container .offset-by-fourteen { padding-left: 672px; }
|
123
|
+
.container .offset-by-fifteen { padding-left: 720px; }
|
124
|
+
}
|
125
|
+
|
126
|
+
|
127
|
+
/* #Mobile (Portrait)
|
128
|
+
================================================== */
|
129
|
+
|
130
|
+
/* Note: Design for a width of 320px */
|
131
|
+
|
132
|
+
@media only screen and (max-width: 767px) {
|
133
|
+
.container { width: 300px; }
|
134
|
+
.container .columns,
|
135
|
+
.container .column { margin: 0; }
|
136
|
+
|
137
|
+
.container .one.column,
|
138
|
+
.container .one.columns,
|
139
|
+
.container .two.columns,
|
140
|
+
.container .three.columns,
|
141
|
+
.container .four.columns,
|
142
|
+
.container .five.columns,
|
143
|
+
.container .six.columns,
|
144
|
+
.container .seven.columns,
|
145
|
+
.container .eight.columns,
|
146
|
+
.container .nine.columns,
|
147
|
+
.container .ten.columns,
|
148
|
+
.container .eleven.columns,
|
149
|
+
.container .twelve.columns,
|
150
|
+
.container .thirteen.columns,
|
151
|
+
.container .fourteen.columns,
|
152
|
+
.container .fifteen.columns,
|
153
|
+
.container .sixteen.columns,
|
154
|
+
.container .one-third.column,
|
155
|
+
.container .two-thirds.column { width: 300px; }
|
156
|
+
|
157
|
+
/* Offsets */
|
158
|
+
.container .offset-by-one,
|
159
|
+
.container .offset-by-two,
|
160
|
+
.container .offset-by-three,
|
161
|
+
.container .offset-by-four,
|
162
|
+
.container .offset-by-five,
|
163
|
+
.container .offset-by-six,
|
164
|
+
.container .offset-by-seven,
|
165
|
+
.container .offset-by-eight,
|
166
|
+
.container .offset-by-nine,
|
167
|
+
.container .offset-by-ten,
|
168
|
+
.container .offset-by-eleven,
|
169
|
+
.container .offset-by-twelve,
|
170
|
+
.container .offset-by-thirteen,
|
171
|
+
.container .offset-by-fourteen,
|
172
|
+
.container .offset-by-fifteen { padding-left: 0; }
|
173
|
+
|
174
|
+
}
|
175
|
+
|
176
|
+
|
177
|
+
/* #Mobile (Landscape)
|
178
|
+
================================================== */
|
179
|
+
|
180
|
+
/* Note: Design for a width of 480px */
|
181
|
+
|
182
|
+
@media only screen and (min-width: 480px) and (max-width: 767px) {
|
183
|
+
.container { width: 420px; }
|
184
|
+
.container .columns,
|
185
|
+
.container .column { margin: 0; }
|
186
|
+
|
187
|
+
.container .one.column,
|
188
|
+
.container .one.columns,
|
189
|
+
.container .two.columns,
|
190
|
+
.container .three.columns,
|
191
|
+
.container .four.columns,
|
192
|
+
.container .five.columns,
|
193
|
+
.container .six.columns,
|
194
|
+
.container .seven.columns,
|
195
|
+
.container .eight.columns,
|
196
|
+
.container .nine.columns,
|
197
|
+
.container .ten.columns,
|
198
|
+
.container .eleven.columns,
|
199
|
+
.container .twelve.columns,
|
200
|
+
.container .thirteen.columns,
|
201
|
+
.container .fourteen.columns,
|
202
|
+
.container .fifteen.columns,
|
203
|
+
.container .sixteen.columns,
|
204
|
+
.container .one-third.column,
|
205
|
+
.container .two-thirds.column { width: 420px; }
|
206
|
+
}
|
207
|
+
|
208
|
+
|
209
|
+
/* #Clearing
|
210
|
+
================================================== */
|
211
|
+
|
212
|
+
/* Self Clearing Goodness */
|
213
|
+
.container:after { content: "\0020"; display: block; height: 0; clear: both; visibility: hidden; }
|
214
|
+
|
215
|
+
/* Use clearfix class on parent to clear nested columns,
|
216
|
+
or wrap each row of columns in a <div class="row"> */
|
217
|
+
.clearfix:before,
|
218
|
+
.clearfix:after,
|
219
|
+
.row:before,
|
220
|
+
.row:after {
|
221
|
+
content: '\0020';
|
222
|
+
display: block;
|
223
|
+
overflow: hidden;
|
224
|
+
visibility: hidden;
|
225
|
+
width: 0;
|
226
|
+
height: 0; }
|
227
|
+
.row:after,
|
228
|
+
.clearfix:after {
|
229
|
+
clear: both; }
|
230
|
+
.row,
|
231
|
+
.clearfix {
|
232
|
+
zoom: 1; }
|
233
|
+
|
234
|
+
/* You can also use a <br class="clear" /> to clear columns */
|
235
|
+
.clear {
|
236
|
+
clear: both;
|
237
|
+
display: block;
|
238
|
+
overflow: hidden;
|
239
|
+
visibility: hidden;
|
240
|
+
width: 0;
|
241
|
+
height: 0;
|
242
|
+
}
|
data/redis.rdb
ADDED
Binary file
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
|
3
|
+
describe Scat do
|
4
|
+
describe 'Auto-complete' do
|
5
|
+
include Scat::Autocomplete
|
6
|
+
|
7
|
+
AC_TARGET ||= 'Malignant lymphoma'
|
8
|
+
|
9
|
+
it "should find matching diagnoses" do
|
10
|
+
matches = autocomplete(:clinical_diagnosis, AC_TARGET)
|
11
|
+
matches.should_not be_empty
|
12
|
+
matches.each do |cv|
|
13
|
+
cv.downcase.should match AC_TARGET.downcase
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/edit_spec.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'spec/spec_helper'
|
2
|
+
require 'jinx/helpers/string_uniquifier'
|
3
|
+
require 'scat/edit'
|
4
|
+
require File.dirname(__FILE__) + '/../test/fixtures/seed'
|
5
|
+
|
6
|
+
describe Scat do
|
7
|
+
describe 'Edit' do
|
8
|
+
before(:all) do
|
9
|
+
title = Jinx::StringUniquifier.uniquify('Scat')
|
10
|
+
pcl = Scat::Seed.protocol_for(title).find(:create)
|
11
|
+
@params = {
|
12
|
+
:user => pcl.coordinators.first,
|
13
|
+
:protocol => title,
|
14
|
+
:mrn => Jinx::StringUniquifier.uniquify('Test'),
|
15
|
+
:spn => Jinx::StringUniquifier.uniquify('Test'),
|
16
|
+
:diagnosis => '[M]Adrenal cortical adenoma NOS',
|
17
|
+
:tissue_site => 'Adrenal gland, NOS',
|
18
|
+
:malignant => 'Malignant',
|
19
|
+
:quantity => '4'
|
20
|
+
}
|
21
|
+
@spc = Scat::Edit.instance.save(@params)
|
22
|
+
end
|
23
|
+
|
24
|
+
subject { @spc }
|
25
|
+
|
26
|
+
it "should save the specimen" do
|
27
|
+
subject.identifier.should_not be nil
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should set the properties" do
|
31
|
+
subject.pathological_status.should == 'Malignant'
|
32
|
+
scg = subject.specimen_collection_group
|
33
|
+
scg.clinical_diagnosis.should == '[M]Adrenal cortical adenoma NOS'
|
34
|
+
subject.characteristics.tissue_site.should == 'Adrenal gland, NOS'
|
35
|
+
subject.initial_quantity.should == 4.0
|
36
|
+
end
|
37
|
+
|
38
|
+
context "add a normal specimen to an existing SCG" do
|
39
|
+
before(:all) do
|
40
|
+
oparams = @params.delete_if { |k, v| k == :malignant }
|
41
|
+
oparams[:quantity] = '5'
|
42
|
+
@other = Scat::Edit.instance.save(oparams)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should save the additional specimen" do
|
46
|
+
@other.identifier.should_not be nil
|
47
|
+
@other.identifier.should_not == subject.identifier
|
48
|
+
@other.initial_quantity.should == 5.0
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should be non-malignant" do
|
52
|
+
@other.pathological_status.should == 'Non-Malignant'
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should use the same SCG" do
|
56
|
+
@other.specimen_collection_group.identifier.should be subject.specimen_collection_group.identifier
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler/setup'
|
3
|
+
Bundler.require(:test, :development)
|
4
|
+
require 'scat'
|
5
|
+
|
6
|
+
module Scat::Test
|
7
|
+
RESULTS = File.dirname(__FILE__) + '/../test/results'
|
8
|
+
end
|
9
|
+
|
10
|
+
# Open the logger.
|
11
|
+
logger(Scat::Test::RESULTS + '/log/scat.log', :debug => true)
|
12
|
+
|
13
|
+
Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |f| require f }
|