Skip to content

Commit

Permalink
UX refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
jsalsman committed May 21, 2024
1 parent 1d75cb0 commit cc7f38d
Showing 1 changed file with 180 additions and 123 deletions.
303 changes: 180 additions & 123 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@

<meta itemprop="name" content="nocode-voice-edu-rpg">
<meta name="description" content="Voice instructional role-playing game generator">
<meta name="robots" content="noindex, follow">
<meta name="robots" content="index, follow">
<meta name="keywords" content="voice, instructional role-playing game generator">
<meta name="author" content="Jim Salsman">
<meta name="language" content="English">
<meta charset="UTF-8">
<!-- <meta name="viewport" content="width=device-width, initial-scale=1.0"> -->
<!-- <link rel="icon" href="icon.png"> -->
<meta itemprop="url" content="https://jsalsman.github.io/nocode-voice-edu-rpg">
<link rel="canonical" href="https://jsalsman.github.io/nocode-voice-edu-rpg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/svg+xml" href="https://vapi.ai/favicon.ico" />

<!-- Preview card: -->
<meta property="og:title" content="nocode-voice-edu-rpg">
Expand All @@ -24,132 +22,191 @@
<meta property="og:site_name" content="github:nocode-voice-edu-rpg" />
<meta property="og:locale" content="en_US" />

<style>
/* General styling for the entire body of the webpage */
body {
margin: 0; /* Removes margin space around everything */
font-family: Arial, sans-serif; /* Sets font to Arial */
}
a, a:visited { /* Links in their normal and visited states */
text-decoration: none; /* Removes underlines from links */
color: blue; /* Links always blue */
}
h1, h2 { /* H1 and H2 headings */
font-family: Georgia, serif; /* Sets font to Georgia */
margin-top: 0px; /* Adjusts the top margin */
}
#menu { /* Menu container */
background-color: lightgreen; /* Light green menu background */
padding: 1em; /* Adds padding around the inside of menu */
overflow-y: auto; /* Allows scrolling menu is too tall */
}
#content { /* Main content container */
overflow-y: auto; /* Allows vertical scrolling */
background-attachment: fixed; /* Image won't move */
}
section { /* Individual sections */
padding: 1em; /* Pads each section to replace margins */
}

/* Desktop or landscape view: 700px or more */
@media (min-width: 700px) {
body {
display: flex; /* Flex layout puts menu and content side by side */
height: 100vh; /* Prevents menu from scrolling away */
}
#menu {
width: 30vw; /* Menu is 30% of viewport width */
}
#content {
width: 70vw; /* Content is 70% of viewport width */
}
}

/* Mobile/portrait view: 699px or less */
@media (max-width: 699px) {
#menu {
height: 20vh; /* Menu is 20% of the viewport height */
bottom: 0; /* Positions menu at bottom of viewport */
position: fixed; /* Menu stays in position on scroll */
display: flex;
flex-direction: column;
}
#greeting, #about, #trailer {
margin: 1px;
}
#trailer {
display: flex;
justify-content: space-between;
align-items: top;
}
#instructions {
width: 40%; /* Adjust width to fit within the flex container */
}
#about {
width: 40%; /* Adjust width to fit within the flex container */
text-align: right; /* Align text to the right */
}
#content {
height: 80vh; /* Content is 80% of viewport height */
}
}
</style>
</head>
<body>
<h1>Voice instructional role-playing game generator</h1>

<hr/>
<div id="conversation"></div>
<hr/>

<script>
// from https://docs.vapi.ai/examples/voice-widget
// kind of want to use a <iframe> for https://vapi.ai?demo=true&shareKey=4922b20f-1964-400c-ac08-21b6889bf23d&assistantId=b9323c5b-7c81-4371-8666-4cd2a04338a5

var vapiInstance = null;
const assistant = "b9323c5b-7c81-4371-8666-4cd2a04338a5"; // assistant ID
const apiKey = "4922b20f-1964-400c-ac08-21b6889bf23d"; // Public key from Vapi Dashboard
const buttonConfig = { /*
position: "bottom-right", // "bottom" | "top" | "left" | "right" | "top-right" | "top-left" | "bottom-left" | "bottom-right"
offset: "40px", // decide how far the button should be from the edge
width: "50px", // min-width of the button
height: "50px", // height of the button
idle: { // button state when the call is not active.
color: `rgb(93, 254, 202)`,
type: "pill", // or "round"
title: "Have a quick question?", // only required in case of Pill
subtitle: "Talk with our AI assistant", // only required in case of pill
icon: `https://unpkg.com/lucide-static@0.321.0/icons/phone.svg`,
},
loading: { // button state when the call is connecting
color: `rgb(93, 124, 202)`,
type: "pill", // or "round"
title: "Connecting...", // only required in case of Pill
subtitle: "Please wait", // only required in case of pill
icon: `https://unpkg.com/lucide-static@0.321.0/icons/loader-2.svg`,
},
active: { // button state when the call is in progress or active.
color: `rgb(255, 0, 0)`,
type: "pill", // or "round"
title: "Call is in progress...", // only required in case of Pill
subtitle: "End the call.", // only required in case of pill
icon: `https://unpkg.com/lucide-static@0.321.0/icons/phone-off.svg`,
},
*/
};

