Feat: Remove workspace promobanner (#3185)

This commit is contained in:
Mike
2024-10-08 09:45:33 +02:00
committed by GitHub
parent 527ea9a2f7
commit 18b7ac1f74
8 changed files with 83 additions and 125 deletions
@@ -26,7 +26,9 @@
class="absolute z-40 lg:static h-full flex w-[17rem] shrink-0 transition-all"
:class="isOpenMobile ? '' : '-translate-x-[17rem] lg:translate-x-0'"
>
<LayoutSidebar class="border-r border-outline-3 px-2 py-3 bg-foundation-page">
<LayoutSidebar
class="border-r border-outline-3 px-2 pt-3 pb-2 bg-foundation-page"
>
<LayoutSidebarMenu>
<LayoutSidebarMenuGroup>
<NuxtLink :to="homeRoute" @click="isOpenMobile = false">
@@ -156,6 +158,14 @@
</NuxtLink>
</LayoutSidebarMenuGroup>
</LayoutSidebarMenu>
<template #promo>
<LayoutSidebarPromo
title="SpeckleCon 2024"
text="Join us in London on Nov 13-14 for the ultimate community event."
button-text="Get tickets"
@on-click="onPromoClick"
/>
</template>
</LayoutSidebar>
</div>
</template>
@@ -173,6 +183,7 @@
import {
FormButton,
LayoutSidebar,
LayoutSidebarPromo,
LayoutSidebarMenu,
LayoutSidebarMenuGroup,
LayoutSidebarMenuGroupItem
@@ -249,6 +260,15 @@ onWorkspaceResult((result) => {
}
})
const onPromoClick = () => {
mixpanel.track('Promo Banner Clicked', {
source: 'sidebar',
campaign: 'specklecon2024'
})
window.open('https://conf.speckle.systems/', '_blank')
}
const openFeedbackDialog = () => {
showFeedbackDialog.value = true
isOpenMobile.value = false
@@ -1,109 +0,0 @@
<template>
<ClientOnly>
<div class="position left-2 sm:left-auto right-2 bottom-2 fixed z-[45]">
<div
v-if="showBanner"
class="rounded-lg flex flex-col w-full sm:max-w-96 border border-outline-2 shadow-md bg-foundation-3 dark:bg-foundation"
>
<img :src="bannerImage" class="w-full" alt="Try workspaces" />
<div class="px-5 py-6 flex flex-col gap-y-2">
<h5 class="text-body-xs md:text-heading-sm text-foreground font-medium">
Still not using workspaces?
</h5>
<p class="text-body-2xs leading-5 md:text-body-xs text-foreground-2">
Be the first to reach more security options, data control, and better
project management with your team.
</p>
<div class="flex items-center gap-x-2 mt-2">
<FormButton color="primary" size="sm" @click="openWorkspaceCreateDialog">
Start for free
</FormButton>
<FormButton color="subtle" size="sm" @click="dismissedCookie = true">
Dismiss
</FormButton>
</div>
</div>
<WorkspaceCreateDialog
v-model:open="showWorkspaceCreateDialog"
navigate-on-success
event-source="promo-banner"
@created="dismissedCookie = true"
/>
</div>
</div>
</ClientOnly>
</template>
<script setup lang="ts">
// This is a temporary component, to meassure if in app-notifications can be succesful
// It will be remove after a certain period, if we continue with in-app notification we should further develop this
import { useMixpanel } from '~~/lib/core/composables/mp'
import { useSynchronizedCookie } from '~~/lib/common/composables/reactiveCookie'
import { CookieKeys } from '~/lib/common/helpers/constants'
import { useIsWorkspacesEnabled } from '~/composables/globals'
import { settingsSidebarQuery } from '~/lib/settings/graphql/queries'
import { useQuery } from '@vue/apollo-composable'
import { useTheme } from '~~/lib/core/composables/theme'
import { useBreakpoints } from '@vueuse/core'
import { TailwindBreakpoints } from '~~/lib/common/helpers/tailwind'
import imageLight from '~/assets/images/banners/workspace-promo-light.png'
import imageDark from '~/assets/images/banners/workspace-promo-dark.png'
import imageMobileLight from '~/assets/images/banners/workspace-promo-mobile-light.png'
import imageMobileDark from '~/assets/images/banners/workspace-promo-mobile-dark.png'
const { isLoggedIn } = useActiveUser()
const breakpoints = useBreakpoints(TailwindBreakpoints)
const { isDarkTheme } = useTheme()
const isWorkspacesEnabled = useIsWorkspacesEnabled()
const mixpanel = useMixpanel()
const dismissedCookie = useSynchronizedCookie<boolean>(
CookieKeys.DismissedWorkspaceBanner,
{
default: () => false
}
)
const { result } = useQuery(settingsSidebarQuery, null, {
enabled: isWorkspacesEnabled.value
})
const showWorkspaceCreateDialog = ref(false)
const isMobile = breakpoints.smaller('md')
const bannerImage = computed(() => {
if (isMobile.value) {
return isDarkTheme.value ? imageMobileDark : imageMobileLight
}
return isDarkTheme.value ? imageDark : imageLight
})
const hasWorkspaces = computed(() =>
result.value?.activeUser?.workspaces.items
? result.value.activeUser.workspaces.items.length > 0
: false
)
const showBanner = computed(
() =>
isWorkspacesEnabled.value &&
isLoggedIn.value &&
!hasWorkspaces.value &&
(import.meta.client ? !dismissedCookie.value : false)
)
const openWorkspaceCreateDialog = () => {
showWorkspaceCreateDialog.value = true
mixpanel.track('Create Workspace Button Clicked', {
source: 'promo-banner'
})
}
watch(
showBanner,
(newVal) => {
if (newVal) {
mixpanel.track('Workspace Promo Banner Viewed', {
source: 'promo-banner'
})
}
},
{ immediate: true }
)
</script>
-1
View File
@@ -1,7 +1,6 @@
<template>
<div>
<HeaderNavBar />
<PromoBannersWorkspace />
<div class="h-dvh w-dvh overflow-hidden flex flex-col">
<!-- Static Spacer to allow for absolutely positioned HeaderNavBar -->
<div class="h-12 w-full shrink-0"></div>
+5 -12
View File
@@ -3,7 +3,10 @@
<Portal to="navigation">
<HeaderNavLink :to="homeRoute" name="Dashboard" hide-chevron :separator="false" />
</Portal>
<PromoBannersWrapper v-if="promoBanners.length" :banners="promoBanners" />
<PromoBannersWrapper
v-if="promoBanners && promoBanners.length"
:banners="promoBanners"
/>
<ProjectsDashboardHeader
:projects-invites="projectsResult?.activeUser || undefined"
:workspaces-invites="workspacesResult?.activeUser || undefined"
@@ -72,7 +75,6 @@ import { downloadManager } from '~~/lib/common/utils/downloadManager'
import { ToastNotificationType, useGlobalToast } from '~~/lib/common/composables/toast'
import type { LayoutDialogButton } from '@speckle/ui-components'
import type { PromoBanner } from '~/lib/promo-banners/types'
import speckleconTicketsImage from '~/assets/images/banners/grab-your-tickets.gif'
useHead({ title: 'Dashboard' })
@@ -187,14 +189,5 @@ const onDownloadManager = (extension: ManagerExtension) => {
}
}
const promoBanners = ref<PromoBanner[]>([
{
primaryText: 'Specklecon - Grab your tickets',
url: 'https://conf.speckle.systems/',
priority: 1,
expiryDate: '2024-11-14',
image: speckleconTicketsImage,
isBackgroundImage: true
}
])
const promoBanners = ref<PromoBanner[]>()
</script>
@@ -0,0 +1,38 @@
<template>
<div
class="flex flex-col gap-y-1 sm:gap-y-2 border border-outline-3 rounded-lg py-2 px-3 sm:p-4 select-none"
>
<h6
v-if="title"
class="text-body-xs sm:text-heading-sm font-medium text-foreground"
>
{{ title }}
</h6>
<p v-if="text" class="text-body-2xs sm:text-body-xs text-foreground-2 !leading-5">
{{ text }}
</p>
<FormButton
v-if="buttonText"
size="sm"
class="mt-1"
:to="to"
:target="to ? '_blank' : undefined"
@click="$emit('onClick')"
>
{{ buttonText }}
</FormButton>
</div>
</template>
<script setup lang="ts">
import FormButton from '~~/src/components/form/Button.vue'
defineEmits(['onClick'])
defineProps<{
title?: string
text?: string
to?: string
buttonText?: string
}>()
</script>
@@ -1,5 +1,6 @@
import type { Meta, StoryObj } from '@storybook/vue3'
import LayoutSidebar from '~~/src/components/layout/sidebar/Sidebar.vue'
import LayoutSidebarPromo from '~~/src/components/layout/sidebar/Promo.vue'
import LayoutSidebarMenu from '~~/src/components/layout/sidebar/menu/Menu.vue'
import LayoutSidebarMenuGroup from '~~/src/components/layout/sidebar/menu/group/Group.vue'
import LayoutSidebarMenuGroupItem from '~~/src/components/layout/sidebar/menu/group/Item.vue'
@@ -20,6 +21,7 @@ export const Dashboard: StoryObj = {
render: (args) => ({
components: {
LayoutSidebar,
LayoutSidebarPromo,
LayoutSidebarMenu,
LayoutSidebarMenuGroup,
LayoutSidebarMenuGroupItem,
@@ -68,6 +70,9 @@ export const Dashboard: StoryObj = {
</LayoutSidebarMenuGroupItem>
</LayoutSidebarMenuGroup>
</LayoutSidebarMenu>
<template #promo>
<LayoutSidebarPromo title="Example Title" text="An example piece of text" />
</template>
</LayoutSidebar>
`
})
@@ -1,7 +1,17 @@
<template>
<!-- If promo content is defined, scroll the menu items. If not, scroll the whole aside -->
<aside
class="flex flex-col justify-between h-full w-full overflow-y-auto overflow-x-hidden simple-scrollbar"
class="flex flex-col justify-between h-full w-full"
:class="$slots.promo ? '' : 'overflow-y-auto overflow-x-hidden simple-scrollbar'"
>
<slot></slot>
<div
class="flex flex-col h-full w-full"
:class="$slots.promo ? 'overflow-y-auto overflow-x-hidden simple-scrollbar' : ''"
>
<slot></slot>
</div>
<div v-if="$slots.promo" class="shrink-0 pt-2">
<slot name="promo"></slot>
</div>
</aside>
</template>
+2
View File
@@ -65,6 +65,7 @@ import InfiniteLoading from '~~/src/components/InfiniteLoading.vue'
import type { InfiniteLoaderState } from '~~/src/helpers/global/components'
import LayoutPanel from '~~/src/components/layout/Panel.vue'
import LayoutSidebar from '~~/src/components/layout/sidebar/Sidebar.vue'
import LayoutSidebarPromo from '~~/src/components/layout/sidebar/Promo.vue'
import LayoutSidebarMenu from '~~/src/components/layout/sidebar/menu/Menu.vue'
import LayoutSidebarMenuGroup from '~~/src/components/layout/sidebar/menu/group/Group.vue'
import LayoutSidebarMenuGroupItem from '~~/src/components/layout/sidebar/menu/group/Item.vue'
@@ -153,6 +154,7 @@ export {
LayoutTabsVertical,
LayoutTable,
LayoutSidebar,
LayoutSidebarPromo,
LayoutSidebarMenu,
LayoutSidebarMenuGroup,
LayoutSidebarMenuGroupItem,