Add cached consult autotype suggestions and doctor/master keyword save
This commit is contained in:
parent
b1d329e462
commit
418fb3e5e7
|
|
@ -534,6 +534,7 @@ $routes->get('Opd_prescription/finding_exam_search', 'Opd_prescription::finding_
|
|||
$routes->get('Opd_prescription/get_complaints', 'Opd_prescription::get_complaints');
|
||||
$routes->get('Opd_prescription/get_disease', 'Opd_prescription::get_disease');
|
||||
$routes->get('Opd_prescription/get_finding_exam', 'Opd_prescription::get_finding_exam');
|
||||
$routes->post('Opd_prescription/autotype_keyword_save', 'Opd_prescription::autotype_keyword_save');
|
||||
$routes->post('Opd_prescription/complaints_parse', 'Opd_prescription::complaints_parse');
|
||||
$routes->post('Opd_prescription/complaints_ai_draft', 'Opd_prescription::complaints_ai_draft');
|
||||
$routes->post('Opd_prescription/clinical_autotype', 'Opd_prescription::clinical_autotype');
|
||||
|
|
|
|||
|
|
@ -3862,25 +3862,65 @@ class Opd_prescription extends BaseController
|
|||
public function complaints_search()
|
||||
{
|
||||
$q = trim((string) $this->request->getGet('q'));
|
||||
if ($q === '' || ! $this->db->tableExists('complaints_master')) {
|
||||
if ($q === '') {
|
||||
return $this->response->setJSON(['rows' => []]);
|
||||
}
|
||||
|
||||
$rows = $this->db->table('complaints_master')
|
||||
->select('Code as code, Name as name, name_hinglish, show_in_short, ai_hint')
|
||||
->where('is_active', 1)
|
||||
->groupStart()
|
||||
->like('Name', $q)
|
||||
->orLike('name_hinglish', $q)
|
||||
->orLike('keywords', $q)
|
||||
->groupEnd()
|
||||
->orderBy('show_in_short', 'DESC')
|
||||
->orderBy('Name', 'ASC')
|
||||
->limit(20)
|
||||
->get()
|
||||
->getResultArray();
|
||||
$rows = [];
|
||||
if ($this->db->tableExists('complaints_master')) {
|
||||
$rows = $this->db->table('complaints_master')
|
||||
->select('Code as code, Name as name, name_hinglish, show_in_short, ai_hint')
|
||||
->where('is_active', 1)
|
||||
->groupStart()
|
||||
->like('Name', $q)
|
||||
->orLike('name_hinglish', $q)
|
||||
->orLike('keywords', $q)
|
||||
->groupEnd()
|
||||
->orderBy('show_in_short', 'DESC')
|
||||
->orderBy('Name', 'ASC')
|
||||
->limit(20)
|
||||
->get()
|
||||
->getResultArray();
|
||||
}
|
||||
|
||||
return $this->response->setJSON(['rows' => $rows]);
|
||||
$keywordRows = $this->fetchAutotypeKeywords(
|
||||
'complaints',
|
||||
$q,
|
||||
max(0, (int) ($this->getCurrentUserId() ?? 0)),
|
||||
20
|
||||
);
|
||||
|
||||
$out = [];
|
||||
$seen = [];
|
||||
foreach ($rows as $row) {
|
||||
$name = trim((string) ($row['name'] ?? ''));
|
||||
if ($name === '') {
|
||||
continue;
|
||||
}
|
||||
$k = strtoupper($name);
|
||||
if (isset($seen[$k])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$k] = true;
|
||||
$out[] = $row;
|
||||
}
|
||||
|
||||
foreach ($keywordRows as $keyword) {
|
||||
$k = strtoupper($keyword);
|
||||
if ($keyword === '' || isset($seen[$k])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$k] = true;
|
||||
$out[] = [
|
||||
'code' => '',
|
||||
'name' => $keyword,
|
||||
'name_hinglish' => '',
|
||||
'show_in_short' => 0,
|
||||
'ai_hint' => '',
|
||||
];
|
||||
}
|
||||
|
||||
return $this->response->setJSON(['rows' => array_slice($out, 0, 20)]);
|
||||
}
|
||||
|
||||
public function provisional_diagnosis_search()
|
||||
|
|
@ -3908,7 +3948,37 @@ class Opd_prescription extends BaseController
|
|||
->get()
|
||||
->getResultArray();
|
||||
|
||||
return $this->response->setJSON(['rows' => $rows]);
|
||||
$keywordRows = $this->fetchAutotypeKeywords(
|
||||
'provisional_diagnosis',
|
||||
$q,
|
||||
max(0, (int) ($this->getCurrentUserId() ?? 0)),
|
||||
20
|
||||
);
|
||||
|
||||
$out = [];
|
||||
$seen = [];
|
||||
foreach ($rows as $row) {
|
||||
$name = trim((string) ($row['name'] ?? ''));
|
||||
if ($name === '') {
|
||||
continue;
|
||||
}
|
||||
$k = strtoupper($name);
|
||||
if (isset($seen[$k])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$k] = true;
|
||||
$out[] = ['name' => $name];
|
||||
}
|
||||
foreach ($keywordRows as $keyword) {
|
||||
$k = strtoupper($keyword);
|
||||
if ($keyword === '' || isset($seen[$k])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$k] = true;
|
||||
$out[] = ['name' => $keyword];
|
||||
}
|
||||
|
||||
return $this->response->setJSON(['rows' => array_slice($out, 0, 20)]);
|
||||
}
|
||||
|
||||
public function finding_exam_search()
|
||||
|
|
@ -3933,7 +4003,112 @@ class Opd_prescription extends BaseController
|
|||
->get()
|
||||
->getResultArray();
|
||||
|
||||
return $this->response->setJSON(['rows' => $rows]);
|
||||
$keywordRows = $this->fetchAutotypeKeywords(
|
||||
'finding_examinations',
|
||||
$q,
|
||||
max(0, (int) ($this->getCurrentUserId() ?? 0)),
|
||||
20
|
||||
);
|
||||
|
||||
$out = [];
|
||||
$seen = [];
|
||||
foreach ($rows as $row) {
|
||||
$text = trim((string) ($row['finding_examinations'] ?? ''));
|
||||
if ($text === '') {
|
||||
continue;
|
||||
}
|
||||
$k = strtoupper($text);
|
||||
if (isset($seen[$k])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$k] = true;
|
||||
$out[] = ['finding_examinations' => $text];
|
||||
}
|
||||
foreach ($keywordRows as $keyword) {
|
||||
$k = strtoupper($keyword);
|
||||
if ($keyword === '' || isset($seen[$k])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$k] = true;
|
||||
$out[] = ['finding_examinations' => $keyword];
|
||||
}
|
||||
|
||||
return $this->response->setJSON(['rows' => array_slice($out, 0, 20)]);
|
||||
}
|
||||
|
||||
public function autotype_keyword_save()
|
||||
{
|
||||
if (! $this->request->isAJAX()) {
|
||||
return $this->response->setStatusCode(400)->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
if (! $this->canAccessPrescription()) {
|
||||
return $this->response->setStatusCode(403)->setJSON(['update' => 0, 'error_text' => 'Access denied']);
|
||||
}
|
||||
|
||||
$section = trim((string) $this->request->getPost('section'));
|
||||
$keyword = trim((string) $this->request->getPost('keyword'));
|
||||
$scope = strtolower(trim((string) $this->request->getPost('scope')));
|
||||
if ($scope === '') {
|
||||
$scope = 'doctor';
|
||||
}
|
||||
|
||||
if (! $this->isAutotypeKeywordSectionAllowed($section)) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Unsupported section']);
|
||||
}
|
||||
|
||||
$keyword = preg_replace('/\s+/', ' ', $keyword) ?? $keyword;
|
||||
if (mb_strlen($keyword) < 2) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Keyword must be at least 2 characters']);
|
||||
}
|
||||
|
||||
if (! $this->ensureAutotypeKeywordTable()) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Keyword storage unavailable']);
|
||||
}
|
||||
|
||||
$docId = max(0, (int) ($this->getCurrentUserId() ?? 0));
|
||||
if ($scope === 'master') {
|
||||
$user = auth()->user();
|
||||
$canMaster = $user && method_exists($user, 'can') && ($user->can('doctor_work.template_workspace.access') || $user->can('doctor_work.access'));
|
||||
if (! $canMaster) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'No permission to save master keyword']);
|
||||
}
|
||||
$docId = 0;
|
||||
}
|
||||
|
||||
$table = $this->db->table('opd_autotype_keyword_master');
|
||||
$existing = $table
|
||||
->where('doc_id', $docId)
|
||||
->where('section_key', $section)
|
||||
->where('keyword', $keyword)
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
|
||||
if (! empty($existing)) {
|
||||
$table->where('id', (int) ($existing['id'] ?? 0))->update([
|
||||
'is_active' => 1,
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
} else {
|
||||
$table->insert([
|
||||
'doc_id' => $docId,
|
||||
'section_key' => $section,
|
||||
'keyword' => $keyword,
|
||||
'is_active' => 1,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => 1,
|
||||
'error_text' => $docId === 0 ? 'Keyword saved in master list' : 'Keyword saved for current doctor',
|
||||
'keyword' => $keyword,
|
||||
'section' => $section,
|
||||
'scope' => $docId === 0 ? 'master' : 'doctor',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
// Legacy-compatible wrappers used by older autocomplete clients.
|
||||
|
|
@ -6132,6 +6307,88 @@ class Opd_prescription extends BaseController
|
|||
return $this->db->tableExists('opd_clinical_template_usage');
|
||||
}
|
||||
|
||||
private function ensureAutotypeKeywordTable(): bool
|
||||
{
|
||||
if ($this->db->tableExists('opd_autotype_keyword_master')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
$sql = "CREATE TABLE IF NOT EXISTS opd_autotype_keyword_master (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
doc_id INT NOT NULL DEFAULT 0,
|
||||
section_key VARCHAR(80) NOT NULL,
|
||||
keyword VARCHAR(255) NOT NULL,
|
||||
is_active TINYINT NOT NULL DEFAULT 1,
|
||||
created_at DATETIME NULL,
|
||||
updated_at DATETIME NULL,
|
||||
UNIQUE KEY uniq_doc_section_keyword (doc_id, section_key, keyword),
|
||||
INDEX idx_section_keyword (section_key, keyword),
|
||||
INDEX idx_doc_active (doc_id, is_active)
|
||||
)";
|
||||
$this->db->query($sql);
|
||||
} catch (\Throwable $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->db->tableExists('opd_autotype_keyword_master');
|
||||
}
|
||||
|
||||
private function isAutotypeKeywordSectionAllowed(string $section): bool
|
||||
{
|
||||
return in_array($section, ['complaints', 'provisional_diagnosis', 'finding_examinations'], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, string>
|
||||
*/
|
||||
private function fetchAutotypeKeywords(string $section, string $q, int $docId, int $limit = 20): array
|
||||
{
|
||||
if ($q === '' || ! $this->isAutotypeKeywordSectionAllowed($section) || ! $this->ensureAutotypeKeywordTable()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$builder = $this->db->table('opd_autotype_keyword_master')
|
||||
->select('keyword,doc_id')
|
||||
->where('is_active', 1)
|
||||
->where('section_key', $section)
|
||||
->like('keyword', $q)
|
||||
->orderBy('doc_id', 'DESC')
|
||||
->orderBy('updated_at', 'DESC')
|
||||
->limit(max(1, $limit));
|
||||
|
||||
if ($docId > 0) {
|
||||
$builder->groupStart()
|
||||
->where('doc_id', 0)
|
||||
->orWhere('doc_id', $docId)
|
||||
->groupEnd();
|
||||
} else {
|
||||
$builder->where('doc_id', 0);
|
||||
}
|
||||
|
||||
$rows = $builder->get()->getResultArray();
|
||||
if (empty($rows)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$out = [];
|
||||
$seen = [];
|
||||
foreach ($rows as $row) {
|
||||
$keyword = trim((string) ($row['keyword'] ?? ''));
|
||||
if ($keyword === '') {
|
||||
continue;
|
||||
}
|
||||
$k = strtoupper($keyword);
|
||||
if (isset($seen[$k])) {
|
||||
continue;
|
||||
}
|
||||
$seen[$k] = true;
|
||||
$out[] = $keyword;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
private function isTemplateSectionAllowed(string $section): bool
|
||||
{
|
||||
return in_array($section, ['finding_examinations', 'diagnosis', 'provisional_diagnosis', 'prescriber_remarks', 'advice'], true);
|
||||
|
|
|
|||
|
|
@ -656,6 +656,7 @@
|
|||
<label class="form-label">Complaints
|
||||
<button type="button" class="btn btn-outline-primary btn-sm rx-ai-btn btn-ai-rewrite btn-complaints-rewrite" data-target="complaints" data-mode="hinglish_to_english" title="Convert Hinglish text to English">↔ Hinglish → English</button>
|
||||
<button type="button" class="btn btn-outline-success btn-sm rx-ai-btn" id="btn_complaints_mic" title="Speech to text for complaints">Mic</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm rx-ai-btn btn-save-autotype-keyword" data-section="complaints" data-target="complaints" title="Save keyword for autocomplete">Save keyword</button>
|
||||
</label>
|
||||
<textarea class="form-control rx-field" id="complaints" rows="4" maxlength="4000"><?= esc($opd_prescription[0]->complaints ?? '') ?></textarea>
|
||||
<div id="complaints_interim_preview" style="display:none;font-size:.8rem;color:#6c757d;padding:2px 4px;font-style:italic;"></div>
|
||||
|
|
@ -670,6 +671,7 @@
|
|||
<button type="button" class="btn btn-outline-secondary btn-sm btn-field-past" data-section="finding_examinations" data-target="finding_examinations">Past Data</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-template-load" data-section="finding_examinations" data-target="finding_examinations">Load Template</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-template-save" data-section="finding_examinations" data-target="finding_examinations">Save as Template</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-save-autotype-keyword" data-section="finding_examinations" data-target="finding_examinations">Save keyword</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-field-clear" data-target="finding_examinations">Clear</button>
|
||||
</div>
|
||||
<textarea class="form-control rx-field" id="finding_examinations" rows="4" maxlength="4000"><?= esc($opd_prescription[0]->Finding_Examinations ?? '') ?></textarea>
|
||||
|
|
@ -698,6 +700,7 @@
|
|||
<button type="button" class="btn btn-outline-secondary btn-sm btn-field-past" data-section="provisional_diagnosis" data-target="provisional_diagnosis">Past Data</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-template-load" data-section="provisional_diagnosis" data-target="provisional_diagnosis">Load Template</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-template-save" data-section="provisional_diagnosis" data-target="provisional_diagnosis">Save as Template</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-save-autotype-keyword" data-section="provisional_diagnosis" data-target="provisional_diagnosis">Save keyword</button>
|
||||
<button type="button" class="btn btn-outline-secondary btn-sm btn-field-clear" data-target="provisional_diagnosis">Clear</button>
|
||||
</div>
|
||||
<textarea class="form-control rx-field" id="provisional_diagnosis" rows="4" maxlength="4000"><?= esc($opd_prescription[0]->Provisional_diagnosis ?? '') ?></textarea>
|
||||
|
|
@ -1192,6 +1195,11 @@
|
|||
var medicineSearchLocalDbKey = 'opd_medicine_search_cache_v1';
|
||||
var medicineSearchCacheMaxEntries = 250;
|
||||
var medicineSearchLocalDbReady = false;
|
||||
var autotypeSuggestCache = {};
|
||||
var autotypeSuggestCacheTtlMs = 300000;
|
||||
var autotypeSuggestCacheMaxEntries = 240;
|
||||
var autotypeSuggestCacheLocalKey = 'opd_autotype_suggest_cache_v1';
|
||||
var autotypeSuggestCacheLocalReady = false;
|
||||
var medInputTimer = null;
|
||||
var crgcMedInputTimer = null;
|
||||
var medicineDoseMasterCache = { dose: [], when: [], freq: [], where: [] };
|
||||
|
|
@ -1201,6 +1209,7 @@
|
|||
};
|
||||
var patientId = <?= (int) ($patient_master[0]->id ?? 0) ?>;
|
||||
var doctorViewId = <?= (int) ($doctorId ?? 0) ?>;
|
||||
autotypeSuggestCacheLocalKey = autotypeSuggestCacheLocalKey + '_' + doctorViewId;
|
||||
var consultSectionPreferenceKey = 'opd_consult_section_pref_' + doctorViewId;
|
||||
var consultSectionMeta = [
|
||||
{ key: 'pain_scale', selector: '#rx_sec_pain_scale', title: 'Pain Measurement Scale' },
|
||||
|
|
@ -1581,6 +1590,106 @@
|
|||
return splitCommaTerms(term).pop() || '';
|
||||
}
|
||||
|
||||
function getAutotypeSuggestCacheKey(endpointUrl, term) {
|
||||
return (endpointUrl || '') + '|' + (term || '').toString().trim().toLowerCase();
|
||||
}
|
||||
|
||||
function pruneAutotypeSuggestCache(nowMs) {
|
||||
var now = nowMs || Date.now();
|
||||
var keys = Object.keys(autotypeSuggestCache || {});
|
||||
if (!keys.length) {
|
||||
autotypeSuggestCache = {};
|
||||
return;
|
||||
}
|
||||
|
||||
var rows = [];
|
||||
keys.forEach(function(k) {
|
||||
var item = autotypeSuggestCache[k] || {};
|
||||
var ts = Number(item.ts || 0);
|
||||
if (!ts || (now - ts) > autotypeSuggestCacheTtlMs) {
|
||||
return;
|
||||
}
|
||||
rows.push({ key: k, ts: ts, rows: Array.isArray(item.rows) ? item.rows : [] });
|
||||
});
|
||||
|
||||
rows.sort(function(a, b) { return b.ts - a.ts; });
|
||||
if (rows.length > autotypeSuggestCacheMaxEntries) {
|
||||
rows = rows.slice(0, autotypeSuggestCacheMaxEntries);
|
||||
}
|
||||
|
||||
var next = {};
|
||||
rows.forEach(function(item) {
|
||||
next[item.key] = { ts: item.ts, rows: item.rows };
|
||||
});
|
||||
autotypeSuggestCache = next;
|
||||
}
|
||||
|
||||
function ensureAutotypeSuggestCacheLoaded() {
|
||||
if (autotypeSuggestCacheLocalReady) {
|
||||
return;
|
||||
}
|
||||
autotypeSuggestCacheLocalReady = true;
|
||||
try {
|
||||
var raw = localStorage.getItem(autotypeSuggestCacheLocalKey);
|
||||
if (!raw) {
|
||||
return;
|
||||
}
|
||||
var parsed = JSON.parse(raw);
|
||||
var entries = parsed && parsed.entries ? parsed.entries : {};
|
||||
if (entries && typeof entries === 'object') {
|
||||
autotypeSuggestCache = entries;
|
||||
pruneAutotypeSuggestCache(Date.now());
|
||||
}
|
||||
} catch (e) {
|
||||
autotypeSuggestCache = {};
|
||||
}
|
||||
}
|
||||
|
||||
function persistAutotypeSuggestCache() {
|
||||
try {
|
||||
pruneAutotypeSuggestCache(Date.now());
|
||||
localStorage.setItem(autotypeSuggestCacheLocalKey, JSON.stringify({
|
||||
saved_at: Date.now(),
|
||||
entries: autotypeSuggestCache
|
||||
}));
|
||||
} catch (e) {
|
||||
// Ignore localStorage write failures.
|
||||
}
|
||||
}
|
||||
|
||||
function getLastKeywordFromField(targetId) {
|
||||
var text = ($('#' + targetId).val() || '').toString();
|
||||
var token = extractLastCommaTerm(text).toString().trim();
|
||||
if (!token) {
|
||||
var parts = text.split(/[;,\n\r]+/);
|
||||
token = (parts.pop() || '').toString().trim();
|
||||
}
|
||||
token = token.replace(/^[-*\s]+/, '').trim();
|
||||
return token;
|
||||
}
|
||||
|
||||
function saveAutotypeKeyword(section, keyword, done) {
|
||||
var scope = 'doctor';
|
||||
var useMaster = window.confirm('Save keyword to Master list for all doctors?\nChoose Cancel to save only for current doctor.');
|
||||
if (useMaster) {
|
||||
scope = 'master';
|
||||
}
|
||||
|
||||
apiPost('<?= base_url('Opd_prescription/autotype_keyword_save') ?>', {
|
||||
section: section,
|
||||
keyword: keyword,
|
||||
scope: scope
|
||||
}, function(data) {
|
||||
if (data && Number(data.update || 0) === 1) {
|
||||
autotypeSuggestCache = {};
|
||||
persistAutotypeSuggestCache();
|
||||
}
|
||||
if (typeof done === 'function') {
|
||||
done(data || {});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function bindLegacyCommaAutocomplete(selector, endpointUrl, extractValue) {
|
||||
var $field = $(selector);
|
||||
if (!$field.length || !($.ui && $.ui.autocomplete)) {
|
||||
|
|
@ -1602,6 +1711,15 @@
|
|||
return;
|
||||
}
|
||||
|
||||
ensureAutotypeSuggestCacheLoaded();
|
||||
var cacheKey = getAutotypeSuggestCacheKey(endpointUrl, term);
|
||||
var hit = autotypeSuggestCache[cacheKey];
|
||||
var now = Date.now();
|
||||
if (hit && (now - Number(hit.ts || 0) < autotypeSuggestCacheTtlMs)) {
|
||||
response(hit.rows || []);
|
||||
return;
|
||||
}
|
||||
|
||||
$.getJSON(endpointUrl, { q: term }, function(data) {
|
||||
var rows = (data && data.rows) ? data.rows : [];
|
||||
var out = [];
|
||||
|
|
@ -1616,6 +1734,8 @@
|
|||
out.push({ label: value, value: value });
|
||||
}
|
||||
});
|
||||
autotypeSuggestCache[cacheKey] = { ts: Date.now(), rows: out };
|
||||
persistAutotypeSuggestCache();
|
||||
response(out);
|
||||
}).fail(function() {
|
||||
response([]);
|
||||
|
|
@ -5827,6 +5947,28 @@
|
|||
loadOldPrescribedPanel();
|
||||
});
|
||||
|
||||
$(document).on('click', '.btn-save-autotype-keyword', function() {
|
||||
var section = ($(this).data('section') || '').toString();
|
||||
var targetId = ($(this).data('target') || '').toString();
|
||||
if (!section || !targetId) {
|
||||
return;
|
||||
}
|
||||
|
||||
var keyword = getLastKeywordFromField(targetId);
|
||||
if (!keyword || keyword.length < 2) {
|
||||
$('.jsError').removeClass('text-success text-muted').addClass('text-danger').text('Type at least 2 characters in this field, then click Save keyword.');
|
||||
return;
|
||||
}
|
||||
|
||||
saveAutotypeKeyword(section, keyword, function(data) {
|
||||
if (Number(data.update || 0) === 1) {
|
||||
$('.jsError').removeClass('text-danger text-muted').addClass('text-success').text((data.error_text || 'Keyword saved') + ': ' + keyword);
|
||||
} else {
|
||||
$('.jsError').removeClass('text-success text-muted').addClass('text-danger').text(data.error_text || 'Unable to save keyword.');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
initConsultSectionDesigner();
|
||||
|
||||
bindLegacyCommaAutocomplete('#complaints', '<?= base_url('Opd_prescription/complaints_search') ?>', function(row) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user