Wie man mit JavaScript arbeitet und Mendix | Mendix

Direkt zum Inhalt

Wie man mit JavaScript arbeitet und Mendix

Wie man mit JavaScript arbeitet und Mendix

Während des Lockdowns hatte ich viel Zeit und wie viele andere Menschen verbrachte ich die meiste Zeit damit, Serien zu gucken und Filmmarathons zu machen. Während eines fast einmonatigen Filmmarathons wurde ich neugierig, ob ich eine Sprach-App bauen könnte, in Mendix unter Verwendung von JavaScript.

Wer Superheldenfilme und andere Science-Fiction-Genres kennt, weiß, dass digitale Sidekicks sich in Sicherheitssysteme hacken, und noch mehr über den Hauptprotagonisten der Geschichte. Aber bei meinem Build würde ich mich auf die Sprach-zu-Text- und Text-zu-Sprache-Aspekte meiner digitalen Sprachassistenten-App konzentrieren. Ich meine, wie schwer kann das schon sein? Ohne Rücksicht auf meine eigene geistige Gesundheit oder mein Stressniveau stürzte ich mich kopfüber in den Abgrund der Sprachsynthesetechnologien und wie man sie in Javascript implementiert und Mendix.

„JavaScript ist die einzige Sprache, die ich kenne, von der die Leute das Gefühl haben, sie müssten sie nicht lernen, bevor sie sie verwenden.“

— Douglas Crockford

Die Idee

Das Design ist einfach – so einfach, wie ich es machen konnte. Die Idee ist, ein Mendix App, die die gesprochenen Worte eines Benutzers hören und verstehen und dann mit ihrer eigenen „Stimme“ antworten kann. Klingt einfach, oder? Nachdem ich mich für ein Design entschieden hatte, war es an der Zeit, nach vorhandenen Technologien zu suchen, die ich verwenden könnte – es macht nicht viel Sinn, dies von Grund auf neu zu entwickeln, wenn es bereits viele Sprachplattformen gibt, wie Watson von IBM und die Cloud AI Platform von Google.

Ich habe jedoch schon früher Chatbots entwickelt - letztes Jahr Mendix World, ich habe mit Jan de Vries einen Low Code Live Build veranstaltet. In der Sitzung habe ich eine Alexa-Fähigkeit entwickelt, die es einem Benutzer ermöglicht, mit einem Mendix App, indem Sie mit Alexa sprechen. Dieses Mal habe ich beschlossen, mich weniger auf die eigentliche Konversation und den Dialog zu konzentrieren, sondern mehr auf den eigentlichen Aspekt des gesprochenen Wortes. Wenn Sie mehr über das Erstellen von Konversationsbäumen erfahren möchten, empfehle ich Ihnen, sich die Aufzeichnung von anzusehen Mendix Welt 2020.

Das Design

Was werde ich also eigentlich bauen? Nach einigen Recherchen habe ich mich für ein Design entschieden. Meine App sollte sich auf zwei Kernaspekte konzentrieren:

  1. Ein steckbares Spracherkennungs-Widget, das die Stimme des Benutzers hören und verstehen kann.
  2. Eine Text-to-Speech-JavaScript-Aktion, die es der App ermöglicht, dem Benutzer laut zu antworten.

Für das Widget würde ich eine Bibliothek verwenden, die ich gefunden habe auf Github, die von Mozillas Sprachsynthesebibliotheken.

Passenderweise für die JavaScript-Aktion stieß ich auf eine JavaScript-Tutorial erstellt von Mendix was genau dies in unserer eigenen Dokumentation tut.

Schließlich hat der Held in den Filmen immer einen coolen Namen für seinen Roboter-Kumpel. Zu Ehren dieses Namens habe ich beschlossen, meine App MAEVIS welches dafür steht "Mendix's Awesome Ausgezeichnet Sehr intelligentes System"

Gebäude MAEVIS

Wenn ich eine App entwickle, versuche ich mich im Allgemeinen zuerst auf die anspruchsvollsten oder komplexesten Prozesse zu konzentrieren. Da ich bereits eine grobe Idee hatte, wie ich die App zum Sprechen bringen könnte, beschloss ich, mich auf die Entwicklung des Widgets zu konzentrieren, das MAEVIS ermöglichen würde, Hör mich. Wie oben erwähnt, habe ich mich für dieses entschieden Bibliothek by NikValdez auf Github.

