Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8d4bbeea8b | |||
| 237501ad30 | |||
| 7160b64f55 | |||
| bdc904201a | |||
| 6d6b5e1fd5 | |||
| b4ce93d26e |
@@ -132,8 +132,11 @@ const openFeedbackDialog = () => {
|
||||
!hostAppStore.isDistributedBySpeckle
|
||||
) {
|
||||
showFeedbackDialog.value = true
|
||||
} else {
|
||||
} else if ($intercom.shouldEnableIntercom.value) {
|
||||
$intercom.show()
|
||||
} else {
|
||||
// community forum fallback
|
||||
app.$openUrl('https://speckle.community')
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -22,7 +22,7 @@ type Documents = {
|
||||
"\n mutation CreateProject($input: ProjectCreateInput) {\n projectMutations {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n": typeof types.CreateProjectDocument,
|
||||
"\n mutation CreateProjectInWorkspace($input: WorkspaceProjectCreateInput!) {\n workspaceMutations {\n projects {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": typeof types.CreateProjectInWorkspaceDocument,
|
||||
"\n mutation StreamAccessRequestCreate($input: String!) {\n streamAccessRequestCreate(streamId: $input) {\n id\n }\n }\n": typeof types.StreamAccessRequestCreateDocument,
|
||||
"\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n": typeof types.WorkspaceListWorkspaceItemFragmentDoc,
|
||||
"\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n canAccessHelpCenter {\n authorized\n }\n }\n }\n": typeof types.WorkspaceListWorkspaceItemFragmentDoc,
|
||||
"\n fragment AutomateFunctionItem on AutomateFunction {\n name\n isFeatured\n id\n creator {\n name\n }\n releases {\n items {\n inputSchema\n }\n }\n }\n": typeof types.AutomateFunctionItemFragmentDoc,
|
||||
"\n mutation CreateAutomation($projectId: ID!, $input: ProjectAutomationCreateInput!) {\n projectMutations {\n automationMutations(projectId: $projectId) {\n create(input: $input) {\n id\n name\n }\n }\n }\n }\n": typeof types.CreateAutomationDocument,
|
||||
"\n fragment AutomateFunctionRunItem on AutomateFunctionRun {\n id\n status\n statusMessage\n results\n contextView\n function {\n id\n name\n logo\n }\n }\n": typeof types.AutomateFunctionRunItemFragmentDoc,
|
||||
@@ -65,6 +65,7 @@ type Documents = {
|
||||
"\n fragment IssuesItem on Issue {\n id\n status\n title\n priority\n viewerState\n identifier\n resourceIdString\n activities(input: { limit: 1, sortDirection: asc }) {\n totalCount\n items {\n actor {\n id\n user {\n name\n id\n avatar\n }\n }\n eventType\n createdAt\n }\n }\n replies {\n totalCount\n items {\n id\n author {\n id\n user {\n name\n id\n avatar\n }\n }\n createdAt\n description {\n doc\n }\n }\n }\n description {\n doc\n }\n labels {\n hexColor\n id\n name\n }\n author {\n id\n user {\n id\n name\n avatar\n }\n }\n dueDate\n assignee {\n id\n user {\n id\n avatar\n name\n }\n }\n }\n": typeof types.IssuesItemFragmentDoc,
|
||||
"\n query IssuesList($projectId: String!) {\n project(id: $projectId) {\n id\n issues {\n totalCount\n items {\n ...IssuesItem\n }\n }\n }\n }\n": typeof types.IssuesListDocument,
|
||||
"\n query IssueResourceMetaSearch(\n $workspaceId: String!\n $resourceType: ResourceMetaType!\n $resourceId: String!\n $projectId: String\n $metaType: String\n ) {\n resourceMetaSearch(\n workspaceId: $workspaceId\n resourceType: $resourceType\n resourceId: $resourceId\n projectId: $projectId\n metaType: $metaType\n ) {\n data\n }\n }\n": typeof types.IssueResourceMetaSearchDocument,
|
||||
"\n query WorkspaceIntercomPermission($workspaceId: String!) {\n workspace(id: $workspaceId) {\n id\n permissions {\n canAccessHelpCenter {\n authorized\n }\n }\n }\n }\n": typeof types.WorkspaceIntercomPermissionDocument,
|
||||
"\n subscription WorkspacePlanUsageUpdated($input: WorkspacePlanUsageSubscriptionInput!) {\n workspacePlanUsageUpdated(input: $input)\n }\n": typeof types.WorkspacePlanUsageUpdatedDocument,
|
||||
};
|
||||
const documents: Documents = {
|
||||
@@ -76,7 +77,7 @@ const documents: Documents = {
|
||||
"\n mutation CreateProject($input: ProjectCreateInput) {\n projectMutations {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n": types.CreateProjectDocument,
|
||||
"\n mutation CreateProjectInWorkspace($input: WorkspaceProjectCreateInput!) {\n workspaceMutations {\n projects {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": types.CreateProjectInWorkspaceDocument,
|
||||
"\n mutation StreamAccessRequestCreate($input: String!) {\n streamAccessRequestCreate(streamId: $input) {\n id\n }\n }\n": types.StreamAccessRequestCreateDocument,
|
||||
"\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n": types.WorkspaceListWorkspaceItemFragmentDoc,
|
||||
"\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n canAccessHelpCenter {\n authorized\n }\n }\n }\n": types.WorkspaceListWorkspaceItemFragmentDoc,
|
||||
"\n fragment AutomateFunctionItem on AutomateFunction {\n name\n isFeatured\n id\n creator {\n name\n }\n releases {\n items {\n inputSchema\n }\n }\n }\n": types.AutomateFunctionItemFragmentDoc,
|
||||
"\n mutation CreateAutomation($projectId: ID!, $input: ProjectAutomationCreateInput!) {\n projectMutations {\n automationMutations(projectId: $projectId) {\n create(input: $input) {\n id\n name\n }\n }\n }\n }\n": types.CreateAutomationDocument,
|
||||
"\n fragment AutomateFunctionRunItem on AutomateFunctionRun {\n id\n status\n statusMessage\n results\n contextView\n function {\n id\n name\n logo\n }\n }\n": types.AutomateFunctionRunItemFragmentDoc,
|
||||
@@ -119,6 +120,7 @@ const documents: Documents = {
|
||||
"\n fragment IssuesItem on Issue {\n id\n status\n title\n priority\n viewerState\n identifier\n resourceIdString\n activities(input: { limit: 1, sortDirection: asc }) {\n totalCount\n items {\n actor {\n id\n user {\n name\n id\n avatar\n }\n }\n eventType\n createdAt\n }\n }\n replies {\n totalCount\n items {\n id\n author {\n id\n user {\n name\n id\n avatar\n }\n }\n createdAt\n description {\n doc\n }\n }\n }\n description {\n doc\n }\n labels {\n hexColor\n id\n name\n }\n author {\n id\n user {\n id\n name\n avatar\n }\n }\n dueDate\n assignee {\n id\n user {\n id\n avatar\n name\n }\n }\n }\n": types.IssuesItemFragmentDoc,
|
||||
"\n query IssuesList($projectId: String!) {\n project(id: $projectId) {\n id\n issues {\n totalCount\n items {\n ...IssuesItem\n }\n }\n }\n }\n": types.IssuesListDocument,
|
||||
"\n query IssueResourceMetaSearch(\n $workspaceId: String!\n $resourceType: ResourceMetaType!\n $resourceId: String!\n $projectId: String\n $metaType: String\n ) {\n resourceMetaSearch(\n workspaceId: $workspaceId\n resourceType: $resourceType\n resourceId: $resourceId\n projectId: $projectId\n metaType: $metaType\n ) {\n data\n }\n }\n": types.IssueResourceMetaSearchDocument,
|
||||
"\n query WorkspaceIntercomPermission($workspaceId: String!) {\n workspace(id: $workspaceId) {\n id\n permissions {\n canAccessHelpCenter {\n authorized\n }\n }\n }\n }\n": types.WorkspaceIntercomPermissionDocument,
|
||||
"\n subscription WorkspacePlanUsageUpdated($input: WorkspacePlanUsageSubscriptionInput!) {\n workspacePlanUsageUpdated(input: $input)\n }\n": types.WorkspacePlanUsageUpdatedDocument,
|
||||
};
|
||||
|
||||
@@ -171,7 +173,7 @@ export function graphql(source: "\n mutation StreamAccessRequestCreate($input:
|
||||
/**
|
||||
* 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 WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n"): (typeof documents)["\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n canAccessHelpCenter {\n authorized\n }\n }\n }\n"): (typeof documents)["\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logoUrl\n role\n readOnly\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n canAccessHelpCenter {\n authorized\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -340,6 +342,10 @@ export function graphql(source: "\n query IssuesList($projectId: String!) {\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 query IssueResourceMetaSearch(\n $workspaceId: String!\n $resourceType: ResourceMetaType!\n $resourceId: String!\n $projectId: String\n $metaType: String\n ) {\n resourceMetaSearch(\n workspaceId: $workspaceId\n resourceType: $resourceType\n resourceId: $resourceId\n projectId: $projectId\n metaType: $metaType\n ) {\n data\n }\n }\n"): (typeof documents)["\n query IssueResourceMetaSearch(\n $workspaceId: String!\n $resourceType: ResourceMetaType!\n $resourceId: String!\n $projectId: String\n $metaType: String\n ) {\n resourceMetaSearch(\n workspaceId: $workspaceId\n resourceType: $resourceType\n resourceId: $resourceId\n projectId: $projectId\n metaType: $metaType\n ) {\n data\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 query WorkspaceIntercomPermission($workspaceId: String!) {\n workspace(id: $workspaceId) {\n id\n permissions {\n canAccessHelpCenter {\n authorized\n }\n }\n }\n }\n"): (typeof documents)["\n query WorkspaceIntercomPermission($workspaceId: String!) {\n workspace(id: $workspaceId) {\n id\n permissions {\n canAccessHelpCenter {\n authorized\n }\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
@@ -95,6 +95,9 @@ export const workspaceListFragment = graphql(`
|
||||
code
|
||||
message
|
||||
}
|
||||
canAccessHelpCenter {
|
||||
authorized
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
|
||||
export const workspaceIntercomPermissionQuery = graphql(`
|
||||
query WorkspaceIntercomPermission($workspaceId: String!) {
|
||||
workspace(id: $workspaceId) {
|
||||
id
|
||||
permissions {
|
||||
canAccessHelpCenter {
|
||||
authorized
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
+69
-36
@@ -8,7 +8,9 @@ import Intercom, {
|
||||
} from '@intercom/messenger-js-sdk'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import { useConfigStore } from '~/store/config'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { workspaceIntercomPermissionQuery } from '~/lib/workspaces/graphql/queries'
|
||||
|
||||
const disabledRoutes: string[] = []
|
||||
|
||||
@@ -17,16 +19,22 @@ export const useIntercom = () => {
|
||||
|
||||
const accountStore = useAccountStore()
|
||||
const hostAppStore = useHostAppStore()
|
||||
const configStore = useConfigStore()
|
||||
|
||||
const { activeAccount } = storeToRefs(accountStore)
|
||||
const { isDistributedBySpeckle } = storeToRefs(hostAppStore)
|
||||
const { userSelectedWorkspaceId } = storeToRefs(configStore)
|
||||
|
||||
const isInitialized = ref(false)
|
||||
const hasIntercomAccess = ref(false)
|
||||
|
||||
const isRouteBlacklisted = computed(() => {
|
||||
return disabledRoutes.some((disabledRoute) => route.path.includes(disabledRoute))
|
||||
})
|
||||
|
||||
const shouldEnableIntercom = computed(() => !isRouteBlacklisted.value)
|
||||
const shouldEnableIntercom = computed(() => {
|
||||
return !isRouteBlacklisted.value && hasIntercomAccess.value
|
||||
})
|
||||
|
||||
const bootIntercom = () => {
|
||||
if (!shouldEnableIntercom.value || isInitialized.value || !activeAccount.value)
|
||||
@@ -44,13 +52,10 @@ export const useIntercom = () => {
|
||||
}
|
||||
|
||||
const showIntercom = () => {
|
||||
if (!isInitialized.value) return
|
||||
show()
|
||||
if (isInitialized.value) show()
|
||||
}
|
||||
|
||||
const hideIntercom = () => {
|
||||
if (!isInitialized.value) return
|
||||
hide()
|
||||
if (isInitialized.value) hide()
|
||||
}
|
||||
|
||||
const shutdownIntercom = () => {
|
||||
@@ -60,8 +65,7 @@ export const useIntercom = () => {
|
||||
}
|
||||
|
||||
const trackIntercom = (event: string, metadata?: Record<string, unknown>) => {
|
||||
if (!isInitialized.value) return
|
||||
trackEvent(event, metadata)
|
||||
if (isInitialized.value) trackEvent(event, metadata)
|
||||
}
|
||||
|
||||
const updateConnectorDetails = (
|
||||
@@ -69,51 +73,80 @@ export const useIntercom = () => {
|
||||
hostAppVersion: string,
|
||||
connectorVersion: string
|
||||
) => {
|
||||
update({
|
||||
page_title: `CNX: (hostApp: ${hostAppName}:v${hostAppVersion}),(version: ${connectorVersion})`
|
||||
})
|
||||
if (isInitialized.value) {
|
||||
update({
|
||||
page_title: `CNX: (hostApp: ${hostAppName}:v${hostAppVersion}),(version: ${connectorVersion})`
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// On route change, check if we need to shutodwn or boot Intercom
|
||||
watch(route, () => {
|
||||
if (isRouteBlacklisted.value) {
|
||||
shutdownIntercom()
|
||||
} else {
|
||||
bootIntercom()
|
||||
const checkPermissions = async () => {
|
||||
if (!activeAccount.value || !userSelectedWorkspaceId.value) {
|
||||
// userSelectedWorkspaceId is only null before any publish/load action,
|
||||
// at which point the NavBar (and feedback button) isn't visible anyway
|
||||
hasIntercomAccess.value = false
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const { data } = await activeAccount.value.client.query({
|
||||
query: workspaceIntercomPermissionQuery,
|
||||
variables: { workspaceId: userSelectedWorkspaceId.value },
|
||||
fetchPolicy: 'cache-first'
|
||||
})
|
||||
|
||||
hasIntercomAccess.value =
|
||||
data?.workspace?.permissions?.canAccessHelpCenter?.authorized === true
|
||||
} catch (e) {
|
||||
console.warn('Failed to fetch Intercom permissions for workspace', e)
|
||||
hasIntercomAccess.value = false
|
||||
}
|
||||
}
|
||||
|
||||
watch(route, () => {
|
||||
if (isRouteBlacklisted.value || !shouldEnableIntercom.value) shutdownIntercom()
|
||||
else bootIntercom()
|
||||
})
|
||||
|
||||
// we listen to changes in the host app distribution status that fetched on updateConnector composable after the intercom is initialized, we cant simply rely on activeAccount watcher
|
||||
watch(isDistributedBySpeckle, (newValue) => {
|
||||
if (!newValue) {
|
||||
shutdownIntercom()
|
||||
}
|
||||
if (!newValue) shutdownIntercom()
|
||||
})
|
||||
|
||||
watch(activeAccount, (newValue) => {
|
||||
if (newValue) {
|
||||
if (!isInitialized.value) {
|
||||
bootIntercom() // if active account changed and itercom is not initialised, do it
|
||||
return // we do not need to update, as that's done by default in the init
|
||||
}
|
||||
update({
|
||||
user_id: activeAccount.value.accountInfo.userInfo.id || '',
|
||||
name: activeAccount.value.accountInfo.userInfo.name,
|
||||
email: activeAccount.value.accountInfo.userInfo.email
|
||||
})
|
||||
} else {
|
||||
if (isInitialized.value) {
|
||||
watch(
|
||||
[activeAccount, userSelectedWorkspaceId],
|
||||
async ([newAccount], [oldAccount]) => {
|
||||
await checkPermissions()
|
||||
|
||||
if (newAccount) {
|
||||
if (!shouldEnableIntercom.value) {
|
||||
shutdownIntercom()
|
||||
return
|
||||
}
|
||||
|
||||
if (!isInitialized.value) {
|
||||
bootIntercom()
|
||||
} else if (newAccount.accountInfo.id !== oldAccount?.accountInfo?.id) {
|
||||
update({
|
||||
user_id: newAccount.accountInfo.userInfo.id || '',
|
||||
name: newAccount.accountInfo.userInfo.name,
|
||||
email: newAccount.accountInfo.userInfo.email
|
||||
})
|
||||
}
|
||||
} else {
|
||||
shutdownIntercom()
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
{ immediate: true }
|
||||
)
|
||||
|
||||
return {
|
||||
show: showIntercom,
|
||||
hide: hideIntercom,
|
||||
shutdown: shutdownIntercom,
|
||||
track: trackIntercom,
|
||||
updateConnectorDetails
|
||||
updateConnectorDetails,
|
||||
shouldEnableIntercom
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user