Browse Source

chore(gui-v2): sync with develop

pull/2795/head
Wing-Kam Wong 2 years ago
parent
commit
fa40cec1fc
  1. 2
      packages/nc-gui-v2/components.d.ts
  2. 3
      packages/nc-gui-v2/components/dashboard/TreeView.vue
  3. 181
      packages/nc-gui-v2/components/dashboard/settings/AppStore.vue
  4. 52
      packages/nc-gui-v2/components/dashboard/settings/AuditTab.vue
  5. 137
      packages/nc-gui-v2/components/dashboard/settings/SettingsModal.vue
  6. 264
      packages/nc-gui-v2/components/dashboard/settings/appStore/AppInstall.vue
  7. 58
      packages/nc-gui-v2/package-lock.json
  8. 2
      packages/nc-gui-v2/package.json
  9. BIN
      packages/nc-gui-v2/public/plugins/aws.png
  10. BIN
      packages/nc-gui-v2/public/plugins/backblaze.jpeg
  11. BIN
      packages/nc-gui-v2/public/plugins/discord.png
  12. BIN
      packages/nc-gui-v2/public/plugins/gcs.png
  13. 1
      packages/nc-gui-v2/public/plugins/linode.svg
  14. 31
      packages/nc-gui-v2/public/plugins/mailersend.svg
  15. BIN
      packages/nc-gui-v2/public/plugins/mattermost.png
  16. BIN
      packages/nc-gui-v2/public/plugins/minio.png
  17. BIN
      packages/nc-gui-v2/public/plugins/ovhCloud.png
  18. BIN
      packages/nc-gui-v2/public/plugins/s3.png
  19. BIN
      packages/nc-gui-v2/public/plugins/scaleway.png
  20. BIN
      packages/nc-gui-v2/public/plugins/slack.webp
  21. BIN
      packages/nc-gui-v2/public/plugins/spaces.png
  22. BIN
      packages/nc-gui-v2/public/plugins/teams.ico
  23. BIN
      packages/nc-gui-v2/public/plugins/twilio.png
  24. BIN
      packages/nc-gui-v2/public/plugins/upcloud.png
  25. BIN
      packages/nc-gui-v2/public/plugins/vultr.png
  26. BIN
      packages/nc-gui-v2/public/plugins/whatsapp.png

2
packages/nc-gui-v2/components.d.ts vendored

