First component to use vuex
All checks were successful
repod / nextcloud (push) Successful in 55s
repod / nodejs (push) Successful in 1m55s

This commit is contained in:
Michel Roux 2023-07-07 18:38:53 +02:00
parent e46925718d
commit 1a9ae3c5c7
8 changed files with 85 additions and 46 deletions

11
package-lock.json generated
View File

@ -17,7 +17,8 @@
"vue": "^2", "vue": "^2",
"vue-fragment": "^1.6.0", "vue-fragment": "^1.6.0",
"vue-material-design-icons": "^5.2.0", "vue-material-design-icons": "^5.2.0",
"vue-router": "^3" "vue-router": "^3",
"vuex": "^3"
}, },
"devDependencies": { "devDependencies": {
"@nextcloud/babel-config": "^1.0.0", "@nextcloud/babel-config": "^1.0.0",
@ -13066,6 +13067,14 @@
"vue": "^2.5.0" "vue": "^2.5.0"
} }
}, },
"node_modules/vuex": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
"integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
"peerDependencies": {
"vue": "^2.0.0"
}
},
"node_modules/watchpack": { "node_modules/watchpack": {
"version": "2.4.0", "version": "2.4.0",
"resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",

View File

@ -26,7 +26,8 @@
"vue": "^2", "vue": "^2",
"vue-fragment": "^1.6.0", "vue-fragment": "^1.6.0",
"vue-material-design-icons": "^5.2.0", "vue-material-design-icons": "^5.2.0",
"vue-router": "^3" "vue-router": "^3",
"vuex": "^3"
}, },
"browserslist": [ "browserslist": [
"extends @nextcloud/browserslist-config" "extends @nextcloud/browserslist-config"

View File

@ -1,8 +1,8 @@
<template> <template>
<ul> <ul>
<NcAppNavigationNewItem :title="t('', 'Add a RSS link')"> <NcAppNavigationNewItem :title="t('Add a RSS link')">
<template #icon> <template #icon>
<Plus size="20" /> <Plus :size="20" />
</template> </template>
</NcAppNavigationNewItem> </NcAppNavigationNewItem>
</ul> </ul>
@ -19,7 +19,6 @@ export default {
Plus, Plus,
}, },
methods: { methods: {
}, },
} }
</script> </script>

View File

@ -1,8 +1,10 @@
import Vuex, { Store } from 'vuex'
import { translate, translatePlural } from '@nextcloud/l10n' import { translate, translatePlural } from '@nextcloud/l10n'
import App from './App.vue' import App from './App.vue'
import { Plugin } from 'vue-fragment' import { Plugin } from 'vue-fragment'
import Vue from 'vue' import Vue from 'vue'
import { generateFilePath } from '@nextcloud/router' import { generateFilePath } from '@nextcloud/router'
import modules from './modules/index.js'
import router from './router.js' import router from './router.js'
// eslint-disable-next-line // eslint-disable-next-line
@ -13,13 +15,18 @@ const n = (...args) => translatePlural('repod', ...args)
Vue.mixin({ methods: { t, n } }) Vue.mixin({ methods: { t, n } })
Vue.use(Plugin) Vue.use(Plugin)
Vue.use(Vuex)
Vue.prototype.OC = window.OC Vue.prototype.OC = window.OC
Vue.prototype.OCA = window.OCA Vue.prototype.OCA = window.OCA
Vue.prototype.OCP = window.OCP Vue.prototype.OCP = window.OCP
Vue.prototype.AppConfig = window.oc_appconfig Vue.prototype.AppConfig = window.oc_appconfig
const store = new Store({ modules })
export default new Vue({ export default new Vue({
el: '#content', el: '#content',
router, router,
store,
render: h => h(App), render: h => h(App),
}) })

5
src/modules/index.js Normal file
View File

@ -0,0 +1,5 @@
import { subscriptions } from './subscriptions.js'
export default {
subscriptions,
}

View File

