fhirsmith 0.8.4 → 0.8.6

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.
package/server.js CHANGED
@@ -28,7 +28,7 @@ try {
28
28
  }
29
29
 
30
30
  const Logger = require('./library/logger');
31
- const serverLog = Logger.getInstance().child({ module: 'server' });
31
+ const serverLog = Logger.getInstance(config.logging || {}).child({ module: 'server' });
32
32
  const packageJson = require('./package.json');
33
33
 
34
34
  // Startup banner
@@ -64,6 +64,7 @@ const FolderModule = require("./folder/folder");
64
64
  const ExtensionTrackerModule = require("./extension-tracker/extension-tracker");
65
65
 
66
66
  htmlServer.useLog(serverLog);
67
+ htmlServer.setSponsorMessage(config.sponsorMessage ? config.sponsorMessage : '');
67
68
 
68
69
  const app = express();
69
70
 
@@ -386,22 +387,44 @@ async function buildRootPageContent() {
386
387
 
387
388
  // Memory usage
388
389
  const memUsage = process.memoryUsage();
389
- const heapUsedMB = (memUsage.heapUsed / 1024 / 1024).toFixed(2);
390
- const heapAvailableMB = ((memUsage.heapTotal - memUsage.heapUsed) / 1024 / 1024).toFixed(2);
391
- const rssMB = (memUsage.rss / 1024 / 1024).toFixed(2);
392
- const freeMemMB = (os.freemem() / 1024 / 1024).toFixed(0);
390
+ const heapStats = v8.getHeapStatistics();
391
+
392
+ // V8 heap: used vs limit
393
+ const v8UsedMB = (memUsage.heapUsed / 1024 / 1024).toFixed(0);
394
+ const v8LimitMB = (heapStats.heap_size_limit / 1024 / 1024).toFixed(0);
395
+ const v8PCT = (memUsage.heapUsed * 100) / heapStats.heap_size_limit;
396
+
397
+ // Process RSS vs cgroup limit (or system total)
398
+ const rssMB = (memUsage.rss / 1024 / 1024).toFixed(0);
399
+ let memLimit;
400
+ try {
401
+ const raw = fs.readFileSync('/sys/fs/cgroup/memory.max', 'utf8').trim();
402
+ memLimit = raw === 'max' ? os.totalmem() : parseInt(raw);
403
+ } catch {
404
+ memLimit = os.totalmem();
405
+ }
406
+ const memLimitMB = (memLimit / 1024 / 1024).toFixed(0);
407
+ const processPCT = (memUsage.rss * 100) / memLimit;
408
+
409
+ // System memory
393
410
  const totalMemMB = (os.totalmem() / 1024 / 1024).toFixed(0);
411
+ const usedMemMB = ((os.totalmem() - os.freemem()) / 1024 / 1024).toFixed(0);
412
+ const sysMemPCT = ((os.totalmem() - os.freemem()) * 100) / os.totalmem();
413
+
414
+ // Average requests per minute
415
+ const uptimeMinutesTotal = uptimeMs / 60000;
416
+ const avgReqPerMin = uptimeMinutesTotal > 0 ? (stats.requestCount / uptimeMinutesTotal).toFixed(1) : '0.0';
394
417
 
395
418
  content += '<table class="grid">';
396
419
  content += '<tr>';
397
420
  content += `<td><strong>Uptime:</strong> ${escape(uptimeStr)}</td>`;
398
421
  content += `<td><strong>Request Count:</strong> ${stats.requestCount} (static: ${stats.staticRequestCount})</td>`;
399
- content += `<td><strong>Free Memory:</strong> ${freeMemMB} MB of ${totalMemMB} MB</td>`;
422
+ content += `<td><strong>Avg Requests/min:</strong> ${avgReqPerMin}</td>`;
400
423
  content += '</tr>';
401
424
  content += '<tr>';
402
- content += `<td><strong>Heap Used:</strong> ${heapUsedMB} MB</td>`;
403
- content += `<td><strong>Heap Available:</strong> ${heapAvailableMB} MB</td>`;
404
- content += `<td><strong>Process Memory:</strong> ${rssMB} MB</td>`;
425
+ content += `<td style="background-color:${pctColor(v8PCT)}"><strong>V8 Memory:</strong> ${v8UsedMB} MB of ${v8LimitMB} MB (${v8PCT.toFixed(0)}%)</td>`;
426
+ content += `<td style="background-color:${pctColor(processPCT)}"><strong>Process Memory:</strong> ${rssMB} MB of ${memLimitMB} MB (${processPCT.toFixed(0)}%)</td>`;
427
+ content += `<td style="background-color:${pctColor(sysMemPCT)}"><strong>System Memory:</strong> ${usedMemMB} MB of ${totalMemMB} MB (${sysMemPCT.toFixed(0)}%)</td>`;
405
428
  content += '</tr>';
406
429
  content += getLogStats();
407
430
  content += '</table>';
@@ -543,10 +566,24 @@ app.get('/dashboard', async (req, res) => {
543
566
  // Memory usage
544
567
  const memUsage = process.memoryUsage();
545
568
  const heapStats = v8.getHeapStatistics();
546
- const nodeMemPCT = (memUsage.heapUsed * 100) / heapStats.heap_size_limit; // % of Node.js memory limit used
569
+ const v8PCT = (memUsage.heapUsed * 100) / heapStats.heap_size_limit; // % of V8 heap limit used
570
+
571
+ // Process RSS as % of cgroup memory limit (or system total as fallback)
572
+ let memLimit;
573
+ try {
574
+ const raw = fs.readFileSync('/sys/fs/cgroup/memory.max', 'utf8').trim();
575
+ memLimit = raw === 'max' ? os.totalmem() : parseInt(raw);
576
+ } catch {
577
+ memLimit = os.totalmem();
578
+ }
579
+ const processPCT = (memUsage.rss * 100) / memLimit;
580
+
547
581
  const totalMemBytes = os.totalmem();
548
582
  const freeMemBytes = os.freemem();
549
583
  const sysMemPCT = ((totalMemBytes - freeMemBytes) * 100) / totalMemBytes; // % of system memory used
584
+
585
+ const memMaxPCT = Math.max(v8PCT, processPCT, sysMemPCT);
586
+
550
587
  const fstats = fs.statfsSync(folders.logsDir());
551
588
  const diskPCT = 100 - ((fstats.bavail * 100) / fstats.blocks); // % of disk used
552
589
 
@@ -555,8 +592,7 @@ app.get('/dashboard', async (req, res) => {
555
592
  content += '<tr>';
556
593
  content += `<td><strong>Uptime:</strong> ${escape(uptimeStr)}</td>`;
557
594
  content += `<td><strong>Request Count:</strong> ${stats.requestCount} (static: ${stats.staticRequestCount})</td>`;
558
- content += `<td style="background-color:${pctColor(nodeMemPCT)}"><strong>Node Memory:</strong> ${nodeMemPCT.toFixed(0)}%</td>`;
559
- content += `<td style="background-color:${pctColor(sysMemPCT)}"><strong>System Memory:</strong> ${sysMemPCT.toFixed(0)}%</td>`;
595
+ content += `<td style="background-color:${pctColor(memMaxPCT)}"><strong>Memory:</strong> ${v8PCT.toFixed(0)}% V8, ${processPCT.toFixed(0)}% Process, ${sysMemPCT.toFixed(0)}% System</td>`;
560
596
  content += `<td style="background-color:${pctColor(diskPCT)}"><strong>Disk:</strong> ${diskPCT.toFixed(0)}%</td>`;
561
597
  content += '</tr>';
562
598
  content += '</table>';
@@ -0,0 +1,31 @@
1
+
2
+ // Tooltip
3
+ $('.btn-copy').tooltip({
4
+ trigger: 'hover',
5
+ placement: 'bottom'
6
+ });
7
+
8
+ function setTooltip(message) {
9
+ button = $(event.target)
10
+ oldMsg = button.tooltip().attr('data-original-title')
11
+ button.tooltip()
12
+ .attr('data-original-title', message)
13
+ .tooltip('show');
14
+ setTimeout(function() {
15
+ button.tooltip()
16
+ .attr('data-original-title', oldMsg)
17
+ .tooltip('hide');
18
+ }, 1000);
19
+ }
20
+
21
+ // Clipboard
22
+
23
+ var clipboard = new ClipboardJS('.btn-copy');
24
+
25
+ clipboard.on('success', function(e) {
26
+ setTooltip('Copied!');
27
+ });
28
+
29
+ clipboard.on('error', function(e) {
30
+ setTooltip('Failed :( - copy manually');
31
+ });
@@ -0,0 +1,7 @@
1
+ /*!
2
+ * clipboard.js v2.0.8
3
+ * https://clipboardjs.com/
4
+ *
5
+ * Licensed MIT © Zeno Rocha
6
+ */
7
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.ClipboardJS=e():t.ClipboardJS=e()}(this,function(){return n={686:function(t,e,n){"use strict";n.d(e,{default:function(){return o}});var e=n(279),i=n.n(e),e=n(370),u=n.n(e),e=n(817),c=n.n(e);function a(t){try{return document.execCommand(t)}catch(t){return}}var f=function(t){t=c()(t);return a("cut"),t};var l=function(t){var e,n,o,r=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{container:document.body},i="";return"string"==typeof t?(e=t,n="rtl"===document.documentElement.getAttribute("dir"),(o=document.createElement("textarea")).style.fontSize="12pt",o.style.border="0",o.style.padding="0",o.style.margin="0",o.style.position="absolute",o.style[n?"right":"left"]="-9999px",n=window.pageYOffset||document.documentElement.scrollTop,o.style.top="".concat(n,"px"),o.setAttribute("readonly",""),o.value=e,o=o,r.container.appendChild(o),i=c()(o),a("copy"),o.remove()):(i=c()(t),a("copy")),i};function r(t){return(r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}var s=function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{},e=t.action,n=void 0===e?"copy":e,o=t.container,e=t.target,t=t.text;if("copy"!==n&&"cut"!==n)throw new Error('Invalid "action" value, use either "copy" or "cut"');if(void 0!==e){if(!e||"object"!==r(e)||1!==e.nodeType)throw new Error('Invalid "target" value, use a valid Element');if("copy"===n&&e.hasAttribute("disabled"))throw new Error('Invalid "target" attribute. Please use "readonly" instead of "disabled" attribute');if("cut"===n&&(e.hasAttribute("readonly")||e.hasAttribute("disabled")))throw new Error('Invalid "target" attribute. You can\'t cut text from elements with "readonly" or "disabled" attributes')}return t?l(t,{container:o}):e?"cut"===n?f(e):l(e,{container:o}):void 0};function d(t){return(d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function p(t,e){for(var n=0;n<e.length;n++){var o=e[n];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(t,o.key,o)}}function y(t,e){return(y=Object.setPrototypeOf||function(t,e){return t.__proto__=e,t})(t,e)}function h(n){var o=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Date.prototype.toString.call(Reflect.construct(Date,[],function(){})),!0}catch(t){return!1}}();return function(){var t,e=m(n);return t=o?(t=m(this).constructor,Reflect.construct(e,arguments,t)):e.apply(this,arguments),e=this,!(t=t)||"object"!==d(t)&&"function"!=typeof t?function(t){if(void 0!==t)return t;throw new ReferenceError("this hasn't been initialised - super() hasn't been called")}(e):t}}function m(t){return(m=Object.setPrototypeOf?Object.getPrototypeOf:function(t){return t.__proto__||Object.getPrototypeOf(t)})(t)}function v(t,e){t="data-clipboard-".concat(t);if(e.hasAttribute(t))return e.getAttribute(t)}var o=function(){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),e&&y(t,e)}(r,i());var t,e,n,o=h(r);function r(t,e){var n;return function(t){if(!(t instanceof r))throw new TypeError("Cannot call a class as a function")}(this),(n=o.call(this)).resolveOptions(e),n.listenClick(t),n}return t=r,n=[{key:"copy",value:function(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{container:document.body};return l(t,e)}},{key:"cut",value:function(t){return f(t)}},{key:"isSupported",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:["copy","cut"],t="string"==typeof t?[t]:t,e=!!document.queryCommandSupported;return t.forEach(function(t){e=e&&!!document.queryCommandSupported(t)}),e}}],(e=[{key:"resolveOptions",value:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:{};this.action="function"==typeof t.action?t.action:this.defaultAction,this.target="function"==typeof t.target?t.target:this.defaultTarget,this.text="function"==typeof t.text?t.text:this.defaultText,this.container="object"===d(t.container)?t.container:document.body}},{key:"listenClick",value:function(t){var e=this;this.listener=u()(t,"click",function(t){return e.onClick(t)})}},{key:"onClick",value:function(t){var e=t.delegateTarget||t.currentTarget,t=s({action:this.action(e),container:this.container,target:this.target(e),text:this.text(e)});this.emit(t?"success":"error",{action:this.action,text:t,trigger:e,clearSelection:function(){e&&e.focus(),document.activeElement.blur(),window.getSelection().removeAllRanges()}})}},{key:"defaultAction",value:function(t){return v("action",t)}},{key:"defaultTarget",value:function(t){t=v("target",t);if(t)return document.querySelector(t)}},{key:"defaultText",value:function(t){return v("text",t)}},{key:"destroy",value:function(){this.listener.destroy()}}])&&p(t.prototype,e),n&&p(t,n),r}()},828:function(t){var e;"undefined"==typeof Element||Element.prototype.matches||((e=Element.prototype).matches=e.matchesSelector||e.mozMatchesSelector||e.msMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector),t.exports=function(t,e){for(;t&&9!==t.nodeType;){if("function"==typeof t.matches&&t.matches(e))return t;t=t.parentNode}}},438:function(t,e,n){var u=n(828);function i(t,e,n,o,r){var i=function(e,n,t,o){return function(t){t.delegateTarget=u(t.target,n),t.delegateTarget&&o.call(e,t)}}.apply(this,arguments);return t.addEventListener(n,i,r),{destroy:function(){t.removeEventListener(n,i,r)}}}t.exports=function(t,e,n,o,r){return"function"==typeof t.addEventListener?i.apply(null,arguments):"function"==typeof n?i.bind(null,document).apply(null,arguments):("string"==typeof t&&(t=document.querySelectorAll(t)),Array.prototype.map.call(t,function(t){return i(t,e,n,o,r)}))}},879:function(t,n){n.node=function(t){return void 0!==t&&t instanceof HTMLElement&&1===t.nodeType},n.nodeList=function(t){var e=Object.prototype.toString.call(t);return void 0!==t&&("[object NodeList]"===e||"[object HTMLCollection]"===e)&&"length"in t&&(0===t.length||n.node(t[0]))},n.string=function(t){return"string"==typeof t||t instanceof String},n.fn=function(t){return"[object Function]"===Object.prototype.toString.call(t)}},370:function(t,e,n){var f=n(879),l=n(438);t.exports=function(t,e,n){if(!t&&!e&&!n)throw new Error("Missing required arguments");if(!f.string(e))throw new TypeError("Second argument must be a String");if(!f.fn(n))throw new TypeError("Third argument must be a Function");if(f.node(t))return c=e,a=n,(u=t).addEventListener(c,a),{destroy:function(){u.removeEventListener(c,a)}};if(f.nodeList(t))return o=t,r=e,i=n,Array.prototype.forEach.call(o,function(t){t.addEventListener(r,i)}),{destroy:function(){Array.prototype.forEach.call(o,function(t){t.removeEventListener(r,i)})}};if(f.string(t))return t=t,e=e,n=n,l(document.body,t,e,n);throw new TypeError("First argument must be a String, HTMLElement, HTMLCollection, or NodeList");var o,r,i,u,c,a}},817:function(t){t.exports=function(t){var e,n="SELECT"===t.nodeName?(t.focus(),t.value):"INPUT"===t.nodeName||"TEXTAREA"===t.nodeName?((e=t.hasAttribute("readonly"))||t.setAttribute("readonly",""),t.select(),t.setSelectionRange(0,t.value.length),e||t.removeAttribute("readonly"),t.value):(t.hasAttribute("contenteditable")&&t.focus(),n=window.getSelection(),(e=document.createRange()).selectNodeContents(t),n.removeAllRanges(),n.addRange(e),n.toString());return n}},279:function(t){function e(){}e.prototype={on:function(t,e,n){var o=this.e||(this.e={});return(o[t]||(o[t]=[])).push({fn:e,ctx:n}),this},once:function(t,e,n){var o=this;function r(){o.off(t,r),e.apply(n,arguments)}return r._=e,this.on(t,r,n)},emit:function(t){for(var e=[].slice.call(arguments,1),n=((this.e||(this.e={}))[t]||[]).slice(),o=0,r=n.length;o<r;o++)n[o].fn.apply(n[o].ctx,e);return this},off:function(t,e){var n=this.e||(this.e={}),o=n[t],r=[];if(o&&e)for(var i=0,u=o.length;i<u;i++)o[i].fn!==e&&o[i].fn._!==e&&r.push(o[i]);return r.length?n[t]=r:delete n[t],this}},t.exports=e,t.exports.TinyEmitter=e}},r={},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,{a:e}),e},o.d=function(t,e){for(var n in e)o.o(e,n)&&!o.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o(686).default;function o(t){if(r[t])return r[t].exports;var e=r[t]={exports:{}};return n[t](e,e.exports,o),e.exports}var n,r});
package/static/fhir.css CHANGED
@@ -623,4 +623,23 @@ div.warning {
623
623
  background-color: #FFE6E6;
624
624
  border: 1px silver solid;
625
625
  padding: 5px;
626
- }
626
+ }
627
+
628
+
629
+ .copy-text .btn-copy{
630
+ visibility: hidden;
631
+ }
632
+
633
+ .copy-text:hover .btn-copy {
634
+ visibility: visible;
635
+ }
636
+
637
+ .btn-copy {
638
+ height: 14px;
639
+ width: 17px;
640
+ background-image: url('images/noun_copy to clipboard_1669410.png');
641
+ background-size: 22px;
642
+ padding: 0px 0px;
643
+ border-width: 0px;
644
+ background-color: transparent;
645
+ }
@@ -1274,7 +1274,7 @@ VALUESET_SHAREABLE_MISSING = Published value sets SHOULD conform to the Shareabl
1274
1274
  VALUESET_SHAREABLE_MISSING_HL7 = Value sets published by HL7 SHALL conform to the ShareableValueSet profile, which says that the element ValueSet.{0} is mandatory, but it is not present
