-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathecl-builder.html
More file actions
458 lines (444 loc) · 32.7 KB
/
ecl-builder.html
File metadata and controls
458 lines (444 loc) · 32.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>SafeRx — ECL Query Builder</title>
<link rel="stylesheet" href="css/styles.css">
<link rel="stylesheet" href="css/ecl-builder.css">
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23007AFF'><path d='M12 2L4 5v6.09c0 5.05 3.41 9.76 8 10.91 4.59-1.15 8-5.86 8-10.91V5l-8-3zm-1 14h2v2h-2v-2zm0-8h2v6h-2V8z'/><rect x='10.5' y='7' width='3' height='10' rx='1' fill='white'/><rect x='7' y='10.5' width='10' height='3' rx='1' fill='white'/></svg>">
</head>
<body class="ecl-body">
<!-- Top Bar -->
<header class="top-bar">
<div class="top-bar-left">
<div class="app-logo">
<span class="logo-icon"><svg width="22" height="22" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 2L4 5v6.09c0 5.05 3.41 9.76 8 10.91 4.59-1.15 8-5.86 8-10.91V5l-8-3z" fill="var(--blue)"/><rect x="10.75" y="7.5" width="2.5" height="9" rx="1.25" fill="white"/><rect x="7.5" y="10.75" width="9" height="2.5" rx="1.25" fill="white"/></svg></span>
<span class="logo-text">SafeRx</span>
</div>
</div>
<div class="top-bar-center">
<div class="demo-switcher" id="demoSwitcher">
<button class="demo-switcher-btn" id="demoSwitcherBtn">
<span class="demo-switcher-label">Demo</span>
<span class="demo-switcher-current" id="demoSwitcherCurrent">ECL Builder</span>
<svg class="demo-switcher-chevron" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M6 9l6 6 6-6"/></svg>
</button>
<div class="demo-switcher-dropdown" id="demoSwitcherDropdown">
<div class="demo-switcher-dropdown-header">Switch Demo</div>
<a class="demo-option" href="index.html" data-demo="prescribing-basic">
<div class="demo-option-name">Product Based Prescribing (basic)</div>
<div class="demo-option-desc">Basic medication prescribing with FHIR R4 resource generation</div>
</a>
<a class="demo-option active" href="ecl-builder.html" data-demo="ecl-builder">
<div class="demo-option-name">ECL Builder</div>
<div class="demo-option-desc">Build & test SNOMED CT Expression Constraint Language queries</div>
</a>
<a class="demo-option disabled" href="#" data-demo="prescribing-advanced">
<div class="demo-option-name">Product Based Prescribing (advanced)</div>
<div class="demo-option-desc">Coming soon</div>
</a>
<a class="demo-option disabled" href="#" data-demo="dispensing">
<div class="demo-option-name">Dispensing</div>
<div class="demo-option-desc">Coming soon</div>
</a>
</div>
</div>
</div>
<div class="top-bar-right">
<div class="status-popover-wrap" id="statusPopoverWrap">
<button class="connection-status" id="connectionStatus" title="Connection status — click for details">
<span class="status-dot disconnected"></span>
<span class="status-text">API Offline</span>
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M6 9l6 6 6-6"/></svg>
</button>
<div class="status-popover" id="statusPopover">
<div class="status-popover-header">Connection Status</div>
<div class="status-popover-current" id="statusPopoverCurrent">
<span class="status-dot disconnected"></span>
<span>API Offline — using unauthenticated requests</span>
</div>
<div class="status-popover-divider"></div>
<div class="status-popover-title">Status Guide</div>
<div class="status-popover-item">
<span class="status-dot connected"></span>
<div>
<strong>API Connected</strong>
<p>Successfully connected to the HSE NMPC FHIR R4 terminology server. ECL queries use authenticated API calls.</p>
</div>
</div>
<div class="status-popover-item">
<span class="status-dot disconnected"></span>
<div>
<strong>API Offline</strong>
<p>Not authenticated. ECL queries will be sent without OAuth2 credentials. Some queries may still work if the server endpoint is publicly accessible.</p>
</div>
</div>
<div class="status-popover-divider"></div>
<div class="status-popover-hint">Configure the API connection in <a href="#" id="statusOpenSettings">Settings</a>.</div>
</div>
</div>
<button class="settings-btn" id="settingsBtn" title="Settings">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M12 1v4M12 19v4M4.22 4.22l2.83 2.83M16.95 16.95l2.83 2.83M1 12h4M19 12h4M4.22 19.78l2.83-2.83M16.95 7.05l2.83-2.83"/></svg>
</button>
</div>
</header>
<!-- ECL Builder Layout -->
<div class="ecl-layout">
<!-- Template Sidebar -->
<aside class="ecl-sidebar">
<div class="ecl-sidebar-header">
<h3>
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
Query Templates
</h3>
<p class="ecl-sidebar-hint">Select a template to start building</p>
</div>
<div class="ecl-sidebar-body">
<!-- Medicines -->
<div class="template-category">
<div class="template-category-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M10.5 1.5H8.25A2.25 2.25 0 006 3.75v16.5a2.25 2.25 0 002.25 2.25h7.5A2.25 2.25 0 0018 20.25V3.75a2.25 2.25 0 00-2.25-2.25H13.5m-3 0V3h3V1.5m-3 0h3m-3 16.5h3"/></svg>
Medicines
</div>
<div class="template-list">
<button class="template-btn" data-template="medicinal-products">
<span class="template-name">All Medicinal Products</span>
<span class="template-desc">Find all types of medicinal products</span>
</button>
<button class="template-btn" data-template="products-by-ingredient">
<span class="template-name">Products by Ingredient</span>
<span class="template-desc">Find products containing a specific substance</span>
</button>
<button class="template-btn" data-template="products-by-dose-form">
<span class="template-name">Products by Dose Form</span>
<span class="template-desc">Find products with a specific dose form</span>
</button>
<button class="template-btn" data-template="vtm-products">
<span class="template-name">NMPC Refset Members</span>
<span class="template-desc">Irish medicinal product refset (^ operator)</span>
</button>
<button class="template-btn" data-template="packaged-drugs">
<span class="template-name">Packaged Products</span>
<span class="template-desc">Find packaged clinical drugs (VMPPs/AMPPs)</span>
</button>
<button class="template-btn" data-template="oral-medications">
<span class="template-name">Oral Medications</span>
<span class="template-desc">Find products with oral dose forms</span>
</button>
</div>
</div>
<!-- Clinical Findings -->
<div class="template-category">
<div class="template-category-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M20.84 4.61a5.5 5.5 0 00-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 00-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 000-7.78z"/></svg>
Clinical Findings
</div>
<div class="template-list">
<button class="template-btn" data-template="disorders">
<span class="template-name">Clinical Findings</span>
<span class="template-desc">Search for diseases and disorders</span>
</button>
<button class="template-btn" data-template="findings-by-site">
<span class="template-name">Findings by Body Site</span>
<span class="template-desc">Find conditions affecting specific anatomy</span>
</button>
<button class="template-btn" data-template="findings-by-morphology">
<span class="template-name">Findings by Morphology</span>
<span class="template-desc">Find conditions with specific morphology</span>
</button>
</div>
</div>
<!-- Procedures -->
<div class="template-category">
<div class="template-category-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
Procedures
</div>
<div class="template-list">
<button class="template-btn" data-template="procedures">
<span class="template-name">All Procedures</span>
<span class="template-desc">Search for clinical procedures</span>
</button>
<button class="template-btn" data-template="procedures-by-site">
<span class="template-name">Procedures by Site</span>
<span class="template-desc">Find procedures on specific body sites</span>
</button>
</div>
</div>
<!-- Basic ECL -->
<div class="template-category">
<div class="template-category-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 18l6-6-6-6M8 6l-6 6 6 6"/></svg>
Basic ECL
</div>
<div class="template-list">
<button class="template-btn" data-template="descendants">
<span class="template-name">Descendants</span>
<span class="template-desc">Find all subtypes of a concept</span>
</button>
<button class="template-btn" data-template="ancestors">
<span class="template-name">Ancestors</span>
<span class="template-desc">Find all supertypes of a concept</span>
</button>
<button class="template-btn" data-template="children">
<span class="template-name">Direct Children</span>
<span class="template-desc">Find immediate children only</span>
</button>
<button class="template-btn" data-template="custom">
<span class="template-name">Custom Query</span>
<span class="template-desc">Write your own ECL expression</span>
</button>
</div>
</div>
</div>
</aside>
<!-- Builder Main -->
<main class="ecl-main">
<!-- Page Guide (collapsible) -->
<div class="ecl-guide" id="eclGuide">
<button class="ecl-guide-header" id="eclGuideToggle">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4M12 8h.01"/></svg>
<span>How to use this page</span>
<svg class="ecl-guide-chevron" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M6 9l6 6 6-6"/></svg>
</button>
<div class="ecl-guide-content" id="eclGuideContent">
<div class="ecl-guide-grid">
<div class="ecl-guide-item">
<div class="ecl-guide-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 6h16M4 12h16M4 18h16"/></svg>
</div>
<div><strong>Query Templates</strong><p>Choose a pre-built query pattern from the sidebar. Each template is designed for a specific use case.</p></div>
</div>
<div class="ecl-guide-item">
<div class="ecl-guide-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/></svg>
</div>
<div><strong>Plain English Description</strong><p>A human-readable explanation of what the query will do.</p></div>
</div>
<div class="ecl-guide-item">
<div class="ecl-guide-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
</div>
<div><strong>Query Parameters</strong><p>Configure the specific values for your query. Search for SNOMED CT concepts to customise the ECL.</p></div>
</div>
<div class="ecl-guide-item">
<div class="ecl-guide-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 18l6-6-6-6M8 6l-6 6 6 6"/></svg>
</div>
<div><strong>Generated ECL Query</strong><p>The actual ECL syntax that will be sent to the terminology server.</p></div>
</div>
<div class="ecl-guide-item">
<div class="ecl-guide-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
</div>
<div><strong>Query Anatomy</strong><p>A detailed breakdown of each component in the ECL query, explaining operators, concepts, and attributes.</p></div>
</div>
<div class="ecl-guide-item">
<div class="ecl-guide-icon">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/></svg>
</div>
<div><strong>Results</strong><p>The SNOMED CT concepts returned by your query, showing concept ID and preferred term.</p></div>
</div>
</div>
</div>
</div>
<!-- Builder Panels -->
<div class="ecl-panels">
<!-- Plain English Description -->
<div class="ecl-panel">
<div class="ecl-panel-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/></svg>
<h3>Plain English Description</h3>
</div>
<div class="ecl-panel-body" id="queryDescription">
<p class="ecl-placeholder-text">Select a template from the sidebar to get started, or choose "Custom Query" to write your own ECL expression.</p>
</div>
</div>
<!-- Query Parameters -->
<div class="ecl-panel">
<div class="ecl-panel-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 00.33 1.82l.06.06a2 2 0 010 2.83 2 2 0 01-2.83 0l-.06-.06a1.65 1.65 0 00-1.82-.33 1.65 1.65 0 00-1 1.51V21a2 2 0 01-4 0v-.09A1.65 1.65 0 009 19.4a1.65 1.65 0 00-1.82.33l-.06.06a2 2 0 01-2.83-2.83l.06-.06A1.65 1.65 0 004.68 15a1.65 1.65 0 00-1.51-1H3a2 2 0 010-4h.09A1.65 1.65 0 004.6 9a1.65 1.65 0 00-.33-1.82l-.06-.06a2 2 0 012.83-2.83l.06.06A1.65 1.65 0 009 4.68a1.65 1.65 0 001-1.51V3a2 2 0 014 0v.09a1.65 1.65 0 001 1.51 1.65 1.65 0 001.82-.33l.06-.06a2 2 0 012.83 2.83l-.06.06A1.65 1.65 0 0019.4 9a1.65 1.65 0 001.51 1H21a2 2 0 010 4h-.09a1.65 1.65 0 00-1.51 1z"/></svg>
<h3>Query Parameters</h3>
</div>
<div class="ecl-panel-body" id="builderForm">
<div class="ecl-form-placeholder">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M15 19l-7-7 7-7"/></svg>
<p>Select a query template to configure parameters</p>
</div>
</div>
</div>
<!-- Generated ECL Query -->
<div class="ecl-panel ecl-output-panel">
<div class="ecl-panel-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M16 18l6-6-6-6M8 6l-6 6 6 6"/></svg>
<h3>Generated ECL Query</h3>
<div class="ecl-panel-actions">
<button class="ecl-action-btn" id="copyEcl" title="Copy to clipboard">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 01-2-2V4a2 2 0 012-2h9a2 2 0 012 2v1"/></svg>
</button>
</div>
</div>
<div class="ecl-panel-body ecl-code-body">
<pre class="ecl-code" id="eclOutput"><code>// ECL query will appear here</code></pre>
</div>
</div>
<!-- Query Anatomy (collapsible) -->
<div class="ecl-panel ecl-anatomy-panel collapsed" id="anatomyPanel">
<button class="ecl-panel-header ecl-anatomy-header" id="anatomyToggle">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
<h3>Query Anatomy</h3>
<svg class="ecl-anatomy-chevron" width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M6 9l6 6 6-6"/></svg>
</button>
<div class="ecl-anatomy-content" id="anatomyContent">
<div class="ecl-anatomy-placeholder">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z"/></svg>
<p>Select a template to see a breakdown of how the ECL query works</p>
</div>
</div>
</div>
<!-- Actions -->
<div class="ecl-actions">
<button class="btn btn-primary ecl-execute-btn" id="executeQuery">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polygon points="5 3 19 12 5 21 5 3"/></svg>
Execute Query
</button>
<button class="btn btn-ghost" id="clearQuery">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/></svg>
Clear
</button>
</div>
<!-- Results -->
<div class="ecl-panel ecl-results-panel">
<div class="ecl-panel-header">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"/></svg>
<h3>Results</h3>
<span class="ecl-result-count" id="resultCount"></span>
</div>
<div class="ecl-panel-body ecl-results-body" id="resultsContainer">
<div class="ecl-results-placeholder">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
<p>Execute a query to see results</p>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- Loading Overlay -->
<div class="ecl-loading" id="loadingOverlay">
<div class="ecl-loading-spinner"></div>
<p>Executing query…</p>
</div>
<!-- Footer -->
<footer class="site-footer">
<div class="footer-bar">
<p>© 2026 SafeRx. For educational & demonstration purposes only. Not for clinical use.</p>
<div class="footer-actions">
<button class="footer-link-btn" id="changelogBtn" title="Changelog">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="16" y1="13" x2="8" y2="13"/><line x1="16" y1="17" x2="8" y2="17"/><polyline points="10 9 9 9 8 9"/></svg>
Changelog
</button>
<a class="footer-link-btn" href="https://github.com/snbyrnes/SafeRx/issues" target="_blank" rel="noopener" title="Log issue or feedback">
<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v 3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/></svg>
Log issue or Feedback
</a>
</div>
</div>
</footer>
<!-- Changelog Modal -->
<div class="modal-overlay" id="changelogModal" style="display:none">
<div class="modal changelog-modal">
<div class="modal-header">
<h3>Changelog</h3>
<button class="btn-close" id="closeChangelog">×</button>
</div>
<div class="modal-body changelog-body">
<div class="changelog-entry">
<div class="changelog-version">v1.2.1 <span class="changelog-date">14 Feb 2026</span></div>
<ul>
<li><strong>New:</strong> NMPC badge with green checkmark (✓ NMPC) for API-sourced medications</li>
<li><strong>New:</strong> Substance name display in medication search dropdown (virtual & brand products)</li>
<li><strong>Improved:</strong> Medication details panel displays substance, strength, dose form, and unit information</li>
<li><strong>Changed:</strong> Footer simplified with GitHub logo on feedback button</li>
<li><strong>Fixed:</strong> Substance field updates in real-time as API lookups complete</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-version">v1.2.0 <span class="changelog-date">12 Feb 2026</span></div>
<ul>
<li><strong>New:</strong> Virtual / Actual product type toggle on the medication search field</li>
<li><strong>New:</strong> Expand checkbox with tooltip for descendant concept searches via ECL</li>
<li><strong>Improved:</strong> Patient banner — allergy info now right-aligned with styled warning badge and pill tags</li>
<li><strong>Improved:</strong> About page redesigned with Quick Start guide, feature highlights, standards info, and exploration prompts</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-version">v1.1.0 <span class="changelog-date">11 Feb 2026</span></div>
<ul>
<li><strong>New:</strong> ECL Builder demo — build and execute SNOMED CT Expression Constraint Language queries</li>
<li><strong>New:</strong> 15 ECL query templates across 4 categories (Medications, Clinical, Hierarchy, Custom)</li>
<li><strong>New:</strong> ECL query anatomy panel with visual breakdown of operators, concepts, and keywords</li>
<li><strong>New:</strong> Demo switcher in the top bar to navigate between Product Based Prescribing and ECL Builder</li>
<li><strong>Fixed:</strong> OAuth2 authentication for NMPC Ontoserver API (required for ValueSet/$expand)</li>
<li><strong>Fixed:</strong> URL encoding for FHIR ValueSet expand — correct encodeURIComponent on full url parameter</li>
<li><strong>Fixed:</strong> ECL pipe terms (|display term|) now stripped before sending to server</li>
</ul>
</div>
<div class="changelog-entry">
<div class="changelog-version">v1.0.0 <span class="changelog-date">11 Feb 2026</span></div>
<ul>
<li><strong>New:</strong> Product-based prescribing with live FHIR R4 resource preview</li>
<li><strong>New:</strong> Medication record with sign, cancel, and FHIR view actions</li>
<li><strong>New:</strong> Collapsible FHIR code panel with drag-to-resize</li>
<li><strong>New:</strong> MedicationRequest, Medication, and Bundle resource generation</li>
<li><strong>New:</strong> HSE NMPC FHIR API integration with OAuth2 authentication</li>
<li><strong>New:</strong> NMPC product catalogue explorer</li>
<li><strong>New:</strong> FHIR Viewer for browsing generated resources</li>
<li><strong>New:</strong> Settings panel for API configuration and connection testing</li>
</ul>
</div>
</div>
</div>
</div>
<!-- Settings Modal -->
<div class="modal-overlay" id="settingsModal" style="display:none">
<div class="modal">
<div class="modal-header">
<h3>Settings</h3>
<button class="btn-close" id="closeSettings">×</button>
</div>
<div class="modal-body">
<div class="form-group">
<label class="form-label">FHIR Server Base URL</label>
<input type="url" class="form-input" id="fhirBaseUrl" placeholder="https://nmpc.hse.ie/production1/fhir" value="https://nmpc.hse.ie/production1/fhir" />
<div class="form-hint">HSE National Medicinal Product Catalogue (Ontoserver) FHIR R4 endpoint</div>
</div>
<div class="form-group">
<label class="form-label">Token URL</label>
<input type="url" class="form-input" id="fhirTokenUrl" placeholder="https://nmpc.hse.ie/authorisation/auth/realms/terminology/protocol/openid-connect/token" value="https://nmpc.hse.ie/authorisation/auth/realms/terminology/protocol/openid-connect/token" />
<div class="form-hint">OAuth2 token endpoint for client credentials authentication</div>
</div>
<div class="form-row" style="margin-bottom: var(--space-lg)">
<div class="form-group flex-1">
<label class="form-label">Client ID</label>
<input type="text" class="form-input" id="fhirClientId" placeholder="your-client-id" />
</div>
<div class="form-group flex-1">
<label class="form-label">Client Secret</label>
<input type="password" class="form-input" id="fhirClientSecret" placeholder="your-client-secret" />
</div>
</div>
<div class="form-actions">
<button class="btn btn-secondary" id="testConnection">Test Connection</button>
<button class="btn btn-primary" id="saveSettings">Save</button>
</div>
<div class="connection-test-result" id="connectionTestResult" style="display:none"></div>
</div>
</div>
</div>
<!-- Toast -->
<div class="toast-container" id="toastContainer"></div>
<script src="js/ecl-builder.js"></script>
</body>
</html>