/// <reference path="../../core/js/santedb.js"/>
/*
* Copyright (C) 2021 - 2024, SanteSuite Inc. and the SanteSuite Contributors (See NOTICE.md for full copyright notices)
* Copyright (C) 2019 - 2021, Fyfe Software Inc. and the SanteSuite Contributors
* Portions Copyright (C) 2015-2018 Mohawk College of Applied Arts and Technology
*
* Licensed under the Apache License, Version 2.0 (the "License"); you
* may not use this file except in compliance with the License. You may
* obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
var ___originalButtonTexts = {};
// Add render of concept name
SanteDBWrapper.prototype.display = new function () {
var __preferredName = "OfficialRecord";
function __cascadeScopeObject(scope, objectNames, value, processList) {
// Make sure we don't double process
processList = processList || [];
if (processList.indexOf(scope.$id) > -1) {
return;
}
processList.push(scope.$id);
objectNames.forEach(n => {
if (scope[n] !== undefined) {
scope[n] = value;
}
});
// Traverse siblings
if (scope.$$nextSibling) {
__cascadeScopeObject(scope.$$nextSibling, objectNames, value, processList);
}
// Traverse children
if (scope.$$childHead) {
__cascadeScopeObject(scope.$$childHead, objectNames, value, processList);
}
}
/**
* @summary Sets the preferred name type for rendering names
* @param {string} nameType The name type preferred
*/
this.setPreferredNameType = function (nameType) {
__preferredName = nameType;
}
/**
* @method
* @memberof SanteDBWrapper.display
* @summary Replaces the content of the button with a defined wait state
* @param {String} target The target of the wait button
* @param {boolean} state True if the object is loading, false if not
* @param {boolean} onlyGlyph True if only a wait glyph should be shown
*/
this.buttonWait = function (target, state, onlyGlyph) {
var btn = $(target);
if (btn) {
if (state) {
btn.attr('disabled', 'disabled');
if (!___originalButtonTexts[target])
___originalButtonTexts[target] = btn.html();
if (!onlyGlyph)
btn.html(`<i class="fas fa-circle-notch fa-spin"></i> ${SanteDB.locale.getString("ui.wait")}`);
else
btn.html('<i class="fas fa-circle-notch fa-spin"></i>');
}
else {
btn.removeAttr('disabled');
btn.html(___originalButtonTexts[target]);
delete (___originalButtonTexts[target]);
}
}
};
/**
* @method
* @memberof SanteDBWrapper.display
* @summary Renders a date in the specified format
* @param {Date} date The date to be rendered
* @param {String} precision The precision of the date
*/
this.renderDate = function (date, precision) {
var dateFormat;
if (!SanteDB.locale.dateFormats) {
SanteDB.resources.locale.findAsync().then(function (locale) {
var localeAsset = locale[SanteDB.locale.getLocale()];
if (localeAsset)
localeAsset.forEach(function (l) {
$.getScript(l);
});
}).catch(function (e) {
console.error(e);
});
}
switch (precision) {
case 1: // Year "Y"
case 'Y':
dateFormat = SanteDB.locale.dateFormats.year;
break;
case 2: // Month "m"
case 'm':
dateFormat = SanteDB.locale.dateFormats.month;
break;
case 3: // Day "D"
case 'D':
dateFormat = SanteDB.locale.dateFormats.day;
break;
case 4: // Hour "H"
case 'H':
dateFormat = SanteDB.locale.dateFormats.hour;
break;
case 5: // Minute "M"
case 'M':
dateFormat = SanteDB.locale.dateFormats.minute;
break;
case 6: // Second "S"
case 'S':
case 0: // Full "F"
case 'F':
default:
dateFormat = SanteDB.locale.dateFormats.second;
break;
}
if (date) {
// Non timed
switch (dateFormat) {
case 1: // Year, Month, Day always expressed in UTC for Javascript will take the original server value and adjust.
case 'Y':
case 2:
case 'm':
case 3:
case 'D':
return moment(date).utc().format(dateFormat);
default:
return moment(date).format(dateFormat);
}
}
return null;
};
/**
* @method
* @memberof SanteDBWrapper.display
* @summary Renders the specified concept name
* @returns The appropriate display name for the concept
* @param {SanteDBModel.Concept} concept The concept to be rendered
*/
this.renderConcept = function (concept) {
var retVal = "";
if (!concept)
retVal = "";
else if (typeof (concept) === "string")
retVal = concept;
else if (concept.name && concept.name[SanteDB.locale.getLanguage()])
retVal = concept.name[SanteDB.locale.getLanguage()];
else if (concept.name)
retVal = concept.name[Object.keys(concept.name)[0]];
else if (concept.mnemonic)
retVal = concept.mnemonic;
else if (concept[SanteDB.locale.getLanguage()])
retVal = concept[SanteDB.locale.getLanguage()];
else
retVal = concept[Object.keys(concept)[0]];
if (Array.isArray(retVal))
{
var name = retVal[0];
return name[0].toUpperCase() + name.substring(1);
}
else
return retVal;
};
/**
* @method
* @member SanteDBWrapper.display
* @summary Renders an entity or act identifier
* @param {EntityIdentifier} id The identifier to be rendered
* @param {String} domain The domain to render
* @param {boolean} emitDomain True if the domain in which the identifier belongs should be emitted
*/
this.renderIdentifier = function (id, domain, emitDomain) {
var retVal = "";
if (id === undefined)
return "";
if (domain && id[domain])
retVal = id[domain][0].value;
else
for (var k in id)
{
retVal = id[k][0].value;
domain = k;
break;
}
if(emitDomain) {
retVal += ` <small>${domain}</small>`;
}
return retVal;
};
/**
* @method
* @memberof SanteDBWrapper.display
* @summary Renders the specified entity name
* @returns The appropriate display name for the entity
* @param {SanteDBModel.EntityName} name The name of the entity to render
* @param {string} type The type of name to render (Legal, Official Record, etc.)
*/
this.renderEntityName = function (name, type) {
if (!name)
return "";
else if (typeof (name) === "string")
return name;
// Get the type of name to render
if (type) {
name = name[type];
}
else if (name[__preferredName])
name = name[__preferredName];
else if (!name.component) {
name = name[Object.keys(name)[0]]
}
// Is the name actually an array? If so, take the first
if (Array.isArray(name))
name = name[0];
// Render name
if (!name)
return "";
else if (name.component) {
var nameStr = "";
// Prefix?
if (name.component.Prefix) {
if (name.component.Prefix.join)
nameStr += name.component.Prefix.join(" ");
else
nameStr += name.component.Prefix;
nameStr += " ";
}
// Given names
if (name.component.Given) {
if (name.component.Given.join)
nameStr += name.component.Given.join(" ");
else
nameStr += name.component.Given;
nameStr += " ";
}
// Family names
if (name.component.Family) {
if (name.component.Family.join)
nameStr += name.component.Family.join(" ");
else
nameStr += name.component.Family;
nameStr += " ";
}
// Suffix?
if (name.component.Suffix) {
if (name.component.Suffix.join)
nameStr += name.component.Suffix.join(" ");
else
nameStr += name.component.Suffix;
nameStr += " ";
}
// Other
if (name.component.$other !== undefined) {
if (name.component.$other.join)
nameStr += name.component.$other.join(' ');
else if (name.component.$other.value)
nameStr += name.component.$other.value;
else
nameStr += name.component.$other;
}
return nameStr;
}
else if (typeof (name) === 'string')
return name;
else
return "N/A";
},
/**
* @method
* @memberof SanteDBWrapper.display
* @summary Renders the specified entity address
* @returns The appropriate display address for the entity
* @param {SanteDBModel.EntityAddress} address The address of the entity to render
* @param {string} type The type of name to render (Legal, Official Record, etc.)
*/
this.renderEntityAddress = function (address, type) {
if (!address)
return "N/A";
if (type)
address = address[type];
else if (!address.component)
address = address[Object.keys(address)[0]]
// Is the address actually an array? If so, take the first
if (Array.isArray(address))
address = address[0];
// Render address
if (!address)
return "";
else if (address.component) {
var addrStr = "";
if (address.component.CareOf)
addrStr += `C/O ${address.component.CareOf}, `;
if (address.component.PostBox)
addrStr += `P.O. Box ${address.component.PostBox}, `;
if (address.component.AdditionalLocator)
addrStr += address.component.AdditionalLocator + ", ";
if (address.component.UnitIdentifier)
addrStr += address.component.UnitIdentifier + ", ";
if (address.component.StreetAddressLine)
addrStr += address.component.StreetAddressLine + ", ";
if (address.component.AddressLine)
addrStr += address.component.AddressLine + ", ";
if (address.component.Precinct)
addrStr += address.component.Precinct + ", ";
if (address.component.City)
addrStr += address.component.City + ", ";
if (address.component.County != null)
addrStr += address.component.County + ", ";
if (address.component.State != null)
addrStr += address.component.State + ", ";
if (address.component.Country != null)
addrStr += address.component.Country + ", ";
return addrStr.substring(0, addrStr.length - 2);
}
};
/**
* @method
* @memberof SanteDB.display
* @param {Patient} patient The patient to be rendered as a string
* @param {String} preferredDomain The preferred identity domain for identity rendering
*/
this.renderPatientAsString = function (patient, preferredDomain) {
var retVal = '';
retVal += "<span class='mr-1'>";
if (patient.name) {
retVal += SanteDB.display.renderEntityName(patient.name);
}
retVal += "</span><span class='mr-1 badge badge-secondary'>";
if (patient.identifier) {
if (preferredDomain && patient.identifier[preferredDomain])
retVal += `<i class="fas fa-id-card"></i> ${SanteDB.display.renderIdentifier(patient.identifier, preferredDomain)}`;
else {
var key = Object.keys(patient.identifier)[0];
retVal += `<i class="far fa-id-card"></i> ${SanteDB.display.renderIdentifier(patient.identifier, key)}`;
}
}
retVal += "</span><span class='mr-1'>";
if (patient.dateOfBirth)
retVal += `<br/><i class='fas fa-birthday-cake'></i> ${SanteDB.display.renderDate(patient.dateOfBirth, patient.dateOfBirthPrecision)} `;
// Deceased?
if (patient.deceasedDate)
retVal += `<span class='badge badge-dark'>${SanteDB.locale.getString("ui.model.patient.deceasedIndicator")}</span>`;
retVal += "</span><span class='mr-1'>";
// Gender
if (patient.genderConceptModel) {
switch (patient.genderConceptModel.mnemonic) {
case 'Male':
retVal += `<i class='fas fa-male' title="${SanteDB.display.renderConcept(patient.genderConceptModel)}"></i> ${SanteDB.display.renderConcept(patient.genderConceptModel)}`;
break;
case 'Female':
retVal += `<i class='fas fa-female' title="${SanteDB.display.renderConcept(patient.genderConceptModel)}"></i> ${SanteDB.display.renderConcept(patient.genderConceptModel)}`;
break;
default:
retVal += `<i class='fas fa-restroom' title="${SanteDB.display.renderConcept(patient.genderConceptModel)}"></i> ${SanteDB.display.renderConcept(patient.genderConceptModel)}`;
break;
}
}
retVal += "</span>";
if(patient.address) {
retVal += "<br/><span class='mr-1'><i class='fas fa-fw fa-house'></i> ";
retVal += SanteDB.display.renderEntityAddress(patient.address);
retVal += "</span>";
}
if (patient.determinerConcept == "6b1d6764-12be-42dc-a5dc-52fc275c4935") {
retVal += `<span class='badge badge-success' title='${SanteDB.locale.getString("ui.mdm.rot")}'><i class='fas fa-gavel'></i> </span>`
}
return retVal;
};
/**
* @method
* @memberof SanteDB.display
* @param {Guid} statusConcept The status concept to render
* @returns {string} The HTML rendering of the status concept
*/
this.renderStatus = function (statusConcept) {
switch (statusConcept) {
case StatusKeys.Active:
return `<span class="badge badge-primary"><i class="fas fa-circle"></i> ${SanteDB.locale.getString('ui.state.active')}</span>`;
case StatusKeys.Obsolete:
return `<span class="badge badge-danger"><i class="fas fa-circle"></i> ${SanteDB.locale.getString('ui.state.obsolete')}</span>`;
case StatusKeys.Nullified:
return `<span class="badge badge-dark"><i class="fas fa-circle"></i> ${SanteDB.locale.getString('ui.state.nullified')}</span>`;
case StatusKeys.New:
return `<span class="badge badge-info"><i class="fas fa-circle"></i> ${SanteDB.locale.getString('ui.state.new')}</span>`;
case StatusKeys.Inactive:
return `<span class="badge badge-warning"><i class="fas fa-circle"></i> ${SanteDB.locale.getString('ui.state.inactive')}</span>`;
}
}
/**
*
* @param {number} decimal The degrees expressed as a decimal
* @returns {Object} A structure with degrees, minutes, and seconds
*/
this.convertToDegrees = function (decimal) {
return {
deg: 0 | (decimal < 0 ? (decimal = -decimal) : decimal),
min: 0 | (((decimal += 1e-9) % 1) * 60),
sec: (0 | (((decimal * 60) % 1) * 6000)) / 100,
};
}
/**
*
* @param {*} scope The scope to traverse up the scope tree for
* @returns The root scope on the tree
*/
this.getRootScope = function (scope) {
while (scope.$parent) {
scope = scope.$parent;
}
return scope;
}
/**
*
* @param {*} scope The scope to traverse up the scope tree for
* @returns The root scope on the tree
*/
this.getRootScope = function (scope) {
while (scope.$parent) {
scope = scope.$parent;
}
return scope;
}
/**
* @method
* @summary Iterates up the parent scope via scope.$parent until {see: nameOfVariable} is encountered
* @param {*} scope The Angular scope that is in the current controller
* @param {string} nameOfVariable The name of the variable to fetch from the scope
* @returns {object} The object with nameOfVariable
*/
this.getParentScopeVariable = function (scope, nameOfVariable) {
var retVal = null;
do {
retVal = scope[nameOfVariable];
scope = scope.$parent;
} while (!retVal && scope)
return retVal;
}
/**
* @method
* @summary Copies an object scross scopes (useful for updating all objects)
* @param {*} scope The angularJS scope to cascade the object to
* @param {*} objectNames The names to propogate on the scope
* @param {*} value The value to set on the @param objectNames
*/
this.cascadeScopeObject = function (scope, objectNames, value) {
// Ensure objects are an array
if (!Array.isArray(objectNames)) {
objectNames = [objectNames];
}
__cascadeScopeObject(scope, objectNames, value, []);
}
};
// Set the sticky style
function attachStickyScrollEvent() {
var contentWrapper = $(".content-wrapper");
if(contentWrapper.length) {
contentWrapper.scroll(() => {
$(".scroll-sticky").each((i, ele) => {
if(CSS.supports && CSS.supports('position','sticky')) {
var cOfs = ele.getBoundingClientRect().top;
var cwOfs = contentWrapper[0].getBoundingClientRect().top;
var stuck = (cOfs - cwOfs) < 50;
ele.classList.toggle('is-sticky', stuck);
}
})
});
}
else {
setTimeout(attachStickyScrollEvent, 50);
}
}
$(document).ready(attachStickyScrollEvent);
$(".content-wrapper").ready(()=> {
$(".content-wrapper").scroll(e => {
})
});