Working on speech rec

This commit is contained in:
Hillel Coren 2017-04-04 16:57:33 +03:00
parent dcee9285d9
commit fcbc9bd885
9 changed files with 66 additions and 32 deletions

View File

@ -100,6 +100,7 @@ class BotController extends Controller
public function handleCommand() public function handleCommand()
{ {
$data = $this->parseMessage(request()->command); $data = $this->parseMessage(request()->command);
//dd($data);
$intent = BaseIntent::createIntent(BOT_PLATFORM_WEB_APP, false, $data); $intent = BaseIntent::createIntent(BOT_PLATFORM_WEB_APP, false, $data);
return $intent->process(); return $intent->process();

View File

@ -194,6 +194,7 @@ class InvoiceController extends BaseController
$invoice = $account->createInvoice($entityType, $clientId); $invoice = $account->createInvoice($entityType, $clientId);
$invoice->public_id = 0; $invoice->public_id = 0;
$invoice->loadFromRequest();
$clients = Client::scope()->with('contacts', 'country')->orderBy('name'); $clients = Client::scope()->with('contacts', 'country')->orderBy('name');
if (! Auth::user()->hasPermission('view_all')) { if (! Auth::user()->hasPermission('view_all')) {

View File

@ -319,6 +319,15 @@ class EntityModel extends Eloquent
return array_get($icons, $entityType); return array_get($icons, $entityType);
} }
public function loadFromRequest()
{
foreach (static::$requestFields as $field) {
if ($value = request()->$field) {
$this->$field = strpos($field, 'date') ? Utils::fromSqlDate($value) : $value;
}
}
}
// isDirty return true if the field's new value is the same as the old one // isDirty return true if the field's new value is the same as the old one
public function isChanged() public function isChanged()
{ {

View File

@ -73,6 +73,18 @@ class Invoice extends EntityModel implements BalanceAffecting
'date:', 'date:',
]; ];
/**
* @var array
*/
public static $requestFields = [
'invoice_number',
'invoice_date',
'due_date',
'po_number',
'discount',
'partial',
];
public static $statusClasses = [ public static $statusClasses = [
INVOICE_STATUS_SENT => 'info', INVOICE_STATUS_SENT => 'info',
INVOICE_STATUS_VIEWED => 'warning', INVOICE_STATUS_VIEWED => 'warning',

View File

@ -187,9 +187,11 @@ class BaseIntent
{ {
$field = str_replace(' ', '_', $field); $field = str_replace(' ', '_', $field);
/* Shouldn't be need any more
if (strpos($field, 'date') !== false) { if (strpos($field, 'date') !== false) {
$field .= '_sql'; $field .= '_sql';
} }
*/
return $field; return $field;
} }

View File

@ -2,6 +2,7 @@
namespace App\Ninja\Intents\WebApp; namespace App\Ninja\Intents\WebApp;
use App\Models\Invoice;
use App\Models\EntityModel; use App\Models\EntityModel;
use App\Ninja\Intents\InvoiceIntent; use App\Ninja\Intents\InvoiceIntent;
use Exception; use Exception;
@ -11,18 +12,21 @@ class CreateInvoiceIntent extends InvoiceIntent
public function process() public function process()
{ {
$client = $this->requestClient(); $client = $this->requestClient();
$invoiceItems = $this->requestInvoiceItems(); $clientPublicId = $client ? $client->public_id : null;
if (! $client) { //$invoiceItems = $this->requestInvoiceItems();
throw new Exception(trans('texts.client_not_found'));
}
$data = array_merge($this->requestFields(), [ $url = '/invoices/create/' . $clientPublicId . '?';
'client_id' => $client->public_id,
'invoice_items' => $invoiceItems,
]);
//var_dump($data); foreach ($this->requestFields() as $field => $value) {
dd($data); if (in_array($field, Invoice::$requestFields)) {
$url .= $field . '=' . urlencode($value) . '&';
}
}
$url = rtrim($url, '?');
$url = rtrim($url, '&');
return redirect($url);
} }
} }

View File

@ -2464,6 +2464,7 @@ $LANG = array(
'confirm_account_to_import' => 'Please confirm your account to import data.', 'confirm_account_to_import' => 'Please confirm your account to import data.',
'import_started' => 'Your import has started, we\'ll send you an email once it completes.', 'import_started' => 'Your import has started, we\'ll send you an email once it completes.',
'listening' => 'Listening...', 'listening' => 'Listening...',
'microphone_help' => 'Say \'Create new invoice for...\'',
); );

