Skip to content

Commit c89815e

Browse files
committed
update storyteller UI
1 parent 264d2ea commit c89815e

File tree

8 files changed

+416
-112
lines changed

8 files changed

+416
-112
lines changed

examples/bedtime-story-teller/assets/app.js

Lines changed: 149 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,58 @@
44

55
const socket = io(`http://${window.location.host}`);
66

7+
let generateStoryButtonOriginalHTML = ''; // To store the original content of the generate story button
8+
let storyBuffer = '';
9+
710

811

912
function initSocketIO() {
10-
socket.on('response', (data) => {
11-
document.getElementById('story-container').style.display = 'flex';
12-
const storyResponse = document.getElementById('story-response');
13-
storyResponse.textContent = data;
14-
document.getElementById('loading-spinner').style.display = 'none';
15-
const clearStoryButton = document.getElementById('clear-story-button');
16-
clearStoryButton.style.display = 'block';
17-
clearStoryButton.disabled = false;
13+
socket.on('prompt', (data) => {
14+
const promptContainer = document.getElementById('prompt-container');
15+
const promptDisplay = document.getElementById('prompt-display');
16+
promptDisplay.innerHTML = data;
17+
promptContainer.style.display = 'block';
1818
});
19+
20+
socket.on('response', (data) => {
21+
22+
document.getElementById('story-container').style.display = 'flex';
23+
24+
storyBuffer += data;
25+
26+
});
27+
28+
29+
30+
socket.on('stream_end', () => {
31+
32+
const storyResponse = document.getElementById('story-response');
33+
34+
storyResponse.innerHTML = storyBuffer;
35+
36+
37+
38+
document.getElementById('loading-spinner').style.display = 'none';
39+
40+
const clearStoryButton = document.getElementById('clear-story-button');
41+
42+
clearStoryButton.style.display = 'block';
43+
44+
clearStoryButton.disabled = false;
45+
46+
47+
48+
const generateStoryButton = document.querySelector('.generate-story-button');
49+
50+
if (generateStoryButton) {
51+
52+
generateStoryButton.disabled = false;
53+
54+
generateStoryButton.innerHTML = generateStoryButtonOriginalHTML; // Restore original content
55+
56+
}
57+
58+
});
1959
}
2060

2161
function unlockAndOpenNext(currentContainer) {
@@ -33,6 +73,12 @@ function unlockAndOpenNext(currentContainer) {
3373
}
3474
}
3575

76+
function getRandomElement(elements) {
77+
if (elements.length === 0) return null;
78+
const randomIndex = Math.floor(Math.random() * elements.length);
79+
return elements[randomIndex];
80+
}
81+
3682
function setupChipSelection(container) {
3783
const chips = container.querySelectorAll('.chip');
3884
const selectedValue = container.querySelector('.selected-value');
@@ -49,6 +95,13 @@ function setupChipSelection(container) {
4995
if (!alreadySelected) {
5096
unlockAndOpenNext(container);
5197
}
98+
99+
// Collapse the current container
100+
const content = container.querySelector('.parameter-content');
101+
const arrow = container.querySelector('.arrow-icon');
102+
content.style.display = 'none';
103+
arrow.classList.remove('rotated');
104+
52105
});
53106
});
54107
}
@@ -129,6 +182,17 @@ function checkCharactersAndUnlockNext(charactersContainer) {
129182
}
130183

131184
function gatherDataAndGenerateStory() {
185+
document.querySelectorAll('.parameter-container').forEach(container => {
186+
const content = container.querySelector('.parameter-content');
187+
if (content && content.style.display === 'block') {
188+
content.style.display = 'none';
189+
const arrow = container.querySelector('.arrow-icon');
190+
if (arrow) {
191+
arrow.classList.remove('rotated');
192+
}
193+
}
194+
});
195+
132196
const age = document.querySelector('.parameter-container:nth-child(1) .chip.selected')?.textContent.trim() || 'any';
133197
const theme = document.querySelector('.parameter-container:nth-child(2) .chip.selected')?.textContent.trim() || 'any';
134198
const storyTypeContainer = document.querySelector('.parameter-container:nth-child(3)');
@@ -168,9 +232,20 @@ function generateStory(data) {
168232
document.querySelector('.story-output-placeholder').style.display = 'none';
169233
const responseArea = document.getElementById('story-response-area');
170234
responseArea.style.display = 'flex';
235+
document.getElementById('prompt-container').style.display = 'none';
236+
document.getElementById('prompt-display').textContent = '';
171237
document.getElementById('story-container').style.display = 'none';
172-
document.getElementById('loading-spinner').style.display = 'block';
173-
document.getElementById('story-response').textContent = '';
238+
document.getElementById('story-response').innerHTML = ''; // Use innerHTML to clear
239+
storyBuffer = ''; // Reset buffer
240+
document.getElementById('loading-spinner').style.display = 'block'; // Show the general loading spinner
241+
242+
const generateStoryButton = document.querySelector('.generate-story-button');
243+
if (generateStoryButton) {
244+
generateStoryButton.disabled = true;
245+
// Append the spinner instead of replacing innerHTML
246+
generateStoryButton.innerHTML += '<div class="button-spinner spinner"></div>';
247+
}
248+
174249
document.getElementById('clear-story-button').style.display = 'none';
175250
socket.emit('generate_story', data);
176251
}
@@ -223,10 +298,12 @@ function resetStoryView() {
223298
}
224299
}
225300

