feat: search KB before submitting ticket (frontend + backend)

Both frontend and admin ticket creation now show a KB search step
first. User types their issue, Smart Search (com_finder) returns
matching articles. If nothing helps, they click through to the
ticket form with the search query pre-filled as the subject.

Frontend (/support/submit-ticket):
- Search input with live results from #__finder_links
- Article links open in new tab
- "Submit Anyway" shows the ticket form
- Falls back to direct form if Smart Search has no indexed content

Admin (New Ticket modal):
- Same KB search step before the form
- Results as clickable list-group items
- Modal resets on close

Also:
- Added searchKb controller task (both frontend + admin)
- Added "Submit a Ticket" child menu item under Support on install
- Fixed innerHTML → safe DOM methods for search results

Authored-by: Moko Consulting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Miller
2026-06-02 18:46:12 -05:00
parent b37120341f
commit 4a18318cb9
5 changed files with 528 additions and 38 deletions
+36
View File
@@ -771,6 +771,42 @@ class Pkg_MokowaasInstallerScript
];
$db->insertObject('#__menu', $item, 'id');
$supportId = (int) $item->id;
// Create "Submit a Ticket" child menu item
if ($supportId)
{
$db->setQuery('SELECT MAX(rgt) FROM #__menu WHERE client_id = 0');
$maxRgt2 = (int) $db->loadResult();
$child = (object) [
'menutype' => 'mainmenu',
'title' => 'Submit a Ticket',
'alias' => 'submit-ticket',
'note' => '',
'path' => 'support/submit-ticket',
'link' => 'index.php?option=com_mokowaas&view=tickets&layout=submit',
'type' => 'component',
'published' => 1,
'parent_id' => $supportId,
'level' => 2,
'component_id' => $componentId,
'checked_out' => null,
'checked_out_time' => null,
'browserNav' => 0,
'access' => 2,
'img' => '',
'template_style_id' => 0,
'params' => '{}',
'lft' => $maxRgt2 + 1,
'rgt' => $maxRgt2 + 2,
'home' => 0,
'language' => '*',
'client_id' => 0,
];
$db->insertObject('#__menu', $child, 'id');
}
}
catch (\Throwable $e)
{