View File

@ -132,6 +132,12 @@
$('#left-menu-toggle').trigger('click'); $('#left-menu-toggle').trigger('click');
}); });
@if (Utils::isNinja())
Mousetrap.bind('r', function(e) {
onMicrophoneClick();
});
@endif
@foreach([ @foreach([
'i' => ENTITY_INVOICE, 'i' => ENTITY_INVOICE,
'p' => ENTITY_PAYMENT, 'p' => ENTITY_PAYMENT,

View File

@ -1,6 +1,6 @@
<i id="microphone" class="fa fa-microphone form-control-feedback" <i id="microphone" class="fa fa-microphone form-control-feedback"
style="" title="{{ trans('texts.microphone_help') }}"
onclick="startButton(event)" aria-hidden="true"></i> onclick="onMicrophoneClick()" aria-hidden="true"></i>
<style type="text/css"> <style type="text/css">
#microphone { #microphone {
@ -10,11 +10,16 @@
pointer-events: auto; pointer-events: auto;
color: #888; color: #888;
} }
#microphone:hover {
color: black;
}
</style> </style>
<script type="text/javascript"> <script type="text/javascript">
// https://developers.google.com/web/updates/2013/01/Voice-Driven-Web-Apps-Introduction-to-the-Web-Speech-API // https://developers.google.com/web/updates/2013/01/Voice-Driven-Web-Apps-Introduction-to-the-Web-Speech-API
/*
$(function() { $(function() {
$('#search').keypress(function(event) { $('#search').keypress(function(event) {
if (event.keyCode === 13) { if (event.keyCode === 13) {
@ -22,6 +27,7 @@
} }
}) })
}) })
*/
var langs = var langs =
[['Afrikaans', ['af-ZA']], [['Afrikaans', ['af-ZA']],
@ -99,10 +105,9 @@
var final_transcript = ''; var final_transcript = '';
var recognizing = false; var recognizing = false;
var ignore_onend; var ignore_onend;
var start_timestamp;
if (!('webkitSpeechRecognition' in window)) { if (!('webkitSpeechRecognition' in window)) {
upgrade(); $('.fa-microphone').hide();
} else { } else {
var recognition = new webkitSpeechRecognition(); var recognition = new webkitSpeechRecognition();
recognition.continuous = false; recognition.continuous = false;
@ -136,6 +141,7 @@
if (!final_transcript) { if (!final_transcript) {
return; return;
} }
$('#search-form').submit();
}; };
recognition.onresult = function(event) { recognition.onresult = function(event) {
@ -143,7 +149,7 @@
if (typeof(event.results) == 'undefined') { if (typeof(event.results) == 'undefined') {
recognition.onend = null; recognition.onend = null;
recognition.stop(); recognition.stop();
upgrade(); $('.fa-microphone').hide();
return; return;
} }
for (var i = event.resultIndex; i < event.results.length; ++i) { for (var i = event.resultIndex; i < event.results.length; ++i) {
@ -154,7 +160,6 @@
} }
} }
final_transcript = capitalize(final_transcript); final_transcript = capitalize(final_transcript);
var value = final_transcript || interim_transcript; var value = final_transcript || interim_transcript;
var $search = document.getElementById('search'); var $search = document.getElementById('search');
$search.value = value; $search.value = value;
@ -162,22 +167,16 @@
}; };
} }
function upgrade() {
$('.fa-microphone').hide();
}
var two_line = /\n\n/g;
var one_line = /\n/g;
function linebreak(s) {
return s.replace(two_line, '<p></p>').replace(one_line, '<br>');
}
var first_char = /\S/; var first_char = /\S/;
function capitalize(s) { function capitalize(s) {
return s.replace(first_char, function(m) { return m.toUpperCase(); }); return s.replace(first_char, function(m) { return m.toUpperCase(); });
} }
function startButton(event) { function onMicrophoneClick() {
$('#search').val('create new invoice for edgar a po number of 1234');
$('#search-form').submit();
return;
$('.fa-microphone').hide(); $('.fa-microphone').hide();
$('#search').val("{{ trans('texts.listening') }}"); $('#search').val("{{ trans('texts.listening') }}");
if (recognizing) { if (recognizing) {
@ -188,7 +187,6 @@
recognition.lang = 'en-US'; recognition.lang = 'en-US';
recognition.start(); recognition.start();
ignore_onend = false; ignore_onend = false;
start_timestamp = event.timeStamp;
} }
</script> </script>