NoLev commited on
Commit
b33f725
·
verified ·
1 Parent(s): f96d6b9

Update static/index.html

Browse files
Files changed (1) hide show
  1. static/index.html +24 -52
static/index.html CHANGED
@@ -17,13 +17,9 @@
17
  <select id="model" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" required>
18
  <option value="nousresearch/hermes-3-llama-3.1-70b">Hermes 3 Llama 3.1 70B (Uncensored, Explicit)</option>
19
  <option value="deepseek/deepseek-chat-v3-0324:free">DeepSeek Chat (Free)</option>
20
- <option value="deepseek/deepseek-chat-v3-0324">DeepSeek Chat (Paid)</option>
21
- <option value="deepseek/deepseek-chat-v3.1">DeepSeek Chat v3.1(Paid)</option>
22
  <option value="deepseek/deepseek-r1-0528:free">DeepSeek R1 (Free)</option>
23
- <option value="deepseek/deepseek-r1-0528">DeepSeek R1 (Paid)</option>
24
  <option value="tngtech/deepseek-r1t2-chimera:free">DeepSeek TNG (Free)</option>
25
  <option value="x-ai/grok-4">Grok 4</option>
26
- <option value="x-ai/grok-4-fast">Grok 4</option>
27
  <option value="x-ai/grok-3">Grok 3</option>
28
  <option value="anthropic/claude-3.7-sonnet">Claude Sonnet 3.7</option>
29
  <option value="anthropic/claude-3.5-sonnet">Claude 3.5 Sonnet</option>
@@ -51,17 +47,9 @@
51
  <div id="outputs" class="space-y-4 hidden">
52
  <div>
53
  <label class="block text-sm font-medium text-gray-700">Outline (10 Chapters for 90k Words)</label>
54
- <textarea id="outline" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" rows="6" readonly></textarea>
55
  </div>
56
- <div>
57
- <label class="block text-sm font-medium text-gray-700">Locations</label>
58
- <textarea id="locations" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" rows="3" readonly></textarea>
59
- </div>
60
- <div>
61
- <label class="block text-sm font-medium text-gray-700">Objects</label>
62
- <textarea id="objects" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" rows="3" readonly></textarea>
63
- </div>
64
- <button id="copy_all" class="mt-2 bg-green-600 text-white p-2 rounded-md hover:bg-green-700">Copy All for NovelCrafter</button>
65
  </div>
66
  </div>
67
 
@@ -71,20 +59,7 @@
71
  const countDisplay = document.getElementById("transcript_count");
72
  const generateButton = document.getElementById("generate_novel");
73
  const outputsDiv = document.getElementById("outputs");
74
-
75
- // Helper to safely stringify for textarea
76
- function safeStringify(value) {
77
- if (value === null || value === undefined) return "";
78
- if (typeof value === 'string') return value;
79
- if (typeof value === 'object') {
80
- try {
81
- return JSON.stringify(value, null, 2);
82
- } catch (e) {
83
- return JSON.stringify(value);
84
- }
85
- }
86
- return String(value);
87
- }
88
 
89
  // Handle file upload: read and populate textarea
90
  fileInput.addEventListener("change", (event) => {
@@ -123,8 +98,9 @@
123
  alert("Please enter a transcript or select a file.");
124
  return;
125
  }
 
126
  const statusDiv = document.createElement("div");
127
- statusDiv.textContent = "Analyzing explicit content & generating dark romance structure... (This may take a few minutes)";
128
  statusDiv.className = "text-center text-blue-600 mb-4";
129
  outputsDiv.insertBefore(statusDiv, outputsDiv.firstChild);
130
  outputsDiv.classList.remove("hidden");
@@ -142,25 +118,25 @@
142
  body: formData
143
  });
144
  if (!response.ok) {
145
- const errorData = await response.json();
146
- throw new Error(errorData.detail || `HTTP error! status: ${response.status}`);
147
  }
148
- const result = await response.json();
149
- statusDiv.remove();
150
- if (result.error) {
151
- document.getElementById("outline").value = `Error: ${result.error}`;
152
- } else {
153
- // Structured fields with safe stringify
154
- document.getElementById("outline").value = safeStringify(result.outline);
155
- document.getElementById("locations").value = safeStringify(result.locations);
156
- document.getElementById("objects").value = safeStringify(result.objects);
157
-
158
- // Fallback if no structured data
159
- if (!result.outline && result.raw_response) {
160
- document.getElementById("outline").value = safeStringify(result.raw_response).substring(0, 2000) + "...";
161
- alert("AI output wasn't strict JSON—showing raw response as fallback in Outline. Check server logs for details.");
162
  }
163
  }
 
 
 
 
 
