/* Solaron Omnichannel — O2 Inbox (native grid) & Conversation JS.
* The inbox is a native list_fields grid; reload re-posts the paging/sort/search
* form to omnichannel_getInbox. Conversation detail opens in a dynamic window
* (the sdesk/ccenter pattern). Posts go to the relative 'action.php' (a module
* .js.php is served without a session — never reference $_SESSION here unguarded). */
var omni_csrf = (typeof omni_csrf !== 'undefined') ? omni_csrf : '';
var omni_form_name = (typeof omni_form_name !== 'undefined') ? omni_form_name : 'form_omni_inbox';
var omni_current_cid = 0;
function omnichannel_region() {
return 'ui-layout-center';
}
/* ---- native grid reload ---- */
function omnichannel_inboxParams(action) {
var par = 'action=' + action;
var fields = ['page_selected', 'page_limit', 'page_sort', 'page_sort_desc', 'page_search_string', 'page_filter_id', 'page_filter_field', 'omni_view',
'f_channel', 'f_department', 'f_employee', 'f_customer', 'f_sale', 'f_status', 'f_participant'];
for (var i = 0; i < fields.length; i++) {
var sel = 'form[name=' + omni_form_name + '] input#' + fields[i];
if ($(sel).length) { par += '&' + fields[i] + '=' + encodeURIComponent($(sel).val()); }
}
return par;
}
/* Landing = the Dashboard (primary start page). Called by the module menu + reused as the Dashboard nav button. */
function omnichannel_getList() {
actionController('action=omnichannel_getDashboard', omnichannel_region());
}
/* Open the Inbox fresh (from the Dashboard / nav) — resets view, filter, search, page, and advanced filters. */
function omnichannel_openInbox() {
actionController('action=omnichannel_getInbox&omni_view=all&page_filter_field=&page_filter_id=0&page_search_string=&page_selected=1&omni_reset=1', omnichannel_region());
}
/* Open the Inbox on a specific quick-view (all/mine/unassigned/unread). */
function omnichannel_openInboxView(v) {
actionController('action=omnichannel_getInbox&omni_view=' + encodeURIComponent(v) + '&page_filter_field=&page_filter_id=0&page_search_string=&page_selected=1', omnichannel_region());
}
/* Open the Inbox filtered by a conversation status code (native column filter). */
function omnichannel_openInboxStatus(code) {
actionController('action=omnichannel_getInbox&omni_view=all&page_filter_field=omnichannel_status&page_filter_id=' + encodeURIComponent(code) + '&page_search_string=&page_selected=1', omnichannel_region());
}
/* Inbox grid reload (sort/filter/search/paging round-trip). */
function omnichannel_reloadInbox() {
actionController(omnichannel_inboxParams('omnichannel_getInbox'), omnichannel_region());
}
/* O1 foundation status page (still available, technical). */
function omnichannel_getFoundation() {
actionController('action=omnichannel_getList', omnichannel_region());
}
/* Inbox quick-view filters (All/Mine/Unassigned/Unread) — stay in the Inbox. */
function omnichannel_setView(v) {
var f = 'form[name=' + omni_form_name + '] input#';
$(f + 'omni_view').val(v);
$(f + 'page_selected').val('1');
omnichannel_reloadInbox();
}
function omnichannel_resetInbox() {
var f = 'form[name=' + omni_form_name + '] input#';
$(f + 'omni_view').val('all');
$(f + 'page_search_string').val('');
$(f + 'page_filter_id').val('0');
$(f + 'page_filter_field').val('');
$(f + 'page_selected').val('1');
['f_channel', 'f_department', 'f_employee', 'f_customer', 'f_sale', 'f_status', 'f_participant'].forEach(function (n) { $(f + n).val(''); });
omnichannel_reloadInbox();
}
/* Reload whichever primary screen is currently shown (Inbox grid vs Dashboard). */
function omnichannel_refreshCurrent() {
if ($('form[name=form_omni_inbox]').length) { omnichannel_reloadInbox(); }
else { omnichannel_getList(); }
}
/* ---- O7.1.5 Inbox advanced filters (native, server-side, combinable) ----
All six controls are native ChosenSelects (Channel/Status/Department/Employee = local option sets;
Customer/Sale = REMOTE searchable selects, options fetched on typing and scoped to the user's CRM
visibility + the dependency chain). On change each control's value is mirrored into the hidden f_*
field and the grid reloads (omnichannel_inboxParams serialises them → one server query; paging/sort/
open-close preserve them). The value is always a real id (or 'unassigned'), never free text. */
function omnichannel_setHidden(name, val) { $('form[name=' + omni_form_name + '] input#' + name).val(val == null ? '' : val); }
function omnichannel_selVal(id) { var v = $('#' + id).val(); return (v == null) ? '' : ('' + v); }
function omnichannel_applyInboxFilters() {
omnichannel_setHidden('f_channel', omnichannel_selVal('omni-f-channel'));
omnichannel_setHidden('f_status', omnichannel_selVal('omni-f-status'));
omnichannel_setHidden('f_department', omnichannel_selVal('omni-f-department'));
omnichannel_setHidden('f_employee', omnichannel_selVal('omni-f-employee'));
omnichannel_setHidden('f_customer', omnichannel_selVal('omni-f-customer'));
omnichannel_setHidden('f_sale', omnichannel_selVal('omni-f-sale'));
omnichannel_setHidden('f_participant', $('#omni-f-participant').val() || '');
omnichannel_setHidden('page_selected', '1'); // filters changed materially → back to page 1 (§12)
omnichannel_reloadInbox();
}
function omnichannel_clearInboxFilters() {
// clear the visible Chosen selects + the participant text + the hidden ids; keep grid prefs + view (§8)
$('#omni-f-channel,#omni-f-status,#omni-f-department,#omni-f-employee,#omni-f-customer,#omni-f-sale').val('').trigger('chosen:updated');
$('#omni-f-participant').val('');
['f_channel', 'f_status', 'f_department', 'f_employee', 'f_customer', 'f_sale', 'f_participant'].forEach(function (n) { omnichannel_setHidden(n, ''); });
omnichannel_setHidden('page_selected', '1');
omnichannel_reloadInbox();
}
// current numeric value of a visible filter select ('unassigned'/'' → 0)
function omnichannel_selInt(id) { return parseInt($('#' + id).val() || '0', 10) || 0; }
/* Wire a native Chosen single-select to a REMOTE, CRM-scoped, dependency-scoped source (searchLinkTarget).
Typing in the Chosen search box fetches a bounded result set (never the whole table) and rebuilds the
options, preserving the current selection. scopeFn() adds the dependency params (employee→customer,
customer→sale); scope:'crm' makes the server restrict to the user's CRM visibility. */
function omnichannel_initFilterRemoteChosen(selectId, type, scopeFn) {
var $sel = $('#' + selectId);
if (!$sel.length || $sel.data('omni-remote')) { return; }
$sel.data('omni-remote', 1);
var $container = $sel.next('.chosen-container');
if (!$container.length) { return; }
var $search = $container.find('.chosen-search input, .chosen-search-input').first();
if (!$search.length) { $search = $container.find('input[type=text]').first(); }
var timer = null;
$search.on('keyup.omnifilter', function () {
var term = $.trim($(this).val());
clearTimeout(timer);
if (term.length < 2) { return; }
timer = setTimeout(function () {
var data = { action: 'omnichannel_searchLinkTarget', target: type, q: term, scope: 'crm' };
var scope = scopeFn() || {};
for (var k in scope) { if (scope.hasOwnProperty(k)) { data[k] = scope[k]; } }
$.post('action.php', data, function (r) {
var j; try { j = (typeof r === 'string') ? JSON.parse(r) : r; } catch (e) { return; }
var curVal = String($sel.val() || '');
var curText = curVal ? $sel.find('option[value="' + curVal + '"]').text() : '';
var opts = '';
if (curVal) { opts += '