mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Working on speech rec
This commit is contained in:
parent
dcee9285d9
commit
fcbc9bd885
@ -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();
|
||||||
|
@ -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')) {
|
||||||
|
@ -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()
|
||||||
{
|
{
|
||||||
|
@ -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',
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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...\'',
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user