Skip to content

Commit

Permalink
feat: add plugin settings by grouping extensions and plugins under "a…
Browse files Browse the repository at this point in the history
…ddon"
  • Loading branch information
caro3801 committed Oct 3, 2024
1 parent 7770ca4 commit a95b832
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 28 deletions.
8 changes: 4 additions & 4 deletions src/components/Addon/AddonCardInstance.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ import { useI18n } from 'vue-i18n'
import AddonCard from '@/components/Addon/AddonCard'
import { useCore } from '@/composables/core'
import { ADDON_TYPE, addonTypeValidator } from '@/enums/addons'
const EXTENSION = 'extension'
const props = defineProps({
addonType: { type: String, validator: (s) => ['extension', 'plugin'].includes(s.toLowerCase()) },
addonType: { type: String, validator: addonTypeValidator },
id: { type: String, required: true },
name: { type: String, required: true },
version: { type: String, required: true },
Expand Down Expand Up @@ -49,10 +49,10 @@ const recommendedVersion = computed(() => {
const homepage = computed(() => props.deliverableFromRegistry?.homepage ?? null)
const addonInstallFn = computed(() => {
return props.addonType === EXTENSION ? core.api.installExtensionFromId : core.api.installPluginFromId
return props.addonType === ADDON_TYPE.EXTENSION ? core.api.installExtensionFromId : core.api.installPluginFromId
})
const addonUninstallFn = computed(() => {
return props.addonType === EXTENSION ? core.api.uninstallExtension : core.api.uninstallPlugin
return props.addonType === ADDON_TYPE.EXTENSION ? core.api.uninstallExtension : core.api.uninstallPlugin
})
async function install() {
const toast = {
Expand Down
21 changes: 21 additions & 0 deletions src/enums/addons.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// SINGULAR
const EXTENSION = 'extension'
const PLUGIN = 'plugin'
export const ADDON_TYPE = Object.freeze({
EXTENSION,
PLUGIN
})
export const ADDON_TYPES = Object.values(ADDON_TYPE)

export const addonTypeValidator = (s) => ADDON_TYPES.includes(s.toLowerCase())

// PLURAL
const EXTENSIONS = 'extensions'
const PLUGINS = 'plugins'
export const ADDONS_TYPE = Object.freeze({
EXTENSIONS,
PLUGINS
})
export const ADDONS_TYPES = Object.values(ADDONS_TYPE)

export const addonsTypeValidator = (s) => ADDONS_TYPES.includes(s)
20 changes: 12 additions & 8 deletions src/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -1162,17 +1162,21 @@
},
"document-processing":{"title": "Document Processing" },
"batch-tasks":{"title": "Batch Tasks" },
"plugins":{"title": "Plugins" },

"addons": {
"installFromUrl": "Install from a URL",
"install": "Install"
},
"extensions":{
"title": "Extensions",
"info": "Extensions are programs that you add to Datashare's back-end to add new features to store and manipulate data.",
"searchPlaceholder": "Search extensions"
"install": "Install",
"plugins":{
"title": "Plugins",
"info": "Plugins are front-end modules to add new features in Datashare's user interface.",
"searchPlaceholder": "Search plugins"
},
"extensions":{
"title": "Extensions",
"info": "Extensions are back-end modules to add new features to store and manipulate data with Datashare.",
"searchPlaceholder": "Search extensions"
}
}

},
"serverSettings": {
"title": "Server Settings",
Expand Down
6 changes: 4 additions & 2 deletions src/router/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,8 @@ export const routes = [
{
name: 'settings.plugins',
path: 'plugins',
component: () => import('@/views/Settings/SettingsViewPlugins'),
component: () => import('@/views/Settings/SettingsViewAddons'),
props: { addonsType: 'plugins' },
meta: {
title: 'Plugins',
breadcrumb: false
Expand All @@ -438,7 +439,8 @@ export const routes = [
{
name: 'settings.extensions',
path: 'extensions',
component: () => import('@/views/Settings/SettingsViewExtensions'),
component: () => import('@/views/Settings/SettingsViewAddons'),
props: { addonsType: 'extensions' },
meta: {
title: 'Extensions',
breadcrumb: false
Expand Down
4 changes: 2 additions & 2 deletions src/views/Settings/SettingsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ const tabs = computed(() => [
{ icon: 'moon', title: t('settings.appearance.title'), name: 'settings.appearance' },
{ icon: 'file-text', title: t('settings.document-processing.title'), name: 'settings.document-processing' },
{ icon: 'rocket-launch', title: t('settings.batch-tasks.title'), name: 'settings.batch-tasks' },
{ icon: 'monitor', title: t('settings.plugins.title'), name: 'settings.plugins' },
{ icon: 'database', title: t('settings.extensions.title'), name: 'settings.extensions' }
{ icon: 'monitor', title: t('settings.addons.plugins.title'), name: 'settings.plugins' },
{ icon: 'database', title: t('settings.addons.extensions.title'), name: 'settings.extensions' }
])
</script>

Expand Down
116 changes: 116 additions & 0 deletions src/views/Settings/SettingsViewAddons.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<script setup>
/**
* A list of extensions for the frontend.
*/
import { computed, onBeforeMount, ref } from 'vue'
import { uniqueId } from 'lodash'
import { useI18n } from 'vue-i18n'
import Fuse from 'fuse.js'
import { useCore } from '@/composables/core'
import AddonUrlInput from '@/components/Addon/AddonUrlInput'
import AddonCardInstance from '@/components/Addon/AddonCardInstance'
import SettingsViewLayout from '@/views/Settings/SettingsViewLayout'
import { ADDONS_TYPE, addonsTypeValidator } from '@/enums/addons'
defineOptions({ name: 'SettingsViewAddons' })
const props = defineProps({ addonsType: { type: String, validator: addonsTypeValidator } })
const { toastedPromise, core, wait } = useCore()
const { t } = useI18n()
const loaderId = uniqueId(`${props.addonType}-loader-`)
const addons = ref([])
const url = ref('')
const isLoading = ref(false)
const filterTerm = ref('')
onBeforeMount(() => {
return loadAddons()
})
async function installFromUrl(urlToInstall) {
isLoading.value = true
try {
const toast = {
successMessage: t(`${props.addonType}.submitSuccess`),
errorMessage: t(`${props.addonType}.submitError`)
}
const promise = installAddonFromUrlFn.value(urlToInstall)
await toastedPromise(promise, toast)
} catch (e) {
} finally {
isLoading.value = false
url.value = ''
}
}
const infoLabel = computed(() => t(`settings.addons.${props.addonsType}.info`))
const dismissInfoLabel = computed(() => t('settings.layout.infoDismiss'))
const searchPlaceholder = computed(() => t(`settings.addons.${props.addonsType}.searchPlaceholder`))
const installAddonFromUrlFn = computed(() =>
props.addonType === ADDONS_TYPE.EXTENSIONS
? core.api.installExtensionFromUrl.bind(core.api)
: core.api.installPluginFromUrl.bind(core.api)
)
const retrieveAddonsFn = computed(() =>
props.addonsType === ADDONS_TYPE.EXTENSIONS
? core.api.getExtensions.bind(core.api)
: core.api.getPlugins.bind(core.api)
)
async function loadAddons(searchTerm) {
wait.start(loaderId)
try {
addons.value = await retrieveAddonsFn.value(searchTerm)
} catch (e) {
console.log('err', e)
} finally {
wait.end(loaderId)
}
}
const fuse = computed(() => {
const options = {
includeScore: true,
keys: ['deliverableFromRegistry.name', 'name'],
shouldSort: true
}
return new Fuse(addons.value, options)
})
const filteredAddons = computed(() => {
if (filterTerm.value.length > 0) {
return fuse.value.search(filterTerm.value).map((r) => r.item)
}
return addons.value
})
</script>
<template>
<settings-view-layout info-name="extensions" :info-label="infoLabel" :dismiss-info-label="dismissInfoLabel">
<template #filter
><form-control-search v-model="filterTerm" :placeholder="searchPlaceholder" clear-text
/></template>
<div class="col-8">
<addon-url-input v-model="url" :loading="isLoading" @install="installFromUrl" />
</div>
<v-wait :for="loaderId" class="row g-4">
<div v-for="addon in filteredAddons" :key="addon.id" class="col-12 col-xl-6 d-flex">
<addon-card-instance
:id="addon.id"
addon-type="extension"
:name="addon.name"
:version="addon.version"
:description="addon.description"
:installed="addon.installed"
:deliverable-from-registry="addon.deliverableFromRegistry"
@installed="addon.installed = true"
@uninstalled="addon.installed = false"
/>
</div>
</v-wait>
</settings-view-layout>
</template>

<style scoped lang="scss"></style>
12 changes: 0 additions & 12 deletions src/views/Settings/SettingsViewPlugins.vue

This file was deleted.

0 comments on commit a95b832

Please sign in to comment.