1275
1275
  VALUESET_SUPPLEMENT_MISSING_one = Required supplement not found: {1}
1276
1276
  VALUESET_SUPPLEMENT_MISSING_other = Required supplements not found: {1}
1277
- VALUESET_TOO_COSTLY = The value set ''{0}'' expansion has too many codes to display ({1})
1277
+ VALUESET_TOO_COSTLY = The value set ''{0}'' expansion has too many codes to produce ({1})
1278
1278
  VALUESET_TOO_COSTLY_COUNT = The value set ''{0}'' expansion has {2} codes, which is too many to display ({1})
1279
1279
  VALUESET_TOO_COSTLY_TIME = The value set ''{0}'' {2} took too long to process (>{1}sec)
1280
1280
  VALUESET_UNC_SYSTEM_WARNING = Unknown System ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
@@ -931,7 +931,7 @@ OP_OUT_SUMM = OperationOutcome ({0} Error(s), {1} Warning(s), {2} Hint(s))
931
931
  BUNDLE_SUMMARY = {0} Bundle, {1} Entries
932
932
  PROF_DRIV_SUMM_PROP = {0} = {1}
933
933
  PROF_DRIV_SUMM_NONE = {0}
934
- PROF_DRIV_SUMM = {0}: {1}
934
+ PROF_DRIV_SUMM = {0}: {1}
935
935
  BUNDLE_HEADER_DOCUMENT_CONTENTS = Additional Resources Included in Document