164
  } catch (error) {
165
  statusDiv.textContent = `Error: ${error.message}`;
166
  statusDiv.className = "text-center text-red-600 mb-4";
@@ -168,13 +144,9 @@
168
  });
169
 
170
  document.getElementById("copy_all").addEventListener("click", () => {
171
- const outputs = [
172
- document.getElementById("outline").value,
173
- document.getElementById("locations").value,
174
- document.getElementById("objects").value
175
- ].join("\n\n---\n\n");
176
- navigator.clipboard.writeText(outputs)
177
- .then(() => alert("All outputs copied to clipboard! Paste into NovelCrafter for full 90k manuscript."))
178
  .catch(err => console.error('Failed to copy: ', err));
179
  });
180
  </script>
 
17
  <select id="model" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" required>
18
  <option value="nousresearch/hermes-3-llama-3.1-70b">Hermes 3 Llama 3.1 70B (Uncensored, Explicit)</option>
19
  <option value="deepseek/deepseek-chat-v3-0324:free">DeepSeek Chat (Free)</option>
 
 
20
  <option value="deepseek/deepseek-r1-0528:free">DeepSeek R1 (Free)</option>
 
21
  <option value="tngtech/deepseek-r1t2-chimera:free">DeepSeek TNG (Free)</option>
22
  <option value="x-ai/grok-4">Grok 4</option>
 
23
  <option value="x-ai/grok-3">Grok 3</option>
24
  <option value="anthropic/claude-3.7-sonnet">Claude Sonnet 3.7</option>
25
  <option value="anthropic/claude-3.5-sonnet">Claude 3.5 Sonnet</option>
 
47
  <div id="outputs" class="space-y-4 hidden">
48
  <div>
49
  <label class="block text-sm font-medium text-gray-700">Outline (10 Chapters for 90k Words)</label>
50
+ <textarea id="outline" class="mt-1 block w-full p-2 border border-gray-300 rounded-md" rows="20" readonly placeholder="Streaming generation..."></textarea>
51
  </div>
52
+ <button id="copy_all" class="mt-2 bg-green-600 text-white p-2 rounded-md hover:bg-green-700">Copy Outline for NovelCrafter</button>
 
 
 
 
 
 
 
 
53
  </div>
54
  </div>
55
 
 
59
  const countDisplay = document.getElementById("transcript_count");
60
  const generateButton = document.getElementById("generate_novel");
61
  const outputsDiv = document.getElementById("outputs");
62
+ const outlineTextarea = document.getElementById("outline");
 
 
 
 
 
 
 
 
 
 
 
 
 
63
 
64
  // Handle file upload: read and populate textarea
65
  fileInput.addEventListener("change", (event) => {
 
98
  alert("Please enter a transcript or select a file.");
99
  return;
100
  }
101
+ outlineTextarea.value = ""; // Clear previous
102
  const statusDiv = document.createElement("div");
103
+ statusDiv.textContent = "Streaming: Summarizing transcript & generating outline...";
104
  statusDiv.className = "text-center text-blue-600 mb-4";
105
  outputsDiv.insertBefore(statusDiv, outputsDiv.firstChild);
106
  outputsDiv.classList.remove("hidden");
 
118
  body: formData
119
  });
120
  if (!response.ok) {
121
+ throw new Error(`HTTP error! status: ${response.status}`);
 
122
  }
123
+ const reader = response.body.getReader();
124
+ const decoder = new TextDecoder();
125
+ let done = false;
126
+ while (!done) {
127
+ const { value, done: readerDone } = await reader.read();
128
+ done = readerDone;
129
+ if (value) {
130
+ const chunk = decoder.decode(value, { stream: true });
131
+ outlineTextarea.value += chunk; // Append in real-time
132
+ outlineTextarea.scrollTop = outlineTextarea.scrollHeight; // Auto-scroll
 
 
 
 
133
  }
134
  }
135
+ statusDiv.remove();
136
+ if (outlineTextarea.value.includes("Error:")) {
137
+ statusDiv.textContent = outlineTextarea.value;
138
+ statusDiv.className = "text-center text-red-600 mb-4";
139
+ }
140
  } catch (error) {
141
  statusDiv.textContent = `Error: ${error.message}`;
142
  statusDiv.className = "text-center text-red-600 mb-4";
 
144
  });
145
 
146
  document.getElementById("copy_all").addEventListener("click", () => {
147
+ const outline = document.getElementById("outline").value;
148
+ navigator.clipboard.writeText(outline)
149
+ .then(() => alert("Outline copied to clipboard! Paste into NovelCrafter for full 90k manuscript."))
 
 
 
 
150
  .catch(err => console.error('Failed to copy: ', err));
151
  });
152
  </script>