@ -0,0 +1,53 @@
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
export const subscriptions = {
namespaced: true,
state: {
subscriptions: [],
},
getters: {
sortedSubscriptions: (state) => state.subscriptions.concat().sort((a, b) => {
if (a.title && b.title) return a.title.localeCompare(b.title)
return a.id - b.id
}),
},
mutations: {
add: (state, subscription) => {
const subscriptionId = state.subscriptions.findIndex(sub => sub.url === subscription.url)
if (subscriptionId === -1) {
state.subscriptions.push(subscription)
} else {
state.subscriptions[subscriptionId] = subscription
}
},
delete: (state, subscription) => {
const subscriptionId = state.subscriptions.findIndex(sub => sub.url === subscription.url)
delete state.subscriptions[subscriptionId]
},
},
actions: {
fetchAll: async (context) => {
const metrics = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/metrics'))
for (const subscriptionId in metrics.data.subscriptions) {
context.commit('add', {
id: subscriptionId,
url: metrics.data.subscriptions[subscriptionId].url,
loading: true,
})
}
for (const subscription of context.state.subscriptions) {
context.dispatch('fetchMeta', subscription)
}
},
fetchMeta: async (context, subscription) => {
try {
const podcasts = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/podcast_data?url={url}', { url: subscription.url }))
context.commit('add', { ...podcasts.data.data, ...subscription, ...{ loading: false } })
} catch (e) {
console.error(e)
}
},
},
}

View File

@ -2,7 +2,7 @@
<div class="main"> <div class="main">
<p> <p>
<NcTextField :value.sync="search" :label="t('Find a podcast')"> <NcTextField :value.sync="search" :label="t('Find a podcast')">
<Magnify size="20" /> <Magnify :size="20" />
</NcTextField> </NcTextField>
</p> </p>
<Top v-if="!search" /> <Top v-if="!search" />

View File

@ -5,13 +5,13 @@
<router-link to="/discover"> <router-link to="/discover">
<NcAppNavigationNew :text="t('Add a podcast')"> <NcAppNavigationNew :text="t('Add a podcast')">
<template #icon> <template #icon>
<Plus size="20" /> <Plus :size="20" />
</template> </template>
</NcAppNavigationNew> </NcAppNavigationNew>
</router-link> </router-link>
<NcLoadingIcon v-if="loading" /> <NcLoadingIcon v-if="loading" />
<ul v-if="!loading"> <ul v-if="!loading">
<NcAppNavigationItem v-for="subscription in sortedSubscriptions" <NcAppNavigationItem v-for="subscription in subscriptions"
:key="subscription.id" :key="subscription.id"
:loading="subscription.loading" :loading="subscription.loading"
:title="subscription.title ?? subscription.url"> :title="subscription.title ?? subscription.url">
@ -38,8 +38,6 @@ import {
NcLoadingIcon, NcLoadingIcon,
} from '@nextcloud/vue' } from '@nextcloud/vue'
import Plus from 'vue-material-design-icons/Plus.vue' import Plus from 'vue-material-design-icons/Plus.vue'
import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs' import { showError } from '@nextcloud/dialogs'
export default { export default {
@ -55,55 +53,22 @@ export default {
}, },
data() { data() {
return { return {
subscriptions: [],
loading: true, loading: true,
} }
}, },
computed: { computed: {
sortedSubscriptions() { subscriptions() {
return this.subscriptions.concat().sort((a, b) => { return this.$store.getters['subscriptions/sortedSubscriptions']
if (a.title && b.title) return a.title.localeCompare(b.title)
return a.id - b.id
})
}, },
}, },
async mounted() { async mounted() {
try { try {
const metrics = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/metrics')) await this.$store.dispatch('subscriptions/fetchAll')
for (const subscriptionId in metrics.data.subscriptions) {
this.addSubscription({
id: subscriptionId,
url: metrics.data.subscriptions[subscriptionId].url,
loading: true,
})
}
for (const subscription of this.subscriptions) {
this.updateSubscriptionMeta(subscription)
}
} catch (e) { } catch (e) {
console.error(e) console.error(e)
showError(t('Could not fetch subscriptions')) showError(t('Could not fetch subscriptions'))
} }
this.loading = false this.loading = false
}, },
methods: {
addSubscription(subscription) {
const subscriptionId = this.subscriptions.findIndex(sub => sub.url === subscription.url)
if (subscriptionId === -1) {
this.subscriptions.push(subscription)
} else {
this.subscriptions[subscriptionId] = subscription
}
},
async updateSubscriptionMeta(subscription) {
try {
const podcasts = await axios.get(generateUrl('/apps/gpoddersync/personal_settings/podcast_data?url={url}', { url: subscription.url }))
this.addSubscription({ ...podcasts.data.data, ...subscription, ...{ loading: false } })
} catch (e) {
console.error(e)
}
},
},
} }
</script> </script>