936
936
  DOCUMENT_SUMMARY = <param name="status"/> Document at <param name="date"/> by <param name="author"/> for <param name="subject"/> <if test="has-encounter = true"> in encounter <param name="encounter"/></if>
937
937
  DATA_REND_ATT_URL = {0} @ {1}
@@ -950,36 +950,36 @@ MATURITY_PUBLISHER = Publisher: {0}
950
950
  MATURITY_STATUS = Status
951
951
  MATURITY_MATURITY = Maturity Level: {0}
952
952
  MATURITY_STDS_STATUS = Standards Status: {0}
953
- DATA_REND_MORNING = Morning
954
- DATA_REND_MORNING_EARLY = Early Morning
955
- DATA_REND_MORNING_LATE = Late Morning
956
- DATA_REND_NOON = Noon
957
- DATA_REND_AFTERNOON = Afternoon
958
- DATA_REND_AFTERNOON_EARLY = Early Afternoon
959
- DATA_REND_AFTERNOON_LATE = Late Afternoon
960
- DATA_REND_EVENING = Evening
961
- DATA_REND_EVENING_EARLY = Early Evening
962
- DATA_REND_EVENING_LATE = Late Evening
963
- DATA_REND_NIGHT = Night
964
- DATA_REND_AFTER_SLEEP = After Sleep
965
- DATA_REND_IMMEDIATE = Immediate
953
+ DATA_REND_MORNING = Morning
954
+ DATA_REND_MORNING_EARLY = Early Morning
955
+ DATA_REND_MORNING_LATE = Late Morning
956
+ DATA_REND_NOON = Noon
957
+ DATA_REND_AFTERNOON = Afternoon
958
+ DATA_REND_AFTERNOON_EARLY = Early Afternoon
959
+ DATA_REND_AFTERNOON_LATE = Late Afternoon
960
+ DATA_REND_EVENING = Evening
961
+ DATA_REND_EVENING_EARLY = Early Evening
962
+ DATA_REND_EVENING_LATE = Late Evening
963
+ DATA_REND_NIGHT = Night
964
+ DATA_REND_AFTER_SLEEP = After Sleep
965
+ DATA_REND_IMMEDIATE = Immediate
966
966
  VALUE_SET_AR = Argentinian Edition