Früher habe ich die Mendix Widget-Generator zum Erstellen meines Widget-Gerüsts. Ich habe mich für die Erstellung mit JavaScript ES6 entschieden und es ist für Web- und hybride mobile Apps konzipiert.

Das Hauptproblem, das ich bei der Anpassung dieses Codes an MAEVIS hatte, war, dass das Beispiel eine Funktionskomponente verwendet und das Widget-Gerüst den Code als Klassenkomponente generiert. Nachdem ich das Problem verstanden hatte, war es einfach, es zu lösen.

Der endgültige Widget-Code lautete wie folgt:

import React,{ Component, createElement, useState, useEffect } from "react";
import "./ui/SpeechToText.css";
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
const mic = new SpeechRecognition();
mic.continuous = true;
mic.interimResults = true;
mic.lang = 'en-US';
export default function SpeechToText(){
const [isListening, setIsListening] = useState(false);
const [note, setNote] = useState('');
const [savedNotes, setSavedNotes] = useState([]);
useEffect(() => {
handleListen()
}, [isListening]);
const handleListen = () => {
if (isListening) {
mic.start()
mic.onend = () => {
console.log('continue..')
mic.start()
}
} else {<mic.stop()
mic.onend = () => {
console.log('Stopped Mic on Click')
handleSaveNote()
}
}
mic.onstart = () => {
console.log('Mics on')
}
mic.onresult = event => {
const transcript = Array.from(event.results)
.map(result => result[0])
.map(result => result.transcript)
.join('')
console.log(transcript)
//textAttribute(transcript)
setNote(transcript)
mic.onerror = event => {
console.log(event.error)
}
}
}
const handleSaveNote = () => {
setSavedNotes([...savedNotes, note])
setNote('')
}
return  <span className="flexColumn">
<>
<p>{note}</p>
<button
className={isListening ? 'pulse-button btn-danger' : 'pulse-button'}
onClick={() => setIsListening(prevState => !prevState)}>
{isListening ? <span>🎙️Stop</span> : <span>🛑Start</span>}
</button>
</>
<>
<h2>Notes</h2>
{savedNotes.map(n => (
<p key={n}>{n}</p>
))}
</&gt
</span>
}

Ich habe auch einige Stile hinzugefügt, um das Frontend der Widgets zu ändern, sodass es besser aussieht als normale Schaltflächen auf einem Bildschirm:

.flexColumn{
display: inline-flex;
flex-direction: column;
}
.container {
width: 200px;
height: 100%;
margin: 0 auto 0;
perspective: 1000;
-webkit-perspective: 1000;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
background: #fff;
}
.pulse-button {
position: relative;
margin: auto;
display: block;
width: 10em;
height: 10em;
font-size: 1.3em;
font-weight: light;
font-family: 'Trebuchet MS', sans-serif;
text-transform: uppercase;
text-align: center;
line-height: 100px;
letter-spacing: -1px;
color: white;
border: none;
border-radius: 50%;
background: #5a99d4;
cursor: pointer;
box-shadow: 0 0 0 0 rgba(90, 153, 212, 0.5);
-webkit-animation: pulse 1.5s infinite;
animation: pulse 1.5s infinite;
}
.pulse-button:hover {
-webkit-animation: none;
animation: none;
}
@-webkit-keyframes pulse {
0% {
-moz-transform: scale(0.9);
-ms-transform: scale(0.9);
-webkit-transform: scale(0.9);
transform: scale(0.9);
}
70% {
-moz-transform: scale(1);
-ms-transform: scale(1);
-webkit-transform: scale(1);
transform: scale(1);
box-shadow: 0 0 0 50px rgba(90, 153, 212, 0);
}
100% {
-moz-transform: scale(0.9);
-ms-transform: scale(0.9);
-webkit-transform: scale(0.9);
transform: scale(0.9);
box-shadow: 0 0 0 0 rgba(90, 153, 212, 0);
}
}
@keyframes pulse {
0% {
-moz-transform: scale(0.9);
-ms-transform: scale(0.9);
-webkit-transform: scale(0.9);
transform: scale(0.9);
}
70% {
-moz-transform: scale(1);
-ms-transform: scale(1);
-webkit-transform: scale(1);
transform: scale(1);
box-shadow: 0 0 0 50px rgba(90, 153, 212, 0);
}
100% {
-moz-transform: scale(0.9);
-ms-transform: scale(0.9);
-webkit-transform: scale(0.9);
transform: scale(0.9);
box-shadow: 0 0 0 0 rgba(90, 153, 212, 0);
}
}

