Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

webui: fix textarea autoscroll #607

Merged
merged 1 commit into from
Dec 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 55 additions & 63 deletions pyglossary/ui/ui_web/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,17 @@
height: auto;
font-family: 'Fira Mono', 'Jetbrains Mono', monospace;
}

#btnConvert {
font-size: 2em;
height: 2em;
}

pre {
font-size:7px;
font-size: 7px;
font-family: 'Fira Mono', 'Jetbrains Mono', Consolas, Monaco, Lucida Console, monospace;
}

article>textarea {
font-family: 'Fira Mono', 'Jetbrains Mono', Consolas, Monaco, Lucida Console, monospace;
font-size: smaller;
Expand All @@ -125,18 +128,19 @@
<h1>
<a style="text-decoration: none;" data-theme-switcher="auto" href="#" id="theme-switcher"
class="theme-switcher">
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
<path
d="M12,18C11.11,18 10.26,17.8 9.5,17.45C11.56,16.5 13,14.42 13,12C13,9.58 11.56,7.5 9.5,6.55C10.26,6.2 11.11,6 12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31L23.31,12L20,8.69Z" />
</svg>
<!--noformat-->
<svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M12,18C11.11,18 10.26,17.8 9.5,17.45C11.56,16.5 13,14.42 13,12C13,9.58 11.56,7.5 9.5,6.55C10.26,6.2 11.11,6 12,6A6,6 0 0,1 18,12A6,6 0 0,1 12,18M20,8.69V4H15.31L12,0.69L8.69,4H4V8.69L0.69,12L4,15.31V20H8.69L12,23.31L15.31,20H20V15.31L23.31,12L20,8.69Z"/></svg>
<!--noformat-->
</a> PyGlossary
</h1>
</li>
</ul>
<ul dir="rtl">
<li>
<details id="dropdown" class="dropdown">
<!--noformat-->
<summary role="button" class="outline"><svg height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg"><path d="M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z"/></svg></summary>
<!--noformat-->
<ul>
<li class="primary"><a id="clearDisplay" href="#">&#10006; Clear log</a></li>
<li class="primary"><a target="_blank"
Expand Down Expand Up @@ -241,61 +245,52 @@ <h5></h5>
<!-- Footer -->
<footer class="container">
<small><a target="_blank" href="https://github.com/ilius/pyglossary">
<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 16 16" width="20" aria-hidden="true"
class="d-block">
<path fill="currentColor"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
</path>
</svg>
<!--noformat-->
<svg xmlns="http://www.w3.org/2000/svg" height="20" viewBox="0 0 16 16" width="20" aria-hidden="true" class="d-block"><path fill="currentColor" d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z"></path></svg>
<!--noformat-->
</a>
</small>
</footer>
<!-- ./ Footer -->
<!-- ConfigDialog -->
<dialog>
<article>
<h2>Conversion Options</h2>
<p>
Please enter valid JSON for custom conversion options.</p>
<p>Example config (See available options in <a target="_blank" href="https://ed-25q.pages.dev/#right=url.https://cdn.jsdelivr.net/gh/ilius/pyglossary/plugins-meta/index.json&left=url.https://y-bad.pages.dev/pyglossary-config.json">plugins options reference</a>):</p>
<section id="configExample">
<details>
<summary>&#x002B; Click for an example</summary>
<p><!--noformat-->
<h2>Conversion Options</h2>
<p>
Please enter valid JSON for custom conversion options.</p>
<p>Example config (See available options in <a target="_blank"
href="https://ed-25q.pages.dev/#right=url.https://cdn.jsdelivr.net/gh/ilius/pyglossary/plugins-meta/index.json&left=url.https://y-bad.pages.dev/pyglossary-config.json">plugins
options reference</a>):</p>
<section id="configExample">
<details>
<summary>&#x002B; Click for an example</summary>
<p><!--noformat-->
<pre>{
"convertOptions": {
"sort": true,
"sortKeyName": "headword_lower:es_ES",
"sortEncoding": "utf-8",
"sqlite": true
},
"readOptions": {
"encoding": "utf-8",
"audio": true,
"example_color": "blue",
"abbrev": "hover"
"example_color": "blue"
},
"writeOptions": {
"compression": "zlib",
"content_type": "text/html; charset=utf-8",
"separate_alternates": true,
"word_title": true,
"version_info": false
"resources": false
}
}</pre><!--noformat-->
</p>
</details>
</section>

<textarea id="allOptions" name="allOptions" id="" cols="30" rows="10"></textarea>
<footer>
<button id="btnOptCancel" class="secondary">
Cancel
</button>
<button id="btnOptOk">Confirm</button>
</footer>
</p>
</details>
</section>

<textarea id="allOptions" name="allOptions" id="" cols="30" rows="10"></textarea>
<footer>
<button id="btnOptCancel" class="secondary">
Cancel
</button>
<button id="btnOptOk">Confirm</button>
</footer>
</article>
</dialog>
</dialog>
<!-- ./ ConfigDialog -->

<script>
Expand Down Expand Up @@ -324,6 +319,11 @@ <h2>Conversion Options</h2>
const progressBar = document.getElementById('progress');
const progressText = document.getElementById('progress-text');

function log(msg) {
consoleArea.value += `${msg}\n`;
consoleArea.scrollTop = consoleArea.scrollHeight;
}

function initWsConnection() {
const socket = new WebSocket('/ws');
window.ws = socket;
Expand All @@ -341,31 +341,28 @@ <h2>Conversion Options</h2>
progressBar.value = message.ratio * 100;
progressText.innerText = message.text;
} else if (message.type == 'info') {
consoleArea.value += `${message.text}\n`;
log(message.text);
}

consoleArea.scrollIntoView({ behavior: "smooth", block: "end", inline: "start" });
});

