mirror of https://github.com/nocodb/nocodb
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
4.9 KiB
182 lines
4.9 KiB
2 years ago
|
<script setup lang="ts">
|
||
|
import { useToast } from 'vue-toastification'
|
||
2 years ago
|
import AppInstall from './AppStore/AppInstall.vue'
|
||
2 years ago
|
import MdiEditIcon from '~icons/ic/round-edit'
|
||
|
import MdiCloseCircleIcon from '~icons/mdi/close-circle-outline'
|
||
|
import MdiPlusIcon from '~icons/mdi/plus'
|
||
|
const { $api, $e } = useNuxtApp()
|
||
|
const toast = useToast()
|
||
|
|
||
2 years ago
|
let apps = $ref<null | Array<any>>(null)
|
||
|
let showPluginUninstallModal = $ref(false)
|
||
|
let showPluginInstallModal = $ref(false)
|
||
|
let pluginApp = $ref<any>(null)
|
||
2 years ago
|
|
||
2 years ago
|
const fetchPluginApps = async () => {
|
||
2 years ago
|
try {
|
||
|
const plugins = (await $api.plugin.list()).list ?? []
|
||
|
|
||
2 years ago
|
apps = plugins.map((p) => ({
|
||
2 years ago
|
...p,
|
||
|
tags: p.tags ? p.tags.split(',') : [],
|
||
|
parsedInput: p.input && JSON.parse(p.input),
|
||
|
}))
|
||
|
} catch (e) {
|
||
|
console.error(e)
|
||
2 years ago
|
toast.error('Something went wrong')
|
||
2 years ago
|
}
|
||
|
}
|
||
|
|
||
2 years ago
|
const resetPlugin = async () => {
|
||
2 years ago
|
try {
|
||
2 years ago
|
await $api.plugin.update(pluginApp.id, {
|
||
2 years ago
|
input: undefined,
|
||
|
active: false,
|
||
|
})
|
||
|
toast.success('Plugin uninstalled successfully')
|
||
2 years ago
|
showPluginUninstallModal = false
|
||
|
await fetchPluginApps()
|
||
2 years ago
|
} catch (e: any) {
|
||
|
console.log(e)
|
||
|
toast.error(e.message)
|
||
|
}
|
||
|
|
||
2 years ago
|
$e('a:appstore:reset', { app: pluginApp.title })
|
||
2 years ago
|
}
|
||
|
|
||
|
const saved = async () => {
|
||
2 years ago
|
showPluginInstallModal = false
|
||
|
await fetchPluginApps()
|
||
|
$e('a:appstore:install', { app: pluginApp.title })
|
||
2 years ago
|
}
|
||
|
|
||
2 years ago
|
const showInstallPluginModal = async (app: any) => {
|
||
|
showPluginInstallModal = true
|
||
|
pluginApp = app
|
||
2 years ago
|
|
||
|
$e('c:appstore:install', { app: app.title })
|
||
|
}
|
||
|
|
||
2 years ago
|
const showResetPluginModal = async (app: any) => {
|
||
|
showPluginUninstallModal = true
|
||
|
pluginApp = app
|
||
2 years ago
|
}
|
||
|
|
||
|
onMounted(async () => {
|
||
2 years ago
|
if (apps === null) {
|
||
|
fetchPluginApps()
|
||
2 years ago
|
}
|
||
|
})
|
||
|
</script>
|
||
|
|
||
|
<template>
|
||
2 years ago
|
<a-modal v-model:visible="showPluginInstallModal" :closable="false" centered min-height="300" :footer="null">
|
||
2 years ago
|
<AppInstall
|
||
|
v-if="pluginApp && showPluginInstallModal"
|
||
|
:id="pluginApp.id"
|
||
|
@close="showPluginInstallModal = false"
|
||
|
@saved="saved()"
|
||
|
/>
|
||
|
</a-modal>
|
||
|
|
||
2 years ago
|
<a-modal v-model:visible="showPluginUninstallModal" :closable="false" width="24rem" centered :footer="null">
|
||
2 years ago
|
<div class="flex flex-col h-full">
|
||
2 years ago
|
<div class="flex flex-row justify-center mt-2 text-center w-full text-base">
|
||
|
{{ `Click on confirm to reset ${pluginApp && pluginApp.title}` }}
|
||
2 years ago
|
</div>
|
||
2 years ago
|
<div class="flex mt-6 justify-center space-x-2">
|
||
2 years ago
|
<a-button @click="showPluginUninstallModal = false"> Cancel </a-button>
|
||
2 years ago
|
<a-button type="primary" danger @click="resetPlugin"> Confirm </a-button>
|
||
2 years ago
|
</div>
|
||
|
</div>
|
||
|
</a-modal>
|
||
|
|
||
|
<div class="h-full overflow-y-scroll grid grid-cols-2 gap-x-2 gap-y-4">
|
||
2 years ago
|
<a-card
|
||
|
v-for="(app, i) in apps"
|
||
|
:key="i"
|
||
|
class="relative flex overflow-x-hidden app-item-card !shadow-sm rounded-md w-full"
|
||
|
:body-style="{ width: '100%' }"
|
||
|
>
|
||
2 years ago
|
<div class="install-btn flex flex-row justify-end space-x-1">
|
||
2 years ago
|
<a-button v-if="app.parsedInput" size="small" outlined @click="showInstallPluginModal(app)">
|
||
|
<div class="flex flex-row justify-center items-center caption capitalize">
|
||
|
<MdiEditIcon class="pr-0.5" :height="12" />
|
||
2 years ago
|
Edit
|
||
|
</div>
|
||
|
</a-button>
|
||
2 years ago
|
<a-button v-if="app.parsedInput" size="small" outlined @click="showResetPluginModal(app)">
|
||
|
<div class="flex flex-row justify-center items-center caption capitalize">
|
||
2 years ago
|
<MdiCloseCircleIcon />
|
||
|
<div class="flex ml-0.5">Reset</div>
|
||
|
</div>
|
||
|
</a-button>
|
||
2 years ago
|
<a-button v-else size="small" outlined @click="showInstallPluginModal(app)">
|
||
|
<div class="flex flex-row justify-center items-center caption capitalize">
|
||
2 years ago
|
<MdiPlusIcon />
|
||
|
Install
|
||
|
</div>
|
||
|
</a-button>
|
||
|
</div>
|
||
|
|
||
|
<div class="flex flex-row space-x-2 items-center justify-start w-full">
|
||
2 years ago
|
<div class="flex w-20 pl-3">
|
||
|
<img
|
||
|
v-if="app.title !== 'SMTP'"
|
||
|
class="avatar"
|
||
2 years ago
|
:style="{
|
||
|
backgroundColor: app.title === 'SES' ? '#242f3e' : '',
|
||
|
}"
|
||
|
:src="`/${app.logo}`"
|
||
2 years ago
|
/>
|
||
|
<div v-else />
|
||
2 years ago
|
</div>
|
||
2 years ago
|
<div class="flex flex-col flex-grow-1 w-3/5 pl-3">
|
||
2 years ago
|
<a-typography-title :level="5">{{ app.title }}</a-typography-title>
|
||
|
{{ app.description }}
|
||
|
</div>
|
||
|
</div>
|
||
|
</a-card>
|
||
|
</div>
|
||
|
</template>
|
||
|
|
||
|
<style scoped lang="scss">
|
||
|
.app-item-card {
|
||
|
position: relative;
|
||
|
transition: 0.4s background-color;
|
||
|
|
||
|
.install-btn {
|
||
|
position: absolute;
|
||
|
opacity: 1;
|
||
|
right: -100%;
|
||
|
top: 10px;
|
||
|
transition: 0.4s opacity, 0.4s right;
|
||
|
}
|
||
|
|
||
|
&:hover .install-btn {
|
||
|
right: 10px;
|
||
|
opacity: 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.app-item-card {
|
||
|
transition: 0.4s background-color, 0.4s transform;
|
||
|
|
||
|
&:hover {
|
||
|
background: rgba(123, 126, 136, 0.1) !important;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
.caption {
|
||
2 years ago
|
font-size: 0.7rem;
|
||
2 years ago
|
color: #242f3e;
|
||
|
}
|
||
2 years ago
|
|
||
|
.avatar {
|
||
|
width: 5rem;
|
||
|
height: 5rem;
|
||
|
padding: 0.25rem;
|
||
|
object-fit: contain;
|
||
|
}
|
||
2 years ago
|
</style>
|