@ -42,12 +42,14 @@ declare module '@vue/runtime-core' {
ASpace: typeof import('ant-design-vue/es')['Space'] ASpace: typeof import('ant-design-vue/es')['Space']
ASpin: typeof import('ant-design-vue/es')['Spin'] ASpin: typeof import('ant-design-vue/es')['Spin']
ASubMenu: typeof import('ant-design-vue/es')['SubMenu'] ASubMenu: typeof import('ant-design-vue/es')['SubMenu']
ASwitch: typeof import('ant-design-vue/es')['Switch']
ATable: typeof import('ant-design-vue/es')['Table'] ATable: typeof import('ant-design-vue/es')['Table']
ATableColumn: typeof import('ant-design-vue/es')['TableColumn'] ATableColumn: typeof import('ant-design-vue/es')['TableColumn']
ATableColumnGroup: typeof import('ant-design-vue/es')['TableColumnGroup'] ATableColumnGroup: typeof import('ant-design-vue/es')['TableColumnGroup']
ATabPane: typeof import('ant-design-vue/es')['TabPane'] ATabPane: typeof import('ant-design-vue/es')['TabPane']
ATabs: typeof import('ant-design-vue/es')['Tabs'] ATabs: typeof import('ant-design-vue/es')['Tabs']
ATag: typeof import('ant-design-vue/es')['Tag'] ATag: typeof import('ant-design-vue/es')['Tag']
ATextarea: typeof import('ant-design-vue/es')['Textarea']
ATooltip: typeof import('ant-design-vue/es')['Tooltip'] ATooltip: typeof import('ant-design-vue/es')['Tooltip']
ATypographyTitle: typeof import('ant-design-vue/es')['TypographyTitle'] ATypographyTitle: typeof import('ant-design-vue/es')['TypographyTitle']
AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger'] AUploadDragger: typeof import('ant-design-vue/es')['UploadDragger']

3
packages/nc-gui-v2/components/dashboard/TreeView.vue

@ -19,6 +19,7 @@ import MdiPlus from '~icons/mdi/plus-circle-outline'
import MdiDrag from '~icons/mdi/drag-vertical' import MdiDrag from '~icons/mdi/drag-vertical'
import MdiMenuIcon from '~icons/mdi/dots-vertical' import MdiMenuIcon from '~icons/mdi/dots-vertical'
import MdiAPIDocIcon from '~icons/mdi/open-in-new' import MdiAPIDocIcon from '~icons/mdi/open-in-new'
import SettingsModal from '~/components/dashboard/settings/SettingsModal.vue'
const { addTab } = useTabs() const { addTab } = useTabs()
const toast = useToast() const toast = useToast()
@ -290,7 +291,7 @@ const addTableTab = (table: TableType) => {
<span> {{ $t('title.teamAndSettings') }}</span> <span> {{ $t('title.teamAndSettings') }}</span>
</div> </div>
<a-modal v-model:visible="settingsDlg" width="max(90vw, 600px)"> Team and settings</a-modal> <SettingsModal :show="settingsDlg" @closed="settingsDlg = false" />
<DlgTableCreate v-model="tableCreateDlg" /> <DlgTableCreate v-model="tableCreateDlg" />
<DlgTableRename v-if="renameTableMeta" v-model="renameTableDlg" :table-meta="renameTableMeta" /> <DlgTableRename v-if="renameTableMeta" v-model="renameTableDlg" :table-meta="renameTableMeta" />
</div> </div>

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

@ -0,0 +1,181 @@
<script setup lang="ts">
import { useToast } from 'vue-toastification'
import AppInstall from './AppStore/AppInstall.vue'
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()
let apps = $ref<null | Array<any>>(null)
let showPluginUninstallModal = $ref(false)
let showPluginInstallModal = $ref(false)
let pluginApp = $ref<any>(null)
const fetchPluginApps = async () => {
try {
const plugins = (await $api.plugin.list()).list ?? []
apps = plugins.map((p) => ({
...p,
tags: p.tags ? p.tags.split(',') : [],
parsedInput: p.input && JSON.parse(p.input),
}))
} catch (e) {
console.error(e)
toast.error('Something went wrong')
}
}
const resetPlugin = async () => {
try {
await $api.plugin.update(pluginApp.id, {
input: undefined,
active: false,
})
toast.success('Plugin uninstalled successfully')
showPluginUninstallModal = false
await fetchPluginApps()
} catch (e: any) {
console.log(e)
toast.error(e.message)
}
$e('a:appstore:reset', { app: pluginApp.title })
}
const saved = async () => {
showPluginInstallModal = false
await fetchPluginApps()
$e('a:appstore:install', { app: pluginApp.title })
}
const showInstallPluginModal = async (app: any) => {
showPluginInstallModal = true
pluginApp = app
$e('c:appstore:install', { app: app.title })
}
const showResetPluginModal = async (app: any) => {
showPluginUninstallModal = true
pluginApp = app
}
onMounted(async () => {
if (apps === null) {
fetchPluginApps()
}
})
</script>
<template>
<a-modal v-model:visible="showPluginInstallModal" :closable="false" centered min-height="300" :footer="null">
<AppInstall
v-if="pluginApp && showPluginInstallModal"
:id="pluginApp.id"
@close="showPluginInstallModal = false"
@saved="saved()"
/>
</a-modal>
<a-modal v-model:visible="showPluginUninstallModal" :closable="false" width="24rem" centered :footer="null">
<div class="flex flex-col h-full">
<div class="flex flex-row justify-center mt-2 text-center w-full text-base">
{{ `Click on confirm to reset ${pluginApp && pluginApp.title}` }}
</div>
<div class="flex mt-6 justify-center space-x-2">
<a-button @click="showPluginUninstallModal = false"> Cancel </a-button>
<a-button type="primary" danger @click="resetPlugin"> Confirm </a-button>
</div>
</div>
</a-modal>
<div class="grid grid-cols-2 gap-x-2 gap-y-4 mt-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"
:body-style="{ width: '100%' }"
>
<div class="install-btn flex flex-row justify-end space-x-1">
<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" />
Edit
</div>
</a-button>
<a-button v-if="app.parsedInput" size="small" outlined @click="showResetPluginModal(app)">
<div class="flex flex-row justify-center items-center caption capitalize">
<MdiCloseCircleIcon />
<div class="flex ml-0.5">Reset</div>
</div>
</a-button>
<a-button v-else size="small" outlined @click="showInstallPluginModal(app)">
<div class="flex flex-row justify-center items-center caption capitalize">
<MdiPlusIcon />
Install
</div>
</a-button>
</div>
<div class="flex flex-row space-x-2 items-center justify-start w-full">
<div class="flex w-20 pl-3">
<img
v-if="app.title !== 'SMTP'"
class="avatar"
:style="{
backgroundColor: app.title === 'SES' ? '#242f3e' : '',
}"
:src="`/${app.logo}`"
/>
<div v-else />
</div>
<div class="flex flex-col flex-grow-1 w-3/5 pl-3">
<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 {
font-size: 0.7rem;
color: #242f3e;
}
.avatar {
width: 5rem;
height: 5rem;
padding: 0.25rem;
object-fit: contain;
}
</style>

52
packages/nc-gui-v2/components/dashboard/settings/AuditTab.vue

@ -5,14 +5,8 @@ import { timeAgo } from '~/utils/dateTimeUtils'
import { h, useNuxtApp, useProject } from '#imports' import { h, useNuxtApp, useProject } from '#imports'
import MdiReload from '~icons/mdi/reload' import MdiReload from '~icons/mdi/reload'
interface Props {
projectId: string
}
const { projectId } = defineProps<Props>()
const { $api } = useNuxtApp() const { $api } = useNuxtApp()
const { project, loadProject } = useProject() const { project } = useProject()
let isLoading = $ref(false) let isLoading = $ref(false)
@ -45,35 +39,36 @@ async function loadAudits(page = currentPage, limit = currentLimit) {
onMounted(async () => { onMounted(async () => {
if (audits === null) { if (audits === null) {
await loadProject(projectId)
await loadAudits(currentPage, currentLimit) await loadAudits(currentPage, currentLimit)
} }
}) })
const tableHeaderRenderer = (label: string) => () => h('div', { class: 'text-gray-500' }, label)
const columns = [ const columns = [
{ {
title: 'Operation Type', title: tableHeaderRenderer('Operation Type'),
dataIndex: 'op_type', dataIndex: 'op_type',
key: 'op_type', key: 'op_type',
}, },
{ {
title: 'Operation sub-type', title: tableHeaderRenderer('Operation sub-type'),
dataIndex: 'op_sub_type', dataIndex: 'op_sub_type',
key: 'op_sub_type', key: 'op_sub_type',
}, },
{ {
title: 'Description', title: tableHeaderRenderer('Description'),
dataIndex: 'description', dataIndex: 'description',
key: 'description', key: 'description',
}, },
{ {
title: 'User', title: tableHeaderRenderer('User'),
dataIndex: 'user', dataIndex: 'user',
key: 'user', key: 'user',
customRender: (value: { text: string }) => h('div', () => value.text || 'Shared base'), customRender: (value: { text: string }) => h('div', {}, value.text || 'Shared base'),
}, },
{ {
title: 'Created', title: tableHeaderRenderer('Created'),
dataIndex: 'created_at', dataIndex: 'created_at',
key: 'created_at', key: 'created_at',
sort: 'desc', sort: 'desc',
@ -85,21 +80,22 @@ const columns = [
<template> <template>
<div class="flex flex-col gap-4 w-full"> <div class="flex flex-col gap-4 w-full">
<a-button class="self-start" @click="loadAudits"> <div class="flex flex-row justify-between items-center">
<div class="flex items-center gap-2"> <a-button class="self-start" @click="loadAudits">
<MdiReload :class="{ 'animate-infinite animate-spin !text-success': isLoading }" /> <div class="flex items-center gap-2 text-gray-600 font-light">
Reload <MdiReload :class="{ 'animate-infinite animate-spin !text-success': isLoading }" />
</div> Reload
</a-button> </div>
</a-button>
<a-pagination
v-model:current="currentPage"
:page-size="currentLimit"
:total="totalRows"
show-less-items
@change="loadAudits"
/>
</div>
<a-table class="w-full" :data-source="audits ?? []" :columns="columns" :pagination="false" :loading="isLoading" /> <a-table class="w-full" :data-source="audits ?? []" :columns="columns" :pagination="false" :loading="isLoading" />
<a-pagination
v-model:current="currentPage"
:page-size="currentLimit"
:total="totalRows"
show-less-items
@change="loadAudits"
/>
</div> </div>
</template> </template>

137
packages/nc-gui-v2/components/dashboard/settings/SettingsModal.vue

@ -0,0 +1,137 @@
<script setup lang="ts">
import type { FunctionalComponent, SVGAttributes } from 'vue'
import AuditTab from './AuditTab.vue'
import AppStore from './AppStore.vue'
import StoreFrontOutline from '~icons/mdi/storefront-outline'
import TeamFillIcon from '~icons/ri/team-fill'
import MultipleTableIcon from '~icons/mdi/table-multiple'
import NootbookOutline from '~icons/mdi/notebook-outline'
interface Props {
show: boolean
}
interface SubTabGroup {
[key: string]: {
title: string
body: any
}
}
interface TabGroup {
[key: string]: {
title: string
icon: FunctionalComponent<SVGAttributes, {}>
subTabs: SubTabGroup
}
}
const { show } = defineProps<Props>()
const emits = defineEmits(['closed'])
const tabsInfo: TabGroup = {
teamAndAuth: {
title: 'Team and Auth',
icon: TeamFillIcon,
subTabs: {
usersManagement: {
title: 'Users Management',
body: () => AuditTab,
},
apiTokenManagement: {
title: 'API Token Management',
body: () => AuditTab,
},
},
},
appStore: {
title: 'App Store',
icon: StoreFrontOutline,
subTabs: {
new: {
title: 'Apps',
body: () => AppStore,
},
},
},
metaData: {
title: 'Project Metadata',
icon: MultipleTableIcon,
subTabs: {
metaData: {
title: 'Metadata',
body: () => AuditTab,
},
acl: {
title: 'UI Access Control',
body: () => AuditTab,
},
},
},
audit: {
title: 'Audit',
icon: NootbookOutline,
subTabs: {
audit: {
title: 'Audit',
body: () => AuditTab,
},
},
},
}
const firstKeyOfObject = (obj: object) => Object.keys(obj)[0]
// Array of keys of tabs which are selected. In our case will be only one.
const selectedTabKeys = $ref<string[]>([firstKeyOfObject(tabsInfo)])
const selectedTab = $computed(() => tabsInfo[selectedTabKeys[0]])
let selectedSubTabKeys = $ref<string[]>([firstKeyOfObject(selectedTab.subTabs)])
const selectedSubTab = $computed(() => selectedTab.subTabs[selectedSubTabKeys[0]])
watch(
() => selectedTabKeys[0],
(newTabKey) => {
selectedSubTabKeys = [firstKeyOfObject(tabsInfo[newTabKey].subTabs)]
},
)
</script>
<template>
<a-modal :footer="null" :visible="show" width="max(90vw, 600px)" @cancel="emits('closed')">
<a-typography-title class="ml-4 mb-2 select-none" type="secondary" :level="5">SETTINGS</a-typography-title>
<a-layout class="mt-3 modal-body">
<!-- Side tabs -->
<a-layout-sider theme="light">
<a-menu v-model:selectedKeys="selectedTabKeys" class="h-full" mode="inline" :open-keys="[]">
<a-menu-item v-for="(tab, key) of tabsInfo" :key="key">
<div class="flex flex-row items-center space-x-2">
<component :is="tab.icon" class="flex" />
<div class="flex select-none">
{{ tab.title }}
</div>
</div>
</a-menu-item>
</a-menu>
</a-layout-sider>
<!-- Sub Tabs -->
<a-layout-content class="h-full px-4 scrollbar-thumb-gray-500">
<a-menu v-model:selectedKeys="selectedSubTabKeys" :open-keys="[]" mode="horizontal">
<a-menu-item v-for="(tab, key) of selectedTab.subTabs" :key="key" class="select-none">
{{ tab.title }}
</a-menu-item>
</a-menu>
<component :is="selectedSubTab.body()" class="px-2 py-6" />
</a-layout-content>
</a-layout>
</a-modal>
</template>
<style scoped>
.modal-body {
@apply h-[70vh];
}
</style>

264
packages/nc-gui-v2/components/dashboard/settings/appStore/AppInstall.vue

@ -0,0 +1,264 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useToast } from 'vue-toastification'
import type { PluginType } from 'nocodb-sdk'
import MdiDeleteOutlineIcon from '~icons/mdi/delete-outline'
import CloseIcon from '~icons/material-symbols/close-rounded'
import MdiPlusIcon from '~icons/mdi/plus'
import { extractSdkResponseErrorMsg } from '~/utils/errorUtils'
interface Props {
id: string
}
type Plugin = PluginType & {
formDetails: Record<string, any>
parsedInput: Record<string, any>
}
const { id } = defineProps<Props>()
const emits = defineEmits(['saved', 'close'])
enum Action {
Save = 'save',
Test = 'test',
}
const toast = useToast()
const { $api } = useNuxtApp()
const formRef = ref()
let plugin = $ref<Plugin | null>(null)
let pluginFormData = $ref<Record<string, any>>({})
let isLoading = $ref(true)
let loadingAction = $ref<null | Action>(null)
const layout = {
labelCol: { span: 14, pull: 4 },
wrapperCol: { span: 20, pull: 4 },
}
const addSetting = () => pluginFormData.push({})
const saveSettings = async () => {
loadingAction = Action.Save
try {
await formRef.value?.validateFields()
await $api.plugin.update(id, {
input: JSON.stringify(pluginFormData),
active: true,
})
emits('saved')
toast.success(plugin?.formDetails.msgOnInstall || 'Plugin settings saved successfully')
} catch (_e: any) {
const e = await extractSdkResponseErrorMsg(_e)
toast.error(e.message)
} finally {
loadingAction = null
}
}
const testSettings = async () => {
loadingAction = Action.Test
try {
const res = await $api.plugin.test({
input: pluginFormData,
id: plugin?.id,
category: plugin?.category,
title: plugin?.title,
})
if (res) {
toast.success('Successfully tested plugin settings')
} else {
toast.info('Invalid credentials')
}
} catch (_e: any) {
const e = await extractSdkResponseErrorMsg(_e)
toast.error(e.message)
} finally {
loadingAction = null
}
}
const doAction = async (action: Action) => {
switch (action) {
case Action.Save:
await saveSettings()
break
case Action.Test:
await testSettings()
break
default:
// noop
break
}
}
const readPluginDetails = async () => {
try {
isLoading = true
const res = await $api.plugin.read(id)
const formDetails = JSON.parse(res.input_schema ?? '{}')
const emptyParsedInput = formDetails.array ? [{}] : {}
const parsedInput = res.input ? JSON.parse(res.input) : emptyParsedInput
plugin = { ...res, formDetails, parsedInput }
pluginFormData = plugin.parsedInput
} catch (e) {
console.log(e)
} finally {
isLoading = false
}
}
const deleteFormRow = (index: number) => pluginFormData.splice(index, 1)
onMounted(async () => {
if (!plugin) {
await readPluginDetails()
}
})
</script>
<template>
<div v-if="isLoading" class="flex flex-row w-full justify-center items-center h-52">
<a-spin size="large" />
</div>
<template v-else>
<div class="flex flex-col">
<div class="w-full relative">
<div class="flex flex-row justify-center pb-4 mb-2 border-b-1 w-full gap-x-1">
<div
v-if="plugin.logo"
class="mr-1 flex items-center justify-center"
:class="[plugin.title === 'SES' ? 'p-2 bg-[#242f3e]' : '']"
>
<img :src="`/${plugin.logo}`" class="h-6" />
</div>
<span class="font-semibold text-lg">{{ plugin.formDetails.title }}</span>
</div>
<div class="absolute -right-2 -top-0.5">
<a-button type="text" class="!rounded-md mr-1" @click="emits('close')">
<template #icon>
<CloseIcon class="flex mx-auto" />
</template>
</a-button>
</div>
</div>
<a-form ref="formRef" v-bind="plugin?.formDetails.array ? {} : layout" :model="pluginFormData" class="mx-4 mt-3">
<!-- Form with multiple entry -->
<div v-if="plugin.formDetails.array" class="flex flex-row justify-center">
<table>
<thead>
<tr>
<th v-for="(columnData, columnIndex) in plugin.formDetails.items" :key="columnIndex">
<div class="text-center font-normal mb-2">
{{ columnData.label }} <span v-if="columnData.required" class="text-red-600">*</span>
</div>
</th>
</tr>
</thead>
<tbody>
<tr v-for="(itemRow, itemIndex) in plugin.parsedInput" :key="itemIndex">
<td v-for="(columnData, columnIndex) in plugin.formDetails.items" :key="columnIndex" class="px-2">
<a-form-item
class="relative mb-3"
:name="[`${itemIndex}`, columnData.key]"
:rules="[{ required: columnData.required, message: `${columnData.label} is required` }]"
>
<a-input-password
v-if="columnData.type === 'Password'"
v-model:value="itemRow[columnData.key]"
:placeholder="columnData.placeholder"
/>
<a-textarea
v-else-if="columnData.type === 'LongText'"
v-model:value="itemRow[columnData.key]"
:placeholder="columnData.placeholder"
/>
<a-switch
v-else-if="columnData.type === 'Checkbox'"
v-model:value="itemRow[columnData.key]"
:placeholder="columnData.placeholder"
/>
<a-input v-else v-model:value="itemRow[columnData.key]" :placeholder="columnData.placeholder" />
<div
v-if="itemIndex !== 0 && columnIndex === plugin.formDetails.items.length - 1"
class="absolute flex flex-col justify-start mt-2 -right-6 top-0"
>
<MdiDeleteOutlineIcon class="hover:text-red-400 cursor-pointer" @click="deleteFormRow(itemIndex)" />
</div>
</a-form-item>
</td>
</tr>
</tbody>
<tr>
<td :colspan="plugin.formDetails.items.length" class="text-center">
<a-button type="default" class="!bg-gray-100 rounded-md border-none mr-1" @click="addSetting">
<template #icon>
<MdiPlusIcon class="flex mx-auto" />
</template>
</a-button>
</td>
</tr>
</table>
</div>
<!-- Form with only one entry -->
<template v-else>
<a-form-item
v-for="(columnData, i) in plugin.formDetails.items"
:key="i"
:label="columnData.label"
:name="columnData.key"
:rules="[{ required: columnData.required, message: `${columnData.label} is required` }]"
>
<a-input-password
v-if="columnData.type === 'Password'"
v-model:value="pluginFormData[columnData.key]"
:placeholder="columnData.placeholder"
/>
<a-textarea
v-else-if="columnData.type === 'LongText'"
v-model:value="pluginFormData[columnData.key]"
:placeholder="columnData.placeholder"
/>
<a-switch
v-else-if="columnData.type === 'Checkbox'"
v-model:checked="pluginFormData[columnData.key]"
:placeholder="columnData.placeholder"
/>
<a-input v-else v-model:value="pluginFormData[columnData.key]" :placeholder="columnData.placeholder" />
</a-form-item>
</template>
<div class="flex flex-row space-x-4 justify-center mt-4">
<a-button
v-for="(action, i) in plugin.formDetails.actions"
:key="i"
:loading="loadingAction === action.key"
:type="action.key === Action.Save ? 'primary' : 'default'"
:disabled="!!loadingAction"
@click="doAction(action.key)"
>
{{ action.label }}
</a-button>
</div>
</a-form>
</div>
</template>
</template>
<style scoped lang="scss"></style>

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

@ -23,8 +23,10 @@
"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",
"@iconify-json/ri": "^1.1.3",
"@intlify/vite-plugin-vue-i18n": "^4.0.0", "@intlify/vite-plugin-vue-i18n": "^4.0.0",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/sortablejs": "^1.13.0", "@types/sortablejs": "^1.13.0",
@ -10422,6 +10424,14 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"node_modules/@iconify-json/ic": {
"version": "1.1.7",
"dev": true,
"license": "Apache 2.0",
"dependencies": {
"@iconify/types": "*"
}
},
"node_modules/@iconify-json/material-symbols": { "node_modules/@iconify-json/material-symbols": {
"version": "1.1.8", "version": "1.1.8",
"dev": true, "dev": true,
@ -10438,6 +10448,14 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"node_modules/@iconify-json/ri": {
"version": "1.1.3",
"dev": true,
"license": "Apache 2.0",
"dependencies": {
"@iconify/types": "*"
}
},
"node_modules/@iconify/types": { "node_modules/@iconify/types": {
"version": "1.1.0", "version": "1.1.0",
"dev": true, "dev": true,
@ -11599,8 +11617,9 @@
}, },
"node_modules/@types/papaparse": { "node_modules/@types/papaparse": {
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.2.tgz",
"integrity": "sha512-BNbCHJkTE4RwmAFkCxEalET4mDvGr/1ld7ZtQ4i/laWI/iiVt+GL07stdvufle4KfywyvloqqpIiJscXNCrKxA==",
"dev": true, "dev": true,
"license": "MIT",
"dependencies": { "dependencies": {
"@types/node": "*" "@types/node": "*"
} }
@ -11625,9 +11644,8 @@
}, },
"node_modules/@types/sortablejs": { "node_modules/@types/sortablejs": {
"version": "1.13.0", "version": "1.13.0",
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz", "dev": true,
"integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==", "license": "MIT"
"dev": true
}, },
"node_modules/@types/tough-cookie": { "node_modules/@types/tough-cookie": {
"version": "4.0.2", "version": "4.0.2",
@ -18633,7 +18651,8 @@
}, },
"node_modules/papaparse": { "node_modules/papaparse": {
"version": "5.3.2", "version": "5.3.2",
"license": "MIT" "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz",
"integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw=="
}, },
"node_modules/parse-cache-control": { "node_modules/parse-cache-control": {
"version": "1.0.1", "version": "1.0.1",
@ -20361,8 +20380,7 @@
}, },
"node_modules/sortablejs": { "node_modules/sortablejs": {
"version": "1.15.0", "version": "1.15.0",
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", "license": "MIT"
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
}, },
"node_modules/source-map": { "node_modules/source-map": {
"version": "0.7.4", "version": "0.7.4",
@ -22872,6 +22890,13 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"@iconify-json/ic": {
"version": "1.1.7",
"dev": true,
"requires": {
"@iconify/types": "*"
}
},
"@iconify-json/material-symbols": { "@iconify-json/material-symbols": {
"version": "1.1.8", "version": "1.1.8",
"dev": true, "dev": true,
@ -22886,6 +22911,13 @@
"@iconify/types": "*" "@iconify/types": "*"
} }
}, },
"@iconify-json/ri": {
"version": "1.1.3",
"dev": true,
"requires": {
"@iconify/types": "*"
}
},
"@iconify/types": { "@iconify/types": {
"version": "1.1.0", "version": "1.1.0",
"dev": true "dev": true
@ -23690,6 +23722,8 @@
}, },
"@types/papaparse": { "@types/papaparse": {
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.3.2.tgz",
"integrity": "sha512-BNbCHJkTE4RwmAFkCxEalET4mDvGr/1ld7ZtQ4i/laWI/iiVt+GL07stdvufle4KfywyvloqqpIiJscXNCrKxA==",
"dev": true, "dev": true,
"requires": { "requires": {
"@types/node": "*" "@types/node": "*"
@ -23712,8 +23746,6 @@
}, },
"@types/sortablejs": { "@types/sortablejs": {
"version": "1.13.0", "version": "1.13.0",
"resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.13.0.tgz",
"integrity": "sha512-C3064MH72iEfeGCYEGCt7FCxXoAXaMPG0QPnstcxvPmbl54erpISu06d++FY37Smja64iWy5L8wOyHHBghWbJQ==",
"dev": true "dev": true
}, },
"@types/tough-cookie": { "@types/tough-cookie": {
@ -34276,7 +34308,9 @@
"dev": true "dev": true
}, },
"papaparse": { "papaparse": {
"version": "5.3.2" "version": "5.3.2",
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.3.2.tgz",
"integrity": "sha512-6dNZu0Ki+gyV0eBsFKJhYr+MdQYAzFUGlBMNj3GNrmHxmz1lfRa24CjFObPXtjcetlOv5Ad299MhIK0znp3afw=="
}, },
"parse-cache-control": { "parse-cache-control": {
"version": "1.0.1", "version": "1.0.1",
@ -35331,9 +35365,7 @@
} }
}, },
"sortablejs": { "sortablejs": {
"version": "1.15.0", "version": "1.15.0"
"resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
"integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
}, },
"source-map": { "source-map": {
"version": "0.7.4", "version": "0.7.4",

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

@ -29,8 +29,10 @@
"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",
"@iconify-json/ri": "^1.1.3",
"@intlify/vite-plugin-vue-i18n": "^4.0.0", "@intlify/vite-plugin-vue-i18n": "^4.0.0",
"@types/papaparse": "^5.3.2", "@types/papaparse": "^5.3.2",
"@types/sortablejs": "^1.13.0", "@types/sortablejs": "^1.13.0",

BIN
packages/nc-gui-v2/public/plugins/aws.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
packages/nc-gui-v2/public/plugins/backblaze.jpeg

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
packages/nc-gui-v2/public/plugins/discord.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

BIN
packages/nc-gui-v2/public/plugins/gcs.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

1
packages/nc-gui-v2/public/plugins/linode.svg

@ -0,0 +1 @@
<svg enable-background="new 0 0 110.9 100" height="100" viewBox="0 0 110.9 100" width="110.9" xmlns="http://www.w3.org/2000/svg"><path d="m90.5 85h-66c-10.3-.6-18-9.3-17.5-19.5.3-5.8 3.4-11.1 8.2-14.3l2 19.3c.4 4.5 4.2 8 8.7 8h33.1c4.5 0 8.3-3.5 8.7-8l4.6-43.9c.3-.1.7-.2 1-.3 12.6 3.6 19.9 16.3 16.9 28.9 8.2.7 14.2 8 13.5 16.2-.4 7.1-6.1 12.8-13.2 13.6z" fill="#010101"/><path d="m70.8 15h-56.4c-2.2 0-3.8 1.7-3.8 3.8s1.7 3.8 3.8 3.8h3.1l5.2 47.1c.1 1.7 1.6 3.1 3.3 3.1h33.1c1.7 0 3.2-1.3 3.4-3.1l5.2-47.1h3.1c2.2 0 3.8-1.7 3.8-3.8s-1.6-3.8-3.8-3.8zm-16.7 53.7c-2.2 0-3.9-1.7-3.9-3.9s1.7-3.9 3.9-3.9 3.9 1.7 3.9 3.9c-.1 2.2-1.8 3.9-3.9 3.9z" fill="#10b057"/></svg>

After

Width:  |  Height:  |  Size: 666 B

31
packages/nc-gui-v2/public/plugins/mailersend.svg

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="30px" height="30px" viewBox="0 0 30 30" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
<title>MailerSend Copy 2</title>
<desc>Created with Sketch.</desc>
<g id="Website" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Desktop-HD-Copy-25" transform="translate(-230.000000, -30.000000)">
<g id="MailerSend-Copy-2" transform="translate(230.000000, 30.000000)">
<g id="symbol-copy-2">
<path d="M29.5793151,10.1663649 C29.4628886,9.99688216 29.2691772,9.90994232 29.0738683,9.90994232 L17.9522395,9.90994232 L23.498176,1.04527667 C23.6409633,0.817634197 23.6489514,0.506049814 23.4756097,0.256222694 C23.3579849,0.0865401142 23.1622765,0 22.9661687,0 L13.3890387,0 C12.4274714,0 11.5290101,0.515643175 10.9904126,1.3764475 L0.106230039,18.7748078 C-0.0361578035,19.0026502 -0.0421488768,19.3142345 0.129395522,19.5640617 C0.245622344,19.7333445 0.439333714,19.8200845 0.634842406,19.8200845 L11.7508795,19.8200845 L6.20434385,28.6869486 C6.10449263,28.846838 6.07393815,29.0480987 6.11947031,29.2399659 C6.18956587,29.5371603 6.45277369,29.7322253 6.73655086,29.7322253 L16.3080893,29.7322253 C17.2768458,29.7322253 18.182097,29.2125849 18.7244888,28.345385 L24.0563444,19.8200845 L24.0565441,19.8200845 L29.6020812,10.9554189 C29.7446688,10.7277764 29.7506598,10.4157923 29.5793151,10.1663649" id="Fill-1" fill="#4E48E0"></path>
<path d="M24.0576142,19.8181059 L18.7245604,28.3452051 C18.1821686,29.2126049 17.2767177,29.7320454 16.3081608,29.7320454 L6.73662243,29.7320454 C6.45284526,29.7320454 6.18963744,29.5371803 6.11954188,29.2399859 C6.07400973,29.0481187 6.1045642,28.846858 6.20441542,28.6869686 L11.7519496,19.8181059 L24.0576142,19.8181059 Z" id="Fill-3" fill="#4E48E0"></path>
<path d="M17.9450419,9.90992233 L29.0738599,9.90992233 C29.2691689,9.90992233 29.4628803,9.99686217 29.5793068,10.166145 C29.7508512,10.4157723 29.7444608,10.7275565 29.6022726,10.9553989 L24.0567355,19.8200645 L11.746278,19.8200645 L17.9450419,9.90992233 Z" id="Fill-5" fill="#1C81C1"></path>
<path d="M0.634794157,19.8200445 C0.439485167,19.8200445 0.245773797,19.7333046 0.129546975,19.5640217 C-0.0421971263,19.3141946 -0.036206053,19.0026102 0.106381492,18.7749677 L10.9905641,1.37640753 C11.5289618,0.515603203 12.4276228,-3.99723392e-05 13.3889904,-3.99723392e-05 L22.9661205,-3.99723392e-05 C23.1622283,-3.99723392e-05 23.3581364,0.0867000036 23.4757611,0.256182722 C23.6489031,0.506009841 23.640915,0.817594225 23.4983275,1.04543656 L11.7520295,19.8200445 L0.634794157,19.8200445 Z" id="Fill-7" fill="#5CC4CD"></path>
</g>
<g id="logo" transform="translate(41.937513, 6.195713)" fill="#3A3945">
<path d="M53.7579806,10.2010809 L54.0445536,10.2010809 L59.7304816,10.2010809 C59.9383718,10.2010809 60.5560515,10.2040788 60.5560515,10.2040788 C60.5560515,10.2040788 60.5558518,10.1639066 60.5211036,10.001419 C60.397288,9.41962162 60.1736213,8.88719006 59.7836024,8.43350402 C58.8769533,7.37983316 57.2675513,7.02048183 55.8914018,7.57529789 C54.7105613,8.05116859 54.0665209,8.9715317 53.7579806,10.2010809 M58.6045592,12.5132808 C57.068448,12.5132808 55.5327362,12.5166785 53.9968247,12.5092836 C53.7963235,12.5080844 53.7585797,12.5500554 53.8122997,12.747119 C54.2148998,14.216702 55.3849564,15.2248044 56.8909125,15.3884912 C58.5851881,15.5725638 60.1368761,15.1472581 61.5877143,14.2916502 L61.8471278,14.138756 L63.0715035,16.3122519 C63.0715035,16.3122519 63.0365555,16.3318384 62.9073481,16.4179788 C61.0828665,17.6383343 59.0740597,18.1663689 56.8875176,18.0386572 C55.9117715,17.9816967 54.9733697,17.7720417 54.0922825,17.3435383 C52.7894238,16.7101766 51.8304526,15.7290555 51.2569072,14.4003749 C50.4592956,12.5528534 50.4117665,10.6655594 51.1211095,8.78506074 C52.0319524,6.36973215 54.2528433,4.86617261 56.9514224,4.78323 C58.3427493,4.7404596 59.6635813,4.99868091 60.8484159,5.75935453 C62.5217226,6.83361114 63.314741,8.43090581 63.5166402,10.364168 C63.582542,10.9961307 63.5487923,11.625695 63.4940738,12.2574578 C63.4743033,12.4866992 63.4683122,12.517278 63.4683122,12.517278 C63.4683122,12.517278 60.1322829,12.5132808 58.6045592,12.5132808" id="Fill-1"></path>
<path d="M89.0300452,10.2010809 L89.3164185,10.2010809 L95.0025462,10.2010809 C95.2104364,10.2010809 95.8281161,10.2040788 95.8281161,10.2040788 C95.8281161,10.2040788 95.8277167,10.1639066 95.7931682,10.001419 C95.669153,9.41962162 95.4454862,8.88719006 95.0554674,8.43350402 C94.149018,7.37983316 92.5394163,7.02048183 91.1634664,7.57529789 C89.9826259,8.05116859 89.3385855,8.9715317 89.0300452,10.2010809 M93.8764241,12.5132808 C92.3405126,12.5132808 90.8046011,12.5166785 89.2686897,12.5092836 C89.0681884,12.5080844 89.0304446,12.5500554 89.0843643,12.747119 C89.4867647,14.216702 90.6568213,15.2248044 92.1629772,15.3884912 C93.857053,15.5725638 95.4089407,15.1472581 96.8597789,14.2916502 L97.1189927,14.138756 L98.3435681,16.3122519 C98.3435681,16.3122519 98.3086202,16.3318384 98.179213,16.4179788 C96.3547315,17.6383343 94.3461243,18.1663689 92.1593825,18.0386572 C91.1836364,17.9816967 90.2452346,17.7720417 89.3643471,17.3435383 C88.0614884,16.7101766 87.1023175,15.7290555 86.5287721,14.4003749 C85.7311606,12.5528534 85.6836314,10.6655594 86.3931742,8.78506074 C87.304017,6.36973215 89.5247082,4.86617261 92.2232873,4.78323 C93.6148139,4.7404596 94.9354462,4.99868091 96.1204805,5.75935453 C97.7935876,6.83361114 98.5868057,8.43090581 98.7885051,10.364168 C98.8544069,10.9961307 98.8206572,11.625695 98.7659388,12.2574578 C98.7461682,12.4866992 98.7401771,12.517278 98.7401771,12.517278 C98.7401771,12.517278 95.4041478,12.5132808 93.8764241,12.5132808" id="Fill-3"></path>
<path d="M79.9145274,4.78119142 C81.3104474,4.80797288 82.7061678,5.29743418 83.8378816,6.4478381 C83.9676881,6.57974682 84.0128209,6.62491556 84.0128209,6.62491556 L82.4297796,8.55398065 C82.4297796,8.55398065 82.4056156,8.53079669 82.2782055,8.41028009 C81.5460963,7.71875862 80.6893728,7.29844947 79.6672957,7.25927658 C79.3465736,7.24708502 79.0348381,7.28985542 78.7426734,7.42955875 C77.9522511,7.80749721 77.8364237,8.73565493 78.508023,9.29706643 C78.7302919,9.48273795 78.9917024,9.59346132 79.257706,9.69758927 C80.2148798,10.0709309 81.1876304,10.4064987 82.108059,10.8687788 C82.7810562,11.2067449 83.3853558,11.6348487 83.8097235,12.2730071 C84.6007449,13.4627838 84.4693407,15.2551434 83.5161609,16.397353 C82.6826029,17.3958621 81.5768505,17.869934 80.3209218,18.021629 C78.5265954,18.2382791 76.8780517,17.8625391 75.4371986,16.7271248 C75.0687476,16.4367258 74.7520195,16.0947624 74.4624509,15.7258177 C74.3767786,15.6164934 74.3520155,15.5815176 74.3520155,15.5815176 L76.0722523,13.7287997 C76.0722523,13.7287997 76.0936205,13.7541821 76.2066521,13.8900881 C76.8982216,14.7217126 77.7679258,15.2653364 78.8399285,15.4568039 C79.4522162,15.5659284 80.0559167,15.543344 80.6180791,15.2393544 C81.1870313,14.9321669 81.4348621,14.3909415 81.2583251,13.8581102 C81.1618688,13.5669117 80.9551768,13.3630528 80.7083446,13.1945694 C80.3790352,12.9695251 80.007389,12.8316205 79.6419335,12.6829234 C78.8589002,12.3647436 78.0586925,12.0879351 77.2952301,11.7229877 C76.2791441,11.2373238 75.5142837,10.5168224 75.2337018,9.38500558 C74.7859689,7.5800546 75.7193781,5.85684706 77.4945331,5.17212089 C78.214061,4.894513 78.9595503,4.78279031 79.9145274,4.78119142" id="Fill-5"></path>
<path d="M29.226173,15.099651 C27.2055837,15.099651 25.5616332,13.4545894 25.5616332,11.4321889 C25.5616332,9.40998829 27.2055837,7.76492667 29.226173,7.76492667 C31.2467623,7.76492667 32.8907128,9.40998829 32.8907128,11.4321889 C32.8907128,13.4545894 31.2467623,15.099651 29.226173,15.099651 L29.226173,15.099651 Z M33.2164275,4.77959252 L32.9166742,6.31493007 C31.9846629,5.35099711 30.5909395,4.79038505 29.226173,4.79038505 C25.5668254,4.79038505 22.5896614,7.76992321 22.5896614,11.4321889 C22.5896614,15.0946545 25.5668254,18.0741927 29.226173,18.0741927 C30.5909395,18.0741927 31.9227551,17.5291698 32.9166742,16.5498475 L33.2164275,18.0801885 L35.8888456,18.0801885 L35.8888456,4.77959252 L33.2164275,4.77959252 Z" id="Fill-7"></path>
<path d="M122.063246,15.099651 C120.042656,15.099651 118.398706,13.4545894 118.398706,11.4321889 C118.398706,9.40998829 120.042656,7.76492667 122.063246,7.76492667 C124.083835,7.76492667 125.727586,9.40998829 125.727586,11.4321889 C125.727586,13.4545894 124.083835,15.099651 122.063246,15.099651 L122.063246,15.099651 Z M125.753747,0.340864122 L125.753747,6.31493007 C124.814946,5.45192727 123.428012,4.79038505 122.063246,4.79038505 C118.403898,4.79038505 115.426734,7.76992321 115.426734,11.4321889 C115.426734,15.0946545 118.403898,18.0741927 122.063246,18.0741927 C123.428012,18.0741927 124.733667,17.4464271 125.753747,16.5496476 L126.053301,18.0801885 L128.725918,18.0801885 L128.725918,0.340864122 L125.753747,0.340864122 Z" id="Fill-10"></path>
<polygon id="Fill-13" points="39.1462721 18.0801685 42.1184435 18.0801685 42.1184435 5.40513964 39.1462721 5.40513964"></polygon>
<path d="M107.336269,4.78948568 C106.235509,4.78948568 104.973989,5.4880023 104.317167,6.33421672 L103.817911,4.77869314 L101.344996,4.77869314 L101.344996,10.6084589 L101.344996,18.0792891 L104.317167,18.0792891 L104.341132,18.0792891 L104.341132,10.6084589 C104.341132,9.04014422 105.68453,7.76402729 107.336269,7.76402729 C108.987608,7.76402729 110.331007,9.04014422 110.331007,10.6084589 L110.331007,18.0792891 L113.327143,18.0792891 L113.327143,10.6084589 C113.327143,7.40007915 110.639547,4.78948568 107.336269,4.78948568" id="Fill-1"></path>
<polygon id="Fill-16" points="45.2152293 18.0801685 48.1874008 18.0801685 48.1874008 0.341043998 45.2152293 0.341043998"></polygon>
<path d="M42.5730861,1.94215603 C42.5730861,0.869698169 41.7039811,-9.99308479e-05 40.6323778,-9.99308479e-05 C39.5605747,-9.99308479e-05 38.6916694,0.869698169 38.6916694,1.94215603 C38.6916694,3.01481375 39.5605747,3.88441199 40.6323778,3.88441199 C41.7039811,3.88441199 42.5730861,3.01481375 42.5730861,1.94215603" id="Fill-17"></path>
<path d="M71.5361911,4.80247669 C70.5452676,4.88142206 69.6440104,5.44683079 68.8649712,5.99744976 L68.5654175,4.77969245 L65.8927997,4.77969245 L65.8927997,10.891663 C65.8658399,11.1263006 65.8504628,11.3595392 65.8504628,11.58958 L65.8504628,17.9963465 L65.8927997,17.9963465 L65.8927997,18.0802884 L68.8649712,18.0802884 L68.8649712,17.9963465 L68.9073081,17.9963465 L68.9073081,11.58958 C68.9073081,10.1767577 70.1129118,7.98487447 71.7782304,7.85236616 C72.1916145,7.81998857 72.5840298,7.87055358 73.1368062,8.02764487 L73.9729603,5.08508112 C73.3640675,4.91180103 72.5363009,4.72333145 71.5361911,4.80247669" id="Fill-18"></path>
<path d="M14.4844781,4.78490884 C12.7632428,4.78490884 11.2149497,5.53818757 10.1495372,6.73156176 C9.08392495,5.53818757 7.53563191,4.78490884 5.81439655,4.78490884 C2.60837352,4.78490884 5.9910733e-05,7.39550231 5.9910733e-05,10.6038821 L5.9910733e-05,18.0747123 L2.97223138,18.0747123 L2.97223138,10.6038821 C2.97223138,9.03556739 4.24713177,7.75945046 5.81439655,7.75945046 C7.38166132,7.75945046 8.65656172,9.03556739 8.65656172,10.6038821 L8.65656172,18.0747123 L8.67014149,18.0747123 L10.1495372,18.0747123 L11.6287332,18.0747123 L11.642313,18.0747123 L11.642313,10.6038821 C11.642313,9.03556739 12.9172134,7.75945046 14.4844781,7.75945046 C16.0517429,7.75945046 17.3266433,9.03556739 17.3266433,10.6038821 L17.3266433,18.0747123 L20.2988148,18.0747123 L20.2988148,10.6038821 C20.2988148,7.39550231 17.6905012,4.78490884 14.4844781,4.78490884" id="Fill-19"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

BIN
packages/nc-gui-v2/public/plugins/mattermost.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

BIN
packages/nc-gui-v2/public/plugins/minio.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
packages/nc-gui-v2/public/plugins/ovhCloud.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
packages/nc-gui-v2/public/plugins/s3.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
packages/nc-gui-v2/public/plugins/scaleway.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

BIN
packages/nc-gui-v2/public/plugins/slack.webp

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 KiB

BIN
packages/nc-gui-v2/public/plugins/spaces.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

BIN
packages/nc-gui-v2/public/plugins/teams.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

BIN
packages/nc-gui-v2/public/plugins/twilio.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 880 B

BIN
packages/nc-gui-v2/public/plugins/upcloud.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 564 B

BIN
packages/nc-gui-v2/public/plugins/vultr.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

BIN
packages/nc-gui-v2/public/plugins/whatsapp.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Loading…
Cancel
Save