Skip to content

Commit

Permalink
frontend: Add extension manifest settings
Browse files Browse the repository at this point in the history
  • Loading branch information
JoaoMario109 committed May 21, 2024
1 parent 830bdec commit d7458a2
Show file tree
Hide file tree
Showing 2 changed files with 405 additions and 2 deletions.
381 changes: 381 additions & 0 deletions core/frontend/src/components/kraken/ExtensionSettings.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,381 @@
<template>
<v-dialog v-model="settings_open" width="500px">
<v-card min-width="100%">
<v-app-bar>
<v-toolbar-title>Extensions Manifest</v-toolbar-title>
<v-spacer />
</v-app-bar>
<v-card class="px-3 pb-3 mx-2" elevation="0">
<v-list>
<v-card-subtitle class="text-md-center" max-width="30">
Drag manifest sources to set priority. <br /><b>Top ones have higher priority.</b>
</v-card-subtitle>
<draggable v-model="manifests">
<v-card
v-for="(element, index) in manifests"
:key="index"
class="pl-3 ma-2 pa-1 d-flex align-center justify-center"
style="cursor: pointer;"
>
{{ order(index + 1) }}
<v-spacer />
{{ element.name }}
<v-spacer />
<v-btn
icon
:disabled="element.factory"
tooltip="Delete Source"
@click="removeSource(element.identifier)"
>
<v-icon>mdi-delete</v-icon>
</v-btn>
<v-btn
icon
@click="setEditingModal(element)"
>
<v-icon>{{ element.factory ? 'mdi-pencil-lock' : 'mdi-pencil' }}</v-icon>
</v-btn>
<v-icon v-text="'mdi-drag'" />
</v-card>
</draggable>
<v-card
class="ma-2 py-1 mt-4 d-flex align-center justify-center"
@click.prevent="setCreateModal"
>
<v-spacer />
<v-icon>mdi-plus</v-icon>
<v-spacer />
</v-card>
</v-list>
<v-alert
v-if="has_operation_error"
class="mx-2"
type="error"
>
{{ operation_error }}
</v-alert>
<v-progress-linear
v-if="operation_loading"
indeterminate
min-width="300"
/>
<v-divider />
<v-card-actions class="justify-center mt-1">
<v-btn
color="primary"
@click="settings_open = false"
>
Cancel
</v-btn>
<v-spacer />
<v-btn
color="success"
@click="reorderSources"
>
Apply
</v-btn>
</v-card-actions>
</v-card>
</v-card>
<v-dialog v-model="operation_open" width="600px">
<v-card elevation="0">
<v-card-title class="mb-7">
{{ is_editing ? 'Update Source' : 'Add a new source' }}
</v-card-title>
<v-card-subtitle class="text-md-center" max-width="30">
<b>Factory sources can only be enabled/disabled.</b>
</v-card-subtitle>
<v-text-field
v-model="source_url"
:disabled="is_factory"
class="mx-6"
label="URL"
outlined
dense
@input="deductNameFromURL"
/>
<v-text-field
v-model="source_name"
:disabled="is_factory"
class="mx-6 pr-8"
label="Name"
outlined
dense
@input="blockNameAutoComplete"
/>
<v-checkbox
v-model="source_enabled"
class="mx-6 mt-0"
label="Source Enabled"
/>
<v-divider />
<v-card-actions class="justify-center pb-4 mt-3 mx-1">
<v-btn
color="primary"
@click="operation_open = false"
>
Cancel
</v-btn>
<v-spacer />
<v-btn
color="success"
@click="applySubModalAction"
>
Apply
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-dialog>
</template>

