Los Addins son "extras" que podemos añadir a nuestras páginas en Business central y que son capaces de aportar una funcionalidad de la que no disponÃamos hasta ese momento.
Lo que haremos será añadir código en Javascript que nos aportará ese "extra" buscado y lo realmente interesante es saber que la comunicación con este código funciona en ambos sentidos, seremos capaces de pasarle información al código, pero también de recibirla.
Lo que haremos será añadir código en Javascript que nos aportará ese "extra" buscado y lo realmente interesante es saber que la comunicación con este código funciona en ambos sentidos, seremos capaces de pasarle información al código, pero también de recibirla.
Pero veamos cómo funciona todo esto.
Primero debemos tener claro qué es lo que necesitamos añadir y si no existe ya algo similar que podamos adaptar. Hay que tener en cuenta que nunca conviene reinventar la rueda, alguien ya se tomó esa molestia en su dÃa.
Por ejemplo, veremos cómo crear un dictado de texto para descripciones largas, texto que guardaremos en un campo de tipo blob, como puede ser Work description de Sales Header y a su vez mostraremos ese texto en otro addin; en vez de mostrar un campo de tipo text con la opción multiline a true que como sabemos sólo mostrará 3 lÃneas de texto.
En este segundo caso, podemos encontrar mil formas distintas de hacerlo por nuestra cuenta, pero Business central ya dispone de un control que hace lo que necesitamos.
En este segundo caso, podemos encontrar mil formas distintas de hacerlo por nuestra cuenta, pero Business central ya dispone de un control que hace lo que necesitamos.
Pasos:
- Crear una nueva carpeta donde se pondrán los archivos necesarios para nuestro addin
- Crear un nuevo fichero con extensión js en el que añadiremos el código Javascript necesario, para el ejemplo lo llamaremos startup.js
En él, añadiremos el siguiente código:
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("ReadyVoice", "");
var SpeechRecognition = SpeechRecognition || webkitSpeechRecognition;
var recognition = new SpeechRecognition();
recognition.continuous = false;
recognition.lang = 'es-ES';
recognition.interimResults = false;
recognition.maxAlternatives = 1;
recognition.onspeechend = function() {
// when user is done speaking
recognition.stop();
};
recognition.onresult = function(event) {
try {
var transcript = event.results[0][0].transcript;
var confidence = event.results[0][0].confidence;
Microsoft.Dynamics.NAV.InvokeExtensibilityMethod("voice",[transcript]);
} catch (err) {
console.log(err);
};
};
function speak(listenTxt){
try {
const utterThis = new SpeechSynthesisUtterance(listenTxt);
utterThis.lang = 'es-ES';
utterThis.pitch = 1;
utterThis.rate = 1;
window.speechSynthesis.speak(utterThis);
} catch (err) {
console.log(err);
};
};
function stoprecording(){
recognition.abort();
};
function startrecording(){
recognition.start();
};
Este código será el encargado de procesar nuestra voz a texto, el funcionamiento está documentado en este Link y como se puede observar además de reconocer voz, también es capaz de convertir texto a voz.Los métodos que vamos a utilizar para comunicarnos con este código se localizan fácilmente, Microsoft.Dynamics.NAV.InvokeExtensibilityMethodNuestro addin va empezando a tener esta apariencia:
- Ahora necesitamos el controlador de AL del objeto, creamos un nuevo fichero al que llamaremos AddinVoz.al
- En él añadiremos lo siguiente:
Al ser un control no visual, le indicamos la altura y anchura mÃnimos.controladdin "Voice"{RequestedHeight = 0;RequestedWidth = 0;Scripts = './AddinVoz/startup.js';event ReadyVoice();procedure stoprecording();procedure startrecording();procedure speak(listenTxt: Text);event voice(listenedText: Text);}
Disponemos de varios elementos:
- Eventos: nos indican que se ha producido en cambio en el control, o más bien, que el código Javascript nos devuelve algún valor o lanza alguna petición para ejecutar alguna de nuestras funciones.
Tenemos el evento ReadyVoice que nos indicarÃa que el control se está cargando, aunque no lo vamos a utilizar en este ejemplo y el evento voice que serÃa el que realmente nos interesa y es el que devuelve una cadena de texto con el dictado. - Procedimientos: son funciones que funcionan en el sentido contrario, Business central pasa valores a Javascript o ejecuta funciones de este.
Startrecording iniciarÃa el reconocimiento de voz, stoprecording lo detendrÃa y speak harÃa que el sintetizador de voz del navegador leyese el texto que le pasamos como parámetro.
- Y por último añadimos nuestro control donde lo necesitemos, por ejemplo, en la ficha de producto; creamos una extensión de la página Item Card y añadimos lo siguiente:
layout
{
addlast(content)
{
usercontrol(voice; voice)
{
trigger voice(listenedText: Text)
begin
LongText := listenedText;
CurrPage.Update(false);
end;
}
field(LongText; LongText)
{
Caption = 'Texto dictado';
Editable = true;
MultiLine = true;
trigger OnAssistEdit()
begin
CurrPage.voice.startrecording();
end;
}
}
}
var
LongText: Text;
Esto generará el siguiente resultado:
Al pulsar el botón de assitedit comenzará el dictado y el resultado será devuelto a la variable LongText, lo que a su vez actualizará el resultado de la casilla.
La primera vez que iniciemos el reconocimiento, el navegador solicitará autorización para utilizar el micrófono.
La primera vez que iniciemos el reconocimiento, el navegador solicitará autorización para utilizar el micrófono.
Nota: este control que utiliza micrófono, altavoces o cámara si fuese el caso, sólo funcionará desde un entorno cuya dirección sea https://... es decir, una cuya dirección comience por http:// no será capaz de arrancar el control.
Como podemos observar el resultado es devuelto a una casilla definida de esta manera:
field(LongText; LongText)
{
Caption = 'Texto dictado';
Editable = true;
MultiLine = true;
trigger OnAssistEdit()
begin
CurrPage.voice.startrecording();
end;
}
Esto significa que el tamaño de la casilla es fijo y estará limitado a 3 lÃneas de altura. Si sobrepasamos esa longitud aparece una barra de scroll que produce que el uso de este control resulte un tanto tedioso.
Para solucionar esto, utilizaremos otro addin, pero en este caso proporcionado por Microsoft.
Añadiremos este control:
Añadiremos este control:
usercontrol(LongText2; "Microsoft.Dynamics.Nav.Client.WebPageViewer")
{
ApplicationArea = All;
trigger ControlAddInReady(callbackUrl: Text)
begin
SetAddInContent();
end;
trigger Callback(data: Text)
begin
LongText := data;
end;
}
Acompañado de la función que lo rellena. Se trata de Textarea, un control de HTML al que le damos la funcionalidad de poder ser redimensionado por el usuario al gusto y nos informa de cualquier cambio realizado a través del evento Callback:
local procedure SetAddInContent()
begin
CurrPage.LongText2.SetContent(StrSubstNo('<textarea Id="TextArea" maxlength="%2" style="width:100%;height:100%; font-family:"Segoe UI", "Segoe WP", Segoe, device-segoe, Tahoma, Helvetica, Arial, sans-serif !important; font-size: 10.5pt !important;" OnChange="window.parent.WebPageViewerHelper.TriggerCallback(document.getElementById(''TextArea'').value)">%1</textarea>', LongText, 5000));
end;
Hay que tener en cuenta que este código sólo actúa al cargar la página, debemos llamar a la función SetAddInContent en cada registro por el que pasemos en el apartado OnAfterGetRecord.
A nivel de HTML, abriendo el inspector de páginas podemos ver que los estos controles son iframes que se añaden a la página web visualizada:
Tenemos la posibilidad desde Javascript de recoger ese iframe y rellenarlo con nuestro propio código HTML o incluso no limitarnos a eso y utilizar jQuery para poder actuar sobre cualquier control mostrado en la página, por ejemplo el icono de la papelera de eliminar, podrÃamos ocultarlo, cambiar la posición, el color, etc.
Aquà se abre un nuevo mundo de posibilidades que nos permitirá añadir controles que capturen imágenes de cámaras web, mostrar controles gráficos como calendarios, lÃneas de tiempo, diagramas, etc.
Estos controles también responden a la aplicación móvil por lo que podremos añadir este tipo de controles a nuestra aplicación móvil de Business central en caso necesario.
El lÃmite sólo lo marca la imaginación.
Espero que os sea de utilidad.
El código en github.



Publicar un comentario