Browse Source

Merge pull request #3159 from nocodb/chore/sidebar-toggle-effect

refactor(gui-v2): show sidebar toggle on hover
pull/3163/head
navi 2 years ago committed by GitHub
parent
commit
369a64eeee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 64
      packages/nc-gui-v2/assets/style-v2.scss
  2. 2
      packages/nc-gui-v2/components/dashboard/TreeView.vue
  3. 124
      packages/nc-gui-v2/components/general/SocialCard.vue
  4. 6
      packages/nc-gui-v2/components/general/Sponsors.vue
  5. 2
      packages/nc-gui-v2/components/smartsheet/Pagination.vue
  6. 8
      packages/nc-gui-v2/components/smartsheet/sidebar/MenuBottom.vue
  7. 3
      packages/nc-gui-v2/components/smartsheet/sidebar/RenameableMenuItem.vue
  8. 43
      packages/nc-gui-v2/components/smartsheet/sidebar/index.vue
  9. 2
      packages/nc-gui-v2/components/smartsheet/sidebar/menu/ApiSnippet.vue
  10. 2
      packages/nc-gui-v2/components/tabs/Smartsheet.vue
  11. 23
      packages/nc-gui-v2/composables/useUIPermission/index.ts
  12. 3
      packages/nc-gui-v2/nuxt.config.ts
  13. 65
      packages/nc-gui-v2/pages/[projectType]/[projectId]/index.vue
  14. 54
      packages/nc-gui-v2/pages/index/index.vue

64
packages/nc-gui-v2/assets/style-v2.scss

@ -31,31 +31,6 @@ nav .v-list {
@apply dark:bg-white
}
.page-enter-active,
.page-leave-active,
.layout-enter-active,
.layout-leave-active {
@apply transition-opacity duration-300 ease-in-out;
}
.page-enter,
.page-leave-active,
.layout-enter,
.layout-leave-active {
@apply opacity-0;
}
.slide-enter-active,
.slide-leave-active {
@apply transition-all duration-200 ease-in-out;
transform: translate(100%, 0);
}
.slide-enter,
.slide-leave-active {
transform: translate(-100%, 0);
}
a {
@apply prose text-primary underline hover:opacity-75 dark:(text-secondary) hover:(opacity-75);
}
@ -153,3 +128,42 @@ html {
background-position: 0% 22%
}
}
.page-enter-active,
.page-leave-active,
.layout-enter-active,
.layout-leave-active {
@apply transition-opacity duration-300 ease-in-out;
}
.page-enter,
.page-leave-active,
.layout-enter,
.layout-leave-active {
@apply opacity-0;
}
.slide-enter-active,
.slide-leave-active {
@apply transition-all duration-200 ease-in-out;
transform: translate(100%, 0);
}
.slide-enter,
.slide-leave-active {
transform: translate(-100%, 0);
}
.glow-enter-active,
.glow-leave-active {
@apply transition-all duration-300 ease-in-out;
}
.glow-enter-active {
@apply ring ring-xl;
}
.glow-enter,
.glow-leave-active {
@apply opacity-0;
}

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

