Add toggle defaults reset to Software

This commit is contained in:
firestar5683
2026-10-30 16:12:04 -05:00
parent d513137550
commit 37bbd2711d
3 changed files with 91 additions and 2 deletions
@@ -42,3 +42,58 @@ await ToggleBackup.methods.restoreBackup.call(moving)
assert.equal(writes,1)
assert.match(moving.error,/Park/)
console.log("Portable layout files and legacy restore through Toggle backup passed")
assert.match(ToggleBackup.template, /Reset toggles to default/)
assert.ok(ToggleBackup.template.indexOf('Restore toggles') < ToggleBackup.template.indexOf('Reset toggles to default'))
const resetCalls = []
const reset = { ...ToggleBackup.data(), request: async (path, body) => {
resetCalls.push([path, body])
if (path.endsWith('non-defaults')) return {view:'fresh-view', count:3, rows:[
{id:0,resetAvailable:true}, {id:1,resetAvailable:false}, {id:2,resetAvailable:true}]}
if (path.endsWith('preview')) return {intent:'fresh-intent', question:'Reset 2 settings?'}
return {saved:true,applied:['First','Second']}
} }
await ToggleBackup.methods.reviewResetDefaults.call(reset)
assert.deepEqual(resetCalls, [['./api/settings/non-defaults',undefined],
['./api/settings/recovery/preview',{view:'fresh-view',selected:[0,2]}]])
assert.equal(reset.resetDraft.intent,'fresh-intent')
assert.equal(resetCalls.some(([path]) => path.endsWith('confirm')),false,'Review must not change settings')
await Promise.all([ToggleBackup.methods.resetDefaults.call(reset),ToggleBackup.methods.resetDefaults.call(reset)])
assert.deepEqual(resetCalls.at(-1),['./api/settings/recovery/confirm',{intent:'fresh-intent',confirmed:true}])
assert.equal(resetCalls.filter(([path]) => path.endsWith('confirm')).length,1)
assert.equal(reset.resetDraft,null)
assert.equal(reset.notice,'2 settings reset to default.')
const alreadyDefault = {...ToggleBackup.data(),request:async path => {
assert.equal(path,'./api/settings/non-defaults'); return {count:0,rows:[]}
} }
await ToggleBackup.methods.reviewResetDefaults.call(alreadyDefault)
assert.match(alreadyDefault.notice,/already use their defaults/)
assert.equal(alreadyDefault.resetDraft,null)
const cannotReset = {...ToggleBackup.data(),request:async path => {
assert.equal(path,'./api/settings/non-defaults');return {count:1,rows:[{id:0,resetAvailable:false}]}
} }
await ToggleBackup.methods.reviewResetDefaults.call(cannotReset)
assert.match(cannotReset.error,/Park/)
assert.equal(cannotReset.resetDraft,null)
const interrupted = {...ToggleBackup.data(),resetDraft:{intent:'approved'},request:async () =>
({saved:false,applied:['First'],reason:'Vehicle state changed'})}
await ToggleBackup.methods.resetDefaults.call(interrupted)
assert.match(interrupted.error,/1 settings reset.*Vehicle state changed/)
assert.equal(interrupted.notice,'')
assert.equal(interrupted.resetDraft,null)
const failedReview = {...ToggleBackup.data(),request:async () => {throw new Error('Sign in to Galaxy')}}
await ToggleBackup.methods.reviewResetDefaults.call(failedReview)
assert.equal(failedReview.error,'Sign in to Galaxy')
assert.equal(failedReview.resetDraft,null)
assert.equal(failedReview.busy,false)
let busyRequests=0
const busyReset = {...ToggleBackup.data(),busy:true,resetDraft:{intent:'old'},request:async () => {busyRequests++}}
await ToggleBackup.methods.reviewResetDefaults.call(busyReset)
await ToggleBackup.methods.resetDefaults.call(busyReset)
assert.equal(busyRequests,0)
console.log('Software-screen default reset uses guarded preview and explicit confirmation')
@@ -8,7 +8,7 @@ export const ToggleBackup = {
name: "ToggleBackup",
components: { GxDialog, GxNotice },
props: { unauthorized: { type: Function, required: true } },
data: () => ({ busy: false, draft: null, legacy: false, error: "", notice: "" }),
data: () => ({ busy: false, draft: null, resetDraft: null, legacy: false, error: "", notice: "" }),
methods: {
async request(path, payload) {
try {
@@ -51,6 +51,32 @@ export const ToggleBackup = {
}
} catch (error) { this.draft = null; this.error = error.message || "Could not read toggle backup." }
},
async reviewResetDefaults() {
if (this.busy) return
this.busy = true; this.resetDraft = null; this.error = this.notice = ""
try {
const snapshot = await this.request("./api/settings/non-defaults")
const selected = snapshot.rows.filter(row => row.resetAvailable === true).map(row => row.id)
if (!selected.length) {
if (snapshot.count) throw new Error("Park the vehicle before resetting available toggles.")
this.notice = "All available toggles already use their defaults."
return
}
this.resetDraft = await this.request("./api/settings/recovery/preview", { view: snapshot.view, selected })
} catch (error) { this.error = error.message || "Could not prepare toggle reset." }
finally { this.busy = false }
},
async resetDefaults() {
if (this.busy || !this.resetDraft) return
const pending = this.resetDraft
this.resetDraft = null; this.busy = true; this.error = this.notice = ""
try {
const result = await this.request("./api/settings/recovery/confirm", { intent: pending.intent, confirmed: true })
if (!result.saved) throw new Error(`${result.applied.length} settings reset. ${result.reason || "Review Toggles before retrying."}`)
this.notice = `${result.applied.length} ${result.applied.length === 1 ? "setting" : "settings"} reset to default.`
} catch (error) { this.error = error.message || "Could not reset toggles. Review Toggles before retrying." }
finally { this.busy = false }
},
async restoreBackup() {
if (this.busy || !this.draft) return
const draft = this.draft, legacy = this.legacy
@@ -75,6 +101,7 @@ export const ToggleBackup = {
<div class="gx-section__header"><i class="bi bi-cloud-arrow-down" aria-hidden="true"></i><span class="gx-section__title">Toggle backup</span></div><p class="gx-note">Save your editable toggles, onroad layout and colors. Restore compatible settings while parked.</p>
<div class="gx-actions"><button type="button" class="gx-btn gx-btn--tonal" @click="exportBackup">Back up toggles</button>
<button type="button" class="gx-btn gx-btn--tonal" @click="$refs.file.click()">Restore toggles</button>
<button type="button" class="gx-btn gx-btn--tonal" @click="reviewResetDefaults">Reset toggles to default</button>
<input ref="file" type="file" accept=".json,application/json" class="gx-sr-only" tabindex="-1" aria-label="Choose toggle backup" @change="chooseFile"></div>
<p v-if="busy" class="gx-note" role="status"><span class="gx-spinner" aria-hidden="true"></span> Working…</p>
<GxNotice v-if="notice" tone="success">{{ notice }}</GxNotice><GxNotice v-if="error" tone="danger">{{ error }}</GxNotice>
@@ -82,5 +109,12 @@ export const ToggleBackup = {
<p>{{ legacy ? 'Replace your saved layout and colors?' : 'Apply the compatible saved toggles, layout and colors from this backup? Unavailable settings will be skipped.' }} Keep the vehicle parked.</p>
<div class="gx-actions"><button type="button" class="gx-btn gx-btn--tonal" @click="draft=null">Cancel</button><button type="button" class="gx-btn" @click="restoreBackup">Restore</button></div>
</GxDialog>
<GxDialog v-if="resetDraft" :inert="busy" labelledby="gx-toggle-reset-title" @close="resetDraft=null">
<h3 id="gx-toggle-reset-title">Reset toggles to default?</h3>
<p>{{ resetDraft.question }}</p>
<p>Keep the vehicle parked. Settings unavailable for this vehicle are left unchanged. Calibration, downloaded models, accounts and network credentials are kept.</p>
<div class="gx-actions"><button type="button" class="gx-btn gx-btn--tonal" @click="resetDraft=null">Cancel</button>
<button type="button" class="gx-btn" @click="resetDefaults">Reset toggles</button></div>
</GxDialog>
</section>`,
}
+1 -1
View File
@@ -1 +1 @@
{"protected_inventory_sha256": "8730d7ea0d5a470b442f0838daf18cab804ee48e3ebef293dc1e9fa7ccb2c59e", "schema_version": 1}
{"protected_inventory_sha256": "859a6c9567fc9ae7352b9dc0787eb96769307adeb21e62fc085a4d2a120ff452", "schema_version": 1}