Browse Source

fix(nc-gui): udpate extension marketplace modal

pull/9351/head
Ramesh Mane 3 months ago
parent
commit
9ef4bae63d
  1. 239
      packages/nc-gui/components/extensions/Market.vue

239
packages/nc-gui/components/extensions/Market.vue

@ -3,16 +3,47 @@ interface Prop {
modelValue?: boolean
}
type TabKeysType = 'extensions' | 'scripts' | 'build-an-extension'
interface TabItem {
title: string
tabKey: TabKeysType
icon: keyof typeof iconMap
isDisabled?: boolean
}
const props = defineProps<Prop>()
const emit = defineEmits(['update:modelValue'])
const tabs = [
{
title: 'Extensions',
tabKey: 'extensions',
icon: 'ncPuzzleOutline',
},
{
title: 'Scripts',
tabKey: 'scripts',
icon: 'ncPuzzleOutline',
isDisabled: true,
},
{
title: 'Build an extension',
tabKey: 'build-an-extension',
icon: 'ncSettings2',
isDisabled: true,
},
] as TabItem[]
const vModel = useVModel(props, 'modelValue', emit)
const { availableExtensions, addExtension, getExtensionAssetsUrl, showExtensionDetails } = useExtensions()
const searchQuery = ref<string>('')
const activeTab = ref<TabKeysType>('extensions')
const filteredAvailableExtensions = computed(() =>
(availableExtensions.value || []).filter(
(ext) =>
@ -30,6 +61,13 @@ const onAddExtension = (ext: any) => {
addExtension(ext)
vModel.value = false
}
const handleSetActiveTab = (tab: TabItem) => {
if (tab.isDisabled) return
searchQuery.value = ''
activeTab.value = tab.tabKey
}
</script>
<template>
@ -37,117 +75,118 @@ const onAddExtension = (ext: any) => {
v-model:visible="vModel"
:class="{ active: vModel }"
:footer="null"
:width="1024"
:width="1280"
size="medium"
wrap-class-name="nc-modal-extension-market"
>
<div class="h-full">
<div class="flex items-center gap-3 p-4 border-b-1 border-gray-200">
<GeneralIcon icon="ncPuzzleSolid" class="h-6 w-6 flex-none text-gray-700" />
<div class="flex-1 font-semibold text-xl">Extensions Marketplace</div>
<NcButton size="small" type="text" @click="vModel = false">
<GeneralIcon icon="close" class="text-gray-600" />
</NcButton>
<div class="nc-extension-market-header flex items-center gap-3 p-4 border-b-1 border-gray-200">
<div
class="flex items-center gap-3 flex-none"
:style="{
width: 'calc(\(100% - 358px - 24px\) / 2)',
}"
>
<GeneralIcon icon="ncPuzzleSolid" class="h-6 w-6 flex-none text-gray-700" />
<div class="flex-1 font-semibold text-xl">Marketplace</div>
</div>
<div class="flex bg-nc-gray-medium rounded-lg p-1">
<div class="flex items-center">
<NcTooltip v-for="(tab, idx) of tabs" :key="idx" :disabled="tab.tabKey === 'extensions'">
<template #title> {{ $t('msg.toast.futureRelease') }}</template>
<div
class="px-3 py-1 flex items-center gap-2 text-xs rounded-md select-none"
:class="{
'active-tab bg-white text-nc-gray-emphasis': activeTab === tab.tabKey,
'text-nc-gray-subtle2': activeTab !== tab.tabKey,
'cursor-not-allowed opacity-70': tab.isDisabled,
'cursor-pointer': !tab.isDisabled,
}"
@click="handleSetActiveTab(tab)"
>
<GeneralIcon :icon="tab.icon" class="h-4 w-4 flex-none stroke-transparent opacity-75" />
{{ tab.title }}
</div>
</NcTooltip>
</div>
</div>
<div class="flex-1 flex gap-3 justify-end">
<div class="flex-1 flex max-w-[290px]">
<a-input
v-model:value="searchQuery"
type="text"
class="nc-input-border-on-value !h-8 !px-3 !py-1 !rounded-lg"
placeholder="Search for an extension or script"
allow-clear
>
<template #prefix>
<GeneralIcon icon="search" class="mr-2 h-4 w-4 text-gray-500 group-hover:text-black" />
</template>
</a-input>
</div>
<NcButton size="small" type="text" @click="vModel = false">
<GeneralIcon icon="close" class="text-gray-600" />
</NcButton>
</div>
</div>
<div class="flex flex-col h-[calc(100%_-_65px)]">
<NcTabs class="h-full">
<template #leftExtra>
<div class="w-2"></div>
</template>
<a-tab-pane key="integrations" class="w-full h-full">
<template #tab>
<div class="tab-title">
{{ $t('general.extensions') }}
</div>
</template>
<div class="h-full py-6">
<div class="h-full flex flex-col gap-6 flex-1">
<div class="flex flex max-w-[470px] px-6">
<a-input
v-model:value="searchQuery"
type="text"
class="nc-input-border-on-value !h-8 !px-3 !py-1 !rounded-lg"
placeholder="Search for an extension..."
allow-clear
>
<template #prefix>
<GeneralIcon icon="search" class="mr-2 h-4 w-4 text-gray-500 group-hover:text-black" />
</template>
</a-input>
</div>
<div v-if="activeTab === 'extensions'" class="h-full py-4">
<div class="h-full flex flex-col gap-6 flex-1">
<div
class="flex flex-wrap gap-4 nc-scrollbar-thin px-6 max-w-[900px] mx-auto py-2"
:class="{
'h-full': searchQuery && !filteredAvailableExtensions.length && availableExtensions.length,
}"
>
<template v-for="ext of filteredAvailableExtensions" :key="ext.id">
<div
class="max-h-[calc(100%_-_40px)] flex flex-wrap gap-6 nc-scrollbar-thin px-6"
:class="{
'h-full': searchQuery && !filteredAvailableExtensions.length && availableExtensions.length,
}"
class="nc-market-extension-item w-full md:w-[calc(50%_-_8px)] flex items-center gap-3 border-1 rounded-xl p-3 cursor-pointer hover:bg-gray-50 transition-all"
@click="onExtensionClick(ext.id)"
>
<template v-for="ext of filteredAvailableExtensions" :key="ext.id">
<div
class="nc-market-extension-item w-full md:w-[calc(50%_-_12px)] flex items-center gap-3 border-1 rounded-xl p-3 cursor-pointer hover:bg-gray-50 transition-all"
@click="onExtensionClick(ext.id)"
>
<div class="h-[60px] w-[60px] overflow-hidden m-auto flex-none">
<img :src="getExtensionAssetsUrl(ext.iconUrl)" alt="icon" class="w-full h-full object-contain" />
</div>
<div class="flex-1 flex flex-grow flex-col gap-1">
<div class="font-weight-600 text-base line-clamp-1">
{{ ext.title }}
</div>
<div class="max-h-[32px] text-xs text-gray-500 line-clamp-2">{{ ext.subTitle }}</div>
</div>
<NcButton size="small" type="secondary" class="flex-none !px-7px" @click.stop="onAddExtension(ext)">
<div class="flex items-center gap-1 -ml-3px text-small">
<GeneralIcon icon="plus" />
{{ $t('general.add') }}
</div>
</NcButton>
</div>
</template>
<div
v-if="searchQuery && !filteredAvailableExtensions.length && availableExtensions.length"
class="w-full h-full flex items-center justify-center"
>
<div class="pb-6 text-gray-500 flex flex-col items-center gap-6 text-center">
<img
src="~assets/img/placeholder/no-search-result-found.png"
class="!w-[164px] flex-none"
alt="No search results found"
/>
{{ $t('title.noResultsMatchedYourSearch') }}
<div class="h-[60px] w-[60px] overflow-hidden m-auto flex-none">
<img :src="getExtensionAssetsUrl(ext.iconUrl)" alt="icon" class="w-full h-full object-contain" />
</div>
<div class="flex-1 flex flex-grow flex-col gap-1">
<div class="font-weight-600 text-base line-clamp-1">
{{ ext.title }}
</div>
<div class="max-h-[32px] text-xs text-gray-500 line-clamp-2">{{ ext.subTitle }}</div>
</div>
<NcButton size="small" type="secondary" class="flex-none !px-7px" @click.stop="onAddExtension(ext)">
<div class="flex items-center gap-1 -ml-3px text-small">
<GeneralIcon icon="plus" />
{{ $t('general.add') }}
</div>
</NcButton>
</div>
</template>
<div
v-if="searchQuery && !filteredAvailableExtensions.length && availableExtensions.length"
class="w-full h-full flex items-center justify-center"
>
<div class="pb-6 text-gray-500 flex flex-col items-center gap-6 text-center">
<img
src="~assets/img/placeholder/no-search-result-found.png"
class="!w-[164px] flex-none"
alt="No search results found"
/>
{{ $t('title.noResultsMatchedYourSearch') }}
</div>
</div>
</div>
</a-tab-pane>
<a-tab-pane key="scripts" class="w-full h-full" disabled>
<template #tab>
<NcTooltip>
<template #title>
{{ $t('msg.toast.futureRelease') }}
</template>
<div class="tab-title text-gray-400">Scripts</div>
</NcTooltip>
</template>
<div class="h-full p-6"></div>
</a-tab-pane>
<a-tab-pane key="build-extension" class="w-full h-full" disabled>
<template #tab>
<NcTooltip>
<template #title>
{{ $t('msg.toast.futureRelease') }}
</template>
<div class="tab-title text-gray-400">Build an extension</div>
</NcTooltip>
</template>
<div class="h-full p-6"></div>
</a-tab-pane>
</NcTabs>
</div>
</div>
<template v-else-if="activeTab === 'scripts'">
<!-- Coming soon -->
</template>
<template v-else-if="activeTab === 'build-an-extension'">
<!-- Coming soon -->
</template>
</div>
</div>
</NcModal>
@ -198,5 +237,11 @@ const onAddExtension = (ext: any) => {
@apply p-5 w-[320px] border-l-1 border-gray-200 flex flex-col gap-4 bg-gray-50 rounded-br-2xl;
}
}
.nc-extension-market-header {
.active-tab {
box-shadow: 0px 3px 1px -2px rgba(0, 0, 0, 0.06), 0px 5px 3px -2px rgba(0, 0, 0, 0.02);
}
}
}
</style>

Loading…
Cancel
Save