Skip to content

Commit

Permalink
✨ Add export/import feature for local stats
Browse files Browse the repository at this point in the history
  • Loading branch information
richardfrost committed May 9, 2024
1 parent 3d7804b commit f53e47b
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/script/mainOptionPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ document.getElementById('setPasswordBtn').addEventListener('click', (evt) => { o
document.getElementById('testText').addEventListener('input', (evt) => { option.populateTest(); });
// Stats
document.getElementById('collectStats').addEventListener('click', (evt) => { option.saveOptions(); });
document.getElementById('statsExport').addEventListener('click', (evt) => { option.exportStats(); });
document.getElementById('statsImport').addEventListener('click', (evt) => { option.confirm('statsImport'); });
document.getElementById('statsImportInput').addEventListener('change', (evt) => { option.importStatsFile(evt.target as HTMLInputElement, (evt.target as HTMLInputElement).files); });
document.getElementById('statsReset').addEventListener('click', (evt) => { option.confirm('statsReset'); });
document.getElementById('lessUsedWordsNumber').addEventListener('input', (evt) => { OptionPage.hideInputError(evt.target as HTMLInputElement); });
document.getElementById('removeLessUsedWords').addEventListener('click', (evt) => { option.confirm('removeLessUsedWords'); });
Expand Down
36 changes: 36 additions & 0 deletions src/script/optionPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -610,6 +610,11 @@ export default class OptionPage {
}
}
break;
case 'statsImport':
this.Class.configureConfirmModal({ content: 'Are you sure you want to overwrite your statistics?' });
this._confirmEventListeners.push(this.importStats.bind(this));
ok.addEventListener('click', lastElement(this._confirmEventListeners));
break;
case 'statsReset':
this.Class.configureConfirmModal({ content: 'Are you sure you want to reset filter statistics?' });
this._confirmEventListeners.push(this.statsReset.bind(this));
Expand Down Expand Up @@ -731,6 +736,11 @@ export default class OptionPage {
}
}

async exportStats(filePrefix = 'apf-stats') {
const stats = await this.getStatsFromStorage();
exportToFile(JSON.stringify(stats, null, 2), `${filePrefix}-${timeForFileName()}.json`);
}

async getStatsFromStorage() {
const { stats }: { stats: Statistics } = await this.Class.Config.getLocalStorage({ stats: { words: {} } }) as any;
return stats;
Expand Down Expand Up @@ -792,6 +802,28 @@ export default class OptionPage {
}
}

importStats() {
const fileImportInput = document.getElementById('statsImportInput') as HTMLInputElement;
fileImportInput.click();
}

async importStatsFile(input: HTMLInputElement, files: FileList) {
const backupStats = await this.getStatsFromStorage();

try {
const file = files[0];
const fileText = await readFile(file) as string;
const stats = JSON.parse(fileText);
if (!this.validStatsForImport(stats)) throw new Error('Invalid stats file.');
await this.Class.Config.saveLocalStorage({ stats: stats });
input.value = '';
await this.populateStats();
} catch (err) {
await this.Class.Config.saveLocalStorage({ stats: backupStats });
this.Class.handleError('Failed to import stats.', err);
}
}

async init(refreshTheme = false) {
await this.initializeCfg();
logger.setLevel(this.cfg.loggingLevel);
Expand Down Expand Up @@ -1829,6 +1861,10 @@ export default class OptionPage {
return valid;
}

validStatsForImport(stats) {
return stats && stats?.startedAt > 1 && stats.words[Object.keys(stats.words)[0]].text >= 0;
}

wordlistTypeFromElement(element: HTMLSelectElement) {
if (element.id === 'textWordlistSelect') return 'wordlistId';
}
Expand Down
7 changes: 6 additions & 1 deletion src/static/optionPage.html
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,12 @@ <h4 class="sectionHeader">Stats</h4>
<span class="notes">(Only stored locally)</span>
</label>

<button id="statsReset" class="w3-btn w3-round-large w3-flat-pomegranate w3-right">RESET STATS</button>
<div class="w3-right">
<input type="file" id="statsImportInput" accept=".json" style="display:none"/>
<button id="statsExport" class="w3-btn w3-round-large w3-flat-peter-river">EXPORT</button>
<button id="statsImport" class="w3-btn w3-round-large w3-flat-peter-river">IMPORT</button>
<button id="statsReset" class="w3-btn w3-round-large w3-flat-pomegranate">RESET</button>
</div>

<h4 class="sectionHeader">Summary</h4>
<div id="statsSummaryContainer">
Expand Down

0 comments on commit f53e47b

Please sign in to comment.