Browse Source

refactor/gui-v2-store-ui-and-code-cleanup

pull/2798/head
Muhammed Mustafa 2 years ago
parent
commit
6c90083ad4
  1. 50
      packages/nc-gui-v2/components/dashboard/settings/AppStore/AppInstall.vue
  2. 104
      packages/nc-gui-v2/components/dashboard/settings/AppStore/index.vue
  3. 19
      packages/nc-gui-v2/package-lock.json
  4. 1
      packages/nc-gui-v2/package.json

50
packages/nc-gui-v2/components/dashboard/settings/AppStore/AppInstall.vue

@ -15,45 +15,45 @@ const emits = defineEmits(['saved'])
const toast = useToast() const toast = useToast()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const plugin = ref<any>(null)
const pluginFormData = ref<any>({})
const formRef = ref() const formRef = ref()
const isLoading = ref(true) let plugin = $ref<any>(null)
const loadingAction = ref<null | string>(null) let pluginFormData = $ref<any>({})
let isLoading = $ref(true)
let loadingAction = $ref<null | string>(null)
const saveSettings = async () => { const saveSettings = async () => {
loadingAction.value = 'save' loadingAction = 'save'
try { try {
await formRef.value?.validateFields() await formRef.value?.validateFields()
await $api.plugin.update(id, { await $api.plugin.update(id, {
input: JSON.stringify(pluginFormData.value), input: JSON.stringify(pluginFormData),
active: true, active: true,
}) })
emits('saved') emits('saved')
toast.success(plugin.value.formDetails.msgOnInstall || 'Plugin settings saved successfully') toast.success(plugin.formDetails.msgOnInstall || 'Plugin settings saved successfully')
} catch (_e: any) { } catch (_e: any) {
const e = await extractSdkResponseErrorMsg(_e) const e = await extractSdkResponseErrorMsg(_e)
toast.error(e.message) toast.error(e.message)
} finally { } finally {
loadingAction.value = null loadingAction = null
} }
} }
const addSetting = () => { const addSetting = () => {
pluginFormData.value.push({}) pluginFormData.push({})
} }
const testSettings = async () => { const testSettings = async () => {
loadingAction.value = 'test' loadingAction = 'test'
try { try {
const res = await $api.plugin.test({ const res = await $api.plugin.test({
input: pluginFormData.value, input: pluginFormData,
id: plugin.value?.id, id: plugin?.id,
category: plugin.value?.category, category: plugin?.category,
title: plugin.value?.title, title: plugin?.title,
}) })
if (res) { if (res) {
toast.success('Successfully tested plugin settings') toast.success('Successfully tested plugin settings')
@ -64,7 +64,7 @@ const testSettings = async () => {
const e = await extractSdkResponseErrorMsg(_e) const e = await extractSdkResponseErrorMsg(_e)
toast.error(e.message) toast.error(e.message)
} finally { } finally {
loadingAction.value = null loadingAction = null
} }
} }
@ -83,35 +83,34 @@ const doAction = async (action: { key: string }) => {
const readPluginDetails = async () => { const readPluginDetails = async () => {
try { try {
isLoading.value = true isLoading = true
const res = await $api.plugin.read(id) const res = await $api.plugin.read(id)
const formDetails = JSON.parse(res.input_schema ?? '{}') const formDetails = JSON.parse(res.input_schema ?? '{}')
const emptyParsedInput = formDetails.array ? [{}] : {} const emptyParsedInput = formDetails.array ? [{}] : {}
const parsedInput = res.input ? JSON.parse(res.input) : emptyParsedInput const parsedInput = res.input ? JSON.parse(res.input) : emptyParsedInput
plugin.value = { ...res, formDetails, parsedInput } plugin = { ...res, formDetails, parsedInput }
pluginFormData.value = plugin.value.parsedInput pluginFormData = plugin.parsedInput
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} finally { } finally {
isLoading.value = false isLoading = false
} }
} }
const deleteRow = (index: number) => { const deleteFormRow = (index: number) => {
pluginFormData.value.splice(index, 1) pluginFormData.splice(index, 1)
} }
onMounted(async () => { onMounted(async () => {
if (plugin.value === null) { if (plugin === null) {
await readPluginDetails() await readPluginDetails()
} }
}) })
</script> </script>
<template> <template>
<div> <div v-if="isLoading" class="flex flex-row w-full justify-center items-center h-52">
<div v-if="isLoading" class="flex flex-row w-full justify-center">
<a-spin size="large" /> <a-spin size="large" />
</div> </div>
<template v-else> <template v-else>
@ -167,7 +166,7 @@ onMounted(async () => {
</a-form-item> </a-form-item>
</td> </td>
<td v-if="itemIndex !== 0" class="pb-4"> <td v-if="itemIndex !== 0" class="pb-4">
<MdiDeleteOutlineIcon class="hover:text-red-400 cursor-pointer" @click="deleteRow(itemIndex)" /> <MdiDeleteOutlineIcon class="hover:text-red-400 cursor-pointer" @click="deleteFormRow(itemIndex)" />
</td> </td>
</tr> </tr>
</tbody> </tbody>
@ -225,7 +224,6 @@ onMounted(async () => {
</a-form> </a-form>
</div> </div>
</template> </template>
</div>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

104
packages/nc-gui-v2/components/dashboard/settings/AppStore/index.vue

@ -1,5 +1,4 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'
import { useToast } from 'vue-toastification' import { useToast } from 'vue-toastification'
import AppInstall from './AppInstall.vue' import AppInstall from './AppInstall.vue'
import MdiEditIcon from '~icons/ic/round-edit' import MdiEditIcon from '~icons/ic/round-edit'
@ -8,63 +7,64 @@ import MdiPlusIcon from '~icons/mdi/plus'
const { $api, $e } = useNuxtApp() const { $api, $e } = useNuxtApp()
const toast = useToast() const toast = useToast()
const apps = ref<null | Array<any>>(null) let apps = $ref<null | Array<any>>(null)
const showPluginUninstallModal = ref(false) let showPluginUninstallModal = $ref(false)
const showPluginInstallModal = ref(false) let showPluginInstallModal = $ref(false)
const pluginApp = ref<any>(null) let pluginApp = $ref<any>(null)
const loadPluginList = async () => { const fetchPluginApps = async () => {
try { try {
const plugins = (await $api.plugin.list()).list ?? [] const plugins = (await $api.plugin.list()).list ?? []
apps.value = plugins.map((p) => ({ apps = plugins.map((p) => ({
...p, ...p,
tags: p.tags ? p.tags.split(',') : [], tags: p.tags ? p.tags.split(',') : [],
parsedInput: p.input && JSON.parse(p.input), parsedInput: p.input && JSON.parse(p.input),
})) }))
} catch (e) { } catch (e) {
console.error(e) console.error(e)
toast.error('Something went wrong')
} }
} }
const confirmResetPlugin = async () => { const resetPlugin = async () => {
try { try {
await $api.plugin.update(pluginApp.value.id, { await $api.plugin.update(pluginApp.id, {
input: undefined, input: undefined,
active: false, active: false,
}) })
toast.success('Plugin uninstalled successfully') toast.success('Plugin uninstalled successfully')
showPluginUninstallModal.value = false showPluginUninstallModal = false
await loadPluginList() await fetchPluginApps()
} catch (e: any) { } catch (e: any) {
console.log(e) console.log(e)
toast.error(e.message) toast.error(e.message)
} }
$e('a:appstore:reset', { app: pluginApp.value.title }) $e('a:appstore:reset', { app: pluginApp.title })
} }
const saved = async () => { const saved = async () => {
showPluginInstallModal.value = false showPluginInstallModal = false
await loadPluginList() await fetchPluginApps()
$e('a:appstore:install', { app: pluginApp.value.title }) $e('a:appstore:install', { app: pluginApp.title })
} }
const installApp = async (app: any) => { const showInstallPluginModal = async (app: any) => {
showPluginInstallModal.value = true showPluginInstallModal = true
pluginApp.value = app pluginApp = app
$e('c:appstore:install', { app: app.title }) $e('c:appstore:install', { app: app.title })
} }
const resetApp = async (app: any) => { const showResetPluginModal = async (app: any) => {
showPluginUninstallModal.value = true showPluginUninstallModal = true
pluginApp.value = app pluginApp = app
} }
onMounted(async () => { onMounted(async () => {
if (apps.value === null) { if (apps === null) {
loadPluginList() fetchPluginApps()
} }
}) })
</script> </script>
@ -79,12 +79,14 @@ onMounted(async () => {
/> />
</a-modal> </a-modal>
<a-modal v-model:visible="showPluginUninstallModal" min-width="400px" max-width="700px" min-height="300" :footer="null"> <a-modal v-model:visible="showPluginUninstallModal" width="22rem" centered :footer="null">
<div class="flex flex-col"> <div class="flex flex-col h-full">
<div class="flex">{{ `Please click on submit to reset ${pluginApp && pluginApp.title}` }}</div> <div class="flex flex-row justify-center mt-2 text-center w-full">
<div class="flex mt-6 justify-center space-x-2"> {{ `Are you sure you to reset ${pluginApp && pluginApp.title}` }}
</div>
<div class="flex mt-10 justify-center space-x-2">
<a-button @click="showPluginUninstallModal = false"> Cancel </a-button> <a-button @click="showPluginUninstallModal = false"> Cancel </a-button>
<a-button type="primary" @click="confirmResetPlugin"> Submit </a-button> <a-button type="primary" danger @click="resetPlugin"> Reset </a-button>
</div> </div>
</div> </div>
</a-modal> </a-modal>
@ -93,29 +95,34 @@ onMounted(async () => {
<v-card v-if="pluginApp"> <v-card v-if="pluginApp">
<v-card-text> Please confirm to reset {{ pluginApp.title }} </v-card-text> <v-card-text> Please confirm to reset {{ pluginApp.title }} </v-card-text>
<v-card-actions> <v-card-actions>
<v-btn color="primary" @click="confirmResetPlugin"> Yes </v-btn> <v-btn color="primary" @click="resetPlugin"> Yes </v-btn>
<v-btn @click="showPluginUninstallModal = false"> No </v-btn> <v-btn @click="showPluginUninstallModal = false"> No </v-btn>
</v-card-actions> </v-card-actions>
</v-card> </v-card>
</v-dialog> </v-dialog>
<div class="h-full overflow-y-scroll grid grid-cols-2 gap-x-2 gap-y-4"> <div class="h-full overflow-y-scroll grid grid-cols-2 gap-x-2 gap-y-4">
<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" :bodyStyle="{width: '100%'}"> <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%' }"
>
<div class="install-btn flex flex-row justify-end space-x-1"> <div class="install-btn flex flex-row justify-end space-x-1">
<a-button v-if="app.parsedInput" size="small" outlined class="!caption capitalize" @click="installApp(app)"> <a-button v-if="app.parsedInput" size="small" outlined @click="showInstallPluginModal(app)">
<div class="flex flex-row justify-center items-center"> <div class="flex flex-row justify-center items-center caption capitalize">
<MdiEditIcon :height="12" /> <MdiEditIcon class="pr-0.5" :height="12" />
Edit Edit
</div> </div>
</a-button> </a-button>
<a-button v-if="app.parsedInput" size="small" outlined class="caption capitalize" @click="resetApp(app)"> <a-button v-if="app.parsedInput" size="small" outlined @click="showResetPluginModal(app)">
<div class="flex flex-row justify-center items-center"> <div class="flex flex-row justify-center items-center caption capitalize">
<MdiCloseCircleIcon /> <MdiCloseCircleIcon />
<div class="flex ml-0.5">Reset</div> <div class="flex ml-0.5">Reset</div>
</div> </div>
</a-button> </a-button>
<a-button v-else size="small" outlined class="caption capitalize" @click="installApp(app)"> <a-button v-else size="small" outlined @click="showInstallPluginModal(app)">
<div class="flex flex-row justify-center items-center"> <div class="flex flex-row justify-center items-center caption capitalize">
<MdiPlusIcon /> <MdiPlusIcon />
Install Install
</div> </div>
@ -123,18 +130,18 @@ onMounted(async () => {
</div> </div>
<div class="flex flex-row space-x-2 items-center justify-start w-full"> <div class="flex flex-row space-x-2 items-center justify-start w-full">
<div class="flex w-20 px-4"> <div class="flex w-20 pl-3">
<a-avatar <img
shape="circle" v-if="app.title !== 'SMTP'"
class="avatar"
:style="{ :style="{
backgroundColor: app.title === 'SES' ? '#242f3e' : '', backgroundColor: app.title === 'SES' ? '#242f3e' : '',
}" }"
:src="`/${app.logo}`" :src="`/${app.logo}`"
:color="app.title === 'SES' ? '#242f3e' : ''" />
> <div v-else />
</a-avatar>
</div> </div>
<div class="flex flex-col flex-grow-1 w-3/4"> <div class="flex flex-col flex-grow-1 w-3/5 pl-3">
<a-typography-title :level="5">{{ app.title }}</a-typography-title> <a-typography-title :level="5">{{ app.title }}</a-typography-title>
{{ app.description }} {{ app.description }}
</div> </div>
@ -171,7 +178,14 @@ onMounted(async () => {
} }
.caption { .caption {
font-size: 12px; font-size: 0.7rem;
color: #242f3e; color: #242f3e;
} }
.avatar {
width: 5rem;
height: 5rem;
padding: 0.25rem;
object-fit: contain;
}
</style> </style>

19
packages/nc-gui-v2/package-lock.json generated

@ -22,6 +22,7 @@
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^0.25.2", "@antfu/eslint-config": "^0.25.2",
"@iconify-json/clarity": "^1.1.4", "@iconify-json/clarity": "^1.1.4",
"@iconify-json/ic": "^1.1.7",
"@iconify-json/material-symbols": "^1.1.8", "@iconify-json/material-symbols": "^1.1.8",
"@iconify-json/mdi": "^1.1.25", "@iconify-json/mdi": "^1.1.25",
"@intlify/vite-plugin-vue-i18n": "^4.0.0", "@intlify/vite-plugin-vue-i18n": "^4.0.0",
@ -968,6 +969,15 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"node_modules/@iconify-json/ic": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@iconify-json/ic/-/ic-1.1.7.tgz",
"integrity": "sha512-CYwkhja02SZoevezNHSqM7d1lpsRJxKt9fzvn3MpRxI8s2v3LNmhGiD/bTq3uFgqQMRPp+OnD+OOjHrMo7ah1g==",
"dev": true,
"dependencies": {
"@iconify/types": "*"
}
},
"node_modules/@iconify-json/material-symbols": { "node_modules/@iconify-json/material-symbols": {
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.1.8.tgz", "resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.1.8.tgz",
@ -14901,6 +14911,15 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"@iconify-json/ic": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/@iconify-json/ic/-/ic-1.1.7.tgz",
"integrity": "sha512-CYwkhja02SZoevezNHSqM7d1lpsRJxKt9fzvn3MpRxI8s2v3LNmhGiD/bTq3uFgqQMRPp+OnD+OOjHrMo7ah1g==",
"dev": true,
"requires": {
"@iconify/types": "*"
}
},
"@iconify-json/material-symbols": { "@iconify-json/material-symbols": {
"version": "1.1.8", "version": "1.1.8",
"resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.1.8.tgz", "resolved": "https://registry.npmjs.org/@iconify-json/material-symbols/-/material-symbols-1.1.8.tgz",

1
packages/nc-gui-v2/package.json

@ -28,6 +28,7 @@
"devDependencies": { "devDependencies": {
"@antfu/eslint-config": "^0.25.2", "@antfu/eslint-config": "^0.25.2",
"@iconify-json/clarity": "^1.1.4", "@iconify-json/clarity": "^1.1.4",
"@iconify-json/ic": "^1.1.7",
"@iconify-json/material-symbols": "^1.1.8", "@iconify-json/material-symbols": "^1.1.8",
"@iconify-json/mdi": "^1.1.25", "@iconify-json/mdi": "^1.1.25",
"@intlify/vite-plugin-vue-i18n": "^4.0.0", "@intlify/vite-plugin-vue-i18n": "^4.0.0",

Loading…
Cancel
Save