(function (d, t) {
var g = document.createElement(t),
s = d.getElementsByTagName(t)[0];
g.src =
"https://cdn.jsdelivr.net/gh/VapiAI/html-script-tag@latest/dist/assets/index.js";
g.defer = true;
g.async = true;
s.parentNode.insertBefore(g, s);

g.onload = function () {
vapiInstance = window.vapiSDK.run({
apiKey: apiKey, // mandatory
assistant: assistant, // mandatory
config: buttonConfig, // optional
});

function log_message(message) {
var timestamp = new Date().toLocaleString();

// Check if the message is an object and has a "type" property
if (typeof message === 'object' && message.type === 'conversation-update') {
// Find the conversation div
var conversationDiv = document.getElementById('conversation');

// Clear the conversation div
conversationDiv.innerHTML = '';

// Add the timestamp

<div id="menu">
<h2 id="greeting">An instructional role-playing game
generator on <a href="https://vapi.ai/"
target="_blank">Vapi.ai.</a></h2>
<div id="trailer">
<h3 id="instructions">Click the 📞 button to begin.</h3>
<p id="about">
See <a href="https://github.com/jsalsman/nocode-voice-edu-rpg/"
target="_blank">github.com/jsalsman/nocode-voice-edu-rpg</a>
for the source prompt and replication details.
</p>
</div>
</div>

<div id="content">
<section id="transcript">
Conversation:
<div id="conversation"></div>
<hr/>
</section>
<br/><br/><br/><br/><br/><br/><br/><br/><br/><br/><!-- space for horizontal scrolling -->
</div>

<script>
const assistant = "b9323c5b-7c81-4371-8666-4cd2a04338a5"; // assistant ID
const apiKey = "4922b20f-1964-400c-ac08-21b6889bf23d"; // Public key from Vapi Dashboard
const buttonConfig = { }; // see https://docs.vapi.ai/examples/voice-widget

var vapiInstance = null;
(function (d, t) {
var g = document.createElement(t),
s = d.getElementsByTagName(t)[0];
g.src =
"https://cdn.jsdelivr.net/gh/VapiAI/html-script-tag@latest/dist/assets/index.js";
g.defer = true;
g.async = true;
s.parentNode.insertBefore(g, s);

g.onload = function () {
vapiInstance = window.vapiSDK.run({
apiKey: apiKey, // mandatory
assistant: assistant, // mandatory
config: buttonConfig, // optional
});

function log_message(message) {
var timestamp = new Date().toLocaleString();
var timestampElement = document.createElement('p');
timestampElement.textContent = `[${timestamp}]`;
conversationDiv.appendChild(timestampElement);

// Loop through the conversation array
message.conversation.forEach(entry => {
var p = document.createElement('p');
p.textContent = entry.content;

// Apply different styles based on the role
if (entry.role === 'user') {
p.style.fontFamily = 'serif';
} else if (entry.role === 'assistant') {
p.style.fontFamily = 'sans-serif';

// Check if the message is an object and has a "type" property
if (typeof message === 'object' && message.type === 'conversation-update') {
// Find the conversation div
var conversationDiv = document.getElementById('conversation');

// Clear the conversation div
conversationDiv.innerHTML = '';

// Add the timestamp
conversationDiv.appendChild(timestampElement);

// Loop through the conversation array
message.conversation.forEach(entry => {
var p = document.createElement('p');
p.textContent = entry.content;

// Apply different styles based on the role
if (entry.role === 'user') {
p.style.fontFamily = 'serif';
} else if (entry.role === 'assistant') {
p.style.fontFamily = 'sans-serif';
}

// Append the paragraph to the conversation div
conversationDiv.appendChild(p);
});
} else {
// Create a <pre> element for normal log messages
var pre = document.createElement('pre');

// Check if the message is an object
if (typeof message === 'object') {
// Convert the object to a string representation
message = JSON.stringify(message, null, 2);
}

// Append the paragraph to the conversation div
conversationDiv.appendChild(p);
});
} else {
// Create a <pre> element for normal log messages
var pre = document.createElement('pre');

// Check if the message is an object
if (typeof message === 'object') {
// Convert the object to a string representation
message = JSON.stringify(message, null, 2);
// Set the message with the timestamp as the text content of the <pre> element
pre.textContent = `[${timestamp}] ${message}`;

// Apply the desired font size and family
pre.style.fontSize = '11pt';
pre.style.fontFamily = 'sans-serif';

// Append the <pre> element to the conversation
var transcriptDiv = document.getElementById('transcript');
transcriptDiv.appendChild(pre);
}
}

// Set the message with the timestamp as the text content of the <pre> element
pre.textContent = `[${timestamp}] ${message}`;
// Function calls and transcripts will be sent via messages
vapiInstance.on('message', (message) => {
log_message(message);
});

// Apply the desired font size and family
pre.style.fontSize = '11pt';
pre.style.fontFamily = 'sans-serif';
vapiInstance.on('error', (e) => {
console.error(e)
log_message(e);
});
};

// Append the <pre> element to the body
document.body.appendChild(pre);
}
}

// Function calls and transcripts will be sent via messages
vapiInstance.on('message', (message) => {
log_message(message);
});

vapiInstance.on('error', (e) => {
console.error(e)
log_message(e);
});

};
})(document, "script");

</script>
</body>
})(document, "script");

</script>
</body>
</html>

0 comments on commit cc7f38d

Please sign in to comment.