#31 improve setup wizard base

pull/1/head
Thomas Ballmann 4 years ago
parent 94339ea160
commit 1ad74f7664

@ -0,0 +1,83 @@
<template>
<v-container
class="_fill-height"
fluid
>
<div v-if="back">
<v-btn
text
color="primary"
class="px-0"
@click="$emit('back')"
>
<v-icon>$prev</v-icon>
Back
</v-btn>
</div>
<v-row
no-gutters
justify="center"
>
<v-col
lg="5"
md="6"
sm="8"
>
<v-card flat>
<div
v-if="hasIconSlot"
class="justify-center text-center"
>
<v-icon
class="my-icon ma-10"
>
<slot name="icon" />
</v-icon>
</div>
<v-card-title
class="display-1 font-weight-bold mb-12 px-0 justify-center text-center"
>
<slot name="headline" />
</v-card-title>
</v-card>
<slot />
<v-card-actions
v-if="hasActionsSlot"
class="flex-column mt-16"
>
<slot name="actions" />
</v-card-actions>
</v-col>
</v-row>
</v-container>
</template>
<script>
export default {
name: 'SetupPanel',
props: {
back: {
type: Boolean,
default: false,
},
},
computed: {
hasIconSlot () {
return !!this.$slots.icon
},
hasActionsSlot () {
return !!this.$slots.actions
},
},
}
</script>
<style scoped>
>>> .my-icon > .v-icon__svg {
transform: scale(3);
}
</style>

@ -1,81 +1,90 @@
<template> <template>
<v-container <setup-panel
class="_fill-height" back
fluid @back="stepBack"
> >
<v-row <template #icon />
no-gutters <template #headline>
justify="center" Appearance
> </template>
<v-col
lg="5"
md="6"
sm="8"
>
<v-card flat>
<v-card-title class="display-2 mb-12 justify-center text-center">
Appearance
</v-card-title>
<v-radio-group <v-radio-group
v-model="settings.device.theme" v-model="form.theme"
row row
> >
<v-radio <v-radio
label="Light" label="Light"
value="white" value="white"
/> />
<v-radio <v-radio
label="Dark" label="Dark"
value="black" value="black"
/> />
</v-radio-group> </v-radio-group>
<v-card-actions> <template #actions>
<v-btn <v-btn
depressed depressed
block block
color="primary" color="primary"
@click="commitStep()" @click="commitStep()"
> >
Continue Continue
</v-btn> </v-btn>
</v-card-actions> </template>
</v-card> </setup-panel>
</v-col>
</v-row>
</v-container>
</template> </template>
<script> <script>
import apiDevice from '@/api/device' import { mapState, mapMutations, mapActions } from 'vuex'
import SetupPanel from '@/components/SetupPanel'
export default { export default {
components: { SetupPanel },
data: () => ({ data: () => ({
isLoading: true, isProcessing: false,
isSaving: false, form: {
settings: null, theme: '',
},
}), }),
computed: {
...mapState([
'settings',
]),
},
created () { created () {
apiDevice.getSettings(settings => { this.resetChanges()
this.settings = settings
this.isLoading = false
})
}, },
methods: { methods: {
...mapMutations(['updateSettings']),
...mapActions(['saveSettings']),
commitStep () { commitStep () {
this.isSaving = true this.isProcessing = true
apiDevice.putSettings({ device: this.settings.device }, () => { this.updateSettings({
this.isSaving = false device: {
theme: this.form.theme,
},
})
/*
this.saveSettings().then(() => {
this.nextStep() this.nextStep()
}) })
*/
this.nextStep()
},
resetChanges () {
this.form.theme = this.settings.device.theme
}, },
nextStep () { nextStep () {
this.$router.push('/setup/done') this.$router.push('/setup/done')
}, },
stepBack () {
this.$router.push('/setup/weather')
},
}, },
} }
</script> </script>

@ -3,6 +3,18 @@
class="_fill-height" class="_fill-height"
fluid fluid
> >
<div>
<v-btn
text
color="primary"
class="px-0"
@click="stepBack"
>
<v-icon>$prev</v-icon>
Back
</v-btn>
</div>
<v-row <v-row
no-gutters no-gutters
justify="center" justify="center"
@ -16,18 +28,18 @@
<!-- country --> <!-- country -->
<v-card flat> <v-card flat>
<v-card-title <v-card-title
class="display-2 mb-12 justify-center text-center" class="display-1 font-weight-bold mb-12 px-0 justify-center text-center"
> >
Select Your Country or Region Select Your Country or Region
</v-card-title> </v-card-title>
<v-list class="ml-5 pa-0"> <v-list class="pa-0">
<template v-for="(country, code) in availableCountries"> <template v-for="(country, code) in availableCountries">
<div :key="code"> <div :key="code">
<v-divider /> <v-divider />
<v-list-item <v-list-item
class="pl-1" class="px-0"
@click="commitCountry(code, country)" @click="commitCountry(code, country)"
> >
<!--<v-list-item-icon>{{ country.emoji }}</v-list-item-icon>--> <!--<v-list-item-icon>{{ country.emoji }}</v-list-item-icon>-->
@ -46,17 +58,17 @@
<template v-else-if="currentStep === 1"> <template v-else-if="currentStep === 1">
<!-- timezone if needed --> <!-- timezone if needed -->
<v-card flat> <v-card flat>
<v-card-title class="display-2 mb-12 justify-center text-center"> <v-card-title class="display-1 font-weight-bold mb-12 px-0 justify-center text-center">
Select Your Timezone Select Your Timezone
</v-card-title> </v-card-title>
<v-list class="ml-5 pa-0"> <v-list class="pa-0">
<template v-for="(zone, i) in availableTimeZones"> <template v-for="(zone, i) in availableTimeZones">
<div :key="i"> <div :key="i">
<v-divider /> <v-divider />
<v-list-item <v-list-item
class="pl-1" class="px-0"
@click="commitTimezone(zone)" @click="commitTimezone(zone)"
> >
<v-list-item-content>{{ zone }}</v-list-item-content> <v-list-item-content>{{ zone }}</v-list-item-content>
@ -133,6 +145,9 @@
this.$router.push('/setup/wifi') this.$router.push('/setup/wifi')
}) })
}, },
stepBack () {
this.$router.push('/setup/start')
},
}, },
} }
</script> </script>