967
- VALUE_SET_AT = Austrian Edition
967
+ VALUE_SET_AT = Austrian Edition
968
968
  VALUE_SET_BE = Belgian Edition
969
- VALUE_SET_CA_EN = Canadian English Edition
970
- VALUE_SET_CA = Canadian Edition
971
- VALUE_SET_EE = Estonian Edition
969
+ VALUE_SET_CA_EN = Canadian English Edition
970
+ VALUE_SET_CA = Canadian Edition
971
+ VALUE_SET_EE = Estonian Edition
972
972
  VALUE_SET_FI = Finnish Edition
973
973
  VALUE_SET_DE = German Edition
974
974
  VALUE_SET_IE = Irish Edition
975
- VALUE_SET_NZ = New Zealand Edition
976
- VALUE_SET_NO = Norwegian Edition
975
+ VALUE_SET_NZ = New Zealand Edition
976
+ VALUE_SET_NO = Norwegian Edition
977
977
  VALUE_SET_KR = Republic of Korea Edition (South Korea)
978
- VALUE_ES_ES = Spanish National Edition
978
+ VALUE_ES_ES = Spanish National Edition
979
979
  VALUE_SET_CH = Swiss Edition
980
- VALUE_SET_UK_CLIN = UK Clinical Edition
981
- VALUE_SET_UY = Uruguay Edition
982
- VALUE_SET_US_ICD10CM = US Edition (with ICD-10-CM maps)
980
+ VALUE_SET_UK_CLIN = UK Clinical Edition
981
+ VALUE_SET_UY = Uruguay Edition
982
+ VALUE_SET_US_ICD10CM = US Edition (with ICD-10-CM maps)
983
983
  VALUE_SET_OTHER_DISPLAY = Other Display ({0})
