hlsv 1.0.0
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 +7 -0
- data/CHANGELOG.md +5 -0
- data/LICENSE +676 -0
- data/README.md +356 -0
- data/bin/hlsv +4 -0
- data/config.default.yaml +19 -0
- data/lib/hlsv/cli.rb +85 -0
- data/lib/hlsv/find_keys.rb +979 -0
- data/lib/hlsv/html2word.rb +602 -0
- data/lib/hlsv/mon_script.rb +169 -0
- data/lib/hlsv/version.rb +5 -0
- data/lib/hlsv/web_app.rb +569 -0
- data/lib/hlsv/xpt/dataset.rb +38 -0
- data/lib/hlsv/xpt/library.rb +28 -0
- data/lib/hlsv/xpt/reader.rb +367 -0
- data/lib/hlsv/xpt/variable.rb +130 -0
- data/lib/hlsv/xpt.rb +11 -0
- data/lib/hlsv.rb +49 -0
- data/public/Contact-LOGO.png +0 -0
- data/public/app.js +569 -0
- data/public/styles.css +586 -0
- data/public/styles_csv.css +448 -0
- data/views/csv_view.erb +85 -0
- data/views/index.erb +233 -0
- data/views/report_template.erb +1144 -0
- metadata +176 -0
data/views/index.erb
ADDED
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Copyright (c) 2026 AdClin
|
|
3
|
+
|
|
4
|
+
This program is free software: you can redistribute it and/or modify
|
|
5
|
+
it under the terms of the GNU Affero General Public License as
|
|
6
|
+
published by the Free Software Foundation, either version 3 of the
|
|
7
|
+
License, or (at your option) any later version.
|
|
8
|
+
-->
|
|
9
|
+
|
|
10
|
+
<!DOCTYPE html>
|
|
11
|
+
<html lang="en">
|
|
12
|
+
<head>
|
|
13
|
+
<title>High Level Check on SDTM Packages</title>
|
|
14
|
+
<meta charset="UTF-8">
|
|
15
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
16
|
+
<link rel="stylesheet" href="/styles.css">
|
|
17
|
+
</head>
|
|
18
|
+
<body>
|
|
19
|
+
<!-- Header with title and logo -->
|
|
20
|
+
<header class="app-header">
|
|
21
|
+
<h1>🔍 High Level Check on SDTM Packages</h1>
|
|
22
|
+
<div class="company-branding">
|
|
23
|
+
<a href="https://adclin.com" target="_blank" rel="noopener noreferrer" class="company-link">
|
|
24
|
+
<img src="/Contact-LOGO.png" alt="AdClin Logo" class="company-logo">
|
|
25
|
+
</a>
|
|
26
|
+
</div>
|
|
27
|
+
</header>
|
|
28
|
+
|
|
29
|
+
<div class="info">
|
|
30
|
+
🔒 Local App - All data stays on your machine
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<!-- Configuration -->
|
|
34
|
+
<div class="container">
|
|
35
|
+
<h2>⚙️ Configuration</h2>
|
|
36
|
+
<h3>General Information</h3>
|
|
37
|
+
|
|
38
|
+
<div class="config-grid">
|
|
39
|
+
<div class="form-group">
|
|
40
|
+
<label for="study_name">Study Name <span class="required">*</span></label>
|
|
41
|
+
<input type="text" id="study_name" value="<%= @config['study_name'] %>" required aria-required="true">
|
|
42
|
+
<small>Unique identifier for this study</small>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<div class="form-group">
|
|
46
|
+
<label for="output_directory">Output Directory <span class="required">*</span></label>
|
|
47
|
+
<input type="text" id="output_directory" value="<%= @config['output_directory'] %>" required aria-required="true">
|
|
48
|
+
<small>Directory name where files with detected duplicates will be stored</small>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<div class="form-group">
|
|
53
|
+
<label for="data_directory">Datasets Directory <span class="required">*</span></label>
|
|
54
|
+
<input type="text" id="data_directory" value="<%= @config['data_directory'] %>" required aria-required="true">
|
|
55
|
+
<small>Path to the directory containing the <strong>xpt</strong> datasets to analyze</small>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="form-group">
|
|
59
|
+
<label for="define_path">Path to define.xml <span class="required">*</span></label>
|
|
60
|
+
<input type="text" id="define_path" value="<%= @config['define_path'] %>" required aria-required="true">
|
|
61
|
+
<small>Enter "-" to skip the define.xml validation part of the analysis</small>
|
|
62
|
+
</div>
|
|
63
|
+
|
|
64
|
+
<h3>Keys Search Information</h3>
|
|
65
|
+
<div class="info-section">
|
|
66
|
+
<p>This section contains the variables tested by default as part of a minimal and
|
|
67
|
+
natural key search for each dataset. These values serve as a starting point and can be adjusted
|
|
68
|
+
according to your needs.</p>
|
|
69
|
+
|
|
70
|
+
<p><strong>Guidelines for completing the form:</strong></p>
|
|
71
|
+
<ul>
|
|
72
|
+
<li><strong>Modifying variables:</strong> The proposed variables can be completed and/or
|
|
73
|
+
modified at any time. Feel free to adjust them based on your analysis.
|
|
74
|
+
</li>
|
|
75
|
+
|
|
76
|
+
<li><strong>"General Observation Datasets" and "DS" fields:</strong> For these fields, enter
|
|
77
|
+
the variable name without the dataset prefix. Example: If the variable to be
|
|
78
|
+
tested is LBSPEC, enter <strong>SPEC</strong> in the Findings Datasets field.
|
|
79
|
+
</li>
|
|
80
|
+
|
|
81
|
+
<li><strong>Other form fields:</strong> For all other fields, enter the full
|
|
82
|
+
variable name, exactly as it appears in the dataset.
|
|
83
|
+
</li>
|
|
84
|
+
|
|
85
|
+
<li><strong>"Excluded Datasets" field:</strong> All datasets listed here will be
|
|
86
|
+
excluded from the analysis. Any variables associated with these datasets
|
|
87
|
+
will not be considered, even if they are specified elsewhere in the form.
|
|
88
|
+
</li>
|
|
89
|
+
<li><strong>Recommendation:</strong> Include <em>identifier variables</em> only if absolutely necessary.</li>
|
|
90
|
+
</ul>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
<div class="form-group">
|
|
94
|
+
<label for="excluded_ds">Excluded Datasets</label>
|
|
95
|
+
<input type="text" id="excluded_ds" value="<%= @config['excluded_ds'] %>" placeholder="e.g., LB DV CO">
|
|
96
|
+
<small>Space-separated list of datasets to exclude (e.g., LB DV CO)</small>
|
|
97
|
+
</div>
|
|
98
|
+
|
|
99
|
+
<h4>General Observation Datasets</h4>
|
|
100
|
+
<div class="config-grid">
|
|
101
|
+
<div class="form-group">
|
|
102
|
+
<label for="event_key">Event datasets <span class="required">*</span></label>
|
|
103
|
+
<input type="text" id="event_key" value="<%= @config['event_key'] %>" required aria-required="true">
|
|
104
|
+
</div>
|
|
105
|
+
|
|
106
|
+
<div class="form-group">
|
|
107
|
+
<label for="intervention_key">Intervention datasets <span class="required">*</span></label>
|
|
108
|
+
<input type="text" id="intervention_key" value="<%= @config['intervention_key'] %>" required aria-required="true">
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<div class="form-group">
|
|
112
|
+
<label for="finding_about_key">Finding About datasets <span class="required">*</span></label>
|
|
113
|
+
<input type="text" id="finding_about_key" value="<%= @config['finding_about_key'] %>" required aria-required="true">
|
|
114
|
+
</div>
|
|
115
|
+
</div>
|
|
116
|
+
|
|
117
|
+
<div class="form-group">
|
|
118
|
+
<label for="finding_key">Findings datasets <span class="required">*</span></label>
|
|
119
|
+
<input type="text" id="finding_key" value="<%= @config['finding_key'] %>" required aria-required="true">
|
|
120
|
+
</div>
|
|
121
|
+
|
|
122
|
+
<h4>Special Datasets</h4>
|
|
123
|
+
<div class="config-grid">
|
|
124
|
+
<div class="form-group">
|
|
125
|
+
<label for="ds_key">DS <span class="required">*</span></label>
|
|
126
|
+
<input type="text" id="ds_key" value="<%= @config['ds_key'] %>" required aria-required="true">
|
|
127
|
+
</div>
|
|
128
|
+
|
|
129
|
+
<div class="form-group">
|
|
130
|
+
<label for="relrec_key">RELREC <span class="required">*</span></label>
|
|
131
|
+
<input type="text" id="relrec_key" value="<%= @config['relrec_key'] %>" required aria-required="true">
|
|
132
|
+
</div>
|
|
133
|
+
|
|
134
|
+
<div class="form-group">
|
|
135
|
+
<label for="CO_key">CO <span class="required">*</span></label>
|
|
136
|
+
<input type="text" id="CO_key" value="<%= @config['CO_key'] %>" required aria-required="true">
|
|
137
|
+
</div>
|
|
138
|
+
</div>
|
|
139
|
+
|
|
140
|
+
<h4>Trial Design Datasets</h4>
|
|
141
|
+
<div class="config-grid">
|
|
142
|
+
<div class="form-group">
|
|
143
|
+
<label for="TA_key">TA <span class="required">*</span></label>
|
|
144
|
+
<input type="text" id="TA_key" value="<%= @config['TA_key'] %>" required aria-required="true">
|
|
145
|
+
</div>
|
|
146
|
+
|
|
147
|
+
<div class="form-group">
|
|
148
|
+
<label for="TE_key">TE <span class="required">*</span></label>
|
|
149
|
+
<input type="text" id="TE_key" value="<%= @config['TE_key'] %>" required aria-required="true">
|
|
150
|
+
</div>
|
|
151
|
+
|
|
152
|
+
<div class="form-group">
|
|
153
|
+
<label for="TI_key">TI <span class="required">*</span></label>
|
|
154
|
+
<input type="text" id="TI_key" value="<%= @config['TI_key'] %>" required aria-required="true">
|
|
155
|
+
</div>
|
|
156
|
+
|
|
157
|
+
<div class="form-group">
|
|
158
|
+
<label for="TS_key">TS <span class="required">*</span></label>
|
|
159
|
+
<input type="text" id="TS_key" value="<%= @config['TS_key'] %>" required aria-required="true">
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<div class="form-group">
|
|
163
|
+
<label for="TV_key">TV <span class="required">*</span></label>
|
|
164
|
+
<input type="text" id="TV_key" value="<%= @config['TV_key'] %>" required aria-required="true">
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
<!-- Configuration Management Buttons -->
|
|
169
|
+
<div class="button-group">
|
|
170
|
+
<button onclick="sauvegarderConfig()" class="btn-primary" aria-label="Save current configuration">
|
|
171
|
+
💾 Save Current Configuration
|
|
172
|
+
</button>
|
|
173
|
+
<button class="btn-secondary" onclick="afficherConfigComplete()" aria-label="View current configuration">
|
|
174
|
+
📄 View Current Configuration
|
|
175
|
+
</button>
|
|
176
|
+
<button class="btn-danger" onclick="effacerChamps()" aria-label="Clear all fields">
|
|
177
|
+
🗑️ Clear All Fields
|
|
178
|
+
</button>
|
|
179
|
+
<button class="btn-secondary" onclick="chargerDefaut()" aria-label="Load default configuration">
|
|
180
|
+
📋 Load Default Configuration
|
|
181
|
+
</button>
|
|
182
|
+
</div>
|
|
183
|
+
|
|
184
|
+
<div id="message-config" role="status" aria-live="polite"></div>
|
|
185
|
+
</div>
|
|
186
|
+
|
|
187
|
+
<!-- Processing -->
|
|
188
|
+
<div class="container">
|
|
189
|
+
<h2>▶️ Start High Level Analysis</h2>
|
|
190
|
+
|
|
191
|
+
<p>This analysis will check:</p>
|
|
192
|
+
<ul>
|
|
193
|
+
<li>The presence of non-ASCII characters in the data</li>
|
|
194
|
+
<li>The validity of keys declared in define.xml</li>
|
|
195
|
+
<li>Ad hoc search for a natural key for all datasets</li>
|
|
196
|
+
</ul>
|
|
197
|
+
|
|
198
|
+
<button class="btn-success" onclick="lancerTraitement()" id="btn-traiter" aria-label="Start analysis">
|
|
199
|
+
🚀 Start Analysis
|
|
200
|
+
</button>
|
|
201
|
+
|
|
202
|
+
<div id="status-traitement" role="status" aria-live="polite"></div>
|
|
203
|
+
</div>
|
|
204
|
+
|
|
205
|
+
<!-- Results -->
|
|
206
|
+
<div class="container">
|
|
207
|
+
<h2>📁 Result Files</h2>
|
|
208
|
+
|
|
209
|
+
<div class="button-group">
|
|
210
|
+
<button class="btn-secondary" onclick="chargerResultats()" id="btn-load-results" aria-label="Load results">
|
|
211
|
+
📂 Load Results
|
|
212
|
+
</button>
|
|
213
|
+
<button class="btn-secondary" onclick="rafraichirResultats()" id="btn-refresh-results" style="display: none;" aria-label="Refresh results">
|
|
214
|
+
🔄 Refresh
|
|
215
|
+
</button>
|
|
216
|
+
<p>Browse files generated in the <code>hlsv_results/</code> directory</p>
|
|
217
|
+
</div>
|
|
218
|
+
|
|
219
|
+
<div id="liste-resultats" style="display: none;" role="region" aria-label="Results list"></div>
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
<!-- Footer with copyright and license on same line -->
|
|
223
|
+
<footer class="app-footer">
|
|
224
|
+
<div class="footer-content">
|
|
225
|
+
<span class="copyright">© 1999-2026 AdClin. All rights reserved.</span>
|
|
226
|
+
<span class="separator">•</span>
|
|
227
|
+
<span class="license">Licensed under <a href="<%= Hlsv::license_path %>" target="_blank" rel="noopener noreferrer">AGPL v3</a></span>
|
|
228
|
+
</div>
|
|
229
|
+
</footer>
|
|
230
|
+
|
|
231
|
+
<script src="/app.js"></script>
|
|
232
|
+
</body>
|
|
233
|
+
</html>
|