SETTINGS: Validate and save; form errors.

This commit is contained in:
punkfairie 2023-05-13 17:17:01 -07:00
parent 14c02f614a
commit d6708ed0ee
5 changed files with 88 additions and 7 deletions

View file

@ -31,7 +31,7 @@
Minimum value: Minimum value:
</label> </label>
<div class="col-2 system charted p-0"> <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>
</div> </div>
@ -40,7 +40,7 @@
Maximum distance: Maximum distance:
</label> </label>
<div class="col-2 system charted p-0"> <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> </div>
</div> </div>

View file

@ -225,3 +225,8 @@ div b.active.landable {
color: var(--accent-light); color: var(--accent-light);
transition: color 300ms; transition: color 300ms;
} }
.form-error {
color: var(--main);
margin-left: 1rem;
}

View file

@ -1,7 +1,9 @@
const fs = require('node:fs/promises') const fs = require('node:fs/promises');
const { statSync, writeFileSync, readFileSync } = require('node:fs') const { statSync, writeFileSync, readFileSync } = require('node:fs');
const os = require('node:os') const os = require('node:os');
const path = require('node:path') const path = require('node:path');
import { Log } from "./Log";
interface settingsFile { interface settingsFile {
minValue: number, minValue: number,
@ -12,6 +14,7 @@ export class Settings {
static #instance: Settings; static #instance: Settings;
#file: string; #file: string;
#writing: boolean;
minValue: number; minValue: number;
maxDistance: number; maxDistance: number;
@ -42,6 +45,8 @@ export class Settings {
const contents: settingsFile = JSON.parse(readFileSync(this.#file, { encoding: 'utf8' })); const contents: settingsFile = JSON.parse(readFileSync(this.#file, { encoding: 'utf8' }));
this.minValue = contents.minValue; this.minValue = contents.minValue;
this.maxDistance = contents.maxDistance; this.maxDistance = contents.maxDistance;
this.#writing = false;
} }
static get(isPackaged: boolean = false): Settings { static get(isPackaged: boolean = false): Settings {
@ -51,4 +56,24 @@ export class Settings {
return Settings.#instance; 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;
}
}
} }

View file

@ -183,4 +183,13 @@ export class UI {
static setValue(row, value) { static setValue(row, value) {
row.children().filter('.value').text(UI.#formatNumber(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);
}
} }

View file

@ -4,8 +4,10 @@ import './assets/index.css';
import './assets/ldom.min'; import './assets/ldom.min';
const { ipcRenderer } = require('electron'); const { ipcRenderer } = require('electron');
const { setTimeout } = require('node:timers/promises');
import { Settings } from './models/Settings'; import { Settings } from './models/Settings';
import { UI } from './models/UI';
const settings = Settings.get(); const settings = Settings.get();
@ -25,3 +27,43 @@ $('.backBtn').on('click', () => {
$('#minValue').attr('value', settings.minValue); $('#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);
}
});