@ -1,52 +1,48 @@
<template> <template>
<v-container <setup-panel
class="_fill-height" back
fluid @back="stepBack"
> >
<v-card <template #headline>
flat Hello {{ settings.device.name }}
class="mx-auto" </template>
width="540"
>
<!--<v-card-title class="display-2 mb-12 justify-center text-center">Welcome to paperdash</v-card-title>-->
<v-card-title class="display-2 mb-12 justify-center text-center">
Hello {{ settings.device.name }}
</v-card-title>
<v-card-actions> <template #actions>
<v-btn <v-btn
outlined outlined
block block
color="primary" color="primary"
@click="onStart" @click="onStart"
> >
Let's start Let's start
</v-btn> </v-btn>
</v-card-actions> </template>
</v-card> </setup-panel>
</v-container>
</template> </template>
<script> <script>
import apiDevice from '@/api/device' import { mapState } from 'vuex'
import SetupPanel from '@/components/SetupPanel'
export default { export default {
components: { SetupPanel },
data: () => ({ data: () => ({
isLoading: true,
isSaving: false,
settings: null,
}), }),
computed: {
...mapState([
'settings',
]),
},
created () { created () {
apiDevice.getSettings(settings => {
this.settings = settings
this.isLoading = false
})
}, },
methods: { methods: {
onStart () { onStart () {
this.$router.push('/') this.$router.push('/')
}, },
stepBack () {
this.$router.push('/setup/appearance')
},
}, },
} }
</script> </script>

