feat: Add import / export settings button (#659) @Larsluph

This commit is contained in:
Rémi Marseault 2023-02-27 15:46:57 +01:00 committed by GitHub
parent bf9484b142
commit 7caa19ab88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 255 additions and 15 deletions

9
package-lock.json generated
View file

@ -11,6 +11,7 @@
"apexcharts": "^3.35.0",
"axios": "^0.26.1",
"dayjs": "^1.10.4",
"jsonschema": "^1.4.1",
"lodash": "^4.17.21",
"quick-score": "^0.2.0",
"typeface-roboto": "^1.1.13",
@ -5382,6 +5383,14 @@
"node": ">=0.10.0"
}
},
"node_modules/jsonschema": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.4.1.tgz",
"integrity": "sha512-S6cATIPVv1z0IlxdN+zUk5EPjkGCdnhN4wVSBlvoUO1tOLJootbo9CquNJmbIh4yikWHiUedhRYrNPn1arpEmQ==",
"engines": {
"node": "*"
}
},
"node_modules/kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",

View file

@ -14,6 +14,7 @@
"apexcharts": "^3.35.0",
"axios": "^0.26.1",
"dayjs": "^1.10.4",
"jsonschema": "^1.4.1",
"lodash": "^4.17.21",
"quick-score": "^0.2.0",
"typeface-roboto": "^1.1.13",

View file

