SETTINGS: Validate and save; form errors.
This commit is contained in:
parent
14c02f614a
commit
d6708ed0ee
5 changed files with 88 additions and 7 deletions
|
@ -31,7 +31,7 @@
|
|||
Minimum value:
|
||||
</label>
|
||||
<div class="col-2 system charted p-0">
|
||||
<input type="text" class="form-control" id="minValue">
|
||||
<input type="text" class="form-control" id="minValue" name="minValue">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
|||
Maximum distance:
|
||||
</label>
|
||||
<div class="col-2 system charted p-0">
|
||||
<input type="text" class="form-control" id="maxDistance">
|
||||
<input type="text" class="form-control" id="maxDistance" name="maxDistance">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -224,4 +224,9 @@ div b.active.landable {
|
|||
.separator .btn:hover {
|
||||
color: var(--accent-light);
|
||||
transition: color 300ms;
|
||||
}
|
||||
|
||||
.form-error {
|
||||
color: var(--main);
|
||||
margin-left: 1rem;
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
const fs = require('node:fs/promises')
|
||||
const { statSync, writeFileSync, readFileSync } = require('node:fs')
|
||||
const os = require('node:os')
|
||||
const path = require('node:path')
|
||||
const fs = require('node:fs/promises');
|
||||
const { statSync, writeFileSync, readFileSync } = require('node:fs');
|
||||
const os = require('node:os');
|
||||
const path = require('node:path');
|
||||
|
||||
import { Log } from "./Log";
|
||||
|
||||
interface settingsFile {
|
||||
minValue: number,
|
||||
|
@ -12,6 +14,7 @@ export class Settings {
|
|||
static #instance: Settings;
|
||||
|
||||
#file: string;
|
||||
#writing: boolean;
|
||||
|
||||
minValue: number;
|
||||
maxDistance: number;
|
||||
|
@ -42,6 +45,8 @@ export class Settings {
|
|||
const contents: settingsFile = JSON.parse(readFileSync(this.#file, { encoding: 'utf8' }));
|
||||
this.minValue = contents.minValue;
|
||||
this.maxDistance = contents.maxDistance;
|
||||
|
||||
this.#writing = false;
|
||||
}
|
||||
|
||||
static get(isPackaged: boolean = false): Settings {
|
||||
|
@ -51,4 +56,24 @@ export class Settings {
|
|||
|
||||
return Settings.#instance;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------------- save ---- */
|
||||
|
||||
async save(settings: settingsFile): Promise<boolean> {
|
||||
if (!this.#writing) {
|
||||
try {
|
||||
// So we don't try to write again before this one finishes.
|
||||
this.#writing = true;
|
||||
await fs.writeFile(this.#file, JSON.stringify(settings));
|
||||
this.#writing = false;
|
||||
|
||||
return true;
|
||||
} catch (err) {
|
||||
Log.write(err);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -183,4 +183,13 @@ export class UI {
|
|||
static setValue(row, value) {
|
||||
row.children().filter('.value').text(UI.#formatNumber(value));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ addFormError ---- */
|
||||
|
||||
static addFormError(field, msg) {
|
||||
const label = $(field).parent().parent().children().filter('label');
|
||||
const error = $('<span>').addClass('form-error');
|
||||
error.text(msg);
|
||||
label.appendChild(error);
|
||||
}
|
||||
}
|
|
@ -4,8 +4,10 @@ import './assets/index.css';
|
|||
import './assets/ldom.min';
|
||||
|
||||
const { ipcRenderer } = require('electron');
|
||||
const { setTimeout } = require('node:timers/promises');
|
||||
|
||||
import { Settings } from './models/Settings';
|
||||
import { UI } from './models/UI';
|
||||
|
||||
const settings = Settings.get();
|
||||
|
||||
|
@ -24,4 +26,44 @@ $('.backBtn').on('click', () => {
|
|||
/* ------------------------------------------------------------------- insert current values ---- */
|
||||
|
||||
$('#minValue').attr('value', settings.minValue);
|
||||
$('#maxDistance').attr('value', settings.maxDistance);
|
||||
$('#maxDistance').attr('value', settings.maxDistance);
|
||||
|
||||
/* ---------------------------------------------------------------------------- process form ---- */
|
||||
|
||||
$('form').on('submit', async function (event) {
|
||||
event.preventDefault();
|
||||
$('.form-error').remove();
|
||||
|
||||
// Retrieve and normalize data.
|
||||
const formData = new FormData(event.target);
|
||||
const data = Object.fromEntries(formData.entries());
|
||||
|
||||
data.minValue = parseInt(data.minValue.replace(/\D/g, ''));
|
||||
data.maxDistance = parseInt(data.maxDistance.replace(/\D/g, ''));
|
||||
|
||||
// Check for any errors.
|
||||
let errors = false;
|
||||
if (isNaN(data.minValue)) {
|
||||
UI.addFormError('#minValue', 'Please enter a number!');
|
||||
errors = true;
|
||||
}
|
||||
|
||||
if (isNaN(data.maxDistance)) {
|
||||
UI.addFormError('#maxDistance', 'Please enter a number!');
|
||||
}
|
||||
|
||||
// If no errors, save.
|
||||
if (!errors) {
|
||||
let tries = 0;
|
||||
do {
|
||||
let result = await settings.save(data);
|
||||
|
||||
if (!result) {
|
||||
await setTimeout(3000);
|
||||
tries++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (tries < 3);
|
||||
}
|
||||
});
|
Loading…
Reference in a new issue