984
984
  GENERAL_VALUE_BOUNDED = The value must be between {0} and {1} (or equal)
985
985
  GENERAL_VALUE_MAX = The value must be less or equal to {0}
@@ -1009,12 +1009,12 @@ SDT_RES = Resource
1009
1009
  SDT_DEF = Definition
1010
1010
  SDT_ORIGINAL_SOURCE = Original Source
1011
1011
  SDR_USAGE = Usages
1012
- SDR_DERIVED = Derived from this {0}
1012
+ SDR_DERIVED = Derived from this {0}
1013
1013
  SDR_DRAW_IN = Draw in Obligations & Additional Bindings from this {0}
1014
1014
  SDR_IMPOSE = Impose this profile {0}
1015
1015
  SDR_COMPLY = Comply with this profile {0}
1016
1016
  SDR_USE = Use this {0}
1017
- SDR_REFER = Refer to this {0}
1017
+ SDR_REFER = Refer to this {0}
1018
1018
  SDR_EXAMPLE = Examples for this {0}
1019
1019
  SDR_SEARCH= Search Parameters using this {0}
1020
1020
  SDR_CAPSTMT = CapabilityStatements using this {0}
@@ -1043,54 +1043,54 @@ SDR_FROM = From {0}
1043
1043
  SDR_SRC_FHIR = FHIR Std.
1044
1044
  SDR_SRC_IG = This IG
1045
1045
  SDR_CODE_FROM = (a valid code from {0})
1046
- SDR_ALL_ELEM = **ALL** elements
1047
- SDR_ALL_EXT = **ALL** extensions
1046
+ SDR_ALL_ELEM = **ALL** elements
1047
+ SDR_ALL_EXT = **ALL** extensions
1048
1048
  SDR_BP = best practice
1049
1049
  SDR_GUIDANCE_PFX = Guidance on how to interpret the contents of this table can be found
1050
1050
  SDR_GUIDANCE_HERE = here
1051
- SDR_GUIDANCE_SFX =
1051
+ SDR_GUIDANCE_SFX =
1052
1052
  SDR_OFF_URL = The official URL for this profile is
1053
1053
  SDR_FROM_ELEM = // from Element: <a href="{0}">extension</a>
1054
- SDR_MOD_SUPP = (this element modifies the meaning of other elements, and must be supported)
1055
- SDR_MOD = (this element modifies the meaning of other elements)
1054
+ SDR_MOD_SUPP = (this element modifies the meaning of other elements, and must be supported)
1055
+ SDR_MOD = (this element modifies the meaning of other elements)
1056
1056
  SDR_SUPP = (this element must be supported)
1057
1057
  SDR_ANY_ORDER = // sliced by {0} in any order
1058
1058
  SDR_SORTED = // sliced by {0} in the specified order {1}
1059
1059
  SDR_PRIM_VALUE = Primitive Value {0}
1060
- SDR_META_CH_NO = Unable to evaluate changes to metadata
1061
- SDR_META_CH_DET = The resource metadata has changed ({0})
1060
+ SDR_META_CH_NO = Unable to evaluate changes to metadata
1061
+ SDR_META_CH_DET = The resource metadata has changed ({0})
1062
1062
  SDR_CONT_CH_NO = Unable to evaluate changes to content
1063
- SDR_CONT_CH_DET_SD = The data elements list has changed
1063
+ SDR_CONT_CH_DET_SD = The data elements list has changed
1064
1064
  SDR_CONT_CH_DET_CS = The list of codes defined by the code system has changed
1065
- SDR_DEFN_CH_NO = Unable to evaluate changes to definitions
1066
- SDR_DEFN_CH_DET_SD = One or more text definitions, invariants or bindings have changed
1067
- SDR_DEFN_CH_DET_CS = One or more text definitions/displays have changed
1065
+ SDR_DEFN_CH_NO = Unable to evaluate changes to definitions
1066
+ SDR_DEFN_CH_DET_SD = One or more text definitions, invariants or bindings have changed
1067
+ SDR_DEFN_CH_DET_CS = One or more text definitions/displays have changed
1068
1068
  SDR_CONT_CH_DET_VS = The logical definition of the value set has changed
1069
1069
  SDR_DEFN_CH_DET_VS = One or more text definitions/displays have changed
1070
1070
  SDR_INTRP_CH_NO_VS = Unable to evaluate changes to the expansion
1071
1071
  SDR_INTRP_CH_DET_VS = The expansion has changed
1072
- SDR_CH_DET = New Content
1072
+ SDR_CH_DET = New Content
1073
1073
  SDR_CH_NO = No changes
1074
1074
  SDR_DRAFT = This is an draft extension definition; the committee is seeking implementation feedback, and the definition or contents of the extension may change in future versions
1075
- SDR_EXPERIMENTAL = This is an experimental extension definition; the definition is intended for testing purposes, education or evaluation, and the definition is not anticipated to be matured to a point where it is intended for genuine usage.
1075
+ SDR_EXPERIMENTAL = This is an experimental extension definition; the definition is intended for testing purposes, education or evaluation, and the definition is not anticipated to be matured to a point where it is intended for production use.
1076
1076
  SDR_EXT_DEPR = This extension is deprecated and should no longer be used
1077
1077
  SDR_EXT_ANY = This extension does not specify which elements it should be used on
1078
- SDR_EXT_ELEM = This extension may be used on the following element(s)
1078
+ SDR_EXT_ELEM = This extension may be used on the following element(s)
1079
1079
  SDR_EXT_MOD = This extension is a modifier extension.
1080
- SDR_EXT_ELEM_ID = Element ID
1081
- SDR_EXT_EXT = Extension
1080
+ SDR_EXT_ELEM_ID = Element ID
1081
+ SDR_EXT_EXT = Extension
1082
1082
  SDR_EXT_PATH = Path