<script lang="ts">
import Vue from 'vue'
import { Manifest, ManifestSource } from '@/types/kraken'
import back_axios from '@/utils/api'
const KRAKEN_API_V2_URL = '/kraken/v2.0'
export default Vue.extend({
name: 'ExtensionSettings',
props: {
value: {
type: Boolean,
required: true,
},
},
data() {
return {
settings_open: false,
operation_open: false,
operation_loading: false,
operation_error: undefined as string | undefined,
source_name: '',
source_url: '',
source_enabled: true,
allow_deduct_name: true,
source_url_copy_icon: 'mdi-content-copy',
editing_source: undefined as Manifest | undefined,
manifests: [] as Manifest[],
}
},
computed: {
is_editing(): boolean {
return this.editing_source !== undefined
},
is_factory(): boolean {
return this.editing_source?.factory ?? false
},
has_operation_error(): boolean {
return this.operation_error !== undefined
},
},
watch: {
value(val) {
this.settings_open = val
if (val) {
this.fetchManifestsSources()
}
},
settings_open(val) {
this.$emit('input', val)
if (!val) {
this.$emit('refresh')
}
},
},
methods: {
order(index: number): string {
// Based over: https://stackoverflow.com/a/39466341
return `${index}${['st', 'nd', 'rd'][((index + 90) % 100 - 10) % 10 - 1] || 'th'}`
},
copyURLToClipboard() {
navigator.clipboard.writeText(this.source_url)
this.source_url_copy_icon = 'mdi-check'
setTimeout(() => {
this.source_url_copy_icon = 'mdi-content-copy'
}, 500)
},
blockNameAutoComplete() {
this.allow_deduct_name = false
},
deductNameFromURL() {
if (!(this.allow_deduct_name && URL.canParse(this.source_url))) {
return
}
const cut_path = new URL(this.source_url).pathname.slice(1)
if (cut_path === '') {
return
}
const parts = cut_path.split('/').filter((part) => !part.endsWith('.json') && !part.endsWith('.txt'))
this.source_name = `${parts[0] ?? ''} ${parts[1] ?? ''}`.trim()
},
prepareRequest() {
this.operation_loading = true
this.operation_error = undefined
},
setDefaultModal() {
this.source_name = ''
this.source_url = ''
this.source_enabled = true
this.editing_source = undefined
this.allow_deduct_name = true
},
setEditingModal(manifest: Manifest) {
this.source_name = manifest.name
this.source_url = manifest.url
this.source_enabled = manifest.enabled
this.editing_source = manifest
this.allow_deduct_name = false
this.operation_open = true
},
setCreateModal() {
this.setDefaultModal()
this.operation_open = true
},
async applySubModalAction() {
// Close the sub modal as soon as applied since errors and loading are performed on main modal
this.operation_open = false
if (this.is_editing) {
if (this.is_factory) {
await this.setSourceEnable(this.editing_source!.identifier, this.source_enabled)
} else {
await this.updateSource(
this.editing_source!.identifier,
this.source_name,
this.source_url,
this.source_enabled,
)
}
} else {
await this.addSource(this.source_name, this.source_url, this.source_enabled)
}
},
async fetchManifestsSources() {
this.prepareRequest()
try {
const sources = await back_axios({
method: 'get',
url: `${KRAKEN_API_V2_URL}/manifest/?data=false`,
timeout: 20000,
})
this.manifests = sources.data as Manifest[]
} catch (error) {
this.operation_error = `Unable to fetch manifest sources: ${error}`
} finally {
this.operation_loading = false
}
},
async addSource(name: string, url: string, enabled: boolean) {
this.prepareRequest()
try {
const source = { name, url, enabled } as ManifestSource
await back_axios({
method: 'post',
url: `${KRAKEN_API_V2_URL}/manifest/`,
data: source,
timeout: 20000,
})
this.fetchManifestsSources()
} catch (error) {
this.operation_error = `Unable to add manifest source: ${error}`
} finally {
this.operation_loading = false
}
},
async removeSource(identifier: string) {
this.prepareRequest()
try {
await back_axios({
method: 'delete',
url: `${KRAKEN_API_V2_URL}/manifest/${identifier}`,
timeout: 15000,
})
this.fetchManifestsSources()
} catch (error) {
this.operation_error = `Unable to remove manifest source: ${error}`
} finally {
this.operation_loading = false
}
},
async updateSource(identifier: string, name: string, url: string, enabled: boolean) {
this.prepareRequest()
try {
const source = { name, url, enabled } as ManifestSource
await back_axios({
method: 'put',
url: `${KRAKEN_API_V2_URL}/manifest/${identifier}/details`,
data: source,
timeout: 20000,
})
this.fetchManifestsSources()
} catch (error) {
this.operation_error = `Unable to update manifest source: ${error}`
} finally {
this.operation_loading = false
}
},
async reorderSources() {
this.prepareRequest()
const ids = this.manifests.map((manifest) => manifest.identifier)
try {
await back_axios({
method: 'put',
url: `${KRAKEN_API_V2_URL}/manifest/orders`,
data: ids,
timeout: 20000,
})
// After some successful apply we should close the main modal to keep consistency
this.settings_open = false
} catch (error) {
this.operation_error = `Unable to update order: ${error}`
} finally {
this.operation_loading = false
}
},
async setSourceEnable(identifier: string, enable: boolean) {
this.prepareRequest()
try {
const postfix = enable ? 'enable' : 'disable'
await back_axios({
method: 'post',
url: `${KRAKEN_API_V2_URL}/manifest/${identifier}/${postfix}`,
timeout: 10000,
})
this.fetchManifestsSources()
} catch (error) {
this.operation_error = `Unable to ${enable ? 'enable' : 'disable'} source: ${error}`
} finally {
this.operation_loading = false
}
},
},
})
</script>

0 comments on commit d7458a2

Please sign in to comment.