🎨 Update to read + write conf from store

This commit is contained in:
Alicia Sykes 2021-10-27 23:33:31 +01:00
parent 06dd8ed525
commit 618ab1c439

View File

@ -1,5 +1,6 @@
<template> <template>
<div class="cloud-backup-restore-wrapper"> <div class="cloud-backup-restore-wrapper">
<!-- Intro text -->
<div class="section intro"> <div class="section intro">
<h2>{{ $t('cloud-sync.title') }}</h2> <h2>{{ $t('cloud-sync.title') }}</h2>
<p class="intro"> <p class="intro">
@ -11,6 +12,7 @@
<a href="https://github.com/Lissy93/dashy/blob/master/docs/backup-restore.md">docs</a> <a href="https://github.com/Lissy93/dashy/blob/master/docs/backup-restore.md">docs</a>
</p> </p>
</div> </div>
<!-- Create or update a backup form -->
<div class="section backup-section"> <div class="section backup-section">
<h3 v-if="backupId">{{ $t('cloud-sync.backup-title-setup') }}</h3> <h3 v-if="backupId">{{ $t('cloud-sync.backup-title-setup') }}</h3>
<h3 v-else>{{ $t('cloud-sync.backup-title-setup') }}</h3> <h3 v-else>{{ $t('cloud-sync.backup-title-setup') }}</h3>
@ -23,11 +25,9 @@
type="password" type="password"
/> />
<Button :click="checkPass"> <Button :click="checkPass">
<template v-slot:text>
{{backupId {{backupId
? $t('cloud-sync.backup-button-update') : $t('cloud-sync.backup-button-setup')}} ? $t('cloud-sync.backup-button-update') : $t('cloud-sync.backup-button-setup')}}
</template> <IconBackup />
<template v-slot:icon><IconBackup /></template>
</Button> </Button>
<div class="results-view" v-if="backupId"> <div class="results-view" v-if="backupId">
<span class="backup-id-label">{{ $t('cloud-sync.backup-id-label') }}: </span> <span class="backup-id-label">{{ $t('cloud-sync.backup-id-label') }}: </span>
@ -35,6 +35,7 @@
<span class="backup-id-note">{{ $t('cloud-sync.backup-id-note') }}</span> <span class="backup-id-note">{{ $t('cloud-sync.backup-id-note') }}</span>
</div> </div>
</div> </div>
<!-- Restore from backup form -->
<div class="section restore-section"> <div class="section restore-section">
<h3>{{ $t('cloud-sync.restore-title') }}</h3> <h3>{{ $t('cloud-sync.restore-title') }}</h3>
<Input <Input
@ -49,32 +50,38 @@
type="password" type="password"
/> />
<Button :click="restoreBackup"> <Button :click="restoreBackup">
<template v-slot:text>{{ $t('cloud-sync.restore-button') }}</template> {{ $t('cloud-sync.restore-button') }}
<template v-slot:icon><IconRestore /></template> <IconRestore />
</Button> </Button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
// Import libraries
import sha256 from 'crypto-js/sha256'; import sha256 from 'crypto-js/sha256';
import ProgressBar from 'rsup-progress'; import ProgressBar from 'rsup-progress';
// Import form elements
import Button from '@/components/FormElements/Button'; import Button from '@/components/FormElements/Button';
import Input from '@/components/FormElements/Input'; import Input from '@/components/FormElements/Input';
import IconBackup from '@/assets/interface-icons/config-backup.svg'; // Import utils and constants
import IconRestore from '@/assets/interface-icons/config-restore.svg'; import StoreKeys from '@/utils/StoreMutations';
import { backup, update, restore } from '@/utils/CloudBackup'; import { backup, update, restore } from '@/utils/CloudBackup';
import { localStorageKeys } from '@/utils/defaults'; import { localStorageKeys } from '@/utils/defaults';
import { InfoHandler, WarningInfoHandler } from '@/utils/ErrorHandler'; import { InfoHandler, WarningInfoHandler } from '@/utils/ErrorHandler';
// Import Icons
import IconBackup from '@/assets/interface-icons/config-backup.svg';
import IconRestore from '@/assets/interface-icons/config-restore.svg';
export default { export default {
name: 'CloudBackupRestore', name: 'CloudBackupRestore',
props: { computed: {
config: Object, config() { // Users config from store
return this.$store.state.config;
},
}, },
data() { data() {
return { return { // Store current form data (temp)
backupPassword: '', backupPassword: '',
restorePassword: '', restorePassword: '',
restoreCode: '', restoreCode: '',
@ -82,36 +89,26 @@ export default {
progress: new ProgressBar({ color: 'var(--progress-bar)' }), progress: new ProgressBar({ color: 'var(--progress-bar)' }),
}; };
}, },
components: { components: { // UI components / icons
Button, Button,
Input, Input,
IconBackup, IconBackup,
IconRestore, IconRestore,
}, },
methods: { methods: {
/* Make request to server-side, then either show error, or proceed to restore */
restoreBackup() { restoreBackup() {
this.progress.start(); this.progress.start();
restore(this.restoreCode, this.restorePassword) restore(this.restoreCode, this.restorePassword)
.then((response) => { .then((response) => {
this.restoreFromBackup(response, this.restoreCode); this.applyRestoredData(response, this.restoreCode);
this.progress.end(); this.progress.end();
}).catch((msg) => { }).catch((msg) => {
this.showErrorMsg(msg); this.showErrorMsg(msg);
this.progress.end(); this.progress.end();
}); });
}, },
checkPass() { /* Send request to backup server, to upload a new backup */
const savedHash = localStorage[localStorageKeys.BACKUP_HASH] || undefined;
if (!this.backupPassword) {
this.showErrorMsg(this.$t('cloud-sync.backup-missing-password'));
} else if (!savedHash) {
this.makeBackup();
} else if (savedHash === this.makeHash(this.backupPassword)) {
this.makeUpdate();
} else {
this.showErrorMsg(this.$t('cloud-sync.backup-error-password'));
}
},
makeBackup() { makeBackup() {
this.progress.start(); this.progress.start();
backup(this.config, this.backupPassword) backup(this.config, this.backupPassword)
@ -127,6 +124,7 @@ export default {
this.progress.end(); this.progress.end();
}); });
}, },
/* Send request to backup server, to update an existing backup */
makeUpdate() { makeUpdate() {
this.progress.start(); this.progress.start();
update(this.config, this.backupPassword, this.backupId) update(this.config, this.backupPassword, this.backupId)
@ -142,17 +140,36 @@ export default {
this.progress.end(); this.progress.end();
}); });
}, },
restoreFromBackup(config, backupId) { /* For create / update a backup- checks pass is valid, then calls makeBackup */
checkPass() {
const savedHash = localStorage[localStorageKeys.BACKUP_HASH] || undefined;
if (!this.backupPassword) {
this.showErrorMsg(this.$t('cloud-sync.backup-missing-password'));
} else if (!savedHash) {
this.makeBackup();
} else if (savedHash === this.makeHash(this.backupPassword)) {
this.makeUpdate();
} else {
this.showErrorMsg(this.$t('cloud-sync.backup-error-password'));
}
},
/* When restored data is revieved, then save to local storage, and apply it in state */
applyRestoredData(config, backupId) {
// Store restored data in local storage
localStorage.setItem(localStorageKeys.CONF_SECTIONS, JSON.stringify(config.sections)); localStorage.setItem(localStorageKeys.CONF_SECTIONS, JSON.stringify(config.sections));
localStorage.setItem(localStorageKeys.APP_CONFIG, JSON.stringify(config.appConfig)); localStorage.setItem(localStorageKeys.APP_CONFIG, JSON.stringify(config.appConfig));
localStorage.setItem(localStorageKeys.PAGE_INFO, JSON.stringify(config.pageInfo)); localStorage.setItem(localStorageKeys.PAGE_INFO, JSON.stringify(config.pageInfo));
if (config.appConfig.theme) { if (config.appConfig.theme) {
localStorage.setItem(localStorageKeys.THEME, config.appConfig.theme); localStorage.setItem(localStorageKeys.THEME, config.appConfig.theme);
} }
// Save hashed token in local storage
this.setBackupIdLocally(backupId, this.restorePassword); this.setBackupIdLocally(backupId, this.restorePassword);
// Update the current state
this.$store.commit(StoreKeys.SET_CONFIG, config);
// Show success message
this.showSuccessMsg(this.$t('cloud-sync.restore-success-msg')); this.showSuccessMsg(this.$t('cloud-sync.restore-success-msg'));
setTimeout(() => { location.reload(); }, 1500); // eslint-disable-line no-restricted-globals
}, },
/* After backup/ update is made, then replace 'Make Backup' with 'Update Backup' */
updateUiAfterBackup(backupId, isUpdate = false) { updateUiAfterBackup(backupId, isUpdate = false) {
this.setBackupIdLocally(backupId, this.backupPassword); this.setBackupIdLocally(backupId, this.backupPassword);
this.showSuccessMsg( this.showSuccessMsg(
@ -160,17 +177,21 @@ export default {
); );
this.backupPassword = ''; this.backupPassword = '';
}, },
/* If the server returns a warning, then show to user and log it */
showErrorMsg(errorMsg) { showErrorMsg(errorMsg) {
WarningInfoHandler(errorMsg, 'Cloud Backup'); WarningInfoHandler(errorMsg, 'Cloud Backup');
this.$toasted.show(errorMsg, { className: 'toast-error' }); this.$toasted.show(errorMsg, { className: 'toast-error' });
}, },
/* When server returns success message, then show to user and log it */
showSuccessMsg(msg) { showSuccessMsg(msg) {
InfoHandler(msg, 'Cloud Backup'); InfoHandler(msg, 'Cloud Backup');
this.$toasted.show(msg, { className: 'toast-success' }); this.$toasted.show(msg, { className: 'toast-success' });
}, },
/* Call to hash function, to hash the users chosen/ entered password */
makeHash(pass) { makeHash(pass) {
return sha256(pass).toString(); return sha256(pass).toString();
}, },
/* After backup is applied, hash the backup ID, and save in browser storage */
setBackupIdLocally(backupId, pass) { setBackupIdLocally(backupId, pass) {
this.backupId = backupId; this.backupId = backupId;
const hash = this.makeHash(pass); const hash = this.makeHash(pass);
@ -185,49 +206,48 @@ export default {
@import '@/styles/style-helpers.scss'; @import '@/styles/style-helpers.scss';
div.cloud-backup-restore-wrapper { div.cloud-backup-restore-wrapper {
display: flex; display: flex;
flex-direction: row;
flex-wrap: wrap; flex-wrap: wrap;
flex-direction: row;
text-align: center; text-align: center;
overflow: auto; overflow: auto;
height: 100%; height: 100%;
background: var(--config-settings-background); color: var(--cloud-backup-color);
color: var(--config-settings-color); background: var(--cloud-backup-background);
@extend .scroll-bar; @extend .scroll-bar;
.section { /* Text styling */
display: flex; h2, h3 { font-size: 1.6rem; }
flex-direction: column;
width: fit-content;
margin: 0 auto 1rem auto;
padding: 0 0.5rem 1rem 0.5rem;
&:first-child {
border-bottom: 1px dashed var(--config-settings-color);
}
&.intro {
width: 100%;
height: fit-content;
a {
color: var(--config-settings-color);
}
}
}
h2 { font-size: 2rem; }
h3 { font-size: 1.6rem; }
p.intro { p.intro {
text-align: left; text-align: left;
font-size: 1rem; font-size: 1rem;
margin: 0.25rem; margin: 0.25rem;
padding: 0.25rem; padding: 0.25rem;
} }
/* Main sections */
.section {
display: flex;
flex-direction: column;
width: fit-content;
margin: 0 auto 1rem auto;
padding: 0 0.5rem 1rem 0.5rem;
}
/* Intro section */
.section.intro {
width: 100%;
height: fit-content;
border-bottom: 1px dashed var(--cloud-backup-color);
a { color: var(--cloud-backup-color); }
}
} }
/* Container to show backup ID result from server */
div.results-view { div.results-view {
width: 16rem; width: 16rem;
margin: 0.5rem auto; margin: 0.5rem auto;
padding: 0.5rem 0.75rem; padding: 0.5rem 0.75rem;
box-sizing: border-box; box-sizing: border-box;
border: 1px dashed var(--config-settings-color); border: 1px dashed var(--cloud-backup-color);
border-radius: var(--curve-factor); border-radius: var(--curve-factor);
text-align: left; text-align: left;
.backup-id-label, .backup-id-value { .backup-id-label, .backup-id-value {
@ -245,21 +265,18 @@ export default {
/* Overide form element colors, so that config menu can be themed by user */ /* Overide form element colors, so that config menu can be themed by user */
input, button { input, button {
color: var(--config-settings-color); color: var(--cloud-backup-color);
border: 1px solid var(--config-settings-color); border: 1px solid var(--cloud-backup-color);
background: none; background: none;
width: 16rem; width: 16rem;
} }
input:focus { input:focus {
box-shadow: 1px 1px 6px var(--config-settings-color); box-shadow: 1px 1px 6px var(--cloud-backup-color);
} }
button:hover { button:hover {
color: var(--config-settings-background); color: var(--cloud-backup-background);
border: 1px solid var(--config-settings-background); border: 1px solid var(--cloud-backup-background);
background: var(--config-settings-color); background: var(--cloud-backup-color);
}
h2, h3 {
margin: 1rem;
} }
</style> </style>