@ -1,125 +1,116 @@
<template> <template>
<v-container <setup-panel
class="_fill-height" back
fluid @back="stepBack"
> >
<v-row <template #icon>
no-gutters $face
justify="center" </template>
<template #headline>
Give it a name
</template>
<p
class="text-center"
> >
<v-col TODO:Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam
lg="5" </p>
md="6"
sm="8"
>
<v-card flat>
<div class="justify-center text-center">
<v-icon
view-box="0 0 24 24"
style="width: 64px; height: 64px; fill: #FF9800"
>
$face
</v-icon>
</div>
<v-card-title class="display-2 mb-12 justify-center text-center">
Give it a name
</v-card-title>
<p <v-card-text>
class="text-center" <v-text-field
v-model="form.name"
label="Name of the device"
>
<template #append-outer>
<v-icon
class="random-icon mt-5 ml-5"
@click="setRandomName()"
> >
TODO:Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam $autorenew
</p> </v-icon>
</template>
<v-skeleton-loader </v-text-field>
v-if="isLoading" </v-card-text>
type="list-item-two-line"
class="mx-auto"
/>
<template v-else> <template #actions>
<v-card-text> <v-btn
<v-text-field :disabled="!isStepValid"
v-model="settings.device.name" depressed
label="i8n:My paperdash name" block
> color="primary"
<template #append-outer> @click="commitStep()"
<v-icon >
view-box="0 0 24 24" Continue
style="width: 48px; height: 48px;" </v-btn>
@click="setRandomeName()" </template>
> </setup-panel>
$autorenew
</v-icon>
</template>
</v-text-field>
</v-card-text>
<v-card-actions class="flex-column">
<v-btn
:disabled="!isStepValid"
:loading="isSaving"
depressed
block
color="primary"
@click="commitStep()"
>
Continue
</v-btn>
</v-card-actions>
</template>
</v-card>
</v-col>
</v-row>
</v-container>
</template> </template>
<script> <script>
import apiDevice from '@/api/device' import { mapState, mapMutations, mapActions } from 'vuex'
import randomNames from '@/assets/fantasyNames.json' import randomNames from '@/assets/fantasyNames.json'
import SetupPanel from '@/components/SetupPanel'
export default { export default {
components: { SetupPanel },
data: () => ({ data: () => ({
isLoading: true, isProcessing: false,
isSaving: false, form: {
settings: null, name: '',
},
}), }),
computed: { computed: {
...mapState([
'settings',
]),
isStepValid () { isStepValid () {
return ( return (
this.settings.device.name !== undefined && this.form.name !== ''
this.settings.device.name !== ''
) )
}, },
}, },
created () { created () {
apiDevice.getSettings(settings => { this.resetChanges()
this.settings = settings
if (!this.isStepValid) { if (!this.isStepValid) {
this.setRandomeName() this.setRandomName()
} }
this.isLoading = false
})
}, },
methods: { methods: {
...mapMutations(['updateSettings']),
...mapActions(['saveSettings']),
commitStep () { commitStep () {
this.isSaving = true this.isProcessing = true
apiDevice.putSettings({ device: this.settings.device }, () => { this.updateSettings({
this.isSaving = false device: {
name: this.form.name,
},
})
/*
this.saveSettings().then(() => {
this.nextStep() this.nextStep()
}) })
*/
this.nextStep()
},
resetChanges () {
this.form.name = this.settings.device.name
}, },
nextStep () { nextStep () {
this.$router.push('/setup/appearance') this.$router.push('/setup/appearance')
}, },
setRandomeName () { setRandomName () {
this.settings.device.name = this.form.name =
randomNames[Math.floor(Math.random() * randomNames.length)] randomNames[Math.floor(Math.random() * randomNames.length)]
}, },
stepBack () {
this.$router.push('/setup/weather')
},
}, },
} }
</script> </script>
@ -129,4 +120,8 @@
font-size: 2.2em; font-size: 2.2em;
max-height: inherit; max-height: inherit;
} }
>>> .random-icon > .v-icon__svg {
transform: scale(2);
}
</style> </style>

