[WBX-31] Make account modal less annoying in the viewer (#2009)

* Changes settings card to team when logged out

* Speckle Logo to Marketing Site when logged out

* Add Signin button to desktop header

* Remove click counter - Launch modal instead

* Fix webhook being in Settings dialog

* Change team icon

* Changes from Benjamins Comments

* Remove Join the conversation

* Move dialogs to parent

* Move loginUrl logic to parent

* Small fixes

* Default active to true in LogoBlock

* Simplify HeaderLogoBlock for this ticket. Change type from CR
This commit is contained in:
andrewwallacespeckle 2024-02-05 15:32:01 +00:00 коммит произвёл GitHub
Родитель c727669be4
Коммит ec95ebdfb3
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
9 изменённых файлов: 94 добавлений и 86 удалений

Просмотреть файл

@ -1,28 +1,35 @@
<template>
<NuxtLink class="flex items-center shrink-0" to="/">
<NuxtLink class="flex items-center shrink-0" :to="to" :target="target">
<img
class="block h-6 w-6"
:class="{ 'mr-2': !minimal, grayscale: active }"
class="h-8 w-8 block"
:class="{
grayscale: active
}"
src="~~/assets/images/speckle_logo_big.png"
alt="Speckle"
/>
<div
v-if="!minimal"
class="text-primary h6 mt-0 hidden font-bold leading-7 md:flex"
class="text-primary text-base mt-0 font-bold leading-7"
:class="showTextOnMobile ? '' : 'hidden md:flex'"
>
Speckle
</div>
</NuxtLink>
</template>
<script setup lang="ts">
defineProps({
minimal: {
type: Boolean,
default: false
},
active: {
type: Boolean,
default: true
withDefaults(
defineProps<{
minimal?: boolean
active?: boolean
to?: string
showTextOnMobile?: boolean
target?: string
}>(),
{
active: true,
to: '/'
}
})
)
</script>

Просмотреть файл

@ -3,7 +3,7 @@
<nav class="fixed z-20 top-0 h-14 bg-foundation shadow hover:shadow-md transition">
<div class="flex items-center justify-between h-full w-screen px-4">
<div class="flex items-center truncate">
<HeaderLogoBlock :active="false" />
<HeaderLogoBlock :active="false" to="/" />
<HeaderNavLink
to="/"
name="Dashboard"
@ -17,8 +17,17 @@
<PortalTarget name="primary-actions"></PortalTarget>
<!-- Notifications dropdown -->
<HeaderNavNotifications />
<FormButton
v-if="!activeUser"
:to="loginUrl.fullPath"
color="invert"
class="hidden md:flex"
size="sm"
>
Sign In
</FormButton>
<!-- Profile dropdown -->
<HeaderNavUserMenu />
<HeaderNavUserMenu :login-url="loginUrl" />
</div>
</div>
<PopupsSignIn v-if="!activeUser" />
@ -28,5 +37,21 @@
</template>
<script setup lang="ts">
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import { loginRoute } from '~~/lib/common/helpers/route'
import type { Optional } from '@speckle/shared'
const { activeUser } = useActiveUser()
const route = useRoute()
const router = useRouter()
const token = computed(() => route.query.token as Optional<string>)
const loginUrl = computed(() =>
router.resolve({
path: loginRoute,
query: {
token: token.value || undefined
}
})
)
</script>

Просмотреть файл

@ -105,7 +105,7 @@
Sign Out
</NuxtLink>
</MenuItem>
<MenuItem v-if="!activeUser" v-slot="{ active }">
<MenuItem v-if="!activeUser && loginUrl" v-slot="{ active }">
<NuxtLink
:class="[
active ? 'bg-foundation-focus' : '',
@ -143,23 +143,24 @@ import {
ChatBubbleLeftRightIcon
} from '@heroicons/vue/24/outline'
import { Roles } from '@speckle/shared'
import type { Optional } from '@speckle/shared'
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import { useAuthManager } from '~~/lib/auth/composables/auth'
import { loginRoute } from '~~/lib/common/helpers/route'
import { useTheme, AppTheme } from '~~/lib/core/composables/theme'
import { useServerInfo } from '~/lib/core/composables/server'
import type { RouteLocationRaw } from 'vue-router'
defineProps<{
loginUrl?: RouteLocationRaw
}>()
const { logout } = useAuthManager()
const { activeUser, isGuest } = useActiveUser()
const { isDarkTheme, setTheme } = useTheme()
const { serverInfo } = useServerInfo()
const route = useRoute()
const router = useRouter()
const showInviteDialog = ref(false)
const showProfileEditDialog = ref(false)
const token = computed(() => route.query.token as Optional<string>)
const Icon = computed(() => (isDarkTheme.value ? SunIcon : MoonIcon))
const version = computed(() => serverInfo.value?.version)
@ -185,13 +186,4 @@ const goToConnectors = () => {
const goToServerManagement = () => {
router.push('/server-management')
}
const loginUrl = computed(() =>
router.resolve({
path: loginRoute,
query: {
token: token.value || undefined
}
})
)
</script>

Просмотреть файл

@ -4,21 +4,12 @@
dialog-mode
max-width="sm"
subtitle="Create a free account to keep using Speckle!"
:hide-closer="dialogOpenCount >= 3"
:prevent-close-on-click-outside="dialogOpenCount >= 3"
/>
</template>
<script setup lang="ts">
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import { debounce } from 'lodash-es'
const { activeUser } = useActiveUser()
const logger = useLogger()
const route = useRoute()
const showDialogBase = ref(false)
const clickyCounts = ref(0)
let clicksToOpenDialog = 6
const showDialog = computed({
get: () => showDialogBase.value,
@ -30,46 +21,4 @@ const showDialog = computed({
showDialogBase.value = newVal
}
})
watch(clickyCounts, (newVal) => {
if (activeUser.value) return
if (newVal < clicksToOpenDialog) return
clickyCounts.value = 0
showDialog.value = true
clicksToOpenDialog *= 2
})
const countClicks = () => {
logger.debug({
clickyCounts: clickyCounts.value,
clicksToOpenDialog,
dialogOpenCount: dialogOpenCount.value
})
clickyCounts.value++
}
const debouncedCounter = debounce(countClicks, 100)
// After three dialog opens, we disallow its closing
const dialogOpenCount = ref(0)
watch(showDialog, (newVal) => {
if (!newVal) return
dialogOpenCount.value++
})
onMounted(() => {
if (activeUser.value) return
// Note: not using the vue use equivalent as it does not detect viewer clicks
// Note: viewer eevnt handlers seem to prevent default on right clicks
document.addEventListener('click', countClicks)
document.addEventListener('touchstart', countClicks)
document.addEventListener('scroll', debouncedCounter)
})
onUnmounted(() => {
if (activeUser.value) return
document.removeEventListener('click', countClicks)
document.removeEventListener('touchstart', countClicks)
document.removeEventListener('scroll', debouncedCounter)
})
</script>

Просмотреть файл

@ -3,10 +3,17 @@
<template #top>
<div class="flex items-center">
<div class="flex items-center justify-between w-full">
<div class="flex items-center gap-0.5 flex-grow select-none">
<div
v-if="activeUser"
class="flex items-center gap-0.5 flex-grow select-none"
>
<Cog6ToothIcon class="h-5 w-5" />
<span class="text-sm">Settings</span>
</div>
<div v-else class="flex items-center gap-0.5 flex-grow select-none">
<UsersIcon class="h-5 w-5" />
<span class="text-sm">Team</span>
</div>
<div class="flex items-center text-xs">
{{ project.role?.split(':').reverse()[0] }}
</div>
@ -16,7 +23,7 @@
<template #bottom>
<div class="flex items-center justify-between mt-3">
<UserAvatarGroup :users="teamUsers" class="max-w-[104px]" />
<div>
<div v-if="activeUser">
<FormButton class="ml-2" @click="dialogOpen = true">
{{ project.role === 'stream:owner' ? 'Manage' : 'View' }}
</FormButton>
@ -29,9 +36,11 @@
</ProjectPageStatsBlock>
</template>
<script setup lang="ts">
import { Cog6ToothIcon } from '@heroicons/vue/24/outline'
import { Cog6ToothIcon, UsersIcon } from '@heroicons/vue/24/outline'
import { useActiveUser } from '~~/lib/auth/composables/activeUser'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageStatsBlockTeamFragment } from '~~/lib/common/generated/gql/graphql'
const { activeUser } = useActiveUser()
graphql(`
fragment ProjectPageStatsBlockTeam on Project {

Просмотреть файл

@ -8,7 +8,7 @@
:project="project"
/>
<ProjectPageTeamDialogManagePermissions :project="project" />
<ProjectPageTeamDialogWebhooks :project="project" />
<ProjectPageTeamDialogWebhooks v-if="isOwner" :project="project" />
<ProjectPageTeamDialogDangerZones
v-if="isOwner || canLeaveProject"
:project="project"

Просмотреть файл

@ -5,10 +5,11 @@
>
<!-- Add new thread bubble -->
<ViewerAnchoredPointNewThread
v-if="canPostComment"
v-model="buttonState"
:can-post-comment="canPostComment"
class="z-[13]"
@close="closeNewThread"
@login="showLoginDialog = true"
/>
<!-- Comment bubbles -->
@ -22,6 +23,7 @@
@update:expanded="onThreadExpandedChange"
@next="(model) => openNextThread(model)"
@prev="(model) => openPrevThread(model)"
@login="showLoginDialog = true"
/>
<!-- Active users -->
@ -32,6 +34,13 @@
class="z-[10]"
/>
<AuthLoginPanel
v-model:open="showLoginDialog"
dialog-mode
max-width="sm"
subtitle="Join the conversation"
/>
<!-- Active user avatars in navbar -->
<Portal to="secondary-actions">
<ViewerScope :state="state">
@ -139,6 +148,8 @@ const {
}
} = useInjectedViewerInterfaceState()
const showLoginDialog = ref(false)
useViewerCommentBubblesProjection({ parentEl })
const { buttonState, closeNewThread } = useViewerNewThreadBubble({

Просмотреть файл

@ -33,7 +33,7 @@
</button>
</div>
<div
v-if="modelValue.isExpanded"
v-if="modelValue.isExpanded && canPostComment"
ref="threadContainer"
class="sm:absolute min-w-[200px] hover:bg-foundation transition bg-white/80 dark:bg-neutral-800/90 dark:hover:bg-neutral-800 backdrop-blur-sm sm:rounded-lg shadow-md"
>
@ -91,10 +91,12 @@ import { useThreadUtilities } from '~~/lib/viewer/composables/ui'
const emit = defineEmits<{
(e: 'update:modelValue', v: ViewerNewThreadBubbleModel): void
(e: 'close'): void
(e: 'login'): void
}>()
const props = defineProps<{
modelValue: ViewerNewThreadBubbleModel
canPostComment?: Nullable<boolean>
}>()
const { onKeyDownHandler, updateIsTyping, pauseAutomaticUpdates } =
@ -114,6 +116,12 @@ const createThread = useSubmitComment()
const onThreadClick = () => {
const newIsExpanded = !props.modelValue.isExpanded
if (!props.canPostComment) {
emit('login')
return
}
if (!newIsExpanded) {
updateIsTyping(false)
}

Просмотреть файл

@ -151,6 +151,12 @@
:model-value="modelValue"
@submit="onNewReply"
/>
<div
v-if="!canReply"
class="p-3 flex flex-col items-center justify-center bg-foundation-2"
>
<FormButton full-width @click="$emit('login')">Reply</FormButton>
</div>
</div>
</div>
</ViewerCommentsPortalOrDiv>
@ -201,6 +207,7 @@ const emit = defineEmits<{
(e: 'update:expanded', v: boolean): void
(e: 'next', v: CommentBubbleModel): void
(e: 'prev', v: CommentBubbleModel): void
(e: 'login'): void
}>()
const props = defineProps<{