changed importexport into a service instead of component for simplicity

This commit is contained in:
Henry Jameson 2021-03-08 19:42:24 +02:00
parent 4baa397ed0
commit bd5b62b107
4 changed files with 112 additions and 142 deletions

View file

@ -1,102 +0,0 @@
<template>
<div class="import-export-container">
<slot name="before" />
<button
class="btn button-default"
@click="exportData"
>
{{ exportLabel }}
</button>
<button
class="btn button-default"
@click="importData"
>
{{ importLabel }}
</button>
<slot name="afterButtons" />
<p
v-if="importFailed"
class="alert error"
>
{{ importFailedText }}
</p>
<slot name="afterError" />
</div>
</template>
<script>
export default {
props: [
'exportObject',
'importLabel',
'exportLabel',
'importFailedText',
'validator',
'onImport',
'onImportFailure'
],
data () {
return {
importFailed: false
}
},
methods: {
exportData () {
const stringified = JSON.stringify(this.exportObject, null, 2) // Pretty-print and indent with 2 spaces
// Create an invisible link with a data url and simulate a click
const e = document.createElement('a')
e.setAttribute('download', 'pleroma_theme.json')
e.setAttribute('href', 'data:application/json;base64,' + window.btoa(stringified))
e.style.display = 'none'
document.body.appendChild(e)
e.click()
document.body.removeChild(e)
},
importData () {
this.importFailed = false
const filePicker = document.createElement('input')
filePicker.setAttribute('type', 'file')
filePicker.setAttribute('accept', '.json')
filePicker.addEventListener('change', event => {
if (event.target.files[0]) {
// eslint-disable-next-line no-undef
const reader = new FileReader()
reader.onload = ({ target }) => {
try {
const parsed = JSON.parse(target.result)
const valid = this.validator(parsed)
if (valid) {
this.onImport(parsed)
} else {
this.importFailed = true
// this.onImportFailure(valid)
}
} catch (e) {
// This will happen both if there is a JSON syntax error or the theme is missing components
this.importFailed = true
// this.onImportFailure(e)
}
}
reader.readAsText(event.target.files[0])
}
})
document.body.appendChild(filePicker)
filePicker.click()
document.body.removeChild(filePicker)
}
}
}
</script>
<style lang="scss">
.import-export-container {
display: flex;
flex-wrap: wrap;
align-items: baseline;
justify-content: center;
}
</style>

View file