@ -207,8 +207,15 @@
</v-col>
</v-row>
</v-list-item>
<v-list-item>
<v-textarea v-model="settingsField" />
</v-list-item>
<v-list-item class="remove-after justify-content-evenly">
<v-btn @click="importSettings">{{ $t('modals.settings.pageVueTorrent.pageGeneral.importSettings') }}</v-btn>
<v-btn @click="exportSettings">{{ $t('modals.settings.pageVueTorrent.pageGeneral.exportSettings') }}</v-btn>
</v-list-item>
<v-list-item class="justify-center pb-2">
<v-btn @click="resetSettings"> {{ $t('modals.settings.pageVueTorrent.pageGeneral.resetSettings') }} </v-btn>
<v-btn dark color="red" @click="resetSettings">{{ $t('modals.settings.pageVueTorrent.pageGeneral.resetSettings') }}</v-btn>
</v-list-item>
</v-card>
</template>
@ -217,16 +224,21 @@
import { mapState, mapGetters } from 'vuex'
import { Qbit } from '@/services/qbit'
import { LOCALES } from '@/lang/locales'
import {TitleOptions} from "@/enums/vuetorrent";
import { General } from '@/mixins'
import { TitleOptions } from '@/enums/vuetorrent'
import { validate } from 'jsonschema'
import { StoreState } from '@/schemas'
export default {
name: 'VueTorrent-General',
mixins: [General],
data() {
return {
languages: LOCALES,
paginationSizes: [5, 15, 30, 50],
titleOptions: [TitleOptions.DEFAULT, TitleOptions.GLOBAL_SPEED, TitleOptions.FIRST_TORRENT_STATUS],
Qbitversion: 0
Qbitversion: 0,
settingsField: ''
}
},
computed: {
@ -243,6 +255,32 @@ export default {
async fetchQbitVersion() {
this.Qbitversion = await Qbit.getAppVersion()
},
importSettings() {
let isValidJson = true
let userState
try {
userState = JSON.parse(this.settingsField)
let validatorResult = validate(userState, StoreState)
console.log(userState)
console.log(validatorResult)
if (!validatorResult.valid)
isValidJson = false
} catch (e) {
console.log(e)
isValidJson = false
}
if (!isValidJson) {
this.$toast.error(this.$t('toast.invalidJson').toString())
return
}
window.localStorage.setItem('vuetorrent', this.settingsField)
location.reload()
},
exportSettings() {
this.settingsField = window.localStorage.getItem('vuetorrent') ?? ''
},
resetSettings() {
window.localStorage.clear()
location.reload()
@ -261,4 +299,11 @@ export default {
@import 'src/styles/styles.scss';
@include reverse-switch;
}
.justify-content-evenly {
justify-content: space-evenly;
}
.remove-after::after {
content: unset;
}
</style>

View file

@ -24,7 +24,7 @@
"inactive": "Inactive",
"stalled": "Stalled",
"errored": "Errored",
"login": "Login in",
"login": "Log in",
"logout": "Log out",
"shutdownApp": "Shutdown Application",
"download": "Download",
@ -50,6 +50,7 @@
"yes": "yes",
"no": "no",
"filter": "Filter",
"close": "Close",
"dashboard": {
"tooltips": {
"toggleSearch": "Toggle Search Filter",
@ -190,6 +191,8 @@
"openSideBarOnStart": "Open Side Bar on launch",
"currentVersion": "Current Version:",
"qbittorrentVersion": "QBittorrent Version:",
"importSettings": "Import Settings",
"exportSettings": "Export Settings",
"resetSettings": "Reset Settings"
},
"pageDashboard": {
@ -505,7 +508,8 @@
"pasteSuccess": "Text pasted!",
"pasteNotSupported": "Unable to paste, context isn't secured",
"shutdownSuccess": "qBittorrent was shutdown successfully!",
"shutdownError": "Unable to shutdown app. Make sure qBittorrent is running!"
"shutdownError": "Unable to shutdown app. Make sure qBittorrent is running!",
"invalidJson": "Invalid JSON!"
},
"rightClick": {
"resume": "resume",

View file

@ -47,6 +47,7 @@
"yes": "oui",
"no": "non",
"filter": "Filtre",
"close": "Fermer",
"dashboard": {
"tooltips": {
"toggleSearch": "Rechercher un torrent",
@ -185,7 +186,10 @@
"dateFormat": "Format de date",
"openSideBarOnStart": "Ouvrir la barre latérale au lancement",
"currentVersion": "Version actuelle:",
"qbittorrentVersion": "Version de QBittorrent:"
"qbittorrentVersion": "Version de QBittorrent:",
"importSettings": "Importer la configuration",
"exportSettings": "Exporter la configuration",
"resetSettings": "Réinitialiser la configuration"
},
"pageDashboard": {
"busyTorrentTip": "Propriétés à afficher pour les torrents occupés",
@ -491,6 +495,7 @@
"copySuccess": "Texte copié!",
"copyNotSupported": "Impossible de copier, le contexte n'est pas sécurisé",
"pasteSuccess": "Texte collé!",
"invalidJson": "JSON invalide!"
"pasteNotSupported": "Impossible de coller, le contexte n'est pas sécurisé"
},
"rightClick": {

170
src/schemas/StoreState.json Normal file
View file

@ -0,0 +1,170 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"sort_options": {
"type": "object",
"properties": {
"isCustomSortEnabled": {
"type": "boolean"
},
"sort": {
"type": "string"
},
"reverse": {
"type": "boolean"
},
"filter": {
"type": ["string", "null"]
},
"category": {
"type": ["string", "null"]
},
"tag": {
"type": ["string", "null"]
},
"tracker": {
"type": ["string", "null"]
}
},
"required": [
"isCustomSortEnabled",
"sort",
"reverse",
"filter",
"category",
"tag",
"tracker"
]
},
"webuiSettings": {
"type": "object",
"properties": {
"lang": {
"type": "string"
},
"darkTheme": {
"type": "boolean"
},
"showFreeSpace": {
"type": "boolean"
},
"showSpeedGraph": {
"type": "boolean"
},
"showSessionStat": {
"type": "boolean"
},
"showAlltimeStat": {
"type": "boolean"
},
"showCurrentSpeed": {
"type": "boolean"
},
"showTrackerFilter": {
"type": "boolean"
},
"showSpeedInTitle": {
"type": "boolean"
},
"deleteWithFiles": {
"type": "boolean"
},
"title": {
"type": "string"
},
"rightDrawer": {
"type": "boolean"
},
"topPagination": {
"type": "boolean"
},
"paginationSize": {
"type": "integer"
},
"dateFormat": {
"type": "string"
},
"openSideBarOnStart": {
"type": "boolean"
},
"busyTorrentProperties": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"active": {
"type": "boolean"
},
"label": {
"type": "string"
}
},
"required": [
"name",
"active",
"label"
]
}
]
},
"doneTorrentProperties": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"active": {
"type": "boolean"
},
"label": {
"type": "string"
}
},
"required": [
"name",
"active",
"label"
]
}
]
}
},
"required": [
"lang",
"darkTheme",
"showFreeSpace",
"showSpeedGraph",
"showSessionStat",
"showAlltimeStat",
"showCurrentSpeed",
"showTrackerFilter",
"showSpeedInTitle",
"deleteWithFiles",
"title",
"rightDrawer",
"topPagination",
"paginationSize",
"dateFormat",
"openSideBarOnStart",
"busyTorrentProperties",
"doneTorrentProperties"
]
},
"authenticated": {
"type": "boolean"
}
},
"required": [
"sort_options",
"webuiSettings",
"authenticated"
]
}

3
src/schemas/index.ts Normal file
View file

@ -0,0 +1,3 @@
import StoreState from './StoreState.json'
export { StoreState }