226-
// Hide "Generate story" button
301+
// Restore "Generate story" button to original state
227302
const generateStoryButton = document.querySelector('.generate-story-button');
228303
if (generateStoryButton) {
229-
generateStoryButton.style.display = 'none';
304+
generateStoryButton.style.display = 'none'; // Keep hidden if no chars, will be set to flex by checkCharactersAndUnlockNext
305+
generateStoryButton.disabled = false;
306+
generateStoryButton.innerHTML = generateStoryButtonOriginalHTML;
230307
}
231308

232309
// Reset parameter containers state
@@ -250,6 +327,11 @@ function resetStoryView() {
250327
document.addEventListener('DOMContentLoaded', () => {
251328
initSocketIO();
252329

330+
const generateStoryButton = document.querySelector('.generate-story-button');
331+
if (generateStoryButton) {
332+
generateStoryButtonOriginalHTML = generateStoryButton.innerHTML; // Store original content
333+
}
334+
253335
const parameterContainers = document.querySelectorAll('.parameter-container');
254336

255337
parameterContainers.forEach((container, index) => {
@@ -259,7 +341,9 @@ document.addEventListener('DOMContentLoaded', () => {
259341
content.style.display = 'block';
260342
arrow.classList.add('rotated');
261343
} else {
262-
container.classList.add('disabled');
344+
if (container.id !== 'prompt-container') {
345+
container.classList.add('disabled');
346+
}
263347
}
264348
});
265349

@@ -374,4 +458,56 @@ document.addEventListener('DOMContentLoaded', () => {
374458
console.error('Could not copy text: ', err);
375459
});
376460
});
461+
462+
document.getElementById('generate-randomly-button').addEventListener('click', () => {
463+
// Age
464+
const ageChips = document.querySelectorAll('.parameter-container:nth-child(1) .chip');
465+
const randomAgeChip = getRandomElement(ageChips);
466+
const age = randomAgeChip ? randomAgeChip.textContent.trim() : 'any';
467+
468+
// Theme
469+
const themeChips = document.querySelectorAll('.parameter-container:nth-child(2) .chip');
470+
const randomThemeChip = getRandomElement(themeChips);
471+
const theme = randomThemeChip ? randomThemeChip.textContent.trim() : 'any';
472+
473+
// Story Type
474+
const storyTypeContainer = document.querySelector('.parameter-container:nth-child(3)');
475+
476+
// Tone
477+
const toneChips = storyTypeContainer.querySelectorAll('.story-type-paragraph:nth-child(1) .chip');
478+
const randomToneChip = getRandomElement(toneChips);
479+
const tone = randomToneChip ? randomToneChip.textContent.trim() : 'any';
480+
481+
// Ending type
482+
const endingTypeChips = storyTypeContainer.querySelectorAll('.story-type-paragraph:nth-child(2) .chip');
483+
const randomEndingTypeChip = getRandomElement(endingTypeChips);
484+
const endingType = randomEndingTypeChip ? randomEndingTypeChip.textContent.trim() : 'any';
485+
486+
// Narrative structure
487+
const narrativeStructureChips = storyTypeContainer.querySelectorAll('.story-type-paragraph:nth-child(3) .chip');
488+
const randomNarrativeStructureChip = getRandomElement(narrativeStructureChips);
489+
const narrativeStructure = randomNarrativeStructureChip ? randomNarrativeStructureChip.textContent.trim() : 'any';
490+
491+
// Duration
492+
const durationChips = storyTypeContainer.querySelectorAll('.story-type-paragraph:nth-child(4) .chip');
493+
const randomDurationChip = getRandomElement(durationChips);
494+
const duration = randomDurationChip ? randomDurationChip.textContent.trim() : 'any';
495+
496+
// Characters and Other will be empty for random generation.
497+
const characters = [];
498+
const other = '';
499+
500+
const storyData = {
501+
age,
502+
theme,
503+
tone,
504+
endingType,
505+
narrativeStructure,
506+
duration,
507+
characters,
508+
other,
509+
};
510+
511+
generateStory(storyData);
512+
});
377513
});
Lines changed: 32 additions & 10 deletions
Loading

0 commit comments

Comments
 (0)