socket.addEventListener('error', (error) => {
msg = `WebSocket error: ${error}\n`;
consoleArea.value += `${msg}\n`;
console.log(msg);
log(msg);
});

socket.addEventListener('close', () => {
console.log('WebSocket connection closed');
log('WebSocket connection closed');
});
}

function loadConfig() {
fetch("/config")
.then(response => {
if (!response.ok) {
consoleArea.value += `Failed to fetch configuration: ${response.status} ${response.text()}\n`;
log(`Failed to fetch configuration: ${response.status} ${response.text()}`);
return Promise.reject(`Failed to fetch configuration: ${response.statusText}`);
} else {
consoleArea.value += `config load ✔️\n`;
log('config load ✔️');
}
return response.json();
})
Expand Down Expand Up @@ -397,8 +394,7 @@ <h2>Conversion Options</h2>
attachListenersPostInit();
})
.catch(error => {
console.error("Error populating dropdowns:", error);
consoleArea.value += `Error populating dropdowns: ${error}\n`;
log(`Error populating dropdowns: ${error}`);
});
}

Expand All @@ -418,12 +414,12 @@ <h2>Conversion Options</h2>
document.querySelector('input[type="submit"]').addEventListener('click', async (event) => {

progressBar.value = 0;
consoleArea.value = 'Starting new conversion job. Please wait... ⏳\n';
log('Starting new conversion job. Please wait... ⏳');
const form = event.target.form;

if (form.checkValidity()) {
event.preventDefault();
consoleArea.value += '\nConversion started, please wait...\n';
log('Conversion started, please wait...');

const inputFilename = form.inputFilename.value;
const inputFormat = form.inputFormat.value;
Expand Down Expand Up @@ -451,16 +447,12 @@ <h2>Conversion Options</h2>
});

if (!response.ok) {
const msg = `Failed to start conversion: ${response.statusText} ${response.json()}\n`
consoleArea.value += `${msg}\n`;
throw new Error(msg);

log(`Failed to start conversion: ${response.statusText} ${response.json()}`);
}
toggleConvertButton();

} catch (error) {
console.error('Error during conversion:', error);
consoleArea.value += `${error}\n`;
log(`Error during conversion: ${error}`);
toggleConvertButton();
}
}
Expand All @@ -478,7 +470,7 @@ <h2>Conversion Options</h2>
ws.send('exit');
}
document.getElementById('dropdown').removeAttribute('open')
consoleArea.value = 'Server stopped! Window can now be closed.\n\n';
log('Server stopped! Window can now be closed.');
});

document.getElementById('btnOptions').addEventListener('click', (evt) => {
Expand All @@ -503,10 +495,10 @@ <h2>Conversion Options</h2>
try {
const allOptionsObj = JSON.parse(allOptions);
localStorage.setItem(KEY_PG_OPTIONS, JSON.stringify(allOptionsObj))
consoleArea.value += `options saved ✔️\n${allOptions}\n`;
log(`options saved ✔️\n${allOptions}`);
} catch (error) {
console.error('Invalid JSON string:', error.message);
consoleArea.value += `invalid options ${error.message} JSON\n`;
log(`invalid options ${error.message} JSON\n`);
}

toggleAttr(optionsDialog, 'open');
Expand All @@ -518,7 +510,7 @@ <h2>Conversion Options</h2>
evt.stopImmediatePropagation();
const optionsDialog = document.querySelector('dialog');
toggleAttr(optionsDialog, 'open');
consoleArea.value += 'options dialog cancelled without saving\n';
log('options dialog cancelled without saving');
});

FIELD_IDS_PERSISTABLE.forEach(fieldId => {
Expand Down
Loading