@ -1,7 +1,6 @@
<template> <template>
<v-container <v-container
class="_fill-height" class="_fill-height fluid_"
fluid
> >
<v-row <v-row
no-gutters no-gutters
@ -13,7 +12,7 @@
sm="8" sm="8"
> >
<v-card flat> <v-card flat>
<v-card-title class="display-2 mt-12 justify-center text-center"> <v-card-title class="display-1 font-weight-bold mb-12 px-0 justify-center text-center">
Hello paperdash Hello paperdash
</v-card-title> </v-card-title>
@ -23,45 +22,48 @@
:class="[device.theme, device.case, device.front, 'case_orange', 'my-12']" :class="[device.theme, device.case, device.front, 'case_orange', 'my-12']"
/> />
<svg <v-responsive>
id="device" <svg
:class="[device.theme, device.case, device.front, 'case_orange front_orange', 'my-12 mx-auto']" v-if="1"
version="1.0" id="device"
xmlns="http://www.w3.org/2000/svg" :class="[device.theme, device.case, device.front, 'case_orange front_orange', 'my-12 mx-auto']"
_width="561px" version="1.0"
_height="527px" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 5610 5270" _width="561px"
preserveAspectRatio="xMidYMid meet" _height="527px"
width="400" viewBox="0 0 5610 5270"
> preserveAspectRatio="xMidYMid meet"
width="400"
<g
id="border"
fill="#262626"
stroke="none"
>
<path
d="M442 5110 c-227 -86 -417 -161 -422 -166 -4 -5 -12 -1063 -16 -2350 -7 -2292 -6 -2342 12 -2352 31 -16 817 -242 844 -242 14 0 1086 158 2383 352 l2358 353 6 25 c9 35 -66 3683 -76 3693 -4 4 -1049 194 -2322 422 -1273 228 -2323 416 -2334 419 -11 2 -206 -67 -433 -154z"
/>
</g>
<g
fill="#f3f3f3"
stroke="none"
> >
<path
id="front" <g
d="M860 2630 l0 -2611 33 6 c17 3 1080 163 2360 355 1281 191 2330 350 2332 352 6 6 -70 3666 -76 3672 -4 4 -4627 836 -4645 836 -2 0 -4 -1175 -4 -2610z m2378 1721 c1217 -175 2214 -320 2216 -322 7 -6 69 -3179 63 -3185 -8 -9 -4489 -624 -4499 -618 -10 6 -11 4444 0 4444 4 0 1003 -144 2220 -319z m2249 2 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z m60 -2890 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z" id="border"
/> fill="#262626"
<path stroke="none"
id="image" >
d="M1022 4642 c-7 -19 5 -4393 13 -4400 5 -5 4465 605 4472 611 4 4 -59 3161 -63 3166 -3 3 -3200 465 -4387 634 -19 2 -31 -1 -35 -11z" <path
/> d="M442 5110 c-227 -86 -417 -161 -422 -166 -4 -5 -12 -1063 -16 -2350 -7 -2292 -6 -2342 12 -2352 31 -16 817 -242 844 -242 14 0 1086 158 2383 352 l2358 353 6 25 c9 35 -66 3683 -76 3693 -4 4 -1049 194 -2322 422 -1273 228 -2323 416 -2334 419 -11 2 -206 -67 -433 -154z"
<path />
id="case" </g>
d="M438 5081 c-214 -81 -390 -150 -393 -153 -7 -6 -28 -4658 -22 -4664 2 -2 182 -56 400 -119 218 -64 403 -118 412 -121 13 -6 15 259 15 2600 0 2078 -3 2606 -12 2605 -7 0 -187 -67 -400 -148z" <g
/> fill="#f3f3f3"
</g> stroke="none"
</svg> >
<path
id="front"
d="M860 2630 l0 -2611 33 6 c17 3 1080 163 2360 355 1281 191 2330 350 2332 352 6 6 -70 3666 -76 3672 -4 4 -4627 836 -4645 836 -2 0 -4 -1175 -4 -2610z m2378 1721 c1217 -175 2214 -320 2216 -322 7 -6 69 -3179 63 -3185 -8 -9 -4489 -624 -4499 -618 -10 6 -11 4444 0 4444 4 0 1003 -144 2220 -319z m2249 2 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z m60 -2890 c-4 -3 -7 0 -7 7 0 7 3 10 7 7 3 -4 3 -10 0 -14z"
/>
<path
id="image"
d="M1022 4642 c-7 -19 5 -4393 13 -4400 5 -5 4465 605 4472 611 4 4 -59 3161 -63 3166 -3 3 -3200 465 -4387 634 -19 2 -31 -1 -35 -11z"
/>
<path
id="case"
d="M438 5081 c-214 -81 -390 -150 -393 -153 -7 -6 -28 -4658 -22 -4664 2 -2 182 -56 400 -119 218 -64 403 -118 412 -121 13 -6 15 259 15 2600 0 2078 -3 2606 -12 2605 -7 0 -187 -67 -400 -148z"
/>
</g>
</svg>
</v-responsive>
<v-card-actions> <v-card-actions>
<v-btn <v-btn