Ich muss sagen, dass ich es als eine meiner größten Entwicklungsleistungen betrachte, dieses Widget auf dem Bildschirm darzustellen, und es ist das erste Mal in meinem Leben, dass ich beim Programmieren in JavaScript wirklich diesen „AHA!“-Moment hatte. Für diejenigen, die sich fragen, wie lange das gedauert hat: Es waren ungefähr drei Tage, in denen ich mir die Haare gerauft und meinen Laptop angebrüllt habe, aber am Ende hat es sich für mich riesig gelohnt.

Nachdem der schwierige Teil erledigt war, war es eine einfache Aufgabe, einfach diesem zu folgen Tutorial zum Erstellen von JavaScript-Aktionen.

In nur ein oder zwei Stunden hatte ich eine Aktion, die jeden Text, den ich als Parameter angab, laut vorlesen konnte. Für diejenigen, die nur nach dem Code suchen, hier ist er, aber ich empfehle, dieses Tutorial zu befolgen, wenn Sie neu bei JavaScript-Aktionen sind in Mendix.

// This file was generated by Mendix Studio Pro.
//
// WARNING: Only the following code will be retained when actions are regenerated:
// - the import list
// - the code between BEGIN USER CODE and END USER CODE
// - the code between BEGIN EXTRA CODE and END EXTRA CODE
// Other code you write will be lost the next time you deploy the project.
import { Big } from "big.js";
// BEGIN EXTRA CODE
// END EXTRA CODE
/**
* @param {string} text
* @returns {Promise.<boolean>}
*/
export async function JS_TextToSpeech(text) {
// BEGIN USER CODE
if (!text) {
return false;
}
if ("speechSynthesis" in window === false) {
throw new Error("Browser does not support text to speech");
}
// const utterance = new SpeechSynthesisUtterance(text);
// window.speechSynthesis.speak(utterance);
// return true;
return new Promise(function(resolve, reject) {
const utterance = new SpeechSynthesisUtterance(text);
utterance.onend = function() {
resolve(true);
};
utterance.onerror = function(event) {
reject("An error occured during playback: " + event.error);
};
window.speechSynthesis.speak(utterance);

});
// ENDBENUTZERCODE
}

Zeit, es auszuprobieren

Ohne weitere Umschweife möchte ich euch allen meine Kreation vorstellen MAEVIS.

Wrapping up

Ich möchte betonen, wie viel ich bei diesem Projekt gelernt habe, und obwohl es eine Herausforderung war, empfehle ich Ihnen dringend, es selbst auszuprobieren. Ich hätte diesem Build gerne noch mehr hinzugefügt, aber da noch andere wirklich spannende Projekte in Arbeit sind, muss ich es dabei belassen.

Idealerweise wollte ich, dass das Widget selbst den Nanoflow auslöst, der die Text-to-Speech-JavaScript-Aktion auslöst. Und ich denke, es wäre toll, Props zu verwenden, um den Dialog aus dem Widget wieder in Mendix, anstatt es einfach im Status des Widgets zu speichern. Ich werde weiter an diesen Funktionen arbeiten und in Zukunft vielleicht einen Folgebeitrag dazu veröffentlichen, aber bis dahin denke ich, dass es eine großartige Übung für Sie alle ist, genau dies auszuprobieren! Bitte wenden Sie sich an mich, wenn Sie dies verwenden. Ich würde gerne sehen, auf welche verrückten Ideen Sie alle dadurch kommen. Bis dahin gilt: Denken Sie daran – Machen Sie es!

Wählen Sie Ihre Sprache