@ -15,6 +15,10 @@ import {
shadows2to3, shadows2to3,
colors2to3 colors2to3
} from 'src/services/style_setter/style_setter.js' } from 'src/services/style_setter/style_setter.js'
import {
newImporter,
newExporter
} from 'src/services/export_import/export_import.js'
import { import {
SLOT_INHERITANCE SLOT_INHERITANCE
} from 'src/services/theme_data/pleromafe.js' } from 'src/services/theme_data/pleromafe.js'
@ -31,7 +35,6 @@ import ShadowControl from 'src/components/shadow_control/shadow_control.vue'
import FontControl from 'src/components/font_control/font_control.vue' import FontControl from 'src/components/font_control/font_control.vue'
import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue' import ContrastRatio from 'src/components/contrast_ratio/contrast_ratio.vue'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js' import TabSwitcher from 'src/components/tab_switcher/tab_switcher.js'
import ExportImport from 'src/components/export_import/export_import.vue'
import Checkbox from 'src/components/checkbox/checkbox.vue' import Checkbox from 'src/components/checkbox/checkbox.vue'
import Preview from './preview.vue' import Preview from './preview.vue'
@ -67,6 +70,15 @@ const colorConvert = (color) => {
export default { export default {
data () { data () {
return { return {
themeImporter: newImporter({
validator: this.importValidator,
onImport: this.onImport,
onImportFailure: this.onImportFailure
}),
themeExporter: newExporter({
filename: 'pleroma_theme',
getExportedObject: () => this.exportedTheme
}),
availableStyles: [], availableStyles: [],
selected: this.$store.getters.mergedConfig.theme, selected: this.$store.getters.mergedConfig.theme,
themeWarning: undefined, themeWarning: undefined,
@ -383,7 +395,6 @@ export default {
FontControl, FontControl,
TabSwitcher, TabSwitcher,
Preview, Preview,
ExportImport,
Checkbox Checkbox
}, },
methods: { methods: {
@ -528,10 +539,15 @@ export default {
this.previewColors.mod this.previewColors.mod
) )
}, },
importTheme () { this.themeImporter.importData() },
exportTheme () { this.themeExporter.exportData() },
onImport (parsed, forceSource = false) { onImport (parsed, forceSource = false) {
this.tempImportFile = parsed this.tempImportFile = parsed
this.loadTheme(parsed, 'file', forceSource) this.loadTheme(parsed, 'file', forceSource)
}, },
onImportFailure (result) {
this.$store.dispatch('pushGlobalNotice', { messageKey: 'settings.invalid_theme_imported', level: 'error' })
},
importValidator (parsed) { importValidator (parsed) {
const version = parsed._pleroma_theme_version const version = parsed._pleroma_theme_version
return version >= 1 || version <= 2 return version >= 1 || version <= 2

View file

@ -48,46 +48,45 @@
</template> </template>
</div> </div>
</div> </div>
<ExportImport <div class="top">
:export-object="exportedTheme" <div class="presets">
:export-label="$t(&quot;settings.export_theme&quot;)" {{ $t('settings.presets') }}
:import-label="$t(&quot;settings.import_theme&quot;)" <label
:import-failed-text="$t(&quot;settings.invalid_theme_imported&quot;)" for="preset-switcher"
:on-import="onImport" class="select"
:validator="importValidator" >
> <select
<template slot="before"> id="preset-switcher"
<div class="presets"> v-model="selected"
{{ $t('settings.presets') }} class="preset-switcher"
<label
for="preset-switcher"
class="select"
> >
<select <option
id="preset-switcher" v-for="style in availableStyles"
v-model="selected" :key="style.name"
class="preset-switcher" :value="style"
:style="{
backgroundColor: style[1] || (style.theme || style.source).colors.bg,
color: style[3] || (style.theme || style.source).colors.text
}"
> >
<option {{ style[0] || style.name }}
v-for="style in availableStyles" </option>
:key="style.name" </select>
:value="style" <FAIcon
:style="{ class="select-down-icon"
backgroundColor: style[1] || (style.theme || style.source).colors.bg, icon="chevron-down"
color: style[3] || (style.theme || style.source).colors.text />
}" </label>
> </div>
{{ style[0] || style.name }} <div class="export-import">
</option> <button class="btn button-default" @click="importTheme">
</select> {{ $t(&quot;settings.import_theme&quot;) }}
<FAIcon </button>
class="select-down-icon" <button class="btn button-default" @click="exportTheme">
icon="chevron-down" {{ $t(&quot;settings.export_theme&quot;) }}
/> </button>
</label> </div>
</div> </div>
</template>
</ExportImport>
</div> </div>
<div class="save-load-options"> <div class="save-load-options">
<span class="keep-option"> <span class="keep-option">

View file

@ -0,0 +1,57 @@
export const newExporter = ({
filename = 'data',
getExportedObject
}) => ({
exportData () {
const stringified = JSON.stringify(getExportedObject(), null, 2) // Pretty-print and indent with 2 spaces
// Create an invisible link with a data url and simulate a click
const e = document.createElement('a')
e.setAttribute('download', `${filename}.json`)
e.setAttribute('href', 'data:application/json;base64,' + window.btoa(stringified))
e.style.display = 'none'
document.body.appendChild(e)
e.click()
document.body.removeChild(e)
}
})
export const newImporter = ({
onImport,
onImportFailure,
validator = () => true
}) => ({
importData () {
const filePicker = document.createElement('input')
filePicker.setAttribute('type', 'file')
filePicker.setAttribute('accept', '.json')
console.log(1)
filePicker.addEventListener('change', event => {
if (event.target.files[0]) {
// eslint-disable-next-line no-undef
const reader = new FileReader()
reader.onload = ({ target }) => {
try {
const parsed = JSON.parse(target.result)
const validationResult = validator(parsed)
if (validationResult === true) {
onImport(parsed)
} else {
onImportFailure({ validationResult })
}
} catch (error) {
onImportFailure({ error })
}
}
console.log(2)
reader.readAsText(event.target.files[0])
}
})
document.body.appendChild(filePicker)
filePicker.click()
document.body.removeChild(filePicker)
}
})