platypush-webext/src/options/Config.vue

169 lines
4.0 KiB
Vue

<template>
<div class="page backup">
<h2>Extension Configuration</h2>
<div class="container">
<form class="loader" ref="loader" @submit.prevent="loadURL">
<div class="head">
Load configuration
<input type="radio" id="_file" value="file" v-model="extConfigType" />
<label for="_file">From file</label>
<input type="radio" id="_url" value="url" v-model="extConfigType" />
<label for="_file">From URL</label>
</div>
<div class="body">
<input type="file" name="file" placeholder="Configuration file" accept="application/json, text/x-json, text/plain" @change="uploadFile" v-if="extConfigType === 'file'" />
<input type="text" name="url" placeholder="Configuration URL" v-model="extURL" v-if="extConfigType === 'url'" />
<input type="submit" value="Load" v-if="extConfigType === 'url'" />
</div>
</form>
<form class="content" ref="content" @submit.prevent="save">
<div class="textarea">
<textarea name="text" ref="text" v-model="config" v-text="loading ? 'Loading...' : config" @focus="onFocus" :disabled="loading" />
</div>
<div class="buttons">
<button type="button" :disabled="savedConfig === config" @click="reload"><i class="fas fa-undo" /> &nbsp; Undo</button>
<button type="submit" :disabled="savedConfig === config"><i class="fas fa-save" /> &nbsp; Save</button>
</div>
</form>
</div>
</div>
</template>
<script>
import axios from 'axios';
import mixins from '../utils';
export default {
name: 'Backup',
mixins: [mixins],
data() {
return {
config: null,
savedConfig: null,
extConfigType: 'file',
extURL: null,
};
},
methods: {
onFocus(event) {
event.target.select();
document.execCommand('copy');
event.target.selectionStart = event.target.selectionEnd = 0;
this.notify('Configuration copied to the clipboard');
},
async reload() {
const config = await this.loadConfig();
this.config = JSON.stringify(config, null, ' ');
this.savedConfig = this.config;
},
async save(event) {
this.loading = true;
try {
const config = JSON.parse(event.target.text.value);
await this.saveConfig(config);
await this.reload();
this.$emit('reload');
} catch (e) {
console.warn(e);
this.notify(e.message, 'Could not save the configuration');
} finally {
this.loading = false;
}
},
uploadFile(event) {
if (!(event.target.files && event.target.files.length)) {
return;
}
const self = this;
const reader = new FileReader();
this.loading = true;
reader.onload = evt => {
self.config = evt.target.result;
self.loading = false;
};
reader.onerror = evt => {
this.notify(reader.error, 'Could not read the file');
self.loading = false;
};
reader.readAsText(event.target.files[0]);
},
async loadURL(event) {
const url = event.target.url.value.trim();
this.loading = true;
try {
const response = await axios.get(url);
this.config = JSON.stringify(response.data, null, ' ');
} catch (e) {
console.warn(e);
this.notify(e.message, 'Unable to parse the URL');
} finally {
this.loading = false;
}
},
},
created() {
this.reload();
},
};
</script>
<style lang="scss" scoped>
textarea,
.loader {
width: 60%;
min-width: 30em;
max-width: 50em;
}
textarea {
height: 50em;
max-height: 80vh;
overflow: auto;
}
.loader {
margin-bottom: 1em;
.head {
margin-bottom: 1em;
}
.body {
display: flex;
align-items: center;
position: relative;
}
[type='text'] {
width: 80%;
min-width: 10em;
max-width: 40em;
margin: 0;
}
[type='submit'] {
position: absolute;
right: 0;
}
}
</style>
<!-- vim:sw=2:ts=2:et: -->