Being common

This commit is contained in:
sheychen 2019-04-16 14:04:25 +02:00
parent 2f52372e35
commit 2e3a988518
20 changed files with 280 additions and 92 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -48,12 +48,12 @@
"vue-chartjs": "^3.4.2", "vue-chartjs": "^3.4.2",
"vue-loader": "^15.4.2", "vue-loader": "^15.4.2",
"vue-style-loader": "^4.1.2", "vue-style-loader": "^4.1.2",
"vue-template-compiler": "^2.5.22", "vue-template-compiler": "^2.6.10",
"webpack": "^4.6.0", "webpack": "^4.6.0",
"webpack-cli": "^3.2.1" "webpack-cli": "^3.2.1"
}, },
"dependencies": { "dependencies": {
"vue": "^2.5.22" "vue": "^2.6.10"
}, },
"babel": { "babel": {
"presets": [ "presets": [

View File

@ -0,0 +1,19 @@
<script>
import { emitErrorMixin, handleOptionsMixin } from '../core/tools'
import serviceHeaderVue from '../core/serviceHeader.vue'
import settingBooleanVue from '../core/input/settingBoolean.vue'
import settingIntVue from '../core/input/settingInt.vue'
import settingStringVue from './input/settingString.vue'
export default {
mixins: [ emitErrorMixin, handleOptionsMixin ],
components: {
serviceHeader: serviceHeaderVue,
settingBoolean: settingBooleanVue,
settingInt: settingIntVue,
settingString: settingStringVue
}
}
</script>

View File

@ -0,0 +1,13 @@
<script>
export default {
props: {
id: String,
title: String
},
methods: {
sendChange(value) {
this.$emit('change', { name: this.id, value: value })
}
}
}
</script>

View File

@ -0,0 +1,3 @@
p.setting
label(:for="id") {{ title }}:
block input

View File

@ -0,0 +1,14 @@
<template lang="pug">
extends model
block input
input(:id="id" type="checkbox" :checked="value" @change.stop="sendChange($event.target.checked)")
</template>
<script>
import baseSettingVue from './baseSetting.vue'
export default {
extends: baseSettingVue,
props: { value: Boolean }
}
</script>

View File

@ -0,0 +1,14 @@
<template lang="pug">
extends model
block input
input(:id="id" type="number" step="1" :value="value" @keyup.enter="sendChange(parseInt($event.target.value))")
</template>
<script>
import baseSettingVue from './baseSetting.vue'
export default {
extends: baseSettingVue,
props: { value: Number }
}
</script>

View File

@ -0,0 +1,14 @@
<template lang="pug">
extends model
block input
input(:id="id" type="text" :value="value" @keyup.enter="sendChange($event.target.value)")
</template>
<script>
import baseSettingVue from './baseSetting.vue'
export default {
extends: baseSettingVue,
props: { value: String }
}
</script>

View File

@ -0,0 +1,15 @@
<template lang="pug">
.service-header
.title(@click="showSettings = !showSettings")
slot(name="title")
.settings(v-show="showSettings")
slot(name="settings")
</template>
<script>
export default {
data() { return {
showSettings: false
} }
}
</script>

View File

@ -15,6 +15,9 @@ export const handleOptionsMixin = {
const options = {...this.$props} const options = {...this.$props}
options[name] = value options[name] = value
this.saveOptions(options) this.saveOptions(options)
},
setOptionCouple(couple) {
this.setOption(couple.name, couple.value)
} }
} }
} }

View File

@ -5,8 +5,9 @@
.list(v-if="statues.length > 0" @scroll="onScroll") .list(v-if="statues.length > 0" @scroll="onScroll")
template(v-for="status in statues") template(v-for="status in statues")
status(v-if="showStatus(status)" :key="status.id" :status="status" :now="now" :showMedia="showMedia" @mark="onStatusMark") status(v-if="showStatus(status)" :key="status.id" :status="status" :now="now" :showMedia="showMedia" @mark="onStatusMark")
.status(v-show="loadingOlder") Loading... .status(v-show="loadingOlder")
template(v-else) Loading... .service-loader
.service-loader(v-else)
.notifications(v-if="notifications.length > 0") .notifications(v-if="notifications.length > 0")
.header .header
| Notifications | Notifications