1083
- SDR_EXT_CTXT_PATH = In addition, the extension can only be used when this FHIRPath expression is true
1084
- SDR_EXT_CTXT_PATHS = In addition, the extension can only be used when these FHIRPath expressions are true
1085
- SDR_EXT_VER_PFX = This extension is allowed for use with
1086
- SDR_EXT_VER_SFX = .
1087
- SDR_VER_TO_PFX = FHIR versions up to
1088
- SDR_VER_TO_SFX =
1089
- SDR_VER_FROM_PFX = FHIR versions
1083
+ SDR_EXT_CTXT_PATH = In addition, the extension can only be used when this FHIRPath expression is true
1084
+ SDR_EXT_CTXT_PATHS = In addition, the extension can only be used when these FHIRPath expressions are true
1085
+ SDR_EXT_VER_PFX = This extension is allowed for use with
1086
+ SDR_EXT_VER_SFX = .
1087
+ SDR_VER_TO_PFX = FHIR versions up to
1088
+ SDR_VER_TO_SFX =
1089
+ SDR_VER_FROM_PFX = FHIR versions
1090
1090
  SDR_VER_FROM_SFX = and after
1091
1091
  SDR_VER_RANGE_PFX = FHIR versions
1092
1092
  SDR_VER_RANGE_MID = to
1093
- SDR_VER_RANGE_SFX =
1093
+ SDR_VER_RANGE_SFX =
1094
1094
  SDR_EXT_UNCHANGED = The extension is unchanged in {0}
1095
1095
  SDR_EXT_CHANGED = The extension is represented a little differently in {0}
1096
1096
  VSR_LOGICAL = Logical Definition (CLD)
@@ -1105,7 +1105,7 @@ R44B_REFERS_TO = <a href="{0}">{1}}</a> refers to the canonical type at {2}
1105
1105
  R44B_HAS_TARGET = has target
1106
1106
  R44B_WRONG_MSG = Something went wrong with the cross-version analysis because
1107
1107
  R44B_USE_OK = This is an {0} IG. None of the features it uses are changed in {1}, so it can be used as is with {1} systems.
1108
- R44B_PACKAGE_REF = Packages for both <a href="{0}">R4 ({1}.r4)</a> and <a href=\"{2}\">R4B ({3}.r4b)</a> are available.
1108
+ R44B_PACKAGE_REF = Packages for both <a href="{0}">R4 ({1}.r4)</a> and <a href="{2}">R4B ({3}.r4b)</a> are available.
1109
1109
  R44B_NOT_COMP = This is an {0} IG that is not compatible with {1}" because
1110
1110
  R44B_NOT_IN = The following resources are not in the {0} version
1111
1111
  R44B_ONLY_IN = The following resources are only in the {0} version
@@ -1116,13 +1116,104 @@ VALUE_SET_NEEDS_SUPPL_one = This ValueSet requires the Code system Supplement
1116
1116
  VALUE_SET_NEEDS_SUPPL_other = This ValueSet requires the Code system Supplements
1117
1117
  SD_XIG_LINK = <p>You can also check for <a href="https://packages2.fhir.org/xig/{0}|current/StructureDefinition/{1}">usages in the FHIR IG Statistics</a></p>
1118
1118
  VS_VERSION_STATED = Version is explicitly stated to be {0}
1119
+ VS_VERSION_LATEST = Version is always the latest available, which is {0} at this time
1119
1120
  VS_VERSION_WILDCARD_BY_PACKAGE = Version is stated to be {0}, which means it is fixed to {1}, the version found through the package references
1120
1121
  VS_VERSION_WILDCARD = Version is stated to be {0}. When building this specification, the most recent matching version {1} has been used
1121
1122
  VS_VERSION_BY_PACKAGE = Version is not explicitly stated, which means it is fixed to {0}, the version found through the package references
1122
1123
  VS_VERSION_THIS_PACKAGE = Version is not explicitly stated, which means it is fixed to the version provided in this specification
1123
- VS_VERSION_FOUND = Version is not explicity stated. When building this specification, the most recent version {0} has been used
1124
- VS_VERSION_NONE = Version is not explicity stated, and the target {0} has no stated version either
1125
- VS_VERSION_NOTHING = Version is not explicity stated. No matching {0} found
1124
+ VS_VERSION_FOUND = Version is not explicitly stated. When building this specification, the most recent version {0} has been used
1125
+ VS_VERSION_NONE = Version is not explicitly stated, and the target {0} has no stated version either
1126
+ VS_VERSION_NOTHING = Version is not explicitly stated. No matching {0} found
1126
1127
  CS_VERSION_NOTHING_TEXT = Not Stated (use latest from terminology server)
1127
1128
  VS_VERSION_NOTHING_TEXT = Not State
