Visão Geral
Esta interface web foi projetada para facilitar o gerenciamento de Tabelas de Pesquisa de Dados (Data Lookup Tables) por meio de uma página web amigável. É particularmente útil quando os valores da sua tabela de pesquisa são grandes, dinâmicos e mudam frequentemente. Ao conceder aos usuários finais acesso controlado a esta interface web (permissões de leitura, escrita e exclusão limitadas a esta página), eles podem gerenciar os dados da tabela de pesquisa de forma eficiente, de acordo com suas necessidades.
Os dados gerenciados por meio desta interface podem ser utilizados perfeitamente em regras ou transformações de dados do HealthConnect, eliminando a necessidade de constante monitoramento e gerenciamento manual das tabelas de pesquisa, economizando tempo significativo.
Nota:
Se a Tabela de Pesquisa de Dados padrão não atender aos seus requisitos de mapeamento, você pode criar uma tabela personalizada e adaptar esta interface web, juntamente com sua classe de suporte, com modificações mínimas. O código de exemplo da classe está disponível mediante solicitação.
Pré-requisitos
Antes de usar a interface web, certifique-se de ter criado uma Lookup Table de Dados vazia no HealthConnect:
- Navegue até Interoperabilidade → Configurar → Data Lookup Tables.
- Clique em Novo para abrir o pop-up "Create New Lookup Table".
- Insira o nome desejado para sua tabela de pesquisa e clique em OK
- Clique em Salvar para finalizar a criação da tabela
- Verifique a criação da tabela de pesquisa clicando em Abrir na mesma janela — sua nova tabela deve aparecer na lista.
Nesta documentação, o nome da Tabela de Pesquisa de Dados de exemplo usado é:
"Example of data lookup table"
Instruções de Uso
O processo de configuração é simples:
- Obtenha o código: Baixe o código fornecido no repositório GitHub ou copie-o do link da comunidade.
- Crie uma página CSP: Crie uma nova página CSP em seu ambiente HealthConnect e cole o código completo do arquivo DataLookupWebApp.
- Crie uma classe: Copie e cole o código da classe fornecido na documentação ou no repositório
Configuração
Antes de compilar e executar:
- Coloque o nome da sua Tabela de Pesquisa de Dados na página web, substituindo o placeholder indicado pela caixa vermelha na captura de tela abaixo pelo nome real da sua tabela de pesquisa.
- Certifique-se de que o nome da classe no código corresponda ao nome da sua classe personalizada.
- Atribua o nome da sua tabela de pesquisa na classe, onde indicado por myDtName = 'your data lookup table'. Veja a captura de tela acima.
- Compile tanto a classe quanto a página CSP para finalizar a configuração.
Testando a Aplicação
Adicionar Registros
- Insira a chave e o par chave-valor correspondente nos campos do formulário.
- Clique em Add Record (Adicionar Registro) para inserir os dados na tabela de pesquisa.
Captura de tela 1: Adicionando Registros (122 – Spine X-ray)
Atualizar Registros
- Selecione um registro existente e modifique o par chave-valor conforme necessário.
- Clique em Update (Atualizar) para salvar as alterações. Exemplo: Atualizando 122 "Spine X-ray" para "Abdominal X-ray (AXR)".
Excluir Registros
- Selecione o registro a ser excluído (144 – MRI).
- Clique no botão Delete (Excluir) para remover o registro da tabela de pesquisa. Exemplo: Excluindo "144 - MRI".
Verificar Tabela de Pesquisa de Dados no HealthConnect
Navegue até Interoperabilidade → Configurar → Data Lookup Tables → Abrir
Pesquisar Registro
Código / Recursos
- O código fonte completo também está disponível no GitHub para download e referência:
https://github.com/pandeySR/Reusable-Web-Interface-for-Data-Lookup-Table
<!DOCTYPE html>
<!--
This web application is designed and developed to insert, update, and delete records (key–value pairs) in the Data Lookup Table through a web interface.
Author: Sanjib Pandey
Date: 16/10/2025
-->
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="author" content="Sanjib Pandey" />
<title>YOUR TITLE : Data Lookup Table - Data Record </title>
<!-- Bootstrap CSS CDN, jQuery, Datatable -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.13.5/css/dataTables.bootstrap5.min.css" />
<script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
<script src="https://cdn.datatables.net/1.13.5/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.5/js/dataTables.bootstrap5.min.js"></script>
<style>
h2 {
text-align: center;
color: #fff;
background-color: #00b300;
padding: 15px 10px;
border-radius: 5px;
margin-bottom: 5px;
margin-top: 0px;
}
html, body {
height: 100%;
margin: 0;
}
body {
display: flex;
min-height: 100vh;
background-color: #f8f9fa;
padding-top: 10px;
flex-direction: column;
align-items: center;
}
.container {
max-width: 1100px;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 15px rgba(0,0,0,0.2);
margin-top: 5px;
width: 100%;
}
.table-scroll-vertical
{
max-height: 450px;
overflow-y: auto;
border: 1px solid #dee2e6;
border-radius: 5px;
margin-top: 0;
}
.small-italic
{
font-size: 0.85em;
font-style: italic;
color: #C0C0C0;
}
.dataTables_filter label
{
font-weight: bold;
color: #333;
color: red;
float: left;
}
.dataTables_filter input
{
border: 2px solid #993399;
border-radius: 5px;
padding: 6px 10px;
outline: none;
width: 250px;
}
.page-footer
{
text-align: center;
padding: 10px 5px;
font-size: 0.95rem;
color: #809fff;
background-color: #f8f9fa;
border-top: 1px solid #993399;
margin-top: 5px;
}
</style>
<style>
@keyframes blink
{
50%
{
opacity: 0;
}
}
</style>
</head>
<body>
<div class="container">
<div style="overflow: hidden;">
<div style="float: left; font-size: smaller; font-weight: bold;color:#b3ffff;animation: blink 1s infinite;">
Environment : DEV
</div>
<h2 style="text-align: center; margin: 0;">
Your Organization Name or Company Name<br>
<span style="font-size: smaller; color: yellow;text-align: center;">Data Lookup Table</span>
</h2>
</div>
<form id="recordForm" class="form-horizontal" action="" method="POST">
<div class="form-group">
<!--for any other information if you want> -->
</div>
<div class="row mb-3">
<label for="key" class="col-sm-3 col-form-label fw-bold">Key :</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="key" name="key" placeholder="Enter the Key data !" required />
</div>
</div>
<div class="row mb-3">
<label for="kvalue" class="col-sm-3 col-form-label fw-bold">Key Pair Value</label>
<div class="col-sm-9">
<input type="text" class="form-control" id="kvalue" name="kvalue" placeholder="Enter the key paris value !" required />
</div>
</div>
<div class="d-flex justify-content-between align-items-center mt-4 flex-wrap">
<p class="mb-2 mb-md-0 text-primary">
<i>Click the edit icon to modify a record, then press "Update" to save. To delete, press the "Delete" button.</i>
</p>
<div class="d-flex flex-wrap justify-content-end">
<button class="btn btn-success me-2" id="Add" type="submit" name="Add">
<i class="fa fa-plus me-1" style="font-size:18px; color:white;"></i> Add Record
</button>
<button class="btn btn-primary me-2" type="submit" name="Update">
<i class="fa fa-edit me-1" style="font-size:18px;"></i> Update
</button>
<button class="btn btn-danger me-2" id="Delete" type="submit" name="Delete">
<i class="fa fa-remove me-1" style="font-size:18px;"></i> Delete
</button>
<button class="btn btn-info" id="Cancel" type="submit" name="Cancel">
<i class="glyphicon glyphicon-refresh" style="font-size:18px;"></i> Cancel
</button>
</div>
</div>
<div></div>
</form>
<script language=SQL name="query">
SELECT KeyName, DataValue FROM Ens_Util.LookupTable WHERE TableName='Data Lookup Table Example'
</script>
<script language=cache runat=server>
S myKeyName=$Get(%request.Data("key",1))
S myKeyValue=$Get(%request.Data("kvalue",1))
S myDtName="Data Lookup Table Example"
I ($Data(%request.Data("Add",1)))
{
I ((myKeyName '="") && (myKeyValue '="") && (myDtName '=""))
{
I ##Class(SANJIB.DataLookup.Methods).ChkLookupKeyValue(myDtName,myKeyName)="F"
{
D ##Class(SANJIB.DataLookup.Methods).InsertLookUpValues(myDtName,myKeyName,myKeyValue)
}
else
{ W "The key has already been inserted.." &html<<div style=color:red>#(myKeyName)#</div>> }
}
}
I ($Data(%request.Data("Update",1)))
{
I ((myKeyName '="") && (myKeyValue '="") && (myDtName '=""))
{
D ##Class(SANJIB.DataLookup.Methods).UpdateLookUpValues(myDtName,myKeyName,myKeyValue)
}
}
I ($Data(%request.Data("Delete",1)))
{
I ((myKeyName '="") && (myKeyValue '="") && (myDtName '=""))
{
D ##Class(SANJIB.DataLookup.Methods).DeleteLookUpValues(myDtName,myKeyName)
}
}
</script>
<div class="table-responsive table-scroll-vertical">
<table class="table table-bordered border-primary table table-hover mt-2" id="dataTable" style="min-width: 1000px;">
<thead class="table-warning">
<tr>
<th>Key Data</th>
<th>Key Pair Value</th>
<th style="text-align:center;">Actions</th>
</tr>
</thead>
<tbody id="tableRecordset">
</tr>
<csp:while counter=myQueryRow condition=query.Next()>
<tr class='#($S(myQueryRow#2:"LightRow",1:"LightRow"))#'>
<csp:while counter=myQueryColumn condition="(myQueryColumn<query.GetColumnCount())">
<td style="background-color:#e6ffff">#(query.GetData(myQueryColumn))#</td>
</csp:while>
<td style="text-align:center;">
<button class="btn btn-sm btn-danger me-2 edit-delete-btn" data-id="#(query.GetData(0))#">
<i class="fa fa-edit"></i>
<i class="fa fa-trash"></i>
</button>
</td>
</tr>
</csp:while>
</tbody>
</table>
</div>
</div>
<script language=javascript>
document.addEventListener('DOMContentLoaded', () =>
{
const editButtons = document.querySelectorAll('.edit-delete-btn');
editButtons.forEach(button =>
{
button.addEventListener('click', () =>
{
const row = button.closest('tr');
document.getElementById("Add").disabled=true
const kID=row.cells[0].textContent.trim();
const pairVal = row.cells[1].textContent.trim();
document.getElementById('key').value = kID;
document.getElementById('kvalue').value = pairVal;
document.getElementById('key').focus();
});
});
});
</script>
<script language=javascript>
document.getElementById('Cancel').addEventListener('click', () =>
{
event.preventDefault();
document.getElementById('recordForm').reset();
});
</script>
<script language=javascript>
$(document).ready(function()
{
$('#dataTable').DataTable(
{
"order": [[0, "asc"]],
"paging": true,
"lengthChange": false,
"searching": true,
"info": true,
"autoWidth": false
});
$('#dataTable_filter input').css('font-size', '12px').attr('placeholder', 'Type to search..?');
});
</script>
</body>
<script language="javascript">
document.addEventListener('DOMContentLoaded', () =>
{
const updateBtn = document.querySelector('button[name="Update"]');
const deleteBtn = document.querySelector('button[name="Delete"]');
const addBtn = document.getElementById('Add');
const cancelBtn = document.getElementById('Cancel');
updateBtn.style.display = 'none';
deleteBtn.style.display = 'none';
addBtn.style.visibility = 'visible';
addBtn.disabled = false;
document.querySelectorAll('.edit-delete-btn').forEach(editBtn =>
{
editBtn.addEventListener('click', () =>
{
updateBtn.style.display = 'inline-block';
deleteBtn.style.display = 'inline-block';
addBtn.style.display = 'none';
addBtn.style.visibility = 'visible';
addBtn.disabled = true;
});
});
updateBtn.addEventListener('click', (e) =>
{
updateBtn.style.display = 'none';
deleteBtn.style.display = 'none';
addBtn.style.display = 'inline-block';
addBtn.style.visibility = 'visible';
addBtn.disabled = false;
});
deleteBtn.addEventListener('click', (e) =>
{
updateBtn.style.display = 'none';
deleteBtn.style.display = 'none';
addBtn.style.display = 'inline-block';
addBtn.style.visibility = 'visible';
addBtn.disabled = false;
});
cancelBtn.addEventListener('click', (e) =>
{
e.preventDefault();
document.getElementById('recordForm').reset();
updateBtn.style.display = 'none';
deleteBtn.style.display = 'none';
addBtn.style.display = 'inline-block';
addBtn.style.visibility = 'visible';
addBtn.disabled = false;
});
});
</script>
<footer class="page-footer">
<a href="https://sanjibpandey.wixsite.com/pandey/" target="_blank" rel="noopener noreferrer" style="color: #6c757d; text-decoration: none;"> https://sanjibpandey.wixsite.com/pandey/</a>
</footer>
</html>
/// Essa classe serve para inserir, atualizar e deletar registros (chave & valor)
/// em Lookup Tables desde uma aplicação web
/// Posteriormente, pode ser usada em regras ou transformações de dados usando a função de Lookup.
/// Autor : Sanjib Pandey
/// Data : 16/10/2025
Class SANJIB.DataLookup.Methods Extends %Persistent
{
/// Esse método insere um valor na Lookup Table. Os parâmetros requeridos são
/// dtTableName : O nome da sua lookup table
/// keyData : A chave
/// keyValue : O valor (par chave-valor)
ClassMethod InsertLookUpValues(dtTable As %String = "", keyData As %String = "", keyValue As %String = "") As %Status
{
S tSC = $$$OK
Try
{
I (dtTable '="") && (keyData '="") && (keyValue '="")
{
S mySQLStatement = "INSERT into Ens_Util.LookupTable (KeyName,DataValue,TableName) values ('"_keyData_"','"_keyValue_"','"_dtTable_"')"
S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
S tSC={"InserRecorded":(myRecordSet)}
}
}
Catch (Exception)
{
Throw Exception
}
Q tSC
}
/// Esse método checa se o valor já existe na lookup table
ClassMethod ChkLookupKeyValue(dtTable As %String, keyData As %String) As %Status
{
S tSC = $$$OK
Try
{
I (dtTable '="") && (keyData '="")
{
S mySQLStatement="SELECT KeyName FROM Ens_Util.LookupTable WHERE TableName='"_dtTable_"' and KeyName='"_keyData_"'"
S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
D myRecordSet.%Next()
I (myRecordSet.%SQLCODE=0)
{
S tSC= "T"
}
else
{
S tSC="F"
}
}
else
{
S tSC= "Invalid Parameters - missing table name or key !"
}
}
Catch (Exception)
{
Throw Exception
}
Q tSC
}
/// Esse métood atualiza somente o valor chave na lookup table.
ClassMethod UpdateLookUpValues(dtTable As %String = "", keyData As %String = "", keyValue As %String = "") As %Status
{
S tSC = $$$OK
Try
{
I (dtTable '="") && (keyData '="") && (keyValue '="")
{
S mySQLStatement = "UPDATE Ens_Util.LookupTable SET DataValue='"_keyValue_"' WHERE TableName='"_dtTable_"' AND KeyName='"_keyData_"'"
S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
S tSC={"Updated Record":(myRecordSet)}
}
}
Catch (Exception)
{
Throw Exception
}
Q tSC
}
/// Esse método é usado para deletar um registro da lookup table.
ClassMethod DeleteLookUpValues(dtTable As %String, keyData As %String) As %Status
{
S tSC = $$$OK
Try
{
I (dtTable '="") && (keyData '="")
{
S mySQLStatement = "DELETE FROM Ens_Util.LookupTable WHERE TableName='"_dtTable_"' And KeyName='"_keyData_"'"
S myRecordSet = ##class(%SQL.Statement).%ExecDirect(,mySQLStatement)
S tSC={"Deleted Record":(myRecordSet)}
}
}
Catch (Exception)
{
Throw Exception
}
Q tSC
}
Storage Default
{
<Data name="MethodsDefaultData">
<Value name="1">
<Value>%%CLASSNAME</Value>
</Value>
</Data>
<DataLocation>^SANJIB.DataLookup.MethodsD</DataLocation>
<DefaultData>MethodsDefaultData</DefaultData>
<IdLocation>^SANJIB.DataLookup.MethodsD</IdLocation>
<IndexLocation>^SANJIB.DataLookup.MethodsI</IndexLocation>
<StreamLocation>^SANJIB.DataLookup.MethodsS</StreamLocation>
<Type>%Storage.Persistent</Type>
}
}
Conclusão
Esta interface web e classe reutilizáveis fornecem uma maneira simples, porém eficaz, de gerenciar Tabelas de Pesquisa de Dados no HealthConnect, aumentando a eficiência e a flexibilidade. Ao capacitar os usuários finais com acesso controlado, ela reduz a sobrecarga administrativa tradicionalmente associada à manutenção da tabela de pesquisa.