View File

@ -1,25 +1,16 @@
<template lang="pug"> <template lang="pug">
.mastodon .mastodon
.header(@click="showSettings = !showSettings") service-header
| Mastodon: template(#title)
span(v-html="parseEmojis(account.display_name, account.emojis)") | Mastodon:
| {{ server ? '@' + server : '' }} span(v-html="parseEmojis(account.display_name, account.emojis)")
.settings(v-show="showSettings") | {{ server ? '@' + server : '' }}
p template(#settings)
label(for="reconnect") Reconnect: setting-boolean(:id="'reconnect'" :title="'Reconnect'" :value="reconnect" @change="setOptionCouple")
input#reconnect(type="checkbox" :checked="reconnect" @change="setOption('reconnect', $event.target.checked)") setting-boolean(:id="'reblog'" :title="'Show reblogs'" :value="reblog" @change="setOptionCouple")
p setting-boolean(:id="'reply'" :title="'Show replies'" :value="reply" @change="setOptionCouple")
label(for="reblog") Show reblogs: setting-int(:id="'buffer'" :title="'Buffer size'" :value="buffer" @change="setOptionCouple")
input#reblog(type="checkbox" :checked="reblog" @change="setOption('reblog', $event.target.checked)") setting-boolean(:id="'showMedia'" :title="'Show medias'" :value="showMedia" @change="setOptionCouple")
p
label(for="reply") Show replies:
input#reply(type="checkbox" :checked="reply" @change="setOption('reply', $event.target.checked)")
p
label(for="buffer") Buffer:
input#buffer(type="number" :value="buffer" @keyup.enter="setOption('buffer', parseInt($event.target.value))")
p
label(for="showMedia") Show media:
input#showMedia(type="checkbox" :checked="showMedia" @change="setOption('showMedia', $event.target.checked)")
client(v-if="server && token" v-bind="$props") client(v-if="server && token" v-bind="$props")
.auth(v-else) .auth(v-else)
form(@submit.prevent="setServer") form(@submit.prevent="setServer")
@ -34,13 +25,15 @@
</template> </template>
<script> <script>
import { emitErrorMixin, handleOptionsMixin } from '../core/tools' import baseServiceVue from '../core/baseService.vue'
import { parseEmojisMixin } from './tools' import { parseEmojisMixin } from './tools'
import clientVue from './client.vue' import clientVue from './client.vue'
export default { //TODO: Use oauth export default { //TODO: Use oauth
name: 'mastodon', name: 'mastodon',
mixins: [ emitErrorMixin, handleOptionsMixin, parseEmojisMixin ], extends: baseServiceVue,
mixins: [ parseEmojisMixin ],
components: { components: {
client: clientVue client: clientVue
}, },
@ -76,7 +69,6 @@ export default { //TODO: Use oauth
return { return {
newServer: this.server, newServer: this.server,
newToken: this.token, newToken: this.token,
showSettings: false,
account: { display_name: 'Loading...', emojis: [] } account: { display_name: 'Loading...', emojis: [] }
}; };
}, },

View File

@ -1,13 +1,10 @@
<template lang="pug"> <template lang="pug">
.nextcloud-news(v-show="unreaded.length > 0 || !server || !token || !username") .nextcloud-news(v-show="unreaded.length > 0 || !server || !token || !username")
.header(@click="showSettings = !showSettings") Nextcloud News service-header
.settings(v-show="showSettings") template(#title) Nextcloud News
p template(#settings)
label(for="update") Update interval: setting-boolean(:id="'update'" :title="'Update interval'" :value="update" @change="setOptionCouple")
input#update(type="number" :value="update" @keyup.enter="setOption('update', parseInt($event.target.value))") setting-int(:id="'buffer'" :title="'Buffer size'" :value="buffer" @change="setOptionCouple")
p
label(for="buffer") Buffer:
input#buffer(type="number" :value="buffer" @keyup.enter="setOption('buffer', parseInt($event.target.value))")
.unreaded .unreaded
.news(v-for="news in unreaded") .news(v-for="news in unreaded")
a(:href="news.url" target="_blank") a(:href="news.url" target="_blank")
@ -31,12 +28,13 @@
</template> </template>
<script> <script>
import { emitErrorMixin, handleOptionsMixin } from '../core/tools' import baseServiceVue from '../core/baseService.vue'
import fromNowVue, { timerMinin } from '../core/fromNow.vue'; import fromNowVue, { timerMinin } from '../core/fromNow.vue'
export default { export default {
name: 'nextcloud-news', name: 'nextcloud-news',
mixins: [ emitErrorMixin, timerMinin, handleOptionsMixin ], extends: baseServiceVue,
mixins: [ timerMinin ],
components: { components: {
fromNow: fromNowVue fromNow: fromNowVue
}, },
@ -68,7 +66,6 @@ export default {
}), }),
unreaded: [], unreaded: [],
now: Date.now(), now: Date.now(),
showSettings: false,
newServer: this.server, newServer: this.server,
newUsername: this.username, newUsername: this.username,
newToken: this.token, newToken: this.token,

View File

@ -1,18 +1,13 @@
<template lang="pug"> <template lang="pug">
.openweathermap .openweathermap
.header(@click="showSettings = !showSettings") OpenWeatherMap service-header
.settings(v-show="showSettings") template(#title) OpenWeatherMap
p template(#settings)
label(for="token") Token: setting-string(:id="'token'" :title="'Token'" :value="token" @change="setOptionCouple")
input#token(:value="token" @keyup.enter="setOption('token', $event.target.value)") setting-int(:id="'update'" :title="'Update interval'" :value="update" @change="setOptionCouple")
p setting-int(:id="'forecastLimit'" :title="'Forecast limit'" :value="forecastLimit" @change="setOptionCouple")
label(for="update") Update interval: p.setting
input#update(type="number" :value="update" @keyup.enter="setOption('update', parseInt($event.target.value))") button(@click="showAdd = true") Add city
p
label(for="forecastLimit") Forecast limit:
input#forecastLimit(type="number" :value="forecastLimit" @keyup.enter="setOption('forecastLimit', parseInt($event.target.value))")
p
button(@click="showAdd = true") Add city
template(v-if="weathers.length > 0 || cities.length == 0") template(v-if="weathers.length > 0 || cities.length == 0")
.list .list
.weather(v-for="(city, id) in weathers" :class="{ selected: selected == id }" @click.stop.prevent="makeSelect(id)") .weather(v-for="(city, id) in weathers" :class="{ selected: selected == id }" @click.stop.prevent="makeSelect(id)")
@ -20,6 +15,7 @@
p {{ main.description }} p {{ main.description }}
.ic .ic
img(:src="`https://openweathermap.org/img/w/${main.icon}.png`" :alt="main.main") img(:src="`https://openweathermap.org/img/w/${main.icon}.png`" :alt="main.main")
span.remove(@click.stop.prevent="removeCity(id)")
.header .header
| {{ city.name }}&nbsp; | {{ city.name }}&nbsp;
img.icon(:src="`https://openweathermap.org/images/flags/${city.sys.country.toLowerCase()}.png`" :alt="city.sys.country" :title="city.sys.country") img.icon(:src="`https://openweathermap.org/images/flags/${city.sys.country.toLowerCase()}.png`" :alt="city.sys.country" :title="city.sys.country")
@ -28,20 +24,21 @@
input.weather(v-show="showAdd" placeholder="city id" @keyup.enter="addCity(parseInt($event.target.value))") input.weather(v-show="showAdd" placeholder="city id" @keyup.enter="addCity(parseInt($event.target.value))")
.forecast .forecast
chart(v-if="forecast" :chartData="forecastChart") chart(v-if="forecast" :chartData="forecastChart")
template(v-else) Loading... .service-loader(v-else)
template(v-else) Loading... .service-loader(v-else)
</template> </template>
<script> <script>
import { emitErrorMixin, handleOptionsMixin } from '../core/tools' import baseServiceVue from '../core/baseService.vue'
import chartVue from './chart.vue' import chartVue from './chart.vue'
export default { export default {
name: 'openweathermap', name: 'openweathermap',
extends: baseServiceVue,
components: { components: {
chart: chartVue chart: chartVue
}, },
mixins: [ emitErrorMixin, handleOptionsMixin ],
props: { props: {
token: String, token: String,
cities: { cities: {
@ -79,7 +76,6 @@ export default {
weathers: [], weathers: [],
forecast: null, forecast: null,
selected: 0, selected: 0,
showSettings: false,
showAdd: this.cities.length == 0 showAdd: this.cities.length == 0
}; };
}, },
@ -144,6 +140,11 @@ export default {
const options = {...this.$props} const options = {...this.$props}
options.cities.push({id: id}) options.cities.push({id: id})
this.saveOptions(options) this.saveOptions(options)
},
removeCity(i) {
const options = {...this.$props}
options.cities.splice(i, 1)
this.saveOptions(options)
} }
}, },
created() { created() {

View File

@ -63,19 +63,60 @@ a {
flex: 1; flex: 1;
} }
#services > div > .header, #services > div > .settings { #services > div .service-header .title, #services > div .service-header .settings {
margin: 0.3em; margin: 0.3em;
background-color: #222; background-color: #222;
border-radius: 0.3em; border-radius: 0.3em;
padding: 0.3em; padding: 0.3em;
} }
#services > div > .header { #services > div .service-header .title {
font-size: large; font-size: large;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
} }
#services .service-loader {
display: inline-block;
width: 64px;
height: 64px;
}
#services .service-loader:after {
content: " ";
display: block;
width: 46px;
height: 46px;
margin: 1px;
border-radius: 50%;
border: 5px solid #aaa;
border-color: #aaa transparent #aaa transparent;
-webkit-animation: service-loader 1.2s linear infinite;
animation: service-loader 1.2s linear infinite;
}
@-webkit-keyframes service-loader {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes service-loader {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.mastodon .client { .mastodon .client {
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
@ -190,16 +231,6 @@ a {
max-width: 30%; max-width: 30%;
} }
.openweathermap .ic {
overflow: hidden;
height: 30px;
display: inline-block;
}
.openweathermap .ic img {
margin-top: -10px;
}
.openweathermap .list { .openweathermap .list {
display: -webkit-box; display: -webkit-box;
display: -ms-flexbox; display: -ms-flexbox;
@ -230,6 +261,13 @@ a {
.openweathermap .weather { .openweathermap .weather {
min-width: 17em; min-width: 17em;
border: 1px solid #222; border: 1px solid #222;
display: -ms-grid;
display: grid;
-ms-grid-columns: auto auto;
grid-template-columns: auto auto;
-ms-grid-rows: 1.2em auto;
grid-template-rows: 1.2em auto;
grid-template-areas: "header main" "data remove";
} }
.openweathermap .weather.selected { .openweathermap .weather.selected {
@ -237,15 +275,25 @@ a {
} }
.openweathermap .weather .header { .openweathermap .weather .header {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: header;
font-size: 1.2em; font-size: 1.2em;
} }
.openweathermap .weather .data { .openweathermap .weather .data {
-ms-grid-row: 2;
-ms-grid-column: 1;
grid-area: data;
margin-top: .5em; margin-top: .5em;
} }
.openweathermap .weather .main { .openweathermap .weather .main {
float: right; -ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: main;
-ms-grid-column-align: right;
justify-self: right;
} }
.openweathermap .weather .main p { .openweathermap .weather .main p {
@ -254,6 +302,28 @@ a {
vertical-align: top; vertical-align: top;
} }
.openweathermap .weather .remove {
-ms-grid-row: 2;
-ms-grid-column: 2;
grid-area: remove;
-ms-grid-column-align: right;
justify-self: right;
-ms-flex-item-align: bottom;
-ms-grid-row-align: bottom;
align-self: bottom;
font-size: .8em;
}
.openweathermap .ic {
overflow: hidden;
height: 30px;
display: inline-block;
}
.openweathermap .ic img {
margin-top: -10px;
}
.nextcloud-news .news { .nextcloud-news .news {
margin: 0.3em; margin: 0.3em;
background-color: #222; background-color: #222;

File diff suppressed because one or more lines are too long

View File

@ -1,4 +1,4 @@
//TODO: discord, weather graph //TODO: discord
const servicesStorage = 'services' const servicesStorage = 'services'
var app = new Vue({ var app = new Vue({

View File

@ -5,6 +5,7 @@ $backColor: #333
$tileColor: #222 $tileColor: #222
$darkColor: #111 $darkColor: #111
$halfColor: #999 $halfColor: #999
$noneColor: #aaa
$foreColor: #eee $foreColor: #eee
@mixin tile @mixin tile
@ -24,7 +25,7 @@ body
a a
text-decoration: none text-decoration: none
color: #aaa color: $noneColor
.icon .icon
width: 1em width: 1em
@ -56,12 +57,32 @@ a
display: flex display: flex
& > div & > div
flex: 1 flex: 1
& > .header, & > .settings .service-header
@include tile .title, .settings
& > .header @include tile
font-size: large .title
text-align: center font-size: large
font-weight: bold text-align: center
font-weight: bold
.service-loader
display: inline-block
width: 64px
height: 64px
&:after
content: " "
display: block
width: 46px
height: 46px
margin: 1px
border-radius: 50%
border: 5px solid $noneColor
border-color: $noneColor transparent $noneColor transparent
animation: service-loader 1.2s linear infinite
@keyframes service-loader
0%
transform: rotate(0deg)
100%
transform: rotate(360deg)
.mastodon .mastodon
.client .client
@ -82,7 +103,7 @@ a
.account .account
.name .name
margin: 0 $borderRadius margin: 0 $borderRadius
color: #eee color: $foreColor
.avatar .avatar
float: left float: left
border-radius: $borderRadius border-radius: $borderRadius
@ -128,13 +149,6 @@ a
float: right float: right
.openweathermap .openweathermap
.ic
overflow: hidden
height: 30px
display: inline-block
img
margin-top: -10px
display: flex display: flex
flex-direction: column flex-direction: column
max-width: 30% max-width: 30%
@ -152,18 +166,36 @@ a
.weather .weather
min-width: 17em min-width: 17em
border: 1px solid $tileColor border: 1px solid $tileColor
display: grid
grid-template-columns: auto auto
grid-template-rows: 1.2em auto
grid-template-areas: "header main" "data remove"
&.selected &.selected
border-color: $halfColor border-color: $halfColor
.header .header
grid-area: header
font-size: 1.2em font-size: 1.2em
.data .data
grid-area: data
margin-top: .5em margin-top: .5em
.main .main
float: right grid-area: main
justify-self: right
p p
margin: $borderRadius margin: $borderRadius
display: inline display: inline
vertical-align: top vertical-align: top
.remove
grid-area: remove
justify-self: right
align-self: bottom
font-size: .8em
.ic
overflow: hidden
height: 30px
display: inline-block
img
margin-top: -10px
.nextcloud-news .nextcloud-news
.news .news