1128
- STRUC_DEF_IMPLEMENTS = Interfaces Implemented
1129
+ STRUC_DEF_IMPLEMENTS = Interfaces Implemented
1130
+ PROV_REFERENCE = This {0} is referenced from the following provenance resources:
1131
+ CONF_SHALL = SHALL
1132
+ CONF_SHALLNOT = SHALL NOT
1133
+ CONF_SHOULD = SHOULD
1134
+ CONF_SHOULDNOT = SHOULD NOT
1135
+ CONF_MAY = MAY
1136
+ CONF_SHALL_PLURAL = SHALL
1137
+ CONF_SHALLNOT_PLURAL = SHALL NOT
1138
+ CONF_SHOULD_PLURAL = SHOULD
1139
+ CONF_SHOULDNOT_PLURAL = SHOULD NOT
1140
+ CONF_MAY_PLURAL = MAY
1141
+ CSREQ_TITLE = Narrative Conformance Statements
1142
+ CSREQ_DESC = Conformance statements found throughout the narrative of the IG consolidated into this computable resource for traceability purposes
1143
+ CSTABLE_HEAD_ID = Id
1144
+ CSTABLE_HEAD_EXPECT = Expectation
1145
+ CSTABLE_HEAD_COND = Conditional?
1146
+ CSTABLE_HEAD_ACTOR_one = Actor{1}
1147
+ CSTABLE_HEAD_ACTOR_other = Actors{1}
1148
+ CSTABLE_HEAD_CAT_one = Category{1}
1149
+ CSTABLE_HEAD_CAT_other = Categories{1}
1150
+ CSTABLE_HEAD_RULE = Rule
1151
+ CSTABLE_TITLE_ID = Filter to only statements with ids that contain the specified text
1152
+ CSTABLE_TITLE_EXPECT = Filter to only statements with one of the selected expectation type(s)
1153
+ CSTABLE_TITLE_COND = Filter to only statements that are conditional, not conditional, or no constraint
1154
+ CSTABLE_TITLE_ACTOR = Filter to only statements that apply to the specified actor(s)
1155
+ CSTABLE_TITLE_CAT = Filter to only statements that apply to the specified category(ies)
1156
+ CSTABLE_TITLE_RULE = Filter to only statements that contain the specified text
1157
+ CSTABLE_TITLE_CLEAR = Clear the Filter
1158
+ CSTABLE_COND_YES = Yes
1159
+ CSTABLE_COND_NO = No
1160
+ CSTABLE_COND_ANY = Any
1161
+ CSTABLE_CLEAR_FILTERS = Clear Filters
1162
+ CONSENT_DATE = Agreement Date
1163
+ CONSENT_PERIOD = Applicable Period
1164
+ CONSENT_HT_PERIOD = Period
1165
+ CONSENT_HT_DATA_PERIOD = Data from Period
1166
+ CONSENT_CATEGORY_one = Category
1167
+ CONSENT_CATEGORY_other = Categories
1168
+ CONSENT_SCOPE_one = Scope
1169
+ CONSENT_SCOPE_other = Scopes
1170
+ GENERAL_IDENTIFIER_one = Identifier
1171
+ GENERAL_IDENTIFIER_other = Identifiers
1172
+ CONSENT_PART_TBL_ROLE = Role
1173
+ CONSENT_PART_TBL_DETAILS = Details
1174
+ CONSENT_PART_TBL_PATIENT = Patient
1175
+ CONSENT_PART_TBL_PARTY = Party
1176
+ CONSENT_PART_TBL_GRANTOR = Grantor
1177
+ CONSENT_PART_TBL_GRANTEE = Grantee
1178
+ CONSENT_PART_TBL_MANAGER = Manager
1179
+ CONSENT_PART_TBL_CONTROLLER = Controller
1180
+ CONSENT_PART_TBL_PATIENT_DESC = Who the consent applies to
1181
+ CONSENT_PART_TBL_GRANTOR_DESC = Who is granting rights according to the policy and rules
1182
+ CONSENT_PART_TBL_PARTY_DESC = Who is agreeing to the policy and rules
1183
+ CONSENT_PART_TBL_GRANTEE_DESC = Who is agreeing to the policy and rules
1184
+ CONSENT_PART_TBL_MANAGER_DESC = Who manages the consent through its lifecycle.
1185
+ CONSENT_PART_TBL_CONTROLLER_DESC = Who controls/enforces the access according to the consent.
1186
+ CONSENT_BASIS_REGULATION_PREFIX_one = This consent is made under the regulation
1187
+ CONSENT_BASIS_REGULATION_PREFIX_other = This consent is made under the regulations
1188
+ CONSENT_BASIS_REGULATION_SUFFIX_MORE = and
1189
+ CONSENT_BASIS_REGULATION_SUFFIX = .
1190
+ CONSENT_BASIS_REGULATION_NONE = This consent is made under
1191
+ CONSENT_BASIS_POLICY_PREFIX_one = the policy
1192
+ CONSENT_BASIS_POLICY_PREFIX_other = the policies
1193
+ CONSENT_BASIS_POLICY_SUFFIX = .
1194
+ CONSENT_HTABLE_RULE = Rule
1195
+ CONSENT_HTABLE_RULE_DESC = Applicable Rule
1196
+ CONSENT_HTABLE_WHEN = Time Period
1197
+ CONSENT_HTABLE_WHEN_DESC = Applicable Period
1198
+ CONSENT_HTABLE_WHO = Who
1199
+ CONSENT_HTABLE_WHO_DESC = Applicable Parties
1200
+ CONSENT_HTABLE_WHAT = What
1201
+ CONSENT_HTABLE_WHAT_DESC = Applicable Data
1202
+ CONSENT_HTABLE_RULES = Rules
1203
+ CONSENT_HTABLE_RULES_DESC = Other Applicable Rules
1204
+ CONSENT_PERMIT = permit
1205
+ CONSENT_DENY = deny
1206
+ CONSENT_PERMIT_DESC = The subject has given their consent.
1207
+ CONSENT_DENY_DESC = The subject has NOT given their consent.
1208
+ CONSENT_PROVISION = Consent Provision
1209
+ CONSENT_HT_SEC_LABEL = Labled as
1210
+ CONSENT_HT_ACTION = For action
1211
+ CONSENT_HT_PURPOSE = Purpose
1212
+ CONSENT_HT_CLASS = Class
1213
+ CONSENT_HT_RESOURCE_TYPE = Resource Type
1214
+ CONSENT_HT_DOC_TYPE = Document Type
1215
+ CONSENT_HT_CODE = Code
1216
+ WEB_SOURCE = Web Source
1217
+ GENERAL_COPY = Click to Copy
1218
+ CODESYSTEM_LVL = Level
1219
+ FEATURE = Feature
package/tx/cs/cs-api.js CHANGED
@@ -719,7 +719,11 @@ class CodeSystemProvider {
719
719
  return false;
720
720
  }
721
721
 
722
+ hasMultiHierarchy() {
723
+ return false;
724
+ }
722
725
  /**
726
+ *
723
727
  * @returns {string} valueset for the code system
724
728
  */