@ -1,127 +1,123 @@
<template> <template>
<v-container <setup-panel
class="_fill-height" back
fluid @back="stepBack"
> >
<v-row <template #icon>
no-gutters $wb_sunny
justify="center" </template>
> <template #headline>
<v-col Weather
lg="5" </template>
md="6"
sm="8"
>
<v-card flat>
<div class="justify-center text-center">
<v-icon
view-box="0 0 24 24"
style="width: 64px; height: 64px; fill: #FF9800"
>
$wb_sunny
</v-icon>
</div>
<v-card-title class="display-2 mb-12 justify-center text-center">
Weather
</v-card-title>
<v-skeleton-loader
v-if="isLoading"
type="list-item-two-line,list-item-two-line"
class="mx-auto"
/>
<template v-else> <v-text-field
<v-card-text> v-model="form.api"
<v-text-field label="OpenWeatherMap API key"
v-model="settings.weather.api" >
label="i8n:OpenWeatherMap API key" <template #append-outer>
> <v-icon @click="registerApiKey()">
<template #append-outer> $open_in_new
<v-icon @click="registerApiKey()"> </v-icon>
$open_in_new </template>
</v-icon> </v-text-field>
</template>
</v-text-field>
<weather-find-location <weather-find-location
:api="settings.weather.api" :api="form.api"
:location.sync="settings.weather.location" :location.sync="form.location"
:lang="lang" :search.sync="form.name"
:unit="unit" :lang="lang"
/> :unit="unit"
</v-card-text> />
<v-card-actions class="flex-column"> <template #actions>
<v-btn <v-btn
:disabled="!isLocationValid" :disabled="!isLocationValid"
depressed depressed
block block
color="primary" color="primary"
@click="commitStep()" @click="commitStep()"
> >
Continue Continue
</v-btn> </v-btn>
<v-btn <v-btn
class="ma-0 mt-3" class="ma-0 mt-3"
text text
block block
color="primary" color="primary"
@click="nextStep()" @click="nextStep()"
> >
Set Up Later in Settings Set Up Later in Settings
</v-btn> </v-btn>
</v-card-actions> </template>
</template> </setup-panel>
</v-card>
</v-col>
</v-row>
</v-container>
</template> </template>
<script> <script>
import apiDevice from '@/api/device' import { mapState, mapMutations, mapActions } from 'vuex'
import weatherFindLocation from '@/components/WeatherFindLocation' import weatherFindLocation from '@/components/WeatherFindLocation'
import SetupPanel from '@/components/SetupPanel'
export default { export default {
components: { components: {
SetupPanel,
weatherFindLocation, weatherFindLocation,
}, },
data: () => ({ data: () => ({
isLoading: true, form: {
settings: null, api: '',
name: '',
location: 0,
},
}), }),
computed: { computed: {
...mapState([
'settings',
]),
lang () { lang () {
return this.settings.language || 'EN' return this.settings.weather.language || 'EN'
}, },
unit () { unit () {
return this.settings.language === 'EN' ? '' : 'metric' return this.lang === 'EN' ? '' : 'metric'
}, },
isLocationValid () { isLocationValid () {
return this.settings.weather.location > 0 return this.settings.weather.location > 0
}, },
}, },
created () { created () {
apiDevice.getSettings(settings => { this.resetChanges()
this.settings = settings
this.isLoading = false
})
}, },
methods: { methods: {
...mapMutations(['updateSettings']),
...mapActions(['saveSettings']),
commitStep () { commitStep () {
// TODO sav this.updateSettings({
weather: {
api: this.form.api,
name: this.form.name,
location: this.form.location,
lang: this.lang,
unit: this.unit,
},
})
this.nextStep() this.nextStep()
}, },
resetChanges () {
this.form.api = this.settings.weather.api
this.form.location = this.settings.weather.location
this.form.name = this.settings.weather.name
},
nextStep () { nextStep () {
this.$router.push('/setup/name') this.$router.push('/setup/name')
}, },
registerApiKey () { registerApiKey () {
window.open('http://openweathermap.org/') window.open('http://openweathermap.org/')
}, },
stepBack () {
this.$router.push('/setup/')
},
}, },
} }
</script> </script>

@ -3,6 +3,18 @@
class="_fill-height" class="_fill-height"
fluid fluid
> >
<div>
<v-btn
text
color="primary"
class="px-0"
@click="stepBack"
>
<v-icon>$prev</v-icon>
Back
</v-btn>
</div>
<v-row <v-row
no-gutters no-gutters
justify="center" justify="center"
@ -13,7 +25,7 @@
sm="8" sm="8"
> >
<v-card flat> <v-card flat>
<v-card-title class="display-2 mb-12 justify-center text-center"> <v-card-title class="display-1 font-weight-bold mb-12 px-0 justify-center text-center">
Choose a Choose a
<br>Wi-Fi Network <br>Wi-Fi Network
</v-card-title> </v-card-title>
@ -142,6 +154,9 @@
apiDevice.wifiConnect(ssid, password, () => {}) apiDevice.wifiConnect(ssid, password, () => {})
}, },
stepBack () {
this.$router.push('/setup/country')
},
}, },
} }
</script> </script>

Loading…
Cancel
Save