View file

@ -92,7 +92,6 @@ export class QBitApi {
const params: Parameters = {
sort: !payload.isCustomSortEnabled ? payload.sort : null,
reverse: !payload.isCustomSortEnabled ? payload.reverse : null,
hashes: payload.hashes.length > 0 ? payload.hashes.join('|') : null,
filter: payload.filter ? payload.filter : null,
category: payload.category !== null ? payload.category : null,
tag: payload.tag !== null ? payload.tag : null

View file

@ -7,6 +7,7 @@ import mutations from './mutations'
import type { StoreState } from '@/types/vuetorrent'
import { Status } from '@/models'
import { TitleOptions } from '@/enums/vuetorrent'
import {AppPreferences} from "@/types/qbit/models";
const vuexPersist = new VuexPersist<StoreState>({
key: 'vuetorrent',
@ -67,12 +68,11 @@ export default new Vuex.Store<StoreState>({
searchPlugins: [],
selectMode: false,
selected_torrents: [],
settings: null,
settings: {} as AppPreferences,
sort_options: {
isCustomSortEnabled: false,
sort: 'priority',
reverse: false,
hashes: [],
filter: null,
category: null,
tag: null,

View file

@ -70,8 +70,7 @@ export default {
FETCH_SETTINGS: async (state: StoreState, settings: AppPreferences) => {
state.settings = settings
},
UPDATE_SORT_OPTIONS: (state: StoreState, { hashes = [], filter = null, category = null, tag = null, tracker = null }) => {
state.sort_options.hashes = hashes
UPDATE_SORT_OPTIONS: (state: StoreState, { filter = null, category = null, tag = null, tracker = null }) => {
state.sort_options.filter = filter
state.sort_options.category = category
state.sort_options.tag = tag

View file

@ -5,7 +5,6 @@ export default interface SortOptions {
isCustomSortEnabled: boolean
sort: string
reverse: boolean
hashes: string[]
filter: Optional<TorrentState>
category: Optional<string>
tag: Optional<string>

View file

@ -4,7 +4,6 @@ import type Category from '../qbit/models/Category'
import type Torrent from '@/models/Torrent'
import type SortOptions from './SortOptions'
import type { AppPreferences } from '../qbit/models'
import type { Optional } from '@/global'
import type ModalTemplate from './ModalTemplate'
import type { Status } from '@/models'
import type WebUISettings from '@/types/vuetorrent/WebUISettings'
@ -30,7 +29,7 @@ export default interface StoreState {
searchPlugins: SearchPlugin[]
selectMode: boolean
selected_torrents: string[]
settings: Optional<AppPreferences>
settings: AppPreferences
sort_options: SortOptions
status: Status
tags: string[]

View file

@ -126,8 +126,15 @@ exports[`General > render correctly 1`] = `
</a></v-col-stub>
</v-row-stub>
</v-list-item-stub>
<v-list-item-stub data-v-7da6d3e2=\\"\\" activeclass=\\"\\" tag=\\"div\\">
<v-textarea-stub data-v-7da6d3e2=\\"\\" errorcount=\\"1\\" errormessages=\\"\\" messages=\\"\\" rules=\\"\\" successmessages=\\"\\" value=\\"\\" backgroundcolor=\\"\\" loaderheight=\\"2\\" clearicon=\\"$clear\\" type=\\"text\\" rowheight=\\"24\\" rows=\\"5\\"></v-textarea-stub>
</v-list-item-stub>
<v-list-item-stub data-v-7da6d3e2=\\"\\" activeclass=\\"\\" tag=\\"div\\" class=\\"remove-after justify-content-evenly\\">
<v-btn-stub data-v-7da6d3e2=\\"\\" tag=\\"button\\" activeclass=\\"\\" type=\\"button\\"></v-btn-stub>
<v-btn-stub data-v-7da6d3e2=\\"\\" tag=\\"button\\" activeclass=\\"\\" type=\\"button\\"></v-btn-stub>
</v-list-item-stub>
<v-list-item-stub data-v-7da6d3e2=\\"\\" activeclass=\\"\\" tag=\\"div\\" class=\\"justify-center pb-2\\">
<v-btn-stub data-v-7da6d3e2=\\"\\" tag=\\"button\\" activeclass=\\"\\" type=\\"button\\"> </v-btn-stub>
<v-btn-stub data-v-7da6d3e2=\\"\\" color=\\"red\\" dark=\\"true\\" tag=\\"button\\" activeclass=\\"\\" type=\\"button\\"></v-btn-stub>
</v-list-item-stub>
</v-card-stub>"
`;