Clean up
This commit is contained in:
parent
9f777238da
commit
74935ced6c
|
@ -4680,14 +4680,12 @@
|
||||||
"balanced-match": {
|
"balanced-match": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.11",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
|
@ -4702,20 +4700,17 @@
|
||||||
"code-point-at": {
|
"code-point-at": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"concat-map": {
|
"concat-map": {
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"console-control-strings": {
|
"console-control-strings": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
|
@ -4832,8 +4827,7 @@
|
||||||
"inherits": {
|
"inherits": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"ini": {
|
"ini": {
|
||||||
"version": "1.3.5",
|
"version": "1.3.5",
|
||||||
|
@ -4845,7 +4839,6 @@
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"number-is-nan": "^1.0.0"
|
"number-is-nan": "^1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -4860,7 +4853,6 @@
|
||||||
"version": "3.0.4",
|
"version": "3.0.4",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"brace-expansion": "^1.1.7"
|
"brace-expansion": "^1.1.7"
|
||||||
}
|
}
|
||||||
|
@ -4868,14 +4860,12 @@
|
||||||
"minimist": {
|
"minimist": {
|
||||||
"version": "0.0.8",
|
"version": "0.0.8",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"minipass": {
|
"minipass": {
|
||||||
"version": "2.3.5",
|
"version": "2.3.5",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"safe-buffer": "^5.1.2",
|
"safe-buffer": "^5.1.2",
|
||||||
"yallist": "^3.0.0"
|
"yallist": "^3.0.0"
|
||||||
|
@ -4894,7 +4884,6 @@
|
||||||
"version": "0.5.1",
|
"version": "0.5.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "0.0.8"
|
"minimist": "0.0.8"
|
||||||
}
|
}
|
||||||
|
@ -4975,8 +4964,7 @@
|
||||||
"number-is-nan": {
|
"number-is-nan": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true
|
||||||
"optional": true
|
|
||||||
},
|
},
|
||||||
"object-assign": {
|
"object-assign": {
|
||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
|
@ -4988,7 +4976,6 @@
|
||||||
"version": "1.4.0",
|
"version": "1.4.0",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"wrappy": "1"
|
"wrappy": "1"
|
||||||
}
|
}
|
||||||
|
@ -5110,7 +5097,6 @@
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"bundled": true,
|
"bundled": true,
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"optional": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"code-point-at": "^1.0.0",
|
"code-point-at": "^1.0.0",
|
||||||
"is-fullwidth-code-point": "^1.0.0",
|
"is-fullwidth-code-point": "^1.0.0",
|
||||||
|
@ -12258,6 +12244,16 @@
|
||||||
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
"integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"vuex": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.1.0.tgz",
|
||||||
|
"integrity": "sha512-mdHeHT/7u4BncpUZMlxNaIdcN/HIt1GsGG5LKByArvYG/v6DvHcOxvDCts+7SRdCoIRGllK8IMZvQtQXLppDYg=="
|
||||||
|
},
|
||||||
|
"vuex-module-decorators": {
|
||||||
|
"version": "0.9.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuex-module-decorators/-/vuex-module-decorators-0.9.8.tgz",
|
||||||
|
"integrity": "sha512-yyh9+0mO7NYZxw5BlXWNA/lHioVOUL0muDpJPL9ssAvje2PHQfFSOCSridK4vA3HasjyaGRtTPJKH7+7UCcpwg=="
|
||||||
|
},
|
||||||
"watchpack": {
|
"watchpack": {
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.6.0.tgz",
|
||||||
|
|
|
@ -13,7 +13,9 @@
|
||||||
"vue": "^2.6.10",
|
"vue": "^2.6.10",
|
||||||
"vue-chartjs": "^3.4.2",
|
"vue-chartjs": "^3.4.2",
|
||||||
"vue-class-component": "^6.0.0",
|
"vue-class-component": "^6.0.0",
|
||||||
"vue-property-decorator": "^7.0.0"
|
"vue-property-decorator": "^7.0.0",
|
||||||
|
"vuex": "^3.1.0",
|
||||||
|
"vuex-module-decorators": "^0.9.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vue/cli-plugin-typescript": "^3.0.3",
|
"@vue/cli-plugin-typescript": "^3.0.3",
|
||||||
|
|
17
src/App.vue
17
src/App.vue
|
@ -32,10 +32,10 @@
|
||||||
import { Component, Vue } from 'vue-property-decorator'
|
import { Component, Vue } from 'vue-property-decorator'
|
||||||
import { Selectable } from './helpers/lists/Selectable'
|
import { Selectable } from './helpers/lists/Selectable'
|
||||||
import LocalStorageHandler from './helpers/storage/LocalStorageHandler'
|
import LocalStorageHandler from './helpers/storage/LocalStorageHandler'
|
||||||
import DiscordVue from './services/discord/Discord.vue'
|
import Discord from './services/discord/Discord.vue'
|
||||||
import MastodonVue from './services/mastodon/Mastodon.vue'
|
import Mastodon from './services/mastodon/Mastodon.vue'
|
||||||
import NextcloudNewsVue from './services/nextcloud/NextcloudNews.vue'
|
import NextcloudNews from './services/nextcloud/NextcloudNews.vue'
|
||||||
import OpenWeatherMapVue from './services/openweathermap/OpenWeatherMap.vue'
|
import OpenWeatherMap from './services/openweathermap/OpenWeatherMap.vue'
|
||||||
import { Auth, Layout, Rect, Service, serviceKey, tileKey } from './types/App'
|
import { Auth, Layout, Rect, Service, serviceKey, tileKey } from './types/App'
|
||||||
import * as Events from './types/Events'
|
import * as Events from './types/Events'
|
||||||
|
|
||||||
|
@ -50,14 +50,7 @@ function saveAuth(auth: Auth) {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Mastodon, NextcloudNews, openweathermap: OpenWeatherMap, Discord } })
|
||||||
components: {
|
|
||||||
mastodon: MastodonVue,
|
|
||||||
'nextcloud-news': NextcloudNewsVue,
|
|
||||||
openweathermap: OpenWeatherMapVue,
|
|
||||||
discord: DiscordVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class App extends Vue {
|
export default class App extends Vue {
|
||||||
showManager = false
|
showManager = false
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/* No CSS *//*# sourceMappingURL=common.css.map */
|
|
@ -0,0 +1,9 @@
|
||||||
|
{
|
||||||
|
"version": 3,
|
||||||
|
"mappings": "",
|
||||||
|
"sources": [
|
||||||
|
"common.sass"
|
||||||
|
],
|
||||||
|
"names": [],
|
||||||
|
"file": "common.css"
|
||||||
|
}
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { Component, Vue } from 'vue-property-decorator'
|
||||||
|
import { TimeModule } from '../store'
|
||||||
|
|
||||||
|
const times = new Map<string, number>([
|
||||||
|
['second', 1000],
|
||||||
|
['minute', 60],
|
||||||
|
['hour', 60],
|
||||||
|
['day', 24],
|
||||||
|
['month', 30.5],
|
||||||
|
['year', 12],
|
||||||
|
['century', 100]
|
||||||
|
])
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class FromNowMixin extends Vue {
|
||||||
|
|
||||||
|
protected static toNumber(date: Date | number | string) {
|
||||||
|
return Number(new Date(date))
|
||||||
|
}
|
||||||
|
|
||||||
|
fromNow(date: Date | number | string) {
|
||||||
|
const milliseconds = Math.floor(FromNowMixin.toNumber(TimeModule.now) - FromNowMixin.toNumber(date))
|
||||||
|
|
||||||
|
let cur = 0
|
||||||
|
let divider = 1
|
||||||
|
let name = 'millisecond'
|
||||||
|
for (const time of times) {
|
||||||
|
divider *= time[1]
|
||||||
|
const next = Math.floor(milliseconds / divider)
|
||||||
|
if(next <= 0) {
|
||||||
|
return `${cur} ${name}${cur > 1 ? 's' : ''}`
|
||||||
|
}
|
||||||
|
name = time[0]
|
||||||
|
cur = next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,14 @@
|
||||||
import { AxiosPromise } from 'axios'
|
import { AxiosPromise } from 'axios'
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator'
|
import { Component, Prop, Vue } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import LoadableBlock from './loadable/LoadableBlock.vue'
|
||||||
|
import LoadableInline from './loadable/LoadableInline.vue'
|
||||||
|
import SuccessLoadable from './loadable/SuccessLoadableBlock.vue'
|
||||||
|
|
||||||
import { ServiceData } from '@/types/App'
|
import { ServiceData } from '@/types/App'
|
||||||
import * as Events from '@/types/Events'
|
import * as Events from '@/types/Events'
|
||||||
|
|
||||||
@Component({})
|
@Component({ components: { LoadableBlock, LoadableInline, SuccessLoadable } })
|
||||||
export default class ServiceEmiter extends Vue {
|
export default class ServiceEmiter extends Vue {
|
||||||
@Prop(Function)
|
@Prop(Function)
|
||||||
readonly emit!: (name: string, msg: any) => void
|
readonly emit!: (name: string, msg: any) => void
|
||||||
|
|
|
@ -8,10 +8,10 @@ block input
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop } from 'vue-property-decorator'
|
import { Component, Prop } from 'vue-property-decorator'
|
||||||
|
|
||||||
import BaseSettingVue from './BaseSetting'
|
import BaseSetting from './BaseSetting'
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class SettingBoolean extends BaseSettingVue {
|
export default class SettingBoolean extends BaseSetting {
|
||||||
|
|
||||||
@Prop(Boolean)
|
@Prop(Boolean)
|
||||||
readonly value!: boolean
|
readonly value!: boolean
|
||||||
|
|
|
@ -8,10 +8,10 @@ block input
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop } from 'vue-property-decorator'
|
import { Component, Prop } from 'vue-property-decorator'
|
||||||
|
|
||||||
import BaseSettingVue from './BaseSetting'
|
import BaseSetting from './BaseSetting'
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class SettingInt extends BaseSettingVue {
|
export default class SettingInt extends BaseSetting {
|
||||||
|
|
||||||
@Prop({
|
@Prop({
|
||||||
type: Number,
|
type: Number,
|
||||||
|
|
|
@ -8,10 +8,10 @@ block input
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Prop } from 'vue-property-decorator'
|
import { Component, Prop } from 'vue-property-decorator'
|
||||||
|
|
||||||
import BaseSettingVue from './BaseSetting'
|
import BaseSetting from './BaseSetting'
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class SettingString extends BaseSettingVue {
|
export default class SettingString extends BaseSetting {
|
||||||
|
|
||||||
@Prop(String)
|
@Prop(String)
|
||||||
readonly value!: string
|
readonly value!: string
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
<template lang="pug">
|
||||||
|
div.loadable-block
|
||||||
|
slot(v-if="loadable.isSuccess") {{ get }}
|
||||||
|
template(v-else-if="loadable.error") {{ loadable.error }}
|
||||||
|
template(v-else)
|
||||||
|
.service-loader
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { Component } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import Loadable from './Loadable'
|
||||||
|
|
||||||
|
@Component
|
||||||
|
export default class SuccessLoadableBlock<T, E> extends Loadable<T, E> { }
|
||||||
|
</script>
|
|
@ -1,18 +1,13 @@
|
||||||
import { Component, Prop, Watch } from 'vue-property-decorator'
|
import { Component, Prop, Watch } from 'vue-property-decorator'
|
||||||
|
|
||||||
import { Auth } from '@/types/App'
|
import { Auth } from '@/types/App'
|
||||||
import SettingBooleanVue from '../input/SettingBoolean.vue'
|
import SettingBoolean from '../input/SettingBoolean.vue'
|
||||||
import SettingIntVue from '../input/SettingInt.vue'
|
import SettingInt from '../input/SettingInt.vue'
|
||||||
import SettingStringVue from '../input/SettingString.vue'
|
import SettingString from '../input/SettingString.vue'
|
||||||
import ServiceEmiter from '../ServiceEmiter'
|
import ServiceEmiter from '../ServiceEmiter'
|
||||||
|
import ServiceHeader from '../ServiceHeader.vue'
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { ServiceHeader, SettingString, SettingInt, SettingBoolean } })
|
||||||
components: {
|
|
||||||
'setting-string': SettingStringVue,
|
|
||||||
'setting-int': SettingIntVue,
|
|
||||||
'setting-boolean': SettingBooleanVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class BaseService extends ServiceEmiter {
|
export default class BaseService extends ServiceEmiter {
|
||||||
|
|
||||||
@Prop({
|
@Prop({
|
||||||
|
|
|
@ -3,16 +3,9 @@ import { Component } from 'vue-property-decorator'
|
||||||
|
|
||||||
import ErrorLoadable from '@/helpers/loadable/ErrorLoadable'
|
import ErrorLoadable from '@/helpers/loadable/ErrorLoadable'
|
||||||
import { Auth } from '@/types/App'
|
import { Auth } from '@/types/App'
|
||||||
import LoadableBlockVue from '../loadable/LoadableBlock.vue'
|
|
||||||
import LoadableInlineVue from '../loadable/LoadableInline.vue'
|
|
||||||
import BaseService from './BaseService'
|
import BaseService from './BaseService'
|
||||||
|
|
||||||
@Component({
|
@Component
|
||||||
components: {
|
|
||||||
'loadable-inline': LoadableInlineVue,
|
|
||||||
'loadable-block': LoadableBlockVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class ConnectedService<T, E> extends BaseService {
|
export default class ConnectedService<T, E> extends BaseService {
|
||||||
|
|
||||||
get isSetup(): boolean {
|
get isSetup(): boolean {
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
<template lang="pug">
|
|
||||||
span {{ timeSince }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts">
|
|
||||||
import { Component, Mixins, Prop } from 'vue-property-decorator'
|
|
||||||
import TimedMixin from './TimedMixin'
|
|
||||||
|
|
||||||
@Component
|
|
||||||
export default class FromNow extends Mixins(TimedMixin) {
|
|
||||||
|
|
||||||
protected static toNumber(date: Date | number | string) {
|
|
||||||
return Number(new Date(date))
|
|
||||||
}
|
|
||||||
|
|
||||||
@Prop([Date, Number, String])
|
|
||||||
readonly date!: Date | number | string
|
|
||||||
|
|
||||||
get timeSince() {
|
|
||||||
const seconds = Math.floor((FromNow.toNumber(this.now) - FromNow.toNumber(this.date)) / 1000)
|
|
||||||
|
|
||||||
let interval = Math.floor(seconds / 31536000)
|
|
||||||
|
|
||||||
if (interval > 1) {
|
|
||||||
return interval + ' years'
|
|
||||||
}
|
|
||||||
interval = Math.floor(seconds / 2592000)
|
|
||||||
if (interval > 1) {
|
|
||||||
return interval + ' months'
|
|
||||||
}
|
|
||||||
interval = Math.floor(seconds / 86400)
|
|
||||||
if (interval > 1) {
|
|
||||||
return interval + ' days'
|
|
||||||
}
|
|
||||||
interval = Math.floor(seconds / 3600)
|
|
||||||
if (interval > 1) {
|
|
||||||
return interval + ' hours'
|
|
||||||
}
|
|
||||||
interval = Math.floor(seconds / 60)
|
|
||||||
if (interval > 1) {
|
|
||||||
return interval + ' minutes'
|
|
||||||
}
|
|
||||||
return Math.floor(seconds) + ' seconds'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
|
@ -1,9 +0,0 @@
|
||||||
import { Component, Prop, Vue } from 'vue-property-decorator'
|
|
||||||
|
|
||||||
@Component
|
|
||||||
export default class TimedMixin extends Vue {
|
|
||||||
|
|
||||||
@Prop([Number, Date])
|
|
||||||
readonly now!: number | Date
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { Component, Vue } from 'vue-property-decorator'
|
|
||||||
|
|
||||||
@Component
|
|
||||||
export default class TimerMixin extends Vue {
|
|
||||||
|
|
||||||
now = Date.now()
|
|
||||||
|
|
||||||
created() {
|
|
||||||
const self = this
|
|
||||||
setInterval(() => {
|
|
||||||
self.now = Date.now()
|
|
||||||
}, 30 * 1000)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,8 +1,10 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue'
|
||||||
import App from './App.vue';
|
import App from './App.vue'
|
||||||
|
import store from './store'
|
||||||
|
|
||||||
Vue.config.productionTip = false;
|
Vue.config.productionTip = false
|
||||||
|
|
||||||
new Vue({
|
new Vue({
|
||||||
|
store,
|
||||||
render: h => h(App)
|
render: h => h(App)
|
||||||
}).$mount('#app');
|
}).$mount('#app');
|
|
@ -11,7 +11,7 @@ import { MappedChannel } from './Types'
|
||||||
const MAX_LENGTH = 20
|
const MAX_LENGTH = 20
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class ChannelTag extends ShowMediaMixin {
|
export default class Channel extends ShowMediaMixin {
|
||||||
|
|
||||||
@Prop(Object)
|
@Prop(Object)
|
||||||
readonly channel!: MappedChannel
|
readonly channel!: MappedChannel
|
|
@ -1,52 +1,39 @@
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.client(@scroll.passive="onScroll")
|
.client(@scroll.passive="onScroll")
|
||||||
loadable-block.guilds(:loadable="guilds")
|
success-loadable.guilds(:loadable="guilds")
|
||||||
template(#success)
|
guild(v-for="(guild, key) in guilds.map(g => g.data, [])" :key="guild.id" :guild="guild" :showMedia="options.showMedia"
|
||||||
guild(v-for="(guild, key) in guilds.get().data" :key="guild.id" :guild="guild" :showMedia="options.showMedia"
|
@click.native="selectGuild(key)" :class="{ selected: guilds.get().isSelected(key) }")
|
||||||
@click.native="selectGuild(key)" :class="{ selected: guilds.get().isSelected(key) }")
|
success-loadable.channels(:loadable="channels")
|
||||||
loadable-block.channels(:loadable="channels")
|
channel(v-for="(channel, key) in mapChannels" :key="channel.id" :channel="channel" :showMedia="options.showMedia"
|
||||||
template(#success)
|
@click.native="selectChannel(key)" :class="{ selected: channels.get().isSelected(key) }")
|
||||||
channel(v-for="(channel, key) in mapChannels" :key="channel.id" :channel="channel" :showMedia="options.showMedia"
|
success-loadable.messages(:loadable="messages")
|
||||||
@click.native="selectChannel(key)" :class="{ selected: channels.get().isSelected(key) }")
|
message(v-for="(message, key) in messages.get()" :key="message.id"
|
||||||
loadable-block.messages(:loadable="messages")
|
:message="message" :showMedia="options.showMedia")
|
||||||
template(#success)
|
|
||||||
message(v-for="(message, key) in messages.get()" :key="message.id"
|
|
||||||
:message="message" :showMedia="options.showMedia" :now="now")
|
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import axios, { AxiosResponse } from 'axios'
|
import axios, { AxiosResponse } from 'axios'
|
||||||
import { Component, Mixins } from 'vue-property-decorator'
|
import { Component, Mixins } from 'vue-property-decorator'
|
||||||
|
|
||||||
import LoadableBlockVue from '@/components/loadable/LoadableBlock.vue'
|
|
||||||
import ServiceClient from '@/components/ServiceClient'
|
import ServiceClient from '@/components/ServiceClient'
|
||||||
import TimerMixin from '@/components/time/TimerMixin'
|
|
||||||
import Lists from '@/helpers/lists/Lists'
|
import Lists from '@/helpers/lists/Lists'
|
||||||
import { Selectable } from '@/helpers/lists/Selectable'
|
import { Selectable } from '@/helpers/lists/Selectable'
|
||||||
import AxiosLoadable from '@/helpers/loadable/AxiosLoadable'
|
import AxiosLoadable from '@/helpers/loadable/AxiosLoadable'
|
||||||
import AxiosLoadableMore from '@/helpers/loadable/AxiosLoadableMore'
|
import AxiosLoadableMore from '@/helpers/loadable/AxiosLoadableMore'
|
||||||
import ChannelTagVue from './ChannelTag.vue'
|
import Channel from './Channel.vue'
|
||||||
import { AUTH, getRest } from './Discord.vue'
|
import { AUTH, getRest } from './Discord.vue'
|
||||||
import GuildTagVue from './GuildTag.vue'
|
import Guild from './Guild.vue'
|
||||||
import MessageTagVue from './MessageTag.vue'
|
import Message from './Message.vue'
|
||||||
import { Channel, getChannelOrder, MappedChannel, Message, Options, PartialGuild, TextChannelTypes } from './Types'
|
import { Channel as IChannel, getChannelOrder, MappedChannel, Message as IMessage, Options, PartialGuild, TextChannelTypes } from './Types'
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Channel, Guild, Message } })
|
||||||
components: {
|
export default class Client extends Mixins<ServiceClient<Options>>(ServiceClient) {
|
||||||
channel: ChannelTagVue,
|
|
||||||
guild: GuildTagVue,
|
|
||||||
message: MessageTagVue,
|
|
||||||
loadableBlock: LoadableBlockVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class Client extends Mixins<ServiceClient<Options>>(ServiceClient, TimerMixin) {
|
|
||||||
|
|
||||||
rest = getRest(this.auth, this.options.timeout)
|
rest = getRest(this.auth, this.options.timeout)
|
||||||
|
|
||||||
guilds = new AxiosLoadable<Selectable<PartialGuild>, object>()
|
guilds = new AxiosLoadable<Selectable<PartialGuild>, object>()
|
||||||
channels = new AxiosLoadable<Selectable<Channel>, object>()
|
channels = new AxiosLoadable<Selectable<IChannel>, object>()
|
||||||
messages = new AxiosLoadableMore<Message[], object>()
|
messages = new AxiosLoadableMore<IMessage[], object>()
|
||||||
|
|
||||||
get mapChannels() {
|
get mapChannels() {
|
||||||
return this.channels.map(cs => cs.data
|
return this.channels.map(cs => cs.data
|
||||||
|
|
|
@ -22,10 +22,9 @@
|
||||||
import axios, { AxiosResponse } from 'axios'
|
import axios, { AxiosResponse } from 'axios'
|
||||||
import { Component, Mixins } from 'vue-property-decorator'
|
import { Component, Mixins } from 'vue-property-decorator'
|
||||||
|
|
||||||
import AccountService from '@/components/service/AccountService';
|
import AccountService from '@/components/service/AccountService'
|
||||||
import ServiceHeaderVue from '@/components/ServiceHeader.vue'
|
|
||||||
import { Auth } from '@/types/App'
|
import { Auth } from '@/types/App'
|
||||||
import ClientVue from './Client.vue'
|
import Client from './Client.vue'
|
||||||
import { Options, User } from './Types'
|
import { Options, User } from './Types'
|
||||||
|
|
||||||
export const AUTH = { TOKEN: 'token' }
|
export const AUTH = { TOKEN: 'token' }
|
||||||
|
@ -37,12 +36,7 @@ export function getRest(auth: Auth, timeout: number) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Client } })
|
||||||
components: {
|
|
||||||
client: ClientVue,
|
|
||||||
'service-header': ServiceHeaderVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class Discord extends Mixins<AccountService<string, object, User>>(AccountService) { // TODO: Use oauth
|
export default class Discord extends Mixins<AccountService<string, object, User>>(AccountService) { // TODO: Use oauth
|
||||||
|
|
||||||
get params(): Options {
|
get params(): Options {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import { PartialGuild } from './Types'
|
||||||
const MAX_LENGTH = 20
|
const MAX_LENGTH = 20
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
export default class GuildTag extends ShowMediaMixin {
|
export default class Guild extends ShowMediaMixin {
|
||||||
|
|
||||||
@Prop(Object)
|
@Prop(Object)
|
||||||
readonly guild!: PartialGuild
|
readonly guild!: PartialGuild
|
|
@ -1,7 +1,7 @@
|
||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
.message
|
.message
|
||||||
span.account {{ message.author.username }}
|
span.account {{ message.author.username }}
|
||||||
from-now.date.osef(:date="message.timestamp" :now="now")
|
span.date.osef {{ fromNow(message.timestamp) }}
|
||||||
.content(v-html="content")
|
.content(v-html="content")
|
||||||
a.embed(v-if="message.embeds" v-for="embed in message.embeds" :href="embed.url") {{ embed.title }}
|
a.embed(v-if="message.embeds" v-for="embed in message.embeds" :href="embed.url") {{ embed.title }}
|
||||||
.react(v-if="message.reactions" v-for="react in message.reactions" :class="{ colored: react.me }")
|
.react(v-if="message.reactions" v-for="react in message.reactions" :class="{ colored: react.me }")
|
||||||
|
@ -12,22 +12,17 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Mixins, Prop } from 'vue-property-decorator'
|
import { Component, Mixins, Prop } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import FromNowMixin from '@/components/FromNowMixin'
|
||||||
import ShowMediaMixin from '@/components/ShowMediaMixin'
|
import ShowMediaMixin from '@/components/ShowMediaMixin'
|
||||||
import fromNow from '@/components/time/FromNow.vue'
|
import { Message as IMessage } from './Types'
|
||||||
import TimedMixin from '@/components/time/TimedMixin'
|
|
||||||
import { Message } from './Types'
|
|
||||||
|
|
||||||
const MAX_LENGTH = 20
|
const MAX_LENGTH = 20
|
||||||
|
|
||||||
@Component({
|
@Component
|
||||||
components:{
|
export default class Message extends Mixins(ShowMediaMixin, FromNowMixin) {
|
||||||
fromNow
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class MessageTag extends Mixins(ShowMediaMixin, TimedMixin) {
|
|
||||||
|
|
||||||
@Prop(Object)
|
@Prop(Object)
|
||||||
readonly message!: Message
|
readonly message!: IMessage
|
||||||
|
|
||||||
get content() {
|
get content() {
|
||||||
let text = this.message.content.split('\n').join('<br />')
|
let text = this.message.content.split('\n').join('<br />')
|
|
@ -2,18 +2,17 @@
|
||||||
.client(@scroll.passive="onScroll")
|
.client(@scroll.passive="onScroll")
|
||||||
.statues
|
.statues
|
||||||
.header(v-if="hasNotifications") Accueil
|
.header(v-if="hasNotifications") Accueil
|
||||||
loadable-block.list(:loadable="statues")
|
success-loadable.list(:loadable="statues")
|
||||||
template(#success)
|
template(v-for="status in statues.get()")
|
||||||
template(v-for="status in statues.get()")
|
status(v-if="showStatus(status)" :key="status.id" :status="status" :showMedia="options.showMedia" @mark="onStatusMark")
|
||||||
status(v-if="showStatus(status)" :key="status.id" :status="status" :now="now" :showMedia="options.showMedia" @mark="onStatusMark")
|
.status(v-show="statues.loadingMore")
|
||||||
.status(v-show="statues.loadingMore")
|
.service-loader
|
||||||
.service-loader
|
|
||||||
.notifications(v-if="hasNotifications")
|
.notifications(v-if="hasNotifications")
|
||||||
.header
|
.header
|
||||||
| Notifications
|
| Notifications
|
||||||
span.date(@click.stop.prevent="onNotificationsClear") ❌
|
span.date(@click.stop.prevent="onNotificationsClear") ❌
|
||||||
.list
|
.list
|
||||||
notification(v-for="notification in notifications.get()" :key="notification.id" :notification="notification" :now="now"
|
notification(v-for="notification in notifications.get()" :key="notification.id" :notification="notification"
|
||||||
:showMedia="options.showMedia" @dismiss="onNotificationDismiss" @mark="onStatusMark")
|
:showMedia="options.showMedia" @dismiss="onNotificationDismiss" @mark="onStatusMark")
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
@ -21,30 +20,22 @@
|
||||||
import axios, { AxiosResponse } from 'axios'
|
import axios, { AxiosResponse } from 'axios'
|
||||||
import { Component, Mixins } from 'vue-property-decorator'
|
import { Component, Mixins } from 'vue-property-decorator'
|
||||||
|
|
||||||
import LoadableBlockVue from '@/components/loadable/LoadableBlock.vue'
|
|
||||||
import ServiceClient from '@/components/ServiceClient'
|
import ServiceClient from '@/components/ServiceClient'
|
||||||
import TimerMixin from '@/components/time/TimerMixin'
|
|
||||||
import Lists from '@/helpers/lists/Lists'
|
import Lists from '@/helpers/lists/Lists'
|
||||||
import AxiosLodable from '@/helpers/loadable/AxiosLoadable'
|
import AxiosLodable from '@/helpers/loadable/AxiosLoadable'
|
||||||
import AxiosLodableMore from '@/helpers/loadable/AxiosLoadableMore'
|
import AxiosLodableMore from '@/helpers/loadable/AxiosLoadableMore'
|
||||||
import { AUTH, getRest } from './Mastodon.vue'
|
import { AUTH, getRest } from './Mastodon.vue'
|
||||||
import NotificationVue from './Notification.vue'
|
import Notification from './Notification.vue'
|
||||||
import StatusVue from './Status.vue'
|
import Status from './Status.vue'
|
||||||
import { MarkMessage, Notification, Options, Status } from './Types'
|
import { MarkMessage, Notification as INotification, Options, Status as IStatus } from './Types'
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Status, Notification } })
|
||||||
components: {
|
export default class Client extends Mixins<ServiceClient<Options>>(ServiceClient) {
|
||||||
status: StatusVue,
|
|
||||||
notification: NotificationVue,
|
|
||||||
loadableBlock: LoadableBlockVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class Client extends Mixins<ServiceClient<Options>>(ServiceClient, TimerMixin) {
|
|
||||||
|
|
||||||
rest = getRest(this.auth, this.options.timeout)
|
rest = getRest(this.auth, this.options.timeout)
|
||||||
|
|
||||||
statues = new AxiosLodableMore<Status[], object>()
|
statues = new AxiosLodableMore<IStatus[], object>()
|
||||||
notifications = new AxiosLodable<Notification[], object>()
|
notifications = new AxiosLodable<INotification[], object>()
|
||||||
|
|
||||||
get hasNotifications() {
|
get hasNotifications() {
|
||||||
if(!this.notifications.isSuccess) {
|
if(!this.notifications.isSuccess) {
|
||||||
|
@ -85,7 +76,7 @@ export default class Client extends Mixins<ServiceClient<Options>>(ServiceClient
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
showStatus(status: Status) {
|
showStatus(status: IStatus) {
|
||||||
return (!status.in_reply_to_id || this.options.reply) && (!status.reblog || this.options.reblog)
|
return (!status.in_reply_to_id || this.options.reply) && (!status.reblog || this.options.reblog)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,9 +32,8 @@ import axios, { AxiosResponse } from 'axios'
|
||||||
import { Component, Mixins } from 'vue-property-decorator'
|
import { Component, Mixins } from 'vue-property-decorator'
|
||||||
|
|
||||||
import AccountService from '@/components/service/AccountService'
|
import AccountService from '@/components/service/AccountService'
|
||||||
import ServiceHeaderVue from '@/components/ServiceHeader.vue'
|
|
||||||
import { Auth } from '@/types/App'
|
import { Auth } from '@/types/App'
|
||||||
import ClientVue from './Client.vue'
|
import Client from './Client.vue'
|
||||||
import { ParseEmojisMixin } from './ParseEmojisMixin'
|
import { ParseEmojisMixin } from './ParseEmojisMixin'
|
||||||
import { Account, Options } from './Types'
|
import { Account, Options } from './Types'
|
||||||
|
|
||||||
|
@ -46,12 +45,7 @@ export function getRest(auth: Auth, timeout: number) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Client } })
|
||||||
components: {
|
|
||||||
client: ClientVue,
|
|
||||||
'service-header': ServiceHeaderVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class Mastodon extends Mixins<AccountService<Account, object>>(AccountService, ParseEmojisMixin) { // TODO: Use oauth
|
export default class Mastodon extends Mixins<AccountService<Account, object>>(AccountService, ParseEmojisMixin) { // TODO: Use oauth
|
||||||
|
|
||||||
get server() {
|
get server() {
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
span.colored.text-icon.letter(v-if="notification.type == 'reblog'") ⟳
|
span.colored.text-icon.letter(v-if="notification.type == 'reblog'") ⟳
|
||||||
span.colored.text-icon.letter(v-if="notification.type == 'favourite'") ⚝
|
span.colored.text-icon.letter(v-if="notification.type == 'favourite'") ⚝
|
||||||
|
|
||||||
from-now.date(:date="notification.created_at" :now="now")
|
span.date {{ fromNow(notification.created_at) }}
|
||||||
|
|
||||||
.content
|
.content
|
||||||
template(v-if="notification.type == 'follow'") Vous suit
|
template(v-if="notification.type == 'follow'") Vous suit
|
||||||
status.reblog(v-else-if="notification.status" :status="notification.status" :now="now"
|
status.reblog(v-else-if="notification.status" :status="notification.status"
|
||||||
:showMedia="showMedia" :withAccount="notification.type != 'mention'" @mark="passMark")
|
:showMedia="showMedia" :withAccount="notification.type != 'mention'" @mark="passMark")
|
||||||
|
|
||||||
a.date(@click.stop.prevent="makeDismiss" style="margin-top: -1em") ❌
|
a.date(@click.stop.prevent="makeDismiss" style="margin-top: -1em") ❌
|
||||||
|
@ -19,21 +19,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Emit, Mixins, Prop } from 'vue-property-decorator'
|
import { Component, Emit, Mixins, Prop } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import FromNowMixin from '@/components/FromNowMixin'
|
||||||
import ShowMediaMixin from '@/components/ShowMediaMixin'
|
import ShowMediaMixin from '@/components/ShowMediaMixin'
|
||||||
import FromNowVue from '@/components/time/FromNow.vue'
|
import Account from './Account.vue'
|
||||||
import TimedMixin from '@/components/time/TimedMixin'
|
import Status from './Status.vue'
|
||||||
import AccountVue from './Account.vue'
|
|
||||||
import StatusVue from './Status.vue'
|
|
||||||
import { MarkMessage, Notification as INotification } from './Types'
|
import { MarkMessage, Notification as INotification } from './Types'
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Account, Status } })
|
||||||
components: {
|
export default class Notification extends Mixins(ShowMediaMixin, FromNowMixin) {
|
||||||
fromNow: FromNowVue,
|
|
||||||
account: AccountVue,
|
|
||||||
status: StatusVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class Notification extends Mixins(TimedMixin, ShowMediaMixin) {
|
|
||||||
|
|
||||||
@Prop(Object)
|
@Prop(Object)
|
||||||
readonly notification!: INotification
|
readonly notification!: INotification
|
||||||
|
|
|
@ -4,8 +4,7 @@
|
||||||
|
|
||||||
span.text-icon.letter(v-if="status.reblog") ⟳
|
span.text-icon.letter(v-if="status.reblog") ⟳
|
||||||
|
|
||||||
a.date(target="_blank" :href="status.uri")
|
a.date(target="_blank" :href="status.uri") {{ fromNow(status.created_at) }}
|
||||||
from-now(:date="status.created_at" :now="now")
|
|
||||||
|
|
||||||
.content(:class="{ avatared: showMedia }")
|
.content(:class="{ avatared: showMedia }")
|
||||||
template(v-if="!status.reblog")
|
template(v-if="!status.reblog")
|
||||||
|
@ -19,7 +18,7 @@
|
||||||
template(v-else) Wrong type
|
template(v-else) Wrong type
|
||||||
.gif(v-if="media.type == 'gifv'") GIF
|
.gif(v-if="media.type == 'gifv'") GIF
|
||||||
template(v-else) Hidden media
|
template(v-else) Hidden media
|
||||||
status.reblog(v-else :status="status.reblog" :now="now" :showMedia="showMedia")
|
status.reblog(v-else :status="status.reblog" :showMedia="showMedia")
|
||||||
|
|
||||||
.meta(v-if="!status.reblog")
|
.meta(v-if="!status.reblog")
|
||||||
a.replies(@click.stop.prevent="makeReply(status)")
|
a.replies(@click.stop.prevent="makeReply(status)")
|
||||||
|
@ -38,20 +37,14 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { Component, Emit, Mixins, Prop } from 'vue-property-decorator'
|
import { Component, Emit, Mixins, Prop } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import FromNowMixin from '@/components/FromNowMixin'
|
||||||
import ShowMediaMixin from '@/components/ShowMediaMixin'
|
import ShowMediaMixin from '@/components/ShowMediaMixin'
|
||||||
import FromNowVue from '@/components/time/FromNow.vue'
|
import Account from './Account.vue'
|
||||||
import TimedMixin from '@/components/time/TimedMixin'
|
|
||||||
import AccountVue from './Account.vue'
|
|
||||||
import { ParseEmojisMixin } from './ParseEmojisMixin'
|
import { ParseEmojisMixin } from './ParseEmojisMixin'
|
||||||
import { MarkMessage, Status as IStatus } from './Types'
|
import { MarkMessage, Status as IStatus } from './Types'
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Account } })
|
||||||
components: {
|
export default class Status extends Mixins(ParseEmojisMixin, ShowMediaMixin, FromNowMixin) {
|
||||||
account: AccountVue,
|
|
||||||
fromNow: FromNowVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class Status extends Mixins(TimedMixin, ParseEmojisMixin, ShowMediaMixin) {
|
|
||||||
|
|
||||||
@Prop(Object)
|
@Prop(Object)
|
||||||
readonly status!: IStatus
|
readonly status!: IStatus
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
template(#success)
|
template(#success)
|
||||||
.news(v-for="line in news.get()")
|
.news(v-for="line in news.get()")
|
||||||
a(:href="line.url" target="_blank")
|
a(:href="line.url" target="_blank")
|
||||||
from-now.date(:date="line.pubDate * 1000" :now="now")
|
span.date {{ fromNow(line.pubDate * 1000) }}
|
||||||
span.read(@click.stop="makeRead(line.id)") 👁
|
span.read(@click.stop="makeRead(line.id)") 👁
|
||||||
span.title(@click.stop="line.open = !line.open") {{ line.author }} ─ {{ line.title }}
|
span.title(@click.stop="line.open = !line.open") {{ line.author }} ─ {{ line.title }}
|
||||||
.content(v-if="line.open && line.body") {{ line.body }}
|
.content(v-if="line.open && line.body") {{ line.body }}
|
||||||
|
@ -35,10 +35,8 @@
|
||||||
import axios, { AxiosInstance, AxiosResponse } from 'axios'
|
import axios, { AxiosInstance, AxiosResponse } from 'axios'
|
||||||
import { Component, Mixins } from 'vue-property-decorator'
|
import { Component, Mixins } from 'vue-property-decorator'
|
||||||
|
|
||||||
|
import FromNowMixin from '@/components/FromNowMixin'
|
||||||
import ConnectedService from '@/components/service/ConnectedService'
|
import ConnectedService from '@/components/service/ConnectedService'
|
||||||
import ServiceHeaderVue from '@/components/ServiceHeader.vue'
|
|
||||||
import FromNowVue from '@/components/time/FromNow.vue'
|
|
||||||
import TimerMixin from '@/components/time/TimerMixin'
|
|
||||||
import Lists from '@/helpers/lists/Lists'
|
import Lists from '@/helpers/lists/Lists'
|
||||||
import AxiosLoadable from '@/helpers/loadable/AxiosLoadable'
|
import AxiosLoadable from '@/helpers/loadable/AxiosLoadable'
|
||||||
import { Auth } from '@/types/App'
|
import { Auth } from '@/types/App'
|
||||||
|
@ -55,13 +53,8 @@ interface News {
|
||||||
|
|
||||||
const AUTH = { SERVER: 'server', USERNAME: 'username', TOKEN: 'token' }
|
const AUTH = { SERVER: 'server', USERNAME: 'username', TOKEN: 'token' }
|
||||||
|
|
||||||
@Component({
|
@Component
|
||||||
components: {
|
export default class NextcloudNews extends Mixins<ConnectedService<object, object>>(ConnectedService, FromNowMixin) { // TODO: handle unread
|
||||||
'service-header': ServiceHeaderVue,
|
|
||||||
fromNow: FromNowVue
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class NextcloudNews extends Mixins<ConnectedService<object, object>>(ConnectedService, TimerMixin) { // TODO: handle unread
|
|
||||||
|
|
||||||
rest!: AxiosInstance // NOTE: set in this.init()
|
rest!: AxiosInstance // NOTE: set in this.init()
|
||||||
news = new AxiosLoadable<News[], object>()
|
news = new AxiosLoadable<News[], object>()
|
||||||
|
|
|
@ -13,9 +13,8 @@
|
||||||
weather(v-for="(city, id) in weathers.get().data" :key="id" :class="{ selected: weathers.get().isSelected(id) }"
|
weather(v-for="(city, id) in weathers.get().data" :key="id" :class="{ selected: weathers.get().isSelected(id) }"
|
||||||
:city="city" @select="makeSelect(id)" @remove="removeCity(id)")
|
:city="city" @select="makeSelect(id)" @remove="removeCity(id)")
|
||||||
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))")
|
||||||
loadable-block.forecast(:loadable="forecast")
|
success-loadable.forecast(:loadable="forecast")
|
||||||
template(#success)
|
chart.chart(:chartData="forecastChart")
|
||||||
chart.chart(:chartData="forecastChart")
|
|
||||||
template(#error)
|
template(#error)
|
||||||
form(@submit.prevent="makeAuth")
|
form(@submit.prevent="makeAuth")
|
||||||
p
|
p
|
||||||
|
@ -30,13 +29,12 @@ import axios, { AxiosInstance, AxiosResponse } from 'axios'
|
||||||
import { Component } from 'vue-property-decorator'
|
import { Component } from 'vue-property-decorator'
|
||||||
|
|
||||||
import ConnectedService from '@/components/service/ConnectedService'
|
import ConnectedService from '@/components/service/ConnectedService'
|
||||||
import ServiceHeaderVue from '@/components/ServiceHeader.vue'
|
|
||||||
import Lists from '@/helpers/lists/Lists'
|
import Lists from '@/helpers/lists/Lists'
|
||||||
import { Selectable } from '@/helpers/lists/Selectable'
|
import { Selectable } from '@/helpers/lists/Selectable'
|
||||||
import AxiosLoadable from '@/helpers/loadable/AxiosLoadable'
|
import AxiosLoadable from '@/helpers/loadable/AxiosLoadable'
|
||||||
import { Auth } from '@/types/App'
|
import { Auth } from '@/types/App'
|
||||||
import Chart from './Chart'
|
import Chart from './Chart'
|
||||||
import WeatherVue, { IWeather } from './Weather.vue'
|
import Weather, { IWeather } from './Weather.vue'
|
||||||
|
|
||||||
interface Forecast {
|
interface Forecast {
|
||||||
dt: number
|
dt: number
|
||||||
|
@ -50,13 +48,7 @@ interface Forecast {
|
||||||
|
|
||||||
const AUTH = { TOKEN: 'token' }
|
const AUTH = { TOKEN: 'token' }
|
||||||
|
|
||||||
@Component({
|
@Component({ components: { Weather, Chart } })
|
||||||
components: {
|
|
||||||
'service-header': ServiceHeaderVue,
|
|
||||||
weather: WeatherVue,
|
|
||||||
chart: Chart
|
|
||||||
}
|
|
||||||
})
|
|
||||||
export default class OpenWeatherMap extends ConnectedService<object, object> {
|
export default class OpenWeatherMap extends ConnectedService<object, object> {
|
||||||
|
|
||||||
rest!: AxiosInstance // NOTE: set in this.init()
|
rest!: AxiosInstance // NOTE: set in this.init()
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { Action, Module, Mutation, VuexModule } from 'vuex-module-decorators'
|
||||||
|
|
||||||
|
export interface TimeState {
|
||||||
|
now: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
@Module({ name: 'time', namespaced: true })
|
||||||
|
export default class Time extends VuexModule implements TimeState {
|
||||||
|
now = new Date
|
||||||
|
|
||||||
|
@Mutation
|
||||||
|
updateTime() {
|
||||||
|
this.now = new Date
|
||||||
|
}
|
||||||
|
|
||||||
|
@Action
|
||||||
|
start() {
|
||||||
|
setInterval(() => {
|
||||||
|
this.updateTime()
|
||||||
|
}, 15 * 1000)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
import Vue from 'vue'
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import { getModule } from 'vuex-module-decorators'
|
||||||
|
import Time from './Time'
|
||||||
|
|
||||||
|
Vue.use(Vuex)
|
||||||
|
|
||||||
|
export interface State {
|
||||||
|
time: Time
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = new Vuex.Store<State>({
|
||||||
|
strict: process.env.NODE_ENV !== 'production',
|
||||||
|
modules: {
|
||||||
|
time: Time
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
export const TimeModule = getModule(Time, store)
|
||||||
|
TimeModule.start()
|
||||||
|
|
||||||
|
export default store
|
|
@ -0,0 +1,4 @@
|
||||||
|
module.exports = {
|
||||||
|
/* ... other settings */
|
||||||
|
transpileDependencies: ["vuex-module-decorators"]
|
||||||
|
}
|
Loading…
Reference in New Issue