@ -137,7 +137,7 @@ const activeTable = computed(() => {
<template>
<div class="nc-treeview-container flex flex-col">
<div class="px-6 py-[8.75px] border-b-1 nc-filter-input">
<div class="px-6 py-[9px] border-b-1 nc-filter-input">
<div class="flex items-center bg-gray-50 rounded relative">
<a-input
v-model:value="filterQuery"

124
packages/nc-gui-v2/components/general/SocialCard.vue

@ -7,67 +7,75 @@ const isRtlLang = $computed(() => ['fa'].includes(currentLang.value))
</script>
<template>
<a-list class="w-[300px] pa-3 elevation-4 rounded-xl mr-10" dense>
<a-list-item class="cursor-pointer">
<nuxt-link class="text-primary" to="https://github.com/nocodb/nocodb" target="_blank">
<div class="flex items-center text-sm">
<mdi-github class="mx-3 text-lg" />
<div v-if="isRtlLang">
<!-- us on Github -->
{{ $t('labels.community.starUs2') }}
<!-- Star -->
{{ $t('labels.community.starUs1') }}
<mdi-star-outline />
<a-card :body-style="{ padding: '0' }" class="w-[300px] shadow-sm rounded-lg">
<a-list class="w-full" dense>
<a-list-item>
<nuxt-link class="text-primary" to="https://github.com/nocodb/nocodb" target="_blank">
<div class="flex items-center text-sm">
<mdi-github class="mx-3 text-lg" />
<div v-if="isRtlLang">
<!-- us on Github -->
{{ $t('labels.community.starUs2') }}
<!-- Star -->
{{ $t('labels.community.starUs1') }}
<mdi-star-outline />
</div>
<div v-else class="flex items-center">
<!-- Star -->
{{ $t('labels.community.starUs1') }}
<mdi-star-outline class="mx-1" />
<!-- us on Github -->
{{ $t('labels.community.starUs2') }}
</div>
</div>
<div v-else class="flex items-center">
<!-- Star -->
{{ $t('labels.community.starUs1') }}
<mdi-star-outline class="mx-1" />
<!-- us on Github -->
{{ $t('labels.community.starUs2') }}
</nuxt-link>
</a-list-item>
<a-list-item>
<nuxt-link class="text-primary" to="https://calendly.com/nocodb-meeting" target="_blank">
<div class="flex items-center text-sm">
<mdi-calendar-month class="mx-3 text-lg" :color="colors.dark[3 % colors.dark.length]" />
<!-- Book a Free DEMO -->
<div>
{{ $t('labels.community.bookDemo') }}
</div>
</div>
</div>
</nuxt-link>
</a-list-item>
<a-list-item>
<nuxt-link class="text-primary" to="https://calendly.com/nocodb-meeting" target="_blank">
<div class="flex items-center text-sm">
<mdi-calendar-month class="mx-3 text-lg" :color="colors.dark[3 % colors.dark.length]" />
<!-- Book a Free DEMO -->
<div>
{{ $t('labels.community.bookDemo') }}
</nuxt-link>
</a-list-item>
<a-list-item>
<nuxt-link class="text-primary" to="https://discord.gg/5RgZmkW" target="_blank">
<div class="flex items-center text-sm">
<mdi-discord class="mx-3 text-lg" :color="colors.dark[0 % colors.dark.length]" />
<!-- Get your questions answered -->
<div>
{{ $t('labels.community.getAnswered') }}
</div>
</div>
</div>
</nuxt-link>
</a-list-item>
<a-list-item>
<nuxt-link class="text-primary" to="https://discord.gg/5RgZmkW" target="_blank">
<div class="flex items-center text-sm">
<mdi-discord class="mx-3 text-lg" :color="colors.dark[0 % colors.dark.length]" />
<!-- Get your questions answered -->
<div>
{{ $t('labels.community.getAnswered') }}
</nuxt-link>
</a-list-item>
<a-list-item>
<nuxt-link class="text-primary" to="https://twitter.com/NocoDB" target="_blank">
<div class="flex items-center text-sm">
<mdi-twitter class="mx-3 text-lg" :color="colors.dark[1 % colors.dark.length]" />
<!-- Follow NocoDB -->
<div>
{{ $t('labels.community.followNocodb') }}
</div>
</div>
</div>
</nuxt-link>
</a-list-item>
<a-list-item>
<nuxt-link class="text-primary" to="https://twitter.com/NocoDB" target="_blank">
<div class="flex items-center text-sm">
<mdi-twitter class="mx-3 text-lg" :color="colors.dark[1 % colors.dark.length]" />
<!-- Follow NocoDB -->
<div>
{{ $t('labels.community.followNocodb') }}
</nuxt-link>
</a-list-item>
<a-list-item v-t="['e:hiring']">
<nuxt-link class="text-primary" target="_blank" to="http://careers.nocodb.com">
<div class="flex items-center text-sm">
<div class="ml-3">🚀 <span class="ml-2">We are Hiring!!!</span></div>
</div>
</div>
</nuxt-link>
</a-list-item>
<a-list-item v-t="['e:hiring']">
<nuxt-link class="text-primary" target="_blank" to="http://careers.nocodb.com">
<div class="flex items-center text-sm">
<div class="ml-3">🚀 <span class="ml-2">We are Hiring!!!</span></div>
</div>
</nuxt-link>
</a-list-item>
</a-list>
</nuxt-link>
</a-list-item>
</a-list>
</a-card>
</template>
<style scoped>
:deep(.ant-list-item) {
@apply hover:(bg-gray-100 !text-primary);
}
</style>

6
packages/nc-gui-v2/components/general/Sponsors.vue

@ -7,9 +7,9 @@ const { nav = false } = defineProps<Props>()
</script>
<template>
<a-card class="w-[300px] ma-10 shadow-lg rounded-lg">
<a-card class="w-[300px] shadow-sm rounded-lg">
<template #cover>
<img class="max-h-[180px]" alt="cover" src="/ants-leaf-cutter.jpeg" />
<img class="max-h-[180px] rounded-t-lg" alt="cover" src="/ants-leaf-cutter.jpeg" />
</template>
<a-card-meta>
@ -26,7 +26,7 @@ const { nav = false } = defineProps<Props>()
<div class="flex justify-center">
<nuxt-link href="https://github.com/sponsors/nocodb" target="_blank">
<a-button class="!shadow" size="large">
<a-button class="!shadow rounded" size="large">
<div class="flex items-center">
<mdi-cards-heart class="text-red-500 mr-2" />
{{ $t('activity.sponsorUs') }}

2
packages/nc-gui-v2/components/smartsheet/Pagination.vue

@ -17,7 +17,7 @@ const page = computed({
</script>
<template>
<div class="flex items-center">
<div class="flex items-center mb-1">
<span v-if="count !== null && count !== Infinity" class="caption ml-5 text-gray-500">
{{ count }} record{{ count !== 1 ? 's' : '' }}
</span>

8
packages/nc-gui-v2/components/smartsheet/sidebar/MenuBottom.vue

@ -46,7 +46,7 @@ function onOpenModal(type: ViewTypes, title = '') {
class="group !flex !items-center !my-0 !h-[30px] nc-create-3-view"
@click="onOpenModal(ViewTypes.GRID)"
>
<a-tooltip placement="left">
<a-tooltip :mouse-enter-delay="1" placement="left">
<template #title>
{{ $t('msg.info.addView.grid') }}
</template>
@ -68,7 +68,7 @@ function onOpenModal(type: ViewTypes, title = '') {
class="group !flex !items-center !-my0 !h-[30px] nc-create-2-view"
@click="onOpenModal(ViewTypes.GALLERY)"
>
<a-tooltip placement="left">
<a-tooltip :mouse-enter-delay="1" placement="left">
<template #title>
{{ $t('msg.info.addView.gallery') }}
</template>
@ -91,7 +91,7 @@ function onOpenModal(type: ViewTypes, title = '') {
class="group !flex !items-center !my-0 !h-[30px] nc-create-1-view"
@click="onOpenModal(ViewTypes.FORM)"
>
<a-tooltip placement="left">
<a-tooltip :mouse-enter-delay="1" placement="left">
<template #title>
{{ $t('msg.info.addView.form') }}
</template>
@ -111,7 +111,7 @@ function onOpenModal(type: ViewTypes, title = '') {
<SmartsheetSidebarMenuApiSnippet v-model="showApiSnippet" />
<div class="flex-auto justify-end flex flex-col gap-4 mt-4">
<div class="flex-auto justify-end flex flex-col gap-3 mt-3">
<button
v-if="isUIAllowed('virtualViewsCreateOrEdit')"
class="flex items-center gap-2 w-full mx-3 px-4 py-3 rounded border transform translate-x-4 hover:(translate-x-0 shadow-lg) transition duration-150 ease !text-xs"

3
packages/nc-gui-v2/components/smartsheet/sidebar/RenameableMenuItem.vue

@ -2,7 +2,7 @@
import type { ViewTypes } from 'nocodb-sdk'
import { message } from 'ant-design-vue'
import { viewIcons } from '~/utils'
import { onKeyStroke, useDebounceFn, useNuxtApp, useVModel } from '#imports'
import { onKeyStroke, useDebounceFn, useNuxtApp, useUIPermission, useVModel } from '#imports'
interface Props {
view: Record<string, any>
@ -163,6 +163,7 @@ function onStopEdit() {
</div>
<a-input v-if="isEditing" :ref="focusInput" v-model:value="vModel.title" @blur="onCancel" @keydown="onKeyDown($event)" />
<div v-else>{{ vModel.alias || vModel.title }}</div>
<div class="flex-1" />

43
packages/nc-gui-v2/components/smartsheet/sidebar/index.vue

@ -3,7 +3,7 @@ import type { FormType, GalleryType, GridType, KanbanType, ViewTypes } from 'noc
import MenuTop from './MenuTop.vue'
import MenuBottom from './MenuBottom.vue'
import Toolbar from './toolbar/index.vue'
import { computed, inject, provide, ref, useRoute, useRouter, useViews, watch } from '#imports'
import { computed, inject, provide, ref, useElementHover, useRoute, useRouter, useViews, watch } from '#imports'
import { ActiveViewInj, MetaInj, RightSidebarInj, ViewListInj } from '~/context'
const meta = inject(MetaInj, ref())
@ -25,6 +25,9 @@ const sidebarOpen = inject(RightSidebarInj, ref(true))
const sidebarCollapsed = computed(() => !sidebarOpen.value)
/** Sidebar ref */
const sidebar = ref()
/** View type to create from modal */
let viewCreateType = $ref<ViewTypes>()
@ -37,6 +40,8 @@ let selectedViewId = $ref('')
/** is view creation modal open */
let modalOpen = $ref(false)
const isHovered = useElementHover(sidebar)
/** Watch route param and change active view based on `viewTitle` */
watch(
[views, () => route.params.viewTitle],
@ -74,6 +79,7 @@ function onCreate(view: GridType | FormType | KanbanType | GalleryType) {
<template>
<a-layout-sider
ref="sidebar"
:collapsed="sidebarCollapsed"
collapsiple
collapsed-width="50"
@ -81,24 +87,27 @@ function onCreate(view: GridType | FormType | KanbanType | GalleryType) {
class="relative shadow-md h-full"
theme="light"
>
<a-tooltip placement="left">
<a-tooltip :mouse-enter-delay="1" placement="left">
<template #title> Toggle sidebar </template>
<div
class="group color-transition cursor-pointer hover:ring active:ring-pink-500 z-1 flex items-center p-[1px] absolute top-1/2 left-[-1rem] shadow bg-gray-100 rounded-full"
>
<MaterialSymbolsChevronRightRounded
v-if="sidebarOpen"
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="sidebarOpen = false"
/>
<MaterialSymbolsChevronLeftRounded
v-else
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="sidebarOpen = true"
/>
</div>
<Transition name="glow">
<div
v-show="sidebarCollapsed || isHovered"
class="group color-transition cursor-pointer hover:ring active:ring-pink-500 z-1 flex items-center p-[1px] absolute top-1/2 left-[-1rem] shadow bg-gray-100 rounded-full"
>
<MaterialSymbolsChevronRightRounded
v-if="sidebarOpen"
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="sidebarOpen = false"
/>
<MaterialSymbolsChevronLeftRounded
v-else
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="sidebarOpen = true"
/>
</div>
</Transition>
</a-tooltip>
<Toolbar v-if="sidebarOpen" class="flex items-center py-3 px-3 justify-between border-b-1" />

2
packages/nc-gui-v2/components/smartsheet/sidebar/menu/ApiSnippet.vue

@ -172,5 +172,3 @@ const afterVisibleChange = (visible: boolean) => {
</div>
</a-drawer>
</template>
<style scoped></style>

2
packages/nc-gui-v2/components/tabs/Smartsheet.vue

@ -34,7 +34,7 @@ provide(ActiveViewInj, activeView)
provide(IsLockedInj, false)
provide(ReloadViewDataHookInj, reloadEventHook)
provide(FieldsInj, fields)
provide(RightSidebarInj, ref(true))
provide(RightSidebarInj, ref(false))
const { isGallery, isGrid, isForm } = useProvideSmartsheetStore(activeView as Ref<TableType>, meta)

23
packages/nc-gui-v2/composables/useUIPermission/index.ts

@ -1,14 +1,15 @@
import type { Permission } from './rolePermissions'
import rolePermissions from './rolePermissions'
import { USER_PROJECT_ROLES, useNuxtApp, useState } from '#imports'
import { USER_PROJECT_ROLES, useGlobal, useState } from '#imports'
export function useUIPermission() {
const { $state } = useNuxtApp()
const { user, previewAs } = useGlobal()
const projectRoles = useState<Record<string, boolean>>(USER_PROJECT_ROLES, () => ({}))
const isUIAllowed = (permission: Permission | string, skipPreviewAs = false) => {
const user = $state.user
let userRoles = user?.value?.roles || {}
const getRoles = (skipPreviewAs = false) => {
let userRoles = user.value?.roles || {}
// if string populate key-value paired object
if (typeof userRoles === 'string') {
userRoles = userRoles.split(',').reduce<Record<string, boolean>>((acc, role) => {
@ -20,16 +21,20 @@ export function useUIPermission() {
// merge user role and project specific user roles
let roles = {
...userRoles,
...(projectRoles?.value || {}),
...projectRoles.value,
}
if ($state.previewAs.value && !skipPreviewAs) {
if (previewAs.value && !skipPreviewAs) {
roles = {
[$state.previewAs.value]: true,
[previewAs.value]: true,
}
}
return Object.entries<boolean>(roles).some(([role, hasRole]) => {
return roles
}
const isUIAllowed = (permission: Permission | string, skipPreviewAs = false) => {
return Object.entries<boolean>(getRoles(skipPreviewAs)).some(([role, hasRole]) => {
const rolePermission = rolePermissions[role as keyof typeof rolePermissions] as '*' | Record<Permission, true>
return hasRole && (rolePermission === '*' || rolePermission?.[permission as Permission])

3
packages/nc-gui-v2/nuxt.config.ts

@ -51,6 +51,9 @@ export default defineNuxtConfig({
// todo: minifiy again
build: {
minify: false,
rollupOptions: {
external: 'httpsnippet',
},
},
css: {
preprocessorOptions: {

65
packages/nc-gui-v2/pages/[projectType]/[projectId]/index.vue

@ -1,7 +1,17 @@
<script setup lang="ts">
import { navigateTo, onKeyStroke, provideSidebar, ref, useProject, useRoute, useTabs, useUIPermission } from '#imports'
import {
navigateTo,
onKeyStroke,
openLink,
provideSidebar,
ref,
useElementHover,
useProject,
useRoute,
useTabs,
useUIPermission,
} from '#imports'
import { TabType } from '~/composables'
import { openLink } from '~/utils'
const route = useRoute()
@ -20,6 +30,9 @@ const openDialogKey = ref<string>()
const dropdownOpen = ref(false)
/** Sidebar ref */
const sidebar = ref()
onKeyStroke(
'Escape',
() => {
@ -42,12 +55,15 @@ function toggleDialog(value?: boolean, key?: string) {
await loadProject()
await loadTables()
const isHovered = useElementHover(sidebar)
</script>
<template>
<NuxtLayout id="content" class="flex">
<template #sidebar>
<a-layout-sider
ref="sidebar"
:collapsed="!isOpen"
width="250"
collapsed-width="50"
@ -56,7 +72,11 @@ await loadTables()
collapsible
theme="light"
>
<div style="height: var(--header-height)" class="flex items-center !bg-primary text-white px-1 pl-5 gap-2">
<div
style="height: var(--header-height)"
:class="isOpen ? 'pl-6' : ''"
class="flex items-center !bg-primary text-white px-1 gap-2"
>
<div
v-if="isOpen && !isSharedBase"
class="w-[40px] min-w-[40px] transition-all duration-200 p-1 cursor-pointer transform hover:scale-105"
@ -64,6 +84,7 @@ await loadTables()
>
<img alt="NocoDB" src="~/assets/img/icons/512x512-trans.png" />
</div>
<a
v-if="isOpen && isSharedBase"
class="w-[40px] min-w-[40px] transition-all duration-200 p-1 cursor-pointer transform hover:scale-105"
@ -77,6 +98,7 @@ await loadTables()
<template v-if="isOpen">
<div class="text-xl font-semibold truncate">{{ project.title }}</div>
</template>
<template v-else>
<MdiFolder class="text-primary cursor-pointer transform hover:scale-105 text-2xl" />
</template>
@ -111,6 +133,7 @@ await loadTables()
<div class="flex items-center gap-1">
<div class="group-hover:(!text-primary)">ID:</div>
<div class="text-xs group-hover:text-pink-500 truncate font-italic">{{ project.id }}</div>
</div>
</div>
@ -212,24 +235,27 @@ await loadTables()
</a-dropdown>
</div>
<a-tooltip placement="right">
<a-tooltip :mouse-enter-delay="1" placement="right">
<template #title> Toggle table list </template>
<div
class="group color-transition cursor-pointer hover:ring active:ring-pink-500 z-1 flex items-center absolute top-1/2 right-[-0.75rem] shadow bg-gray-100 rounded-full"
>
<MaterialSymbolsChevronLeftRounded
v-if="isOpen"
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="toggle(false)"
/>
<MaterialSymbolsChevronRightRounded
v-else
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="toggle(true)"
/>
</div>
<Transition name="glow">
<div
v-show="!isOpen || isHovered"
class="group color-transition cursor-pointer hover:ring active:ring-pink-500 z-1 flex items-center absolute top-1/2 right-[-0.75rem] shadow bg-gray-100 rounded-full"
>
<MaterialSymbolsChevronLeftRounded
v-if="isOpen"
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="toggle(false)"
/>
<MaterialSymbolsChevronRightRounded
v-else
class="transform group-hover:(scale-115 text-pink-500) text-xl text-gray-400"
@click="toggle(true)"
/>
</div>
</Transition>
</a-tooltip>
<DashboardTreeView v-show="isOpen" />
@ -237,6 +263,7 @@ await loadTables()
</template>
<dashboard-settings-modal v-model="dialogOpen" :open-key="openDialogKey" />
<NuxtPage />
<GeneralPreviewAs float />

54
packages/nc-gui-v2/pages/index/index.vue

@ -1,8 +1,17 @@
<script lang="ts" setup>
import { Modal, message } from 'ant-design-vue'
import type { ProjectType } from 'nocodb-sdk'
import { computed, navigateTo, onMounted, ref, useApi, useNuxtApp, useSidebar } from '#imports'
import { extractSdkResponseErrorMsg } from '~/utils'
import {
computed,
extractSdkResponseErrorMsg,
navigateTo,
onMounted,
ref,
useApi,
useNuxtApp,
useSidebar,
useUIPermission,
} from '#imports'
const { $e } = useNuxtApp()
@ -54,11 +63,14 @@ onMounted(() => {
<template>
<NuxtLayout>
<a-row>
<a-col :span="8"></a-col>
<a-col :span="8" class="!bg-red">
<a-card :loading="isLoading" class="mx-auto mt-10 !max-w-[600px] shadow-lg">
<h1 class="text-center text-4xl pa-2 nc-project-page-title flex align-center justify-center gap-2 text-gray-600">
<div class="flex flex-col md:flex-row flex-wrap gap-6 py-6 px-12">
<div class="hidden xl:(block)">
<GeneralSponsors />
</div>
<div class="min-w-2/4 flex-auto">
<a-card :loading="isLoading" class="!rounded-lg shadow">
<h1 class="text-center text-4xl p-2 nc-project-page-title flex items-center justify-center gap-2 text-gray-600">
<!-- My Projects -->
<b>{{ $t('title.myProject') }}</b>
@ -66,16 +78,17 @@ onMounted(() => {
v-t="['a:project:refresh']"
class="text-sm text-gray-500 hover:text-primary mt-1 cursor-pointer"
@click="loadProjects"
></MdiRefresh>
/>
</h1>
<div class="flex mb-6">
<div class="order-1 flex mb-6">
<a-input-search
v-model:value="filterQuery"
class="max-w-[200px] nc-project-page-search"
:placeholder="$t('activity.searchProject')"
></a-input-search>
<div class="flex-grow"></div>
/>
<div class="flex-grow" />
<a-dropdown v-if="isUIAllowed('projectCreate', true)" @click.stop>
<a-button class="nc-new-project-menu !shadow">
@ -93,14 +106,17 @@ onMounted(() => {
@click="navigateTo('/project/create')"
>
<MdiPlus class="col-span-2 mr-1 mt-[1px] text-primary text-lg" />
<div class="col-span-10 text-sm xl:text-md">{{ $t('activity.createProject') }}</div>
</div>
<div
v-t="['c:project:create:extdb']"
class="grid grid-cols-12 cursor-pointer hover:bg-gray-200 flex items-center p-2 nc-create-external-db-project"
@click="navigateTo('/project/create-external')"
>
<MdiDatabaseOutline class="col-span-2 mr-1 mt-[1px] text-green-500 text-lg" />
<div class="col-span-10 text-sm xl:text-md" v-html="$t('activity.createProjectExtended.extDB')" />
</div>
</a-menu>
@ -151,16 +167,16 @@ onMounted(() => {
</a-table-column>
</a-table>
</a-card>
</a-col>
<a-col :span="8" class="">
<div class="justify-end flex">
</div>
<div class="flex gap-6 md:block">
<GeneralSocialCard />
<div class="block mt-0 md:(!mt-6) xl:hidden">
<GeneralSponsors />
</div>
<div class="justify-end flex">
<GeneralSocialCard />
</div>
</a-col>
</a-row>
</div>
</div>
</NuxtLayout>
</template>

Loading…
Cancel
Save