Fix: Unable to delete project from workspace settings (#3708)

This commit is contained in:
Mike
2024-12-18 12:50:46 +01:00
committed by GitHub
parent 866e31a3e0
commit 29bcb66eb4
10 changed files with 199 additions and 365 deletions
@@ -13,9 +13,10 @@
</FormButton>
</template>
</ProjectPageSettingsBlock>
<ProjectPageSettingsGeneralBlockDeleteDialog
<ProjectsDeleteDialog
v-if="project"
v-model:open="showDeleteDialog"
redirect-on-complete
:project="project"
/>
</div>
@@ -23,27 +24,16 @@
<script setup lang="ts">
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectPageSettingsGeneralBlockDelete_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import type { ProjectsDeleteDialog_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
graphql(`
fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {
id
name
role
models(limit: 0) {
totalCount
}
commentThreads(limit: 0) {
totalCount
}
workspace {
slug
}
...ProjectsDeleteDialog_Project
}
`)
defineProps<{
project?: ProjectPageSettingsGeneralBlockDelete_ProjectFragment
project?: ProjectsDeleteDialog_ProjectFragment
}>()
const showDeleteDialog = ref(false)
@@ -1,92 +0,0 @@
<template>
<LayoutDialog v-model:open="isOpen" max-width="md" :buttons="dialogButtons">
<template #header>Delete project</template>
<div class="space-y-4 text-body-xs">
<p>
Are you sure you want to permanently
<strong>delete {{ project.name }}</strong>
and all its contents, including
<strong>{{ project.models.totalCount }} {{ modelText }}</strong>
<span v-if="project.commentThreads.totalCount">
and
<strong>{{ project.commentThreads.totalCount }} {{ discussionText }}</strong>
</span>
?
</p>
<p>To confirm deletion, type the project name below.</p>
<FormTextInput
v-model="projectNameInput"
name="projectNameConfirm"
label="Project name"
size="lg"
placeholder="Type the project name here..."
full-width
hide-error-message
class="text-sm"
color="foundation"
/>
</div>
</LayoutDialog>
</template>
<script setup lang="ts">
import {
LayoutDialog,
FormTextInput,
type LayoutDialogButton
} from '@speckle/ui-components'
import { useDeleteProject } from '~~/lib/projects/composables/projectManagement'
import { useMixpanel } from '~~/lib/core/composables/mp'
import type { ProjectPageSettingsGeneralBlockDelete_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import { Roles } from '@speckle/shared'
const isOpen = defineModel<boolean>('open', { required: true })
const props = defineProps<{
project: ProjectPageSettingsGeneralBlockDelete_ProjectFragment
}>()
const projectNameInput = ref('')
const deleteProject = useDeleteProject()
const mp = useMixpanel()
const modelText = computed(() =>
props.project.models.totalCount === 1 ? 'model' : 'models'
)
const discussionText = computed(() =>
props.project.commentThreads.totalCount === 1 ? 'discussion' : 'discussions'
)
const dialogButtons = computed<LayoutDialogButton[]>(() => [
{
text: 'Cancel',
props: { color: 'outline' },
onClick: () => {
isOpen.value = false
projectNameInput.value = ''
}
},
{
text: 'Delete',
props: {
color: 'danger',
disabled: projectNameInput.value !== props.project.name
},
onClick: async () => {
if (
projectNameInput.value === props.project.name &&
props.project.role === Roles.Stream.Owner
) {
await deleteProject(props.project.id, {
goHome: true,
workspaceSlug: props.project.workspace?.slug
})
isOpen.value = false
mp.track('Stream Action', { type: 'action', name: 'delete' })
}
}
}
])
</script>
@@ -0,0 +1,144 @@
<template>
<LayoutDialog v-model:open="isOpen" max-width="sm" :buttons="dialogButtons">
<template #header>Delete project</template>
<div class="flex flex-col gap-4 text-body-xs text-foreground">
<div class="flex flex-col gap-2">
<p>
Are you sure you want to
<span class="font-medium">permanently delete</span>
the
<span class="font-medium">"{{ project.name }}"</span>
project? This action
<span class="font-medium">cannot</span>
be undone.
</p>
<CommonCard class="bg-foundation !py-4 text-body-2xs flex flex-row gap-y-2">
<p>
{{ modelText }}
</p>
<p>
{{ discussionText }}
</p>
<p>
{{ versionsText }}
</p>
</CommonCard>
</div>
<div class="flex flex-col gap-2">
<p>To confirm, type the project name below.</p>
<FormTextInput
v-model="projectNameInput"
name="projectNameConfirm"
label="Project name"
size="lg"
placeholder="Project name..."
full-width
hide-error-message
class="text-sm"
color="foundation"
/>
</div>
</div>
</LayoutDialog>
</template>
<script setup lang="ts">
import { LayoutDialog, type LayoutDialogButton } from '@speckle/ui-components'
import { useDeleteProject } from '~~/lib/projects/composables/projectManagement'
import { useMixpanel } from '~~/lib/core/composables/mp'
import { graphql } from '~~/lib/common/generated/gql'
import type { ProjectsDeleteDialog_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import { Roles } from '@speckle/shared'
graphql(`
fragment ProjectsDeleteDialog_Project on Project {
id
name
role
models(limit: 0) {
totalCount
}
commentThreads(limit: 0) {
totalCount
}
workspace {
slug
id
}
versions(limit: 0) {
totalCount
}
}
`)
const props = defineProps<{
open: boolean
project: ProjectsDeleteDialog_ProjectFragment
redirectOnComplete?: boolean
}>()
const isOpen = defineModel<boolean>('open', { required: true })
const deleteProject = useDeleteProject()
const mixpanel = useMixpanel()
const { isAdmin } = useActiveUser()
const projectNameInput = ref('')
const modelText = computed(
() =>
`${props.project.models.totalCount} ${
props.project.models.totalCount === 1 ? 'model' : 'models'
}`
)
const versionsText = computed(
() =>
`${props.project.versions.totalCount} ${
props.project.versions.totalCount === 1 ? 'version' : 'versions'
}`
)
const discussionText = computed(
() =>
`${props.project.commentThreads.totalCount} ${
props.project.commentThreads.totalCount === 1 ? 'discussion' : 'discussions'
}`
)
const dialogButtons = computed<LayoutDialogButton[]>(() => [
{
text: 'Cancel',
props: { color: 'outline' },
onClick: () => {
isOpen.value = false
projectNameInput.value = ''
}
},
{
text: 'Delete',
props: {
color: 'danger',
disabled: projectNameInput.value !== props.project.name
},
onClick: async () => {
if (
projectNameInput.value === props.project.name &&
(props.project.role === Roles.Stream.Owner || isAdmin.value)
) {
const options = {
goHome: props.redirectOnComplete,
workspaceSlug: props.project.workspace?.slug
}
await deleteProject(props.project.id, options)
isOpen.value = false
mixpanel.track('Stream Action', {
type: 'action',
name: 'delete',
// eslint-disable-next-line camelcase
workspace_id: props.project.workspace?.id
})
}
}
}
])
</script>
@@ -1,36 +0,0 @@
<template>
<div>
<div
class="flex flex-col gap-3 justify-between sm:items-center sm:flex-row px-4 pt-3 pb-4 sm:py-2 transition hover:bg-primary-muted"
>
<div class="flex gap-2 items-center">
<div class="h-8 w-8 flex items-center justify-center">
<SparklesIcon class="h-5 w-5 text-primary" />
</div>
<div class="text-foreground text-sm">Announcing the new Speckle web app</div>
</div>
<div class="flex gap-3">
<FormButton color="primary" text @click="emit('dismissed')">Skip</FormButton>
<FormButton class="px-4" to="/" @click="showDialog = true">
See What's New
</FormButton>
</div>
</div>
<ProjectsNewSpeckleDialog v-model:open="showDialog" />
</div>
</template>
<script setup lang="ts">
import { SparklesIcon } from '@heroicons/vue/24/solid'
const emit = defineEmits<{ dismissed: [] }>()
const showDialog = ref(false)
watch(showDialog, (newValue, oldValue) => {
if (!newValue && oldValue) {
showDialog.value = false
emit('dismissed')
}
})
</script>
@@ -1,41 +0,0 @@
<template>
<LayoutDialog v-model:open="open" max-width="sm" :buttons="dialogButtons">
<h2 class="text-heading-lg text-center sm:-mt-2 mt-2 mb-2">
What's new in Speckle?
</h2>
<p class="text-foreground-2 text-center mb-6">A new way to collaborate in AEC.</p>
<CommonVimeoEmbed
vimeo-id="925455838"
title="What's new in Speckle?"
autoplay
muted
/>
</LayoutDialog>
</template>
<script setup lang="ts">
import { computed } from 'vue'
import { ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/outline'
import { CommonVimeoEmbed, type LayoutDialogButton } from '@speckle/ui-components'
const open = defineModel<boolean>('open', { required: true })
const dialogButtons = computed((): LayoutDialogButton[] => [
{
text: 'Close',
props: { color: 'outline' },
onClick: () => {
open.value = false
}
},
{
text: 'Learn more',
props: {
iconRight: ArrowTopRightOnSquareIcon,
to: 'https://speckle.systems/blog/the-new-way-to-collaborate-in-aec/',
external: true,
target: '_blank'
}
}
])
</script>
@@ -1,137 +0,0 @@
<template>
<LayoutDialog v-model:open="isOpen" max-width="sm" :buttons="dialogButtons">
<template #header>Delete project</template>
<div class="flex flex-col gap-6 text-body-xs text-foreground">
<p>
Are you sure you want to
<span class="font-medium">permanently delete</span>
the selected project?
</p>
<div
v-if="project"
class="rounded border bg-foundation-2 border-outline-3 text-body-2xs py-3 px-4"
>
<p class="font-medium">{{ project.name }}</p>
<p>
{{ project.models.totalCount }} models,
{{ project.versions.totalCount }} versions,
</p>
</div>
<p>
This action
<span class="font-medium">cannot</span>
be undone.
</p>
</div>
</LayoutDialog>
</template>
<script setup lang="ts">
import { useMutation } from '@vue/apollo-composable'
import { LayoutDialog, type LayoutDialogButton } from '@speckle/ui-components'
import type { ProjectItem } from '~~/lib/server-management/helpers/types'
import { adminDeleteProjectMutation } from '~~/lib/server-management/graphql/mutations'
import { useGlobalToast, ToastNotificationType } from '~~/lib/common/composables/toast'
import {
ROOT_QUERY,
convertThrowIntoFetchResult,
getCacheId,
getFirstErrorMessage,
modifyObjectFields
} from '~~/lib/common/helpers/graphql'
import type { ProjectCollection } from '~~/lib/common/generated/gql/graphql'
const props = defineProps<{
open: boolean
project: ProjectItem | null
}>()
const { triggerNotification } = useGlobalToast()
const { mutate: adminDeleteMutation } = useMutation(adminDeleteProjectMutation)
const isOpen = defineModel<boolean>('open', { required: true })
const deleteConfirmed = async () => {
const projectId = props.project?.id
if (!projectId) {
return
}
const result = await adminDeleteMutation(
{
ids: [projectId]
},
{
update: (cache, { data }) => {
if (data?.projectMutations.batchDelete) {
// Remove project from cache
const cacheId = getCacheId('Project', projectId)
cache.evict({
id: cacheId
})
// Modify 'admin' field of ROOT_QUERY so that we can modify all `projectList` instances
modifyObjectFields<undefined, { [key: string]: ProjectCollection }>(
cache,
ROOT_QUERY,
(_fieldName, _variables, value, details) => {
// Find all `projectList` fields (there can be multiple due to differing variables)
const projectListFields = Object.keys(value).filter(
(k) =>
details.revolveFieldNameAndVariables(k).fieldName === 'projectList'
)
// Being careful not to mutate original `value`
const newVal: typeof value = { ...value }
// Iterate over each and adjust `items` and `totalCount`
for (const field of projectListFields) {
const oldItems = value[field]?.items || []
const newItems = oldItems.filter((i) => i.__ref !== cacheId)
newVal[field] = {
...value[field],
...(value[field]?.items ? { items: newItems } : {}),
totalCount: Math.max(0, (value[field]?.totalCount || 0) - 1)
}
}
return newVal
},
{ fieldNameWhitelist: ['admin'] }
)
}
}
}
).catch(convertThrowIntoFetchResult)
if (result?.data?.projectMutations.batchDelete) {
triggerNotification({
type: ToastNotificationType.Success,
title: 'Project deleted',
description: 'The project has been successfully deleted'
})
isOpen.value = false
} else {
const errorMessage = getFirstErrorMessage(result?.errors)
triggerNotification({
type: ToastNotificationType.Danger,
title: 'Failed to delete project',
description: errorMessage
})
}
}
const dialogButtons: LayoutDialogButton[] = [
{
text: 'Cancel',
props: { color: 'outline' },
onClick: () => (isOpen.value = false)
},
{
text: 'Delete',
props: { color: 'danger' },
onClick: deleteConfirmed
}
]
</script>
@@ -89,7 +89,8 @@
</template>
</LayoutTable>
<SettingsSharedProjectsDeleteDialog
<ProjectsDeleteDialog
v-if="projectToModify"
v-model:open="showProjectDeleteDialog"
:project="projectToModify"
/>
@@ -99,10 +100,11 @@
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { HorizontalDirection } from '~~/lib/common/composables/window'
import type { ItemType, ProjectItem } from '~~/lib/server-management/helpers/types'
import type { SettingsSharedProjects_ProjectFragment } from '~~/lib/common/generated/gql/graphql'
import type {
SettingsSharedProjects_ProjectFragment,
ProjectsDeleteDialog_ProjectFragment
} from '~~/lib/common/generated/gql/graphql'
import {
MagnifyingGlassIcon,
EllipsisHorizontalIcon,
@@ -116,15 +118,16 @@ import { projectCollaboratorsRoute, projectRoute } from '~/lib/common/helpers/ro
graphql(`
fragment SettingsSharedProjects_Project on Project {
...ProjectsDeleteDialog_Project
id
name
visibility
createdAt
updatedAt
models {
models(limit: 0) {
totalCount
}
versions {
versions(limit: 0) {
totalCount
}
team {
@@ -151,26 +154,24 @@ const search = defineModel<string>('search')
const { on, bind } = useDebouncedTextInput({ model: search })
const router = useRouter()
const projectToModify = ref<ProjectItem | null>(null)
const projectToModify = ref<ProjectsDeleteDialog_ProjectFragment | null>(null)
const showProjectDeleteDialog = ref(false)
const openNewProject = ref(false)
const openProjectDeleteDialog = (item: ItemType) => {
if (isProject(item)) {
projectToModify.value = item
showProjectDeleteDialog.value = true
}
const openProjectDeleteDialog = (item: ProjectsDeleteDialog_ProjectFragment) => {
projectToModify.value = item
showProjectDeleteDialog.value = true
}
const handleProjectClick = (item: ItemType) => {
router.push(projectRoute(item.id))
const handleProjectClick = (id: string) => {
router.push(projectRoute(id))
emit('close')
}
enum ActionTypes {
ViewProject = 'view-project',
EditMembers = 'edit-members',
RemoveProject = 'remove-project'
DeleteProject = 'delete-project'
}
const showActionsMenu = ref<Record<string, boolean>>({})
@@ -179,17 +180,20 @@ const actionItems: LayoutMenuItem[][] = [
[
{ title: 'View project', id: ActionTypes.ViewProject },
{ title: 'Edit members', id: ActionTypes.EditMembers },
{ title: 'Remove project...', id: ActionTypes.RemoveProject }
{ title: 'Delete project...', id: ActionTypes.DeleteProject }
]
]
const onActionChosen = (actionItem: LayoutMenuItem, project: ProjectItem) => {
const onActionChosen = (
actionItem: LayoutMenuItem,
project: ProjectsDeleteDialog_ProjectFragment
) => {
if (actionItem.id === ActionTypes.EditMembers) {
router.push(projectCollaboratorsRoute(project.id))
emit('close')
} else if (actionItem.id === ActionTypes.ViewProject) {
handleProjectClick(project)
} else if (actionItem.id === ActionTypes.RemoveProject) {
handleProjectClick(project.id)
} else if (actionItem.id === ActionTypes.DeleteProject) {
openProjectDeleteDialog(project)
}
}
@@ -83,7 +83,7 @@ const documents = {
"\n query ProjectPageSettingsCollaboratorsWorkspace($workspaceId: String!) {\n workspace(id: $workspaceId) {\n ...ProjectPageTeamInternals_Workspace\n }\n }\n": types.ProjectPageSettingsCollaboratorsWorkspaceDocument,
"\n query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n role\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\n }\n }\n": types.ProjectPageSettingsGeneralDocument,
"\n fragment ProjectPageSettingsGeneralBlockAccess_Project on Project {\n id\n visibility\n }\n": types.ProjectPageSettingsGeneralBlockAccess_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n workspace {\n slug\n }\n }\n": types.ProjectPageSettingsGeneralBlockDelete_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n ...ProjectsDeleteDialog_Project\n }\n": types.ProjectPageSettingsGeneralBlockDelete_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockDiscussions_Project on Project {\n id\n visibility\n allowPublicComments\n }\n": types.ProjectPageSettingsGeneralBlockDiscussions_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockLeave_Project on Project {\n id\n name\n role\n team {\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n workspace {\n id\n }\n }\n": types.ProjectPageSettingsGeneralBlockLeave_ProjectFragmentDoc,
"\n fragment ProjectPageSettingsGeneralBlockProjectInfo_Project on Project {\n id\n role\n name\n description\n }\n": types.ProjectPageSettingsGeneralBlockProjectInfo_ProjectFragmentDoc,
@@ -97,6 +97,7 @@ const documents = {
"\n fragment ProjectsDashboardFilledUser on UserProjectCollection {\n items {\n ...ProjectDashboardItem\n }\n }\n": types.ProjectsDashboardFilledUserFragmentDoc,
"\n fragment ProjectsDashboardHeaderProjects_User on User {\n projectInvites {\n ...ProjectsInviteBanner\n }\n }\n": types.ProjectsDashboardHeaderProjects_UserFragmentDoc,
"\n fragment ProjectsDashboardHeaderWorkspaces_User on User {\n discoverableWorkspaces {\n ...WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace\n }\n workspaceInvites {\n ...WorkspaceInviteBanner_PendingWorkspaceCollaborator\n }\n }\n": types.ProjectsDashboardHeaderWorkspaces_UserFragmentDoc,
"\n fragment ProjectsDeleteDialog_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n workspace {\n slug\n id\n }\n versions(limit: 0) {\n totalCount\n }\n }\n": types.ProjectsDeleteDialog_ProjectFragmentDoc,
"\n fragment ProjectsHiddenProjectWarning_User on User {\n id\n expiredSsoSessions {\n id\n slug\n name\n logo\n }\n }\n": types.ProjectsHiddenProjectWarning_UserFragmentDoc,
"\n fragment ProjectsMoveToWorkspaceDialog_Workspace on Workspace {\n id\n role\n name\n logo\n ...WorkspaceHasCustomDataResidency_Workspace\n ...ProjectsWorkspaceSelect_Workspace\n }\n": types.ProjectsMoveToWorkspaceDialog_WorkspaceFragmentDoc,
"\n fragment ProjectsMoveToWorkspaceDialog_User on User {\n workspaces {\n items {\n ...ProjectsMoveToWorkspaceDialog_Workspace\n }\n }\n }\n": types.ProjectsMoveToWorkspaceDialog_UserFragmentDoc,
@@ -111,7 +112,7 @@ const documents = {
"\n fragment SettingsServerRegionsAddEditDialog_ServerRegionItem on ServerRegionItem {\n id\n name\n description\n key\n }\n": types.SettingsServerRegionsAddEditDialog_ServerRegionItemFragmentDoc,
"\n fragment SettingsServerRegionsTable_ServerRegionItem on ServerRegionItem {\n id\n name\n key\n description\n }\n": types.SettingsServerRegionsTable_ServerRegionItemFragmentDoc,
"\n fragment SettingsSharedDeleteUserDialog_Workspace on Workspace {\n id\n plan {\n status\n name\n }\n subscription {\n currentBillingCycleEnd\n seats {\n guest\n plan\n }\n }\n }\n": types.SettingsSharedDeleteUserDialog_WorkspaceFragmentDoc,
"\n fragment SettingsSharedProjects_Project on Project {\n id\n name\n visibility\n createdAt\n updatedAt\n models {\n totalCount\n }\n versions {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n": types.SettingsSharedProjects_ProjectFragmentDoc,
"\n fragment SettingsSharedProjects_Project on Project {\n ...ProjectsDeleteDialog_Project\n id\n name\n visibility\n createdAt\n updatedAt\n models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n": types.SettingsSharedProjects_ProjectFragmentDoc,
"\n fragment SettingsUserEmails_User on User {\n id\n emails {\n ...SettingsUserEmailCards_UserEmail\n }\n }\n": types.SettingsUserEmails_UserFragmentDoc,
"\n fragment SettingsUserNotifications_User on User {\n id\n notificationPreferences\n }\n": types.SettingsUserNotifications_UserFragmentDoc,
"\n fragment SettingsUserProfile_User on User {\n ...SettingsUserProfileChangePassword_User\n ...SettingsUserProfileDeleteAccount_User\n ...SettingsUserProfileDetails_User\n }\n": types.SettingsUserProfile_UserFragmentDoc,
@@ -675,7 +676,7 @@ export function graphql(source: "\n fragment ProjectPageSettingsGeneralBlockAcc
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n workspace {\n slug\n }\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n workspace {\n slug\n }\n }\n"];
export function graphql(source: "\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n ...ProjectsDeleteDialog_Project\n }\n"): (typeof documents)["\n fragment ProjectPageSettingsGeneralBlockDelete_Project on Project {\n ...ProjectsDeleteDialog_Project\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -728,6 +729,10 @@ export function graphql(source: "\n fragment ProjectsDashboardHeaderProjects_Us
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment ProjectsDashboardHeaderWorkspaces_User on User {\n discoverableWorkspaces {\n ...WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace\n }\n workspaceInvites {\n ...WorkspaceInviteBanner_PendingWorkspaceCollaborator\n }\n }\n"): (typeof documents)["\n fragment ProjectsDashboardHeaderWorkspaces_User on User {\n discoverableWorkspaces {\n ...WorkspaceInviteDiscoverableWorkspaceBanner_LimitedWorkspace\n }\n workspaceInvites {\n ...WorkspaceInviteBanner_PendingWorkspaceCollaborator\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment ProjectsDeleteDialog_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n workspace {\n slug\n id\n }\n versions(limit: 0) {\n totalCount\n }\n }\n"): (typeof documents)["\n fragment ProjectsDeleteDialog_Project on Project {\n id\n name\n role\n models(limit: 0) {\n totalCount\n }\n commentThreads(limit: 0) {\n totalCount\n }\n workspace {\n slug\n id\n }\n versions(limit: 0) {\n totalCount\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
@@ -787,7 +792,7 @@ export function graphql(source: "\n fragment SettingsSharedDeleteUserDialog_Wor
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
export function graphql(source: "\n fragment SettingsSharedProjects_Project on Project {\n id\n name\n visibility\n createdAt\n updatedAt\n models {\n totalCount\n }\n versions {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n"): (typeof documents)["\n fragment SettingsSharedProjects_Project on Project {\n id\n name\n visibility\n createdAt\n updatedAt\n models {\n totalCount\n }\n versions {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n"];
export function graphql(source: "\n fragment SettingsSharedProjects_Project on Project {\n ...ProjectsDeleteDialog_Project\n id\n name\n visibility\n createdAt\n updatedAt\n models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n"): (typeof documents)["\n fragment SettingsSharedProjects_Project on Project {\n ...ProjectsDeleteDialog_Project\n id\n name\n visibility\n createdAt\n updatedAt\n models(limit: 0) {\n totalCount\n }\n versions(limit: 0) {\n totalCount\n }\n team {\n id\n user {\n name\n id\n avatar\n }\n }\n }\n"];
/**
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
*/
File diff suppressed because one or more lines are too long
@@ -98,8 +98,7 @@ export function useProjectUpdateTracking(
if (redirectOnDeletion || notifyOnUpdate) {
triggerNotification({
type: ToastNotificationType.Info,
title: isDeleted ? 'Project deleted' : 'Project updated',
description: isDeleted ? 'Redirecting to home' : undefined
title: isDeleted ? 'Project deleted' : 'Project updated'
})
}
}
@@ -423,11 +422,6 @@ export function useDeleteProject() {
.catch(convertThrowIntoFetchResult)
if (result?.data?.projectMutations.delete) {
triggerNotification({
type: ToastNotificationType.Info,
title: 'Project deleted'
})
if (goHome) {
if (workspaceSlug) {
router.push(workspaceRoute(workspaceSlug))