725
729
  valueSet() {
@@ -919,6 +923,14 @@ class CodeSystemFactoryProvider {
919
923
  async close() {
920
924
 
921
925
  }
926
+
927
+ /**
928
+ * if known, the right place to point to on the web for the code system
929
+ * @returns {String}
930
+ */
931
+ webSource() {
932
+ return undefined;
933
+ }
922
934
  }
923
935
 
924
936
  module.exports = {
package/tx/cs/cs-cs.js CHANGED
@@ -1521,7 +1521,11 @@ class FhirCodeSystemProvider extends BaseCSServices {
1521
1521
  }
1522
1522
 
1523
1523
  versionNeeded() {
1524
- return this.codeSystem.jsonObj.versionNeeded;
1524
+ return this.codeSystem.jsonObj.versionNeeded ? true : false;
1525
+ }
1526
+
1527
+ hasMultiHierarchy() {
1528
+ return this.codeSystem.hasMultiHierarchy;
1525
1529
  }
1526
1530
 
1527
1531
  }
@@ -401,20 +401,24 @@ class SnomedServices {
401
401
  }
402
402
 
403
403
 
404
- filterIn(id) {
404
+ filterIn(idList) {
405
405
  const result = new SnomedFilterContext();
406
- const conceptResult = this.concepts.findConcept(id);
406
+ let members = [];
407
+ for (let id of idList.split(',')) {
408
+ const conceptResult = this.concepts.findConcept(id);
407
409
 
408
- if (!conceptResult.found) {
409
- throw new Error(`The SNOMED CT Concept ${id} is not known`);
410
- }
410
+ if (!conceptResult.found) {
411
+ throw new Error(`The SNOMED CT Concept ${id} is not known`);
412
+ }
411
413
 
412
- const refSetIndex = this.getConceptRefSet(conceptResult.index, false);
413
- if (refSetIndex === 0) {
414
- throw new Error(`The SNOMED CT Concept ${id} is not a reference set`);
414
+ const refSetIndex = this.getConceptRefSet(conceptResult.index, false);
415
+ if (refSetIndex === 0) {
416
+ members.push(conceptResult.index);
417
+ } else {
418
+ members.push(...this.refSetMembers.getMembers(refSetIndex));
419
+ }
415
420
  }
416
-
417
- result.members = this.refSetMembers.getMembers(refSetIndex) || [];
421
+ result.members = members;
418
422
  return result;
419
423
  }
420
424
 
@@ -894,6 +898,17 @@ class SnomedProvider extends BaseCSServices {
894
898
  if (id !== 0n && ['=', 'is-a', 'descendent-of', 'in', 'generalizes', 'child-of'].includes(op)) {
895
899
  return this.sct.conceptExists(value);
896
900
  }
901
+ if (op === 'in' && value.includes(',')) {
902
+ let ok = true;
903
+ for (const idStr of value.split(',')) {
904
+ const id = this.sct.stringToIdOrZero(idStr);
905
+ if (id === 0n) {
906
+ ok = false;
907
+ break;
908
+ }
909
+ }
910
+ return ok;
911
+ }
897
912
  }
898
913
  if (prop === 'inactive') {
899
914
  return op === '=' && ['true', 'false'].includes(value);
@@ -927,7 +942,7 @@ class SnomedProvider extends BaseCSServices {
927
942
 
928
943
  if (prop === 'concept') {
929
944
  const id = this.sct.stringToIdOrZero(value);
930
- if (id === 0n) {
945
+ if (id === 0n && op !== 'in') {
931
946
  throw new Error(`Invalid concept ID: ${value}`);
932
947
  }
933
948
 
@@ -953,7 +968,7 @@ class SnomedProvider extends BaseCSServices {
953
968
  return null;
954
969
  }
955
970
  case 'in': {
956
- filterContext.filters.push(this.sct.filterIn(id));
971
+ filterContext.filters.push(this.sct.filterIn(value));
957
972
  return null;
958
973
  }
959
974
  default:
@@ -1333,6 +1348,10 @@ class SnomedProvider extends BaseCSServices {
1333
1348
  return result;
1334
1349
  }
1335
1350
 
1351
+ hasMultiHierarchy() {
1352
+ return true;
1353
+ }
1354
+
1336
1355
  }
1337
1356
 
1338
1357
  /**
@@ -1621,6 +1640,11 @@ class SnomedServicesFactory extends CodeSystemFactoryProvider {
1621
1640
  return null;
1622
1641
  }
1623
1642
  }
1643
+
1644
+ webSource() {
1645
+ return this.version();
1646
+ }
1647
+
1624
1648
  }
1625
1649
 
1626
1650
  function getEditionName(edition) {
@@ -117,18 +117,22 @@
117
117
  <div class="container">
118
118
  <div class="inner-wrapper">
119
119
  <p>
120
- <a href="http://www.hl7.org/fhir" style="color: gold" title="Fast Healthcare Interoperability Resources - Home Page"><img border="0" src="/icon-fhir-16.png" style="vertical-align: text-bottom"/> <b>FHIR</b></a> &copy; HL7.org 2011+. &nbsp;|&nbsp;
120
+ <a href="http://www.hl7.org/fhir" style="color: gold" title="Fast Healthcare Interoperability Resources - Home Page"><img border="0" src="/icon-fhir-16.png" style="vertical-align: text-bottom"/> <b>FHIR</b></a> v[%fhir-version%] &copy; HL7.org 2011+. &nbsp;|&nbsp;
121
121
  <a href="https://github.com/HealthIntersections/FHIRsmith/blob/main/README.md" style="color: gold"><img border="0" src="/FHIRsmith16.png" style="vertical-align: text-bottom"/> FHIRsmith</a> [%ver%] &copy; HealthIntersections.com.au 2023+ &nbsp;|&nbsp;
122
- FHIR Version [%fhir-version%] &nbsp;|&nbsp; ([%ms%] ms)
122
+ &nbsp; ([%ms%] ms)
123
+ [%sponsorMessage%]
123
124
  </p>
124
125
  </div>
125
126
  </div>
126
127
  </div>
127
128
 
128
129
  <!-- JS and analytics only. -->
129
- <script src="/assets/js/respond.min.js"/>
130
- <script src="/assets/js/fhir.js"/>
130
+ <script src="/assets/js/respond.min.js"> </script>
131
+ <script src="/assets/js/fhir.js"> </script>
132
+ <script src="/assets/js/clipboard.min.js"> </script>
133
+ <script src="/assets/js/clipboard-btn.js"> </script>
131
134
 
132
135
  </body>
133
136
 
134
137
  </html>
138
+