refactor(fe2): Change workspace creation triggers (#3211)
* Tasks from ticket * Update copy * Add confirm dialog to cancel button * Show Workspace create dialog when on explainer page * Reorder * Add new mixpanel event * Use 1 confirm modal
This commit is contained in:
committed by
GitHub
parent
1866d3369b
commit
d956fbf79d
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<LayoutDialog v-model:open="open" max-width="xs" :buttons="dialogButtons">
|
||||
<template #header>Discard changes?</template>
|
||||
<p v-if="text" class="mb-2">{{ text }}</p>
|
||||
<p v-else class="mb-2">You have unsaved changes. Are you sure you want to leave?</p>
|
||||
</LayoutDialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { LayoutDialogButton } from '@speckle/ui-components'
|
||||
|
||||
defineProps<{
|
||||
text?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits(['confirm'])
|
||||
|
||||
const open = defineModel<boolean>('open', { required: true })
|
||||
|
||||
const dialogButtons = computed((): LayoutDialogButton[] => {
|
||||
return [
|
||||
{
|
||||
text: 'Cancel',
|
||||
props: { color: 'outline' },
|
||||
onClick: () => {
|
||||
open.value = false
|
||||
}
|
||||
},
|
||||
{
|
||||
text: 'Continue',
|
||||
onClick: () => {
|
||||
open.value = false
|
||||
emit('confirm')
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
</script>
|
||||
@@ -58,16 +58,10 @@
|
||||
v-if="isWorkspacesEnabled"
|
||||
collapsible
|
||||
title="Workspaces"
|
||||
:plus-click="
|
||||
isNotGuest
|
||||
? () => {
|
||||
openWorkspaceCreateDialog()
|
||||
}
|
||||
: undefined
|
||||
"
|
||||
:plus-click="isNotGuest ? handlePlusClick : undefined"
|
||||
plus-text="Create workspace"
|
||||
>
|
||||
<NuxtLink :to="workspacesRoute" @click="isOpenMobile = false">
|
||||
<NuxtLink :to="workspacesRoute" @click="handleIntroducingWorkspacesClick">
|
||||
<LayoutSidebarMenuGroupItem
|
||||
label="Introducing workspaces"
|
||||
:active="isActive(workspacesRoute)"
|
||||
@@ -206,6 +200,7 @@ import { Roles } from '@speckle/shared'
|
||||
const { isLoggedIn } = useActiveUser()
|
||||
const isWorkspacesEnabled = useIsWorkspacesEnabled()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { activeUser: user } = useActiveUser()
|
||||
const mixpanel = useMixpanel()
|
||||
|
||||
@@ -241,13 +236,6 @@ const workspacesItems = computed(() =>
|
||||
: []
|
||||
)
|
||||
|
||||
const openWorkspaceCreateDialog = () => {
|
||||
showWorkspaceCreateDialog.value = true
|
||||
mixpanel.track('Create Workspace Button Clicked', {
|
||||
source: 'sidebar'
|
||||
})
|
||||
}
|
||||
|
||||
onWorkspaceResult((result) => {
|
||||
if (result.data?.activeUser) {
|
||||
const workspaceIds = result.data.activeUser.workspaces.items.map(
|
||||
@@ -273,4 +261,29 @@ const openFeedbackDialog = () => {
|
||||
showFeedbackDialog.value = true
|
||||
isOpenMobile.value = false
|
||||
}
|
||||
|
||||
const openWorkspaceCreateDialog = () => {
|
||||
showWorkspaceCreateDialog.value = true
|
||||
mixpanel.track('Create Workspace Button Clicked', {
|
||||
source: 'sidebar'
|
||||
})
|
||||
}
|
||||
|
||||
const handlePlusClick = () => {
|
||||
if (route.path === workspacesRoute) {
|
||||
openWorkspaceCreateDialog()
|
||||
} else {
|
||||
mixpanel.track('Clicked Link to Workspace Explainer', {
|
||||
source: 'sidebar'
|
||||
})
|
||||
router.push(workspacesRoute)
|
||||
}
|
||||
}
|
||||
|
||||
const handleIntroducingWorkspacesClick = () => {
|
||||
isOpenMobile.value = false
|
||||
mixpanel.track('Clicked Link to Workspace Explainer', {
|
||||
source: 'sidebar'
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<LayoutDialog v-model:open="open" max-width="sm" :buttons="dialogButtons">
|
||||
<LayoutDialog
|
||||
v-model:open="open"
|
||||
max-width="sm"
|
||||
:buttons="dialogButtons"
|
||||
hide-closer
|
||||
prevent-close-on-click-outside
|
||||
>
|
||||
<template #header>Create a new project</template>
|
||||
<form class="flex flex-col text-foreground" @submit="onSubmit">
|
||||
<div class="flex flex-col gap-y-4 mb-2">
|
||||
@@ -28,7 +34,7 @@
|
||||
<ProjectVisibilitySelect v-model="visibility" mount-menu-on-body />
|
||||
</div>
|
||||
<template v-if="isWorkspacesEnabled && !workspaceId">
|
||||
<div v-if="!isCreatingWorkspace" class="flex gap-y-2 flex-col">
|
||||
<div class="flex gap-y-2 flex-col">
|
||||
<p class="text-body-xs text-foreground font-medium">Workspace</p>
|
||||
<div v-if="hasWorkspaces">
|
||||
<div class="flex gap-x-2 items-center">
|
||||
@@ -39,31 +45,31 @@
|
||||
disabled-item-tooltip="You dont have rights to create projects in this workspace"
|
||||
class="flex-1"
|
||||
/>
|
||||
<FormButton
|
||||
:icon-left="PlusIcon"
|
||||
hide-text
|
||||
class="flex"
|
||||
color="outline"
|
||||
@click="isCreatingWorkspace = true"
|
||||
/>
|
||||
<div v-tippy="'Create workspace'" class="flex">
|
||||
<FormButton
|
||||
:icon-left="PlusIcon"
|
||||
hide-text
|
||||
class="flex"
|
||||
color="outline"
|
||||
@click="navigateToWorkspaceExplainer"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<FormButton v-else color="outline" @click="isCreatingWorkspace = true">
|
||||
<FormButton v-else color="outline" @click="navigateToWorkspaceExplainer">
|
||||
New workspace
|
||||
</FormButton>
|
||||
<p class="text-foreground-2 text-body-2xs">
|
||||
Workspace offers better project management and higher data security.
|
||||
Workspaces offer better project management and higher data security.
|
||||
</p>
|
||||
</div>
|
||||
<ProjectsNewWorkspace
|
||||
v-if="isCreatingWorkspace"
|
||||
mixpanel-event-source="create-project-modal"
|
||||
@cancel="isCreatingWorkspace = false"
|
||||
@workspace-created="onWorkspaceCreated"
|
||||
/>
|
||||
</template>
|
||||
</div>
|
||||
</form>
|
||||
<CommonConfirmDialog
|
||||
v-model:open="showConfirmDialog"
|
||||
@confirm="handleConfirmAction"
|
||||
/>
|
||||
</LayoutDialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
@@ -80,6 +86,7 @@ import { graphql } from '~~/lib/common/generated/gql'
|
||||
import { projectWorkspaceSelectQuery } from '~/lib/projects/graphql/queries'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import { Roles } from '@speckle/shared'
|
||||
import { workspacesRoute } from '~/lib/common/helpers/route'
|
||||
|
||||
graphql(`
|
||||
fragment ProjectsAddDialog_Workspace on Workspace {
|
||||
@@ -114,24 +121,21 @@ const emit = defineEmits<{
|
||||
|
||||
const isWorkspacesEnabled = useIsWorkspacesEnabled()
|
||||
const createProject = useCreateProject()
|
||||
const { handleSubmit } = useForm<FormValues>()
|
||||
const router = useRouter()
|
||||
const { handleSubmit, meta } = useForm<FormValues>()
|
||||
const { result: workspaceResult } = useQuery(projectWorkspaceSelectQuery, null, () => ({
|
||||
enabled: isWorkspacesEnabled.value
|
||||
}))
|
||||
|
||||
const visibility = ref(ProjectVisibility.Unlisted)
|
||||
const selectedWorkspace = ref<ProjectsAddDialog_WorkspaceFragment>()
|
||||
const isCreatingWorkspace = ref<boolean>(false)
|
||||
const showConfirmDialog = ref(false)
|
||||
const confirmActionType = ref<'navigate' | 'close' | null>(null)
|
||||
|
||||
const open = defineModel<boolean>('open', { required: true })
|
||||
|
||||
const mp = useMixpanel()
|
||||
|
||||
const onWorkspaceCreated = (workspace: ProjectsAddDialog_WorkspaceFragment) => {
|
||||
isCreatingWorkspace.value = false
|
||||
selectedWorkspace.value = workspace
|
||||
}
|
||||
|
||||
const onSubmit = handleSubmit(async (values) => {
|
||||
await createProject({
|
||||
name: values.name,
|
||||
@@ -154,14 +158,11 @@ const workspaces = computed(
|
||||
)
|
||||
const hasWorkspaces = computed(() => workspaces.value.length > 0)
|
||||
const dialogButtons = computed((): LayoutDialogButton[] => {
|
||||
if (isCreatingWorkspace.value) return []
|
||||
return [
|
||||
{
|
||||
text: 'Cancel',
|
||||
props: { color: 'outline' },
|
||||
onClick: () => {
|
||||
open.value = false
|
||||
}
|
||||
onClick: confirmCancel
|
||||
},
|
||||
{
|
||||
text: 'Create',
|
||||
@@ -173,6 +174,37 @@ const dialogButtons = computed((): LayoutDialogButton[] => {
|
||||
]
|
||||
})
|
||||
|
||||
const formIsDirty = computed(() => {
|
||||
return meta.value.dirty
|
||||
})
|
||||
|
||||
const navigateToWorkspaceExplainer = () => {
|
||||
if (formIsDirty.value) {
|
||||
confirmActionType.value = 'navigate'
|
||||
showConfirmDialog.value = true
|
||||
} else {
|
||||
router.push(workspacesRoute)
|
||||
}
|
||||
}
|
||||
|
||||
const confirmCancel = () => {
|
||||
if (formIsDirty.value) {
|
||||
confirmActionType.value = 'close'
|
||||
showConfirmDialog.value = true
|
||||
} else {
|
||||
open.value = false
|
||||
}
|
||||
}
|
||||
|
||||
const handleConfirmAction = () => {
|
||||
if (confirmActionType.value === 'navigate') {
|
||||
router.push(workspacesRoute)
|
||||
} else if (confirmActionType.value === 'close') {
|
||||
open.value = false
|
||||
}
|
||||
confirmActionType.value = null
|
||||
}
|
||||
|
||||
watch(open, (newVal, oldVal) => {
|
||||
if (newVal && !oldVal) {
|
||||
selectedWorkspace.value = undefined
|
||||
|
||||
@@ -85,15 +85,17 @@
|
||||
/>
|
||||
</template>
|
||||
</LayoutSidebarMenuGroup>
|
||||
<LayoutSidebarMenuGroupItem
|
||||
<NuxtLink
|
||||
v-if="canCreateWorkspace"
|
||||
label="Add workspace"
|
||||
@click="openWorkspaceCreateDialog"
|
||||
:to="workspacesRoute"
|
||||
@click="isOpen = false"
|
||||
>
|
||||
<template #icon>
|
||||
<PlusIcon class="h-4 w-4 text-foreground-2" />
|
||||
</template>
|
||||
</LayoutSidebarMenuGroupItem>
|
||||
<LayoutSidebarMenuGroupItem label="Create workspace">
|
||||
<template #icon>
|
||||
<PlusIcon class="h-4 w-4 text-foreground-2" />
|
||||
</template>
|
||||
</LayoutSidebarMenuGroupItem>
|
||||
</NuxtLink>
|
||||
</LayoutSidebarMenuGroup>
|
||||
</LayoutSidebarMenu>
|
||||
</LayoutSidebar>
|
||||
@@ -136,6 +138,7 @@ import {
|
||||
import { graphql } from '~~/lib/common/generated/gql'
|
||||
import type { WorkspaceRoles } from '@speckle/shared'
|
||||
import { useMixpanel } from '~~/lib/core/composables/mp'
|
||||
import { workspacesRoute } from '~/lib/common/helpers/route'
|
||||
|
||||
graphql(`
|
||||
fragment SettingsDialog_Workspace on Workspace {
|
||||
@@ -209,13 +212,6 @@ const onWorkspaceMenuItemClick = (id: string, target: string, disabled?: boolean
|
||||
})
|
||||
}
|
||||
|
||||
const openWorkspaceCreateDialog = () => {
|
||||
showWorkspaceCreateDialog.value = true
|
||||
mixpanel.track('Create Workspace Button Clicked', {
|
||||
source: 'settings'
|
||||
})
|
||||
}
|
||||
|
||||
const workspaceMenuItemClasses = (
|
||||
itemKey: string | number,
|
||||
workspaceId: string,
|
||||
|
||||
Reference in New Issue
Block a user