mirror of
https://github.com/VueTorrent/VueTorrent.git
synced 2024-11-25 02:45:48 +03:00
Merge pull request #451 from WDaan/feat/rss
feat: basic rss interface (#447)
This commit is contained in:
commit
04cd58c693
15 changed files with 575 additions and 49 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -2,6 +2,9 @@
|
||||||
node_modules
|
node_modules
|
||||||
/dist
|
/dist
|
||||||
|
|
||||||
|
# asdf config
|
||||||
|
.tool-versions
|
||||||
|
|
||||||
# local env files
|
# local env files
|
||||||
.env.local
|
.env.local
|
||||||
.env.*.local
|
.env.*.local
|
||||||
|
|
95
src/components/Modals/Rss/FeedForm.vue
Normal file
95
src/components/Modals/Rss/FeedForm.vue
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
<template>
|
||||||
|
<v-dialog v-model="dialog" content-class="rounded-form" max-width="300px">
|
||||||
|
<v-card>
|
||||||
|
<v-card-title class="pa-0">
|
||||||
|
<v-toolbar-title class="ma-4 primarytext--text">
|
||||||
|
<h3>{{ hasInitialFeed ? $t('edit') : $t('createNew') }} {{ $t('feed') }}</h3>
|
||||||
|
</v-toolbar-title>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-form ref="feedForm" class="px-6 mt-3">
|
||||||
|
<v-container>
|
||||||
|
<v-text-field
|
||||||
|
v-model="feed.url"
|
||||||
|
:label="$t('modals.newFeed.url')"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</v-container>
|
||||||
|
</v-form>
|
||||||
|
</v-card-text>
|
||||||
|
<v-divider />
|
||||||
|
<v-card-actions class="justify-end">
|
||||||
|
<v-btn
|
||||||
|
v-if="!hasInitialFeed"
|
||||||
|
class="accent white--text elevation-0 px-4"
|
||||||
|
@click="create"
|
||||||
|
>
|
||||||
|
{{ $t('create') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
v-else
|
||||||
|
class="accent white--text elevation-0 px-4"
|
||||||
|
@click="edit"
|
||||||
|
>
|
||||||
|
{{ $t('edit') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
class="error white--text elevation-0 px-4"
|
||||||
|
@click="cancel"
|
||||||
|
>
|
||||||
|
{{ $t('cancel') }}
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import qbit from '@/services/qbit'
|
||||||
|
import { Modal } from '@/mixins'
|
||||||
|
import { mdiCancel, mdiTagPlus, mdiPencil } from '@mdi/js'
|
||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'FeedForm',
|
||||||
|
mixins: [Modal],
|
||||||
|
props: {
|
||||||
|
initialFeed: Object
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
feed: { url: '' },
|
||||||
|
mdiCancel, mdiTagPlus, mdiPencil
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getSelectedFeed']),
|
||||||
|
hasInitialFeed() {
|
||||||
|
return !!(this.initialFeed &&
|
||||||
|
this.initialFeed.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$store.commit('FETCH_FEEDS')
|
||||||
|
if (this.hasInitialFeed) {
|
||||||
|
this.feed = this.initialFeed
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
create() {
|
||||||
|
qbit.createFeed(this.feed)
|
||||||
|
this.cancel()
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
this.$store.commit('FETCH_FEEDS')
|
||||||
|
this.dialog = false
|
||||||
|
},
|
||||||
|
edit() {
|
||||||
|
qbit.editfeed(this.feed)
|
||||||
|
Vue.$toast.success(this.$t('toast.feedSaved'))
|
||||||
|
this.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
123
src/components/Modals/Rss/RuleForm.vue
Normal file
123
src/components/Modals/Rss/RuleForm.vue
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<v-dialog v-model="dialog" max-width="300px">
|
||||||
|
<v-card flat>
|
||||||
|
<v-card-title class="pa-0">
|
||||||
|
<v-toolbar-title class="ma-4 primarytext--text">
|
||||||
|
<h3>{{ hasInitialRule ? $t('edit') : $t('createNew') }} {{ $t('rule') }}</h3>
|
||||||
|
</v-toolbar-title>
|
||||||
|
</v-card-title>
|
||||||
|
<v-card-text>
|
||||||
|
<v-form ref="ruleForm" class="px-6 mt-3">
|
||||||
|
<v-container>
|
||||||
|
<v-text-field
|
||||||
|
v-model="rule.name"
|
||||||
|
:label="$t('modals.newRule.name')"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</v-container>
|
||||||
|
<v-container>
|
||||||
|
<v-text-field
|
||||||
|
v-model="rule.def.mustContain"
|
||||||
|
:label="$t('modals.newRule.def.mustContain')"
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</v-container>
|
||||||
|
<v-container>
|
||||||
|
<v-subheader>{{ $t('modals.newRule.def.affectedFeeds') }}</v-subheader>
|
||||||
|
<template v-for="(item, index) in availableFeeds">
|
||||||
|
<v-checkbox
|
||||||
|
:key="index"
|
||||||
|
v-model="rule.def.affectedFeeds"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.url"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</v-container>
|
||||||
|
</v-form>
|
||||||
|
</v-card-text>
|
||||||
|
<v-divider />
|
||||||
|
<v-card-actions class="justify-end">
|
||||||
|
<v-btn
|
||||||
|
v-if="!hasInitialRule"
|
||||||
|
class="accent white--text elevation-0 px-4"
|
||||||
|
@click="create"
|
||||||
|
>
|
||||||
|
{{ $t('create') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
v-else
|
||||||
|
class="accent white--text elevation-0 px-4"
|
||||||
|
@click="edit"
|
||||||
|
>
|
||||||
|
{{ $t('edit') }}
|
||||||
|
</v-btn>
|
||||||
|
<v-btn
|
||||||
|
class="error white--text elevation-0 px-4"
|
||||||
|
@click="cancel"
|
||||||
|
>
|
||||||
|
{{ $t('cancel') }}
|
||||||
|
</v-btn>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import qbit from '@/services/qbit'
|
||||||
|
import { Modal } from '@/mixins'
|
||||||
|
import { mdiCancel, mdiTagPlus, mdiPencil } from '@mdi/js'
|
||||||
|
import Vue from 'vue'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'RuleForm',
|
||||||
|
mixins: [Modal],
|
||||||
|
props: {
|
||||||
|
initialRule: Object
|
||||||
|
},
|
||||||
|
data: () => ({
|
||||||
|
rule: {
|
||||||
|
name: '',
|
||||||
|
def: {
|
||||||
|
mustContain: '',
|
||||||
|
affectedFeeds: [],
|
||||||
|
enabled: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mdiCancel, mdiTagPlus, mdiPencil
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getSelectedRule', 'getFeeds']),
|
||||||
|
availableFeeds() {
|
||||||
|
return this.getFeeds()
|
||||||
|
},
|
||||||
|
hasInitialRule() {
|
||||||
|
return !!(this.initialRule &&
|
||||||
|
this.initialRule.name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$store.commit('FETCH_RULES')
|
||||||
|
if (this.hasInitialRule) {
|
||||||
|
this.rule = this.initialRule
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
create() {
|
||||||
|
qbit.createRule(this.rule.name, this.rule.def)
|
||||||
|
this.cancel()
|
||||||
|
},
|
||||||
|
cancel() {
|
||||||
|
this.$store.commit('FETCH_RULES')
|
||||||
|
this.dialog = false
|
||||||
|
},
|
||||||
|
edit() {
|
||||||
|
qbit.editRule(this.rule)
|
||||||
|
Vue.$toast.success(this.$t('toast.ruleSaved'))
|
||||||
|
this.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style></style>
|
4
src/components/Modals/Rss/index.js
Normal file
4
src/components/Modals/Rss/index.js
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
import FeedForm from './FeedForm.vue'
|
||||||
|
import RuleForm from './RuleForm.vue'
|
||||||
|
|
||||||
|
export { FeedForm, RuleForm }
|
44
src/components/Settings/Tabs/Rss.vue
Normal file
44
src/components/Settings/Tabs/Rss.vue
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
<template>
|
||||||
|
<v-card flat>
|
||||||
|
<v-tabs v-model="tab">
|
||||||
|
<v-tab href="#general">
|
||||||
|
{{ $t('modals.settings.pageRss.tabName.general') }}
|
||||||
|
</v-tab>
|
||||||
|
<v-tab href="#feeds">
|
||||||
|
{{ $t('modals.settings.pageRss.tabName.feeds') }}
|
||||||
|
</v-tab>
|
||||||
|
<v-tab href="#rules">
|
||||||
|
{{ $t('modals.settings.pageRss.tabName.rules') }}
|
||||||
|
</v-tab>
|
||||||
|
</v-tabs>
|
||||||
|
<v-tabs-items v-model="tab" touchless>
|
||||||
|
<v-tab-item eager value="general">
|
||||||
|
<General />
|
||||||
|
</v-tab-item>
|
||||||
|
<v-tab-item eager value="feeds">
|
||||||
|
<Feeds />
|
||||||
|
</v-tab-item>
|
||||||
|
<v-tab-item eager value="rules">
|
||||||
|
<Rules />
|
||||||
|
</v-tab-item>
|
||||||
|
</v-tabs-items>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import General from './Rss/General'
|
||||||
|
import Feeds from './Rss/Feeds'
|
||||||
|
import Rules from './Rss/Rules'
|
||||||
|
import { FullScreenModal } from '@/mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'VueTorrent',
|
||||||
|
components: {
|
||||||
|
General, Feeds, Rules
|
||||||
|
},
|
||||||
|
mixins: [FullScreenModal],
|
||||||
|
data: () => ({
|
||||||
|
tab: null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
</script>
|
69
src/components/Settings/Tabs/Rss/Feeds.vue
Normal file
69
src/components/Settings/Tabs/Rss/Feeds.vue
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<template>
|
||||||
|
<v-card flat>
|
||||||
|
<v-row dense class="ma-0 pa-0">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-subheader>{{ $t('modals.settings.pageRss.pageFeeds.feeds') }}</v-subheader>
|
||||||
|
<template v-for="(item, index) in availableFeeds">
|
||||||
|
<v-list-item :key="item.uid">
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title v-text="item.name" />
|
||||||
|
</v-list-item-content>
|
||||||
|
<v-list-item-action>
|
||||||
|
<v-icon color="red" @click="deleteFeed(item)">
|
||||||
|
{{ mdiDelete }}
|
||||||
|
</v-icon>
|
||||||
|
</v-list-item-action>
|
||||||
|
</v-list-item>
|
||||||
|
<v-divider
|
||||||
|
v-if="index < availableFeeds.length - 1"
|
||||||
|
:key="index"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<v-list-item>
|
||||||
|
<v-btn
|
||||||
|
class="mx-auto accent white--text elevation-0 px-4"
|
||||||
|
@click="createFeed"
|
||||||
|
>
|
||||||
|
{{ $t('modals.settings.pageRss.pageFeeds.btnCreateNew') }}
|
||||||
|
</v-btn>
|
||||||
|
</v-list-item>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import qbit from '@/services/qbit'
|
||||||
|
import { mdiDelete } from '@mdi/js'
|
||||||
|
|
||||||
|
import { Tab, General, FullScreenModal } from '@/mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Feeds',
|
||||||
|
mixins: [Tab, General, FullScreenModal],
|
||||||
|
data: () => ({
|
||||||
|
mdiDelete
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getFeeds']),
|
||||||
|
availableFeeds() {
|
||||||
|
return this.getFeeds()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$store.commit('FETCH_FEEDS')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
activeMethod() {
|
||||||
|
this.$store.commit('FETCH_FEEDS')
|
||||||
|
},
|
||||||
|
deleteFeed(item) {
|
||||||
|
qbit.deleteFeed(item.name)
|
||||||
|
this.$store.commit('FETCH_FEEDS')
|
||||||
|
},
|
||||||
|
createFeed() {
|
||||||
|
this.createModal('FeedForm')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
30
src/components/Settings/Tabs/Rss/General.vue
Normal file
30
src/components/Settings/Tabs/Rss/General.vue
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
<template>
|
||||||
|
<v-card flat>
|
||||||
|
<v-subheader>{{ $t('modals.settings.pageRss.pageGeneral.rssAutoProcessing') }}</v-subheader>
|
||||||
|
<v-list-item>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="settings.rss_processing_enabled"
|
||||||
|
hide-details
|
||||||
|
class="ma-0 pa-0"
|
||||||
|
:label="$t('modals.settings.pageRss.pageGeneral.input.enableRssProcessing')"
|
||||||
|
/>
|
||||||
|
</v-list-item>
|
||||||
|
<v-subheader>{{ $t('modals.settings.pageRss.pageGeneral.rssAutoDownloader') }}</v-subheader>
|
||||||
|
<v-list-item>
|
||||||
|
<v-checkbox
|
||||||
|
v-model="settings.rss_auto_downloading_enabled"
|
||||||
|
hide-details
|
||||||
|
class="ma-0 pa-0"
|
||||||
|
:label="$t('modals.settings.pageRss.pageGeneral.input.enableRssAutoDownload')"
|
||||||
|
/>
|
||||||
|
</v-list-item>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { FullScreenModal, SettingsTab } from '@/mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Rss',
|
||||||
|
mixins: [SettingsTab, FullScreenModal]
|
||||||
|
}
|
||||||
|
</script>
|
69
src/components/Settings/Tabs/Rss/Rules.vue
Normal file
69
src/components/Settings/Tabs/Rss/Rules.vue
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
<template>
|
||||||
|
<v-card flat>
|
||||||
|
<v-row dense class="ma-0 pa-0">
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<v-subheader>{{ $t('modals.settings.pageRss.pageRules.rules') }}</v-subheader>
|
||||||
|
<template v-for="(item, index) in availableRules">
|
||||||
|
<v-list-item :key="item.uid">
|
||||||
|
<v-list-item-content>
|
||||||
|
<v-list-item-title v-text="item.name" />
|
||||||
|
</v-list-item-content>
|
||||||
|
<v-list-item-action>
|
||||||
|
<v-icon color="red" @click="deleteRule(item)">
|
||||||
|
{{ mdiDelete }}
|
||||||
|
</v-icon>
|
||||||
|
</v-list-item-action>
|
||||||
|
</v-list-item>
|
||||||
|
<v-divider
|
||||||
|
v-if="index < availableRules.length - 1"
|
||||||
|
:key="index"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
<v-list-item>
|
||||||
|
<v-btn
|
||||||
|
class="mx-auto accent white--text elevation-0 px-4"
|
||||||
|
@click="createRule"
|
||||||
|
>
|
||||||
|
{{ $t('modals.settings.pageRss.pageRules.btnCreateNew') }}
|
||||||
|
</v-btn>
|
||||||
|
</v-list-item>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-card>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { mapGetters } from 'vuex'
|
||||||
|
import qbit from '@/services/qbit'
|
||||||
|
import { mdiDelete } from '@mdi/js'
|
||||||
|
|
||||||
|
import { Tab, General, FullScreenModal } from '@/mixins'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'Rules',
|
||||||
|
mixins: [Tab, General, FullScreenModal],
|
||||||
|
data: () => ({
|
||||||
|
mdiDelete
|
||||||
|
}),
|
||||||
|
computed: {
|
||||||
|
...mapGetters(['getRules']),
|
||||||
|
availableRules() {
|
||||||
|
return this.getRules()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.$store.commit('FETCH_RULES')
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
activeMethod() {
|
||||||
|
this.$store.commit('FETCH_RULES')
|
||||||
|
},
|
||||||
|
deleteRule(item) {
|
||||||
|
qbit.deleteRule(item.name)
|
||||||
|
this.$store.commit('FETCH_RULES')
|
||||||
|
},
|
||||||
|
createRule() {
|
||||||
|
this.createModal('RuleForm')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -4,5 +4,6 @@ import Downloads from './Downloads.vue'
|
||||||
import VueTorrent from './VueTorrent.vue'
|
import VueTorrent from './VueTorrent.vue'
|
||||||
import TagsAndCategories from './TagsAndCategories.vue'
|
import TagsAndCategories from './TagsAndCategories.vue'
|
||||||
import Connection from './Connection.vue'
|
import Connection from './Connection.vue'
|
||||||
|
import Rss from './Rss.vue'
|
||||||
|
|
||||||
export { WebUI, BitTorrent, Downloads, VueTorrent, TagsAndCategories, Connection }
|
export { WebUI, BitTorrent, Downloads, VueTorrent, TagsAndCategories, Connection, Rss }
|
||||||
|
|
|
@ -84,6 +84,17 @@ const locale = {
|
||||||
|
|
||||||
/** Modals */
|
/** Modals */
|
||||||
modals: {
|
modals: {
|
||||||
|
newFeed: {
|
||||||
|
feedName: 'Name',
|
||||||
|
url: 'URL'
|
||||||
|
},
|
||||||
|
newRule: {
|
||||||
|
name: 'Name',
|
||||||
|
def: {
|
||||||
|
mustContain: 'Must Contain',
|
||||||
|
affectedFeeds: 'Apply Rule to Feeds'
|
||||||
|
}
|
||||||
|
},
|
||||||
pluginManager: {
|
pluginManager: {
|
||||||
title: 'Plugin manager'
|
title: 'Plugin manager'
|
||||||
},
|
},
|
||||||
|
@ -106,6 +117,7 @@ const locale = {
|
||||||
downloads: 'downloads',
|
downloads: 'downloads',
|
||||||
connection: 'connection',
|
connection: 'connection',
|
||||||
bittorrent: 'bittorrent',
|
bittorrent: 'bittorrent',
|
||||||
|
rss: 'Rss',
|
||||||
webUI: 'WEB UI',
|
webUI: 'WEB UI',
|
||||||
tagsAndCategories: 'tags & categories'
|
tagsAndCategories: 'tags & categories'
|
||||||
},
|
},
|
||||||
|
@ -191,6 +203,29 @@ const locale = {
|
||||||
whenRatioReaches: 'When ratio reaches',
|
whenRatioReaches: 'When ratio reaches',
|
||||||
whenSeedingTimeReaches: 'When seeding time reaches'
|
whenSeedingTimeReaches: 'When seeding time reaches'
|
||||||
},
|
},
|
||||||
|
pageRss: {
|
||||||
|
tabName: {
|
||||||
|
general: 'General',
|
||||||
|
feeds: 'Feeds',
|
||||||
|
rules: 'Rules'
|
||||||
|
},
|
||||||
|
pageRules: {
|
||||||
|
rules: 'Rules',
|
||||||
|
btnCreateNew: 'Create Rule'
|
||||||
|
},
|
||||||
|
pageFeeds: {
|
||||||
|
feeds: 'Feeds',
|
||||||
|
btnCreateNew: 'Add feed'
|
||||||
|
},
|
||||||
|
pageGeneral: {
|
||||||
|
rssAutoProcessing: 'RSS Reader',
|
||||||
|
rssAutoDownloader: 'RSS Torrent Auto Downloader',
|
||||||
|
input: {
|
||||||
|
enableRssAutoDownload: 'Enable auto downloading of RSS torrents',
|
||||||
|
enableRssProcessing: 'Enable fetching RSS feeds'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
pageWebUI: {
|
pageWebUI: {
|
||||||
useAlternativeWebUI: 'Use Alternative WebUI',
|
useAlternativeWebUI: 'Use Alternative WebUI',
|
||||||
filesLocation: 'Files location',
|
filesLocation: 'Files location',
|
||||||
|
@ -345,7 +380,9 @@ const locale = {
|
||||||
loginSuccess: 'Successfully logged in! 🎉',
|
loginSuccess: 'Successfully logged in! 🎉',
|
||||||
loginFailed: 'Login failed 😕',
|
loginFailed: 'Login failed 😕',
|
||||||
settingsSaved: 'Settings saved successfully!',
|
settingsSaved: 'Settings saved successfully!',
|
||||||
categorySaved: 'Category edited successfully!'
|
categorySaved: 'Category edited successfully!',
|
||||||
|
feedSaved: 'Feed saved successfully!',
|
||||||
|
ruleSaved: 'Rule saved!'
|
||||||
},
|
},
|
||||||
|
|
||||||
/** RightClick **/
|
/** RightClick **/
|
||||||
|
|
|
@ -154,6 +154,52 @@ class Qbit {
|
||||||
}).then(res => res.data)
|
}).then(res => res.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RSS
|
||||||
|
|
||||||
|
createFeed(feed) {
|
||||||
|
return this.execute('post', '/rss/addFeed', {
|
||||||
|
url: feed.url,
|
||||||
|
path: feed.url
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
createRule(ruleName, defs) {
|
||||||
|
return this.execute('post', '/rss/setRule', {
|
||||||
|
ruleName: ruleName,
|
||||||
|
ruleDef: JSON.stringify(defs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
getFeeds() {
|
||||||
|
return this.axios.get('/rss/items')
|
||||||
|
.then(res => res.data)
|
||||||
|
.then(data =>
|
||||||
|
Object.entries(data).map(feed => {
|
||||||
|
return { name: feed[0], ...feed[1] }
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
getRules() {
|
||||||
|
return this.axios.get('/rss/rules')
|
||||||
|
.then(res => res.data)
|
||||||
|
.then(data =>
|
||||||
|
Object.entries(data).map(rule => {
|
||||||
|
return { name: rule[0], ...rule[1] }
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteRule(ruleName) {
|
||||||
|
return this.execute('post', 'rss/removeRule', {
|
||||||
|
ruleName
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
deleteFeed(name) {
|
||||||
|
return this.execute('post', 'rss/removeItem', {
|
||||||
|
path: name
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Post
|
// Post
|
||||||
|
|
||||||
addTorrents(params, torrents) {
|
addTorrents(params, torrents) {
|
||||||
|
|
|
@ -11,6 +11,8 @@ export default {
|
||||||
getWebuiSettings: state => () => state.webuiSettings,
|
getWebuiSettings: state => () => state.webuiSettings,
|
||||||
getAvailableTags: state => () => state.tags,
|
getAvailableTags: state => () => state.tags,
|
||||||
getCategories: state => () => state.categories,
|
getCategories: state => () => state.categories,
|
||||||
|
getFeeds: state => () => state.rss.feeds,
|
||||||
|
getRules: state => () => state.rss.rules,
|
||||||
getModals: state => () => state.modals,
|
getModals: state => () => state.modals,
|
||||||
getTorrents: state => () => state.torrents,
|
getTorrents: state => () => state.torrents,
|
||||||
getTrackers: state => () => state.trackers,
|
getTrackers: state => () => state.trackers,
|
||||||
|
|
|
@ -22,6 +22,10 @@ export default new Vuex.Store({
|
||||||
state: {
|
state: {
|
||||||
version: 0,
|
version: 0,
|
||||||
intervals: [],
|
intervals: [],
|
||||||
|
rss: {
|
||||||
|
feeds: [],
|
||||||
|
rules: []
|
||||||
|
},
|
||||||
status: {
|
status: {
|
||||||
status: '',
|
status: '',
|
||||||
downloaded: '',
|
downloaded: '',
|
||||||
|
|
|
@ -80,6 +80,8 @@ export default {
|
||||||
state.sort_options.tracker = tracker
|
state.sort_options.tracker = tracker
|
||||||
},
|
},
|
||||||
FETCH_CATEGORIES: async state => state.categories = Object.values(await (qbit.getCategories())),
|
FETCH_CATEGORIES: async state => state.categories = Object.values(await (qbit.getCategories())),
|
||||||
|
FETCH_FEEDS: async state => state.rss.feeds = await qbit.getFeeds(),
|
||||||
|
FETCH_RULES: async state => state.rss.rules = await qbit.getRules(),
|
||||||
FETCH_SEARCH_PLUGINS: async state => state.searchPlugins = await qbit.getSearchPlugins(),
|
FETCH_SEARCH_PLUGINS: async state => state.searchPlugins = await qbit.getSearchPlugins(),
|
||||||
SET_CURRENT_ITEM_COUNT: (state, count) => (state.filteredTorrentsCount = count),
|
SET_CURRENT_ITEM_COUNT: (state, count) => (state.filteredTorrentsCount = count),
|
||||||
SET_LANGUAGE: async state => await loadLanguageAsync(state.webuiSettings.lang)
|
SET_LANGUAGE: async state => await loadLanguageAsync(state.webuiSettings.lang)
|
||||||
|
|
|
@ -1,33 +1,17 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div class="px-1 px-sm-5 background noselect">
|
||||||
class="px-1 px-sm-5 background noselect"
|
<v-row no-gutters class="grey--text" align="center" justify="center">
|
||||||
>
|
|
||||||
<v-row
|
|
||||||
no-gutters
|
|
||||||
class="grey--text"
|
|
||||||
align="center"
|
|
||||||
justify="center"
|
|
||||||
>
|
|
||||||
<v-col>
|
<v-col>
|
||||||
<h1 style="font-size: 1.6em !important" class="subtitle-1 ml-2">
|
<h1 style="font-size: 1.6em !important" class="subtitle-1 ml-2">
|
||||||
{{ $t('settings') | titleCase }}
|
{{ $t("settings") | titleCase }}
|
||||||
</h1>
|
</h1>
|
||||||
</v-col>
|
</v-col>
|
||||||
<v-col class="align-center justify-center">
|
<v-col class="align-center justify-center">
|
||||||
<v-card-actions class="justify-end">
|
<v-card-actions class="justify-end">
|
||||||
<v-btn
|
<v-btn class="accent" small elevation="0" @click="saveSettings">
|
||||||
class="accent"
|
|
||||||
small
|
|
||||||
elevation="0"
|
|
||||||
@click="saveSettings"
|
|
||||||
>
|
|
||||||
<v-icon>{{ mdiContentSave }}</v-icon>
|
<v-icon>{{ mdiContentSave }}</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn
|
<v-btn small elevation="0" @click="close">
|
||||||
small
|
|
||||||
elevation="0"
|
|
||||||
@click="close"
|
|
||||||
>
|
|
||||||
<v-icon>{{ mdiClose }}</v-icon>
|
<v-icon>{{ mdiClose }}</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
</v-card-actions>
|
</v-card-actions>
|
||||||
|
@ -42,26 +26,28 @@
|
||||||
background-color="primary"
|
background-color="primary"
|
||||||
>
|
>
|
||||||
<v-tab class="white--text" href="#vuetorrent">
|
<v-tab class="white--text" href="#vuetorrent">
|
||||||
<h4>{{ $t('modals.settings.tabName.VueTorrent') }}</h4>
|
<h4>{{ $t("modals.settings.tabName.VueTorrent") }}</h4>
|
||||||
</v-tab>
|
</v-tab>
|
||||||
<v-tab class="white--text" href="#downloads">
|
<v-tab class="white--text" href="#downloads">
|
||||||
<h4>{{ $t('modals.settings.tabName.downloads') }}</h4>
|
<h4>{{ $t("modals.settings.tabName.downloads") }}</h4>
|
||||||
</v-tab>
|
</v-tab>
|
||||||
<v-tab class="white--text" href="#connection">
|
<v-tab class="white--text" href="#connection">
|
||||||
<h4>{{ $t('modals.settings.tabName.connection') }}</h4>
|
<h4>{{ $t("modals.settings.tabName.connection") }}</h4>
|
||||||
</v-tab>
|
</v-tab>
|
||||||
<v-tab class="white--text" href="#bittorrent">
|
<v-tab class="white--text" href="#bittorrent">
|
||||||
<h4>{{ $t('modals.settings.tabName.bittorrent') }}</h4>
|
<h4>{{ $t("modals.settings.tabName.bittorrent") }}</h4>
|
||||||
|
</v-tab>
|
||||||
|
<v-tab class="white--text" href="#rss">
|
||||||
|
<h4>{{ $t("modals.settings.tabName.rss") }}</h4>
|
||||||
</v-tab>
|
</v-tab>
|
||||||
<v-tab class="white--text" href="#webui">
|
<v-tab class="white--text" href="#webui">
|
||||||
<h4>{{ $t('modals.settings.tabName.webUI') }}</h4>
|
<h4>{{ $t("modals.settings.tabName.webUI") }}</h4>
|
||||||
</v-tab>
|
</v-tab>
|
||||||
<v-tab class="white--text" href="#tagsAndCategories">
|
<v-tab class="white--text" href="#tagsAndCategories">
|
||||||
<h4>{{ $t('modals.settings.tabName.tagsAndCategories') }}</h4>
|
<h4>{{ $t("modals.settings.tabName.tagsAndCategories") }}</h4>
|
||||||
</v-tab>
|
</v-tab>
|
||||||
</v-tabs>
|
</v-tabs>
|
||||||
|
|
||||||
|
|
||||||
<!--<v-divider />-->
|
<!--<v-divider />-->
|
||||||
<v-card-text class="pa-0">
|
<v-card-text class="pa-0">
|
||||||
<v-tabs-items v-model="tab" touchless>
|
<v-tabs-items v-model="tab" touchless>
|
||||||
|
@ -77,6 +63,9 @@
|
||||||
<v-tab-item eager value="bittorrent">
|
<v-tab-item eager value="bittorrent">
|
||||||
<BitTorrent :is-active="tab === 'bittorrent'" />
|
<BitTorrent :is-active="tab === 'bittorrent'" />
|
||||||
</v-tab-item>
|
</v-tab-item>
|
||||||
|
<v-tab-item eager value="rss">
|
||||||
|
<Rss :is-active="tab === 'rss'" />
|
||||||
|
</v-tab-item>
|
||||||
<v-tab-item eager value="webui">
|
<v-tab-item eager value="webui">
|
||||||
<WebUI :is-active="tab === 'webui'" />
|
<WebUI :is-active="tab === 'webui'" />
|
||||||
</v-tab-item>
|
</v-tab-item>
|
||||||
|
@ -90,46 +79,54 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from "vuex";
|
||||||
import { mdiClose, mdiContentSave } from '@mdi/js'
|
import { mdiClose, mdiContentSave } from "@mdi/js";
|
||||||
import {
|
import {
|
||||||
WebUI,
|
WebUI,
|
||||||
BitTorrent,
|
BitTorrent,
|
||||||
Downloads,
|
Downloads,
|
||||||
VueTorrent,
|
VueTorrent,
|
||||||
TagsAndCategories,
|
TagsAndCategories,
|
||||||
Connection
|
Connection,
|
||||||
} from '@/components/Settings/Tabs'
|
} from "@/components/Settings/Tabs";
|
||||||
import { SettingsTab } from '../mixins'
|
import { SettingsTab } from "../mixins";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Settings',
|
name: "Settings",
|
||||||
components: { WebUI, BitTorrent, Downloads, VueTorrent, TagsAndCategories, Connection },
|
components: {
|
||||||
|
WebUI,
|
||||||
|
BitTorrent,
|
||||||
|
Downloads,
|
||||||
|
VueTorrent,
|
||||||
|
TagsAndCategories,
|
||||||
|
Connection,
|
||||||
|
},
|
||||||
mixins: [SettingsTab],
|
mixins: [SettingsTab],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
tab: null,
|
tab: null,
|
||||||
items: [],
|
items: [],
|
||||||
peers: [],
|
peers: [],
|
||||||
mdiClose, mdiContentSave
|
mdiClose,
|
||||||
}
|
mdiContentSave,
|
||||||
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['getSettings']),
|
...mapGetters(["getSettings"]),
|
||||||
settings() {
|
settings() {
|
||||||
return this.getSettings()
|
return this.getSettings();
|
||||||
},
|
},
|
||||||
isPhone() {
|
isPhone() {
|
||||||
return this.$vuetify.breakpoint.xsOnly
|
return this.$vuetify.breakpoint.xsOnly;
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$store.dispatch('FETCH_SETTINGS')
|
this.$store.dispatch("FETCH_SETTINGS");
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
close() {
|
close() {
|
||||||
this.$router.back()
|
this.$router.back();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
Loading…
Reference in a new issue