feat: new business model changes (#85)
* feat: initial can create version implementation on model card * feat: disable model card CTAs for send * feat: initial model ingestion tests * fix: apply ingestion send to all CTAs * feat: sketchup bridge * feat: centeralize the start ingestion logic in host app store * fix: sketchup is handling via model ingestion * chore: cosmetics * feat(ingestion): add failWithError and failWithCancel GraphQL mutations * feat(ingestion): add failIngestion and cancelIngestion methods to useModelIngestion composable * feat(ingestion): handle ingestion failure and cancellation in hostAppStore * fix: reviewers comments * fix: don't know where the f that came from * refactor(ingestion): remove unused statusData and fix lint errors * feat(wizard): add canCreateVersion permission check to publish wizard * TODOs * feat(permissions): add 1s polling for canCreateVersion to reflect workspace limit changes * fix(tooltip): undefined doesnt refresh v-tippy * fix(wizard): too much ctrl z lol * refactor(permissions): check canCreateVersion on action instead of polling * feat(hostApp): adds fallback for model ingestion on older servers * fix: ingestion available check and rock'n roll * feat: workspace plan updated subscription boilerplate * fix: bump the timeout to 2h * feat: handle version limits in publish flows via subscription * feat: align Archicad and Vectorworks with new ingestion flow * chore: onMounted at end of file * fix: logic and ui adjustments * fix: refactoring and permissions * refactor: ingestionStatus renamed to activeIngestions * fix: error handling and notifications * fix: global error handling * chore: general alignment and clean up * fix(vectorworks): now uses capital V * chore: revert codegen --------- Co-authored-by: Björn Steinhagen <88777268+bjoernsteinhagen@users.noreply.github.com> Co-authored-by: Björn Steinhagen <steinhagen.bjoern@gmail.com>
This commit is contained in:
@@ -27,9 +27,9 @@
|
|||||||
>
|
>
|
||||||
{{ notification.secondaryCta.name }}
|
{{ notification.secondaryCta.name }}
|
||||||
</FormButton>
|
</FormButton>
|
||||||
|
<div v-if="notification.cta" v-tippy="notification.cta.tooltipText">
|
||||||
<FormButton
|
<FormButton
|
||||||
v-if="notification.cta"
|
:disabled="notification.cta.disabled"
|
||||||
v-tippy="notification.cta.tooltipText"
|
|
||||||
size="sm"
|
size="sm"
|
||||||
color="primary"
|
color="primary"
|
||||||
full-width
|
full-width
|
||||||
@@ -39,6 +39,7 @@
|
|||||||
</FormButton>
|
</FormButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="notification.dismissible"
|
v-if="notification.dismissible"
|
||||||
class="flex items-center w-0 group-hover:w-5 transition-[width]"
|
class="flex items-center w-0 group-hover:w-5 transition-[width]"
|
||||||
|
|||||||
@@ -5,10 +5,12 @@
|
|||||||
>
|
>
|
||||||
<div v-if="modelData" class="relative px-1 py-1">
|
<div v-if="modelData" class="relative px-1 py-1">
|
||||||
<div class="relative flex items-center space-x-2 min-w-0">
|
<div class="relative flex items-center space-x-2 min-w-0">
|
||||||
<div class="text-foreground-2 mt-[2px] flex items-center -space-x-2 relative">
|
<div
|
||||||
|
v-tippy="buttonTooltip"
|
||||||
|
class="text-foreground-2 mt-[2px] flex items-center -space-x-2 relative"
|
||||||
|
>
|
||||||
<!-- CTA button -->
|
<!-- CTA button -->
|
||||||
<FormButton
|
<FormButton
|
||||||
v-tippy="buttonTooltip"
|
|
||||||
color="outline"
|
color="outline"
|
||||||
:icon-left="
|
:icon-left="
|
||||||
modelCard.progress
|
modelCard.progress
|
||||||
@@ -19,7 +21,7 @@
|
|||||||
"
|
"
|
||||||
hide-text
|
hide-text
|
||||||
class=""
|
class=""
|
||||||
:disabled="!canEdit || isSettingsMissing"
|
:disabled="!canEdit || isSettingsMissing || ctaDisabled"
|
||||||
@click.stop="$emit('manual-publish-or-load')"
|
@click.stop="$emit('manual-publish-or-load')"
|
||||||
></FormButton>
|
></FormButton>
|
||||||
</div>
|
</div>
|
||||||
@@ -260,11 +262,18 @@ const store = useHostAppStore()
|
|||||||
const accStore = useAccountStore()
|
const accStore = useAccountStore()
|
||||||
const { trackEvent } = useMixpanel()
|
const { trackEvent } = useMixpanel()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = withDefaults(
|
||||||
|
defineProps<{
|
||||||
modelCard: IModelCard
|
modelCard: IModelCard
|
||||||
project: ProjectModelGroup
|
project: ProjectModelGroup
|
||||||
canEdit: boolean
|
canEdit: boolean
|
||||||
}>()
|
ctaDisabled?: boolean
|
||||||
|
ctaDisabledMessage?: string
|
||||||
|
}>(),
|
||||||
|
{
|
||||||
|
ctaDisabled: false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
defineEmits<{
|
defineEmits<{
|
||||||
(e: 'manual-publish-or-load'): void
|
(e: 'manual-publish-or-load'): void
|
||||||
@@ -275,6 +284,7 @@ const isSender = computed(() => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const buttonTooltip = computed(() => {
|
const buttonTooltip = computed(() => {
|
||||||
|
if (props.ctaDisabled) return props.ctaDisabledMessage
|
||||||
return props.modelCard.progress
|
return props.modelCard.progress
|
||||||
? 'Cancel'
|
? 'Cancel'
|
||||||
: isSender.value
|
: isSender.value
|
||||||
|
|||||||
+79
-17
@@ -4,6 +4,8 @@
|
|||||||
:model-card="modelCard"
|
:model-card="modelCard"
|
||||||
:project="project"
|
:project="project"
|
||||||
:can-edit="canEdit"
|
:can-edit="canEdit"
|
||||||
|
:cta-disabled="ctaDisabled"
|
||||||
|
:cta-disabled-message="ctaDisabledMessage"
|
||||||
@manual-publish-or-load="sendOrCancel"
|
@manual-publish-or-load="sendOrCancel"
|
||||||
>
|
>
|
||||||
<div class="flex max-[275px]:w-full overflow-hidden my-2">
|
<div class="flex max-[275px]:w-full overflow-hidden my-2">
|
||||||
@@ -17,7 +19,6 @@
|
|||||||
full-width
|
full-width
|
||||||
@click.stop="openFilterDialog = true"
|
@click.stop="openFilterDialog = true"
|
||||||
>
|
>
|
||||||
<!-- Sending -->
|
|
||||||
<span class="font-bold">{{ modelCard.sendFilter?.name }}: </span>
|
<span class="font-bold">{{ modelCard.sendFilter?.name }}: </span>
|
||||||
<span class="truncate">{{ modelCard.sendFilter?.summary }}</span>
|
<span class="truncate">{{ modelCard.sendFilter?.summary }}</span>
|
||||||
</FormButton>
|
</FormButton>
|
||||||
@@ -31,14 +32,19 @@
|
|||||||
<FilterListSelect :filter="modelCard.sendFilter" @update:filter="updateFilter" />
|
<FilterListSelect :filter="modelCard.sendFilter" @update:filter="updateFilter" />
|
||||||
|
|
||||||
<div class="mt-4 flex justify-end items-center space-x-2">
|
<div class="mt-4 flex justify-end items-center space-x-2">
|
||||||
<!-- TODO: Ux wise, users might want to just save the selection and publish it later. -->
|
|
||||||
<FormButton size="sm" color="outline" @click.stop="saveFilter()">
|
<FormButton size="sm" color="outline" @click.stop="saveFilter()">
|
||||||
Save
|
Save
|
||||||
</FormButton>
|
</FormButton>
|
||||||
<FormButton size="sm" @click.stop="saveFilterAndSend()">
|
<div v-tippy="!canCreateVersionPerm ? canCreateVersionMessage : ''">
|
||||||
|
<FormButton
|
||||||
|
size="sm"
|
||||||
|
:disabled="!canCreateVersionPerm"
|
||||||
|
@click.stop="saveFilterAndSend()"
|
||||||
|
>
|
||||||
Save & Publish
|
Save & Publish
|
||||||
</FormButton>
|
</FormButton>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</CommonDialog>
|
</CommonDialog>
|
||||||
|
|
||||||
<CommonDialog
|
<CommonDialog
|
||||||
@@ -108,7 +114,7 @@
|
|||||||
</ModelCardBase>
|
</ModelCardBase>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import ModelCardBase from '~/components/model/CardBase.vue'
|
import ModelCardBase from '~/components/model/CardBase.vue'
|
||||||
import { Square3Stack3DIcon } from '@heroicons/vue/20/solid'
|
import { Square3Stack3DIcon } from '@heroicons/vue/20/solid'
|
||||||
import type { ModelCardNotification } from '~/lib/models/card/notification'
|
import type { ModelCardNotification } from '~/lib/models/card/notification'
|
||||||
@@ -117,13 +123,22 @@ import type { ProjectModelGroup } from '~/store/hostApp'
|
|||||||
import { useHostAppStore } from '~/store/hostApp'
|
import { useHostAppStore } from '~/store/hostApp'
|
||||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||||
import { ToastNotificationType, ValidationHelpers } from '@speckle/ui-components'
|
import { ToastNotificationType, ValidationHelpers } from '@speckle/ui-components'
|
||||||
import { provideApolloClient, useMutation } from '@vue/apollo-composable'
|
import {
|
||||||
|
provideApolloClient,
|
||||||
|
useMutation,
|
||||||
|
useSubscription
|
||||||
|
} from '@vue/apollo-composable'
|
||||||
import { useAccountStore, type DUIAccount } from '~/store/accounts'
|
import { useAccountStore, type DUIAccount } from '~/store/accounts'
|
||||||
import { setVersionMessageMutation } from '~/lib/graphql/mutationsAndQueries'
|
import { setVersionMessageMutation } from '~/lib/graphql/mutationsAndQueries'
|
||||||
const hostAppStore = useHostAppStore()
|
import { workspacePlanUsageUpdatedSubscription } from '~/lib/workspaces/graphql/subscriptions'
|
||||||
|
import { useCheckGraphql } from '~/lib/core/composables/useCheckGraphql'
|
||||||
|
|
||||||
|
const store = useHostAppStore()
|
||||||
|
const accountStore = useAccountStore()
|
||||||
|
|
||||||
const { trackEvent } = useMixpanel()
|
const { trackEvent } = useMixpanel()
|
||||||
const app = useNuxtApp()
|
const app = useNuxtApp()
|
||||||
|
const { canCreateModelIngestion } = useCheckGraphql()
|
||||||
|
|
||||||
const cardBase = ref<InstanceType<typeof ModelCardBase>>()
|
const cardBase = ref<InstanceType<typeof ModelCardBase>>()
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -132,18 +147,62 @@ const props = defineProps<{
|
|||||||
canEdit: boolean
|
canEdit: boolean
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const store = useHostAppStore()
|
const account = accountStore.accounts.find(
|
||||||
|
(acc) => acc.accountInfo.id === props.project.accountId
|
||||||
|
) as DUIAccount
|
||||||
|
const clientId = account.accountInfo.id
|
||||||
|
|
||||||
const openFilterDialog = ref(false)
|
const openFilterDialog = ref(false)
|
||||||
app.$baseBinding?.on('documentChanged', () => {
|
app.$baseBinding?.on('documentChanged', () => {
|
||||||
openFilterDialog.value = false
|
openFilterDialog.value = false
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const canCreateVersionPerm = ref(true)
|
||||||
|
const canCreateVersionMessage = ref<string | null>(null)
|
||||||
|
|
||||||
|
const checkPermissions = async () => {
|
||||||
|
const res = await canCreateModelIngestion(
|
||||||
|
props.modelCard.projectId,
|
||||||
|
props.modelCard.modelId,
|
||||||
|
props.modelCard.accountId
|
||||||
|
)
|
||||||
|
if (res.queryAvailable) {
|
||||||
|
canCreateVersionPerm.value = res.authorized
|
||||||
|
canCreateVersionMessage.value = res.message || null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ctaDisabled = computed(
|
||||||
|
() => !canCreateVersionPerm.value || !!props.modelCard.progress
|
||||||
|
)
|
||||||
|
const ctaDisabledMessage = computed(() => canCreateVersionMessage.value || undefined)
|
||||||
|
|
||||||
|
const { onResult: onWorkspacePlanUsageUpdated } = useSubscription(
|
||||||
|
workspacePlanUsageUpdatedSubscription,
|
||||||
|
() => ({
|
||||||
|
input: {
|
||||||
|
workspaceId: props.modelCard.workspaceId as string
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
() => ({ clientId })
|
||||||
|
)
|
||||||
|
|
||||||
|
onWorkspacePlanUsageUpdated(() => {
|
||||||
|
void checkPermissions()
|
||||||
|
})
|
||||||
|
|
||||||
const sendOrCancel = () => {
|
const sendOrCancel = () => {
|
||||||
if (!props.canEdit) {
|
// check for progress first to allow cancelling even if permissions changed
|
||||||
|
if (props.modelCard.progress) {
|
||||||
|
store.sendModelCancel(props.modelCard.modelCardId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (props.modelCard.progress) store.sendModelCancel(props.modelCard.modelCardId)
|
|
||||||
else store.sendModel(props.modelCard.modelCardId, 'ModelCardButton')
|
if (!props.canEdit || !canCreateVersionPerm.value) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
store.sendModel(props.modelCard.modelCardId, 'ModelCardButton')
|
||||||
hasSetVersionMessage.value = false
|
hasSetVersionMessage.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,11 +232,6 @@ const isUpdatingVersionMessage = ref(false)
|
|||||||
const hasSetVersionMessage = ref(false)
|
const hasSetVersionMessage = ref(false)
|
||||||
const versionMessage = ref<string>()
|
const versionMessage = ref<string>()
|
||||||
|
|
||||||
const accountStore = useAccountStore()
|
|
||||||
const account = accountStore.accounts.find(
|
|
||||||
(acc) => acc.accountInfo.id === props.project.accountId
|
|
||||||
) as DUIAccount
|
|
||||||
|
|
||||||
const setVersionMessage = async (message: string) => {
|
const setVersionMessage = async (message: string) => {
|
||||||
if (!props.modelCard.latestCreatedVersionId) {
|
if (!props.modelCard.latestCreatedVersionId) {
|
||||||
return
|
return
|
||||||
@@ -203,14 +257,14 @@ const setVersionMessage = async (message: string) => {
|
|||||||
if (res?.data?.versionMutations.update.id) {
|
if (res?.data?.versionMutations.update.id) {
|
||||||
// seemed to noisy, and autoclose does not work for some reason.
|
// seemed to noisy, and autoclose does not work for some reason.
|
||||||
// nicer ux to just close the dialog
|
// nicer ux to just close the dialog
|
||||||
// hostAppStore.setNotification({
|
// store.setNotification({
|
||||||
// type: ToastNotificationType.Info,
|
// type: ToastNotificationType.Info,
|
||||||
// title: 'Version message saved',
|
// title: 'Version message saved',
|
||||||
// autoClose: true
|
// autoClose: true
|
||||||
// })
|
// })
|
||||||
hasSetVersionMessage.value = true
|
hasSetVersionMessage.value = true
|
||||||
} else {
|
} else {
|
||||||
hostAppStore.setNotification({
|
store.setNotification({
|
||||||
type: ToastNotificationType.Danger,
|
type: ToastNotificationType.Danger,
|
||||||
title: 'Request failed',
|
title: 'Request failed',
|
||||||
description: 'Failed to update version message.',
|
description: 'Failed to update version message.',
|
||||||
@@ -261,6 +315,10 @@ const expiredNotification = computed(() => {
|
|||||||
const ctaType = props.modelCard.progress ? 'Restart' : 'Update'
|
const ctaType = props.modelCard.progress ? 'Restart' : 'Update'
|
||||||
notification.cta = {
|
notification.cta = {
|
||||||
name: ctaType,
|
name: ctaType,
|
||||||
|
disabled: !canCreateVersionPerm.value,
|
||||||
|
tooltipText: !canCreateVersionPerm.value
|
||||||
|
? canCreateVersionMessage.value || 'Publish limit reached'
|
||||||
|
: undefined,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
hasSetVersionMessage.value = false
|
hasSetVersionMessage.value = false
|
||||||
if (props.modelCard.progress) {
|
if (props.modelCard.progress) {
|
||||||
@@ -337,4 +395,8 @@ const latestVersionNotification = computed(() => {
|
|||||||
}
|
}
|
||||||
return notification
|
return notification
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
void checkPermissions()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
+68
-16
@@ -21,7 +21,6 @@
|
|||||||
@search-text-update="updateSearchText"
|
@search-text-update="updateSearchText"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- Model selector wizard -->
|
|
||||||
<div v-if="step === 2 && selectedProject && selectedAccountId">
|
<div v-if="step === 2 && selectedProject && selectedAccountId">
|
||||||
<WizardModelSelector
|
<WizardModelSelector
|
||||||
:project="selectedProject"
|
:project="selectedProject"
|
||||||
@@ -32,7 +31,6 @@
|
|||||||
@next="selectModel"
|
@next="selectModel"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- Version selector wizard -->
|
|
||||||
<div v-if="step === 3">
|
<div v-if="step === 3">
|
||||||
<SendFiltersAndSettings
|
<SendFiltersAndSettings
|
||||||
v-model="filter"
|
v-model="filter"
|
||||||
@@ -44,8 +42,10 @@
|
|||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
<div class="mt-2">
|
<div v-tippy="!canPublish ? publishLimitMessage : ''" class="mt-2">
|
||||||
<FormButton full-width @click="addModel">Publish</FormButton>
|
<FormButton full-width :disabled="!canPublish" @click="addModel">
|
||||||
|
Publish
|
||||||
|
</FormButton>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="urlParseError" class="p-2 text-danger">
|
<div v-if="urlParseError" class="p-2 text-danger">
|
||||||
@@ -55,6 +55,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { useSubscription } from '@vue/apollo-composable'
|
||||||
import type {
|
import type {
|
||||||
ModelListModelItemFragment,
|
ModelListModelItemFragment,
|
||||||
ProjectListProjectItemFragment
|
ProjectListProjectItemFragment
|
||||||
@@ -67,6 +68,8 @@ import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
|||||||
import { useSettingsTracking } from '~/lib/core/composables/trackSettings'
|
import { useSettingsTracking } from '~/lib/core/composables/trackSettings'
|
||||||
import type { CardSetting } from '~/lib/models/card/setting'
|
import type { CardSetting } from '~/lib/models/card/setting'
|
||||||
import { useAddByUrl } from '~/lib/core/composables/addByUrl'
|
import { useAddByUrl } from '~/lib/core/composables/addByUrl'
|
||||||
|
import { useCheckGraphql } from '~/lib/core/composables/useCheckGraphql'
|
||||||
|
import { workspacePlanUsageUpdatedSubscription } from '~/lib/workspaces/graphql/subscriptions'
|
||||||
|
|
||||||
const { trackEvent } = useMixpanel()
|
const { trackEvent } = useMixpanel()
|
||||||
const { trackSettingsChange } = useSettingsTracking()
|
const { trackSettingsChange } = useSettingsTracking()
|
||||||
@@ -87,6 +90,11 @@ const settings = ref<CardSetting[] | undefined>(undefined)
|
|||||||
const settingsWereChanged = ref(false)
|
const settingsWereChanged = ref(false)
|
||||||
|
|
||||||
const { tryParseUrl, urlParsedData, urlParseError } = useAddByUrl()
|
const { tryParseUrl, urlParsedData, urlParseError } = useAddByUrl()
|
||||||
|
const { canCreateModelIngestion, canCreateVersion } = useCheckGraphql()
|
||||||
|
|
||||||
|
const canPublish = ref(true)
|
||||||
|
const publishLimitMessage = ref<string | undefined>(undefined)
|
||||||
|
|
||||||
const updateSearchText = (text: string | undefined) => {
|
const updateSearchText = (text: string | undefined) => {
|
||||||
urlParseError.value = undefined
|
urlParseError.value = undefined
|
||||||
if (!text) return
|
if (!text) return
|
||||||
@@ -105,6 +113,62 @@ watch(showSendDialog, (newVal) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const checkPermissions = async () => {
|
||||||
|
if (!selectedProject.value || !selectedModel.value) return
|
||||||
|
|
||||||
|
const res = await canCreateModelIngestion(
|
||||||
|
selectedProject.value.id,
|
||||||
|
selectedModel.value.id,
|
||||||
|
selectedAccountId.value
|
||||||
|
)
|
||||||
|
if (res.queryAvailable) {
|
||||||
|
canPublish.value = res.authorized
|
||||||
|
publishLimitMessage.value = res.message || undefined
|
||||||
|
} else {
|
||||||
|
// check legacy canCreateVersion in else block
|
||||||
|
const legacyRes = await canCreateVersion(
|
||||||
|
selectedProject.value.id,
|
||||||
|
selectedModel.value.id,
|
||||||
|
selectedAccountId.value
|
||||||
|
)
|
||||||
|
canPublish.value = legacyRes.authorized
|
||||||
|
publishLimitMessage.value = legacyRes.message || undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(step, async (newVal, oldVal) => {
|
||||||
|
if (newVal > oldVal) {
|
||||||
|
if (newVal === 3) {
|
||||||
|
await checkPermissions()
|
||||||
|
}
|
||||||
|
return // exit fast on forward
|
||||||
|
}
|
||||||
|
if (newVal === 1) {
|
||||||
|
selectedProject.value = undefined
|
||||||
|
selectedModel.value = undefined
|
||||||
|
}
|
||||||
|
if (newVal === 2) selectedModel.value = undefined
|
||||||
|
})
|
||||||
|
|
||||||
|
const workspaceId = computed(() => selectedProject.value?.workspace?.id)
|
||||||
|
|
||||||
|
const { onResult: onUsageUpdate } = useSubscription(
|
||||||
|
workspacePlanUsageUpdatedSubscription,
|
||||||
|
() => ({
|
||||||
|
input: {
|
||||||
|
workspaceId: workspaceId.value || ''
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
() => ({
|
||||||
|
enabled: !!workspaceId.value && step.value === 3,
|
||||||
|
clientId: selectedAccountId.value
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
onUsageUpdate(() => {
|
||||||
|
void checkPermissions()
|
||||||
|
})
|
||||||
|
|
||||||
const selectProject = (accountId: string, project: ProjectListProjectItemFragment) => {
|
const selectProject = (accountId: string, project: ProjectListProjectItemFragment) => {
|
||||||
step.value++
|
step.value++
|
||||||
selectedAccountId.value = accountId
|
selectedAccountId.value = accountId
|
||||||
@@ -125,18 +189,6 @@ const selectModel = (model: ModelListModelItemFragment) => {
|
|||||||
void trackEvent('DUI3 Action', { name: 'Publish Wizard', step: 'model selected' })
|
void trackEvent('DUI3 Action', { name: 'Publish Wizard', step: 'model selected' })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clears data if going backwards in the wizard
|
|
||||||
watch(step, (newVal, oldVal) => {
|
|
||||||
if (newVal > oldVal) {
|
|
||||||
return // exit fast on forward
|
|
||||||
}
|
|
||||||
if (newVal === 1) {
|
|
||||||
selectedProject.value = undefined
|
|
||||||
selectedModel.value = undefined
|
|
||||||
}
|
|
||||||
if (newVal === 2) selectedModel.value = undefined
|
|
||||||
})
|
|
||||||
|
|
||||||
const hostAppStore = useHostAppStore()
|
const hostAppStore = useHostAppStore()
|
||||||
|
|
||||||
// accountId, serverUrl, projectId, modelId, sendFilter, settings
|
// accountId, serverUrl, projectId, modelId, sendFilter, settings
|
||||||
|
|||||||
+62
-8
@@ -16,6 +16,9 @@ import type { Emitter } from 'nanoevents'
|
|||||||
import { useDesktopService } from '~/lib/core/composables/desktopService'
|
import { useDesktopService } from '~/lib/core/composables/desktopService'
|
||||||
import type { ToastNotification } from '@speckle/ui-components'
|
import type { ToastNotification } from '@speckle/ui-components'
|
||||||
import { ToastNotificationType } from '@speckle/ui-components'
|
import { ToastNotificationType } from '@speckle/ui-components'
|
||||||
|
import { useModelIngestion } from '../ingestion/composables/useModelIngestion'
|
||||||
|
import type { ISenderModelCard } from '../models/card/send'
|
||||||
|
import { useCheckGraphql } from '~/lib/core/composables/useCheckGraphql'
|
||||||
|
|
||||||
export type SendBatchViaBrowserArgs = {
|
export type SendBatchViaBrowserArgs = {
|
||||||
modelCardId: string
|
modelCardId: string
|
||||||
@@ -466,24 +469,75 @@ export class ArchicadBridge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async createVersion(args: CreateVersionArgs) {
|
private async createVersion(args: CreateVersionArgs) {
|
||||||
const accountStore = useAccountStore()
|
const hostAppStore = useHostAppStore()
|
||||||
const { accounts } = storeToRefs(accountStore)
|
const { completeIngestionWithVersion } = useModelIngestion()
|
||||||
const account = accounts.value.find((acc) => acc.accountInfo.id === args.accountId)
|
const { canCreateModelIngestion } = useCheckGraphql()
|
||||||
|
|
||||||
const createVersion = provideApolloClient((account as DUIAccount).client)(() =>
|
const modelCard = hostAppStore.models.find(
|
||||||
|
(model) => model.modelCardId === args.modelCardId
|
||||||
|
) as ISenderModelCard
|
||||||
|
|
||||||
|
const canCreateIngestion = await canCreateModelIngestion(
|
||||||
|
modelCard.projectId,
|
||||||
|
modelCard.modelId,
|
||||||
|
modelCard.accountId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (canCreateIngestion.queryAvailable) {
|
||||||
|
const ingestionId = hostAppStore.activeIngestions[args.modelCardId]
|
||||||
|
if (!ingestionId) {
|
||||||
|
hostAppStore.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Failed',
|
||||||
|
description: 'Ingestion ID not found to create version.'
|
||||||
|
})
|
||||||
|
throw new Error(`Ingestion failed: Ingestion ID not found to create version.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await completeIngestionWithVersion(
|
||||||
|
modelCard,
|
||||||
|
ingestionId,
|
||||||
|
args.referencedObjectId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (res?.statusData.__typename === 'ModelIngestionSuccessStatus') {
|
||||||
|
return res?.statusData.versionId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res?.statusData.__typename === 'ModelIngestionFailedStatus') {
|
||||||
|
const errorReason = res?.statusData.errorReason || 'Unknown error'
|
||||||
|
hostAppStore.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Failed',
|
||||||
|
description: errorReason
|
||||||
|
})
|
||||||
|
throw new Error(`Ingestion failed: ${errorReason}.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
hostAppStore.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Error',
|
||||||
|
description: 'Ingestion status does not match expected types.'
|
||||||
|
})
|
||||||
|
throw new Error(
|
||||||
|
`Ingestion status does not match with the expected types as success or failure.`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
const accountStore = useAccountStore()
|
||||||
|
const account = accountStore.getAccountClient(args.accountId)
|
||||||
|
const { mutate } = provideApolloClient(account)(() =>
|
||||||
useMutation(createVersionMutation)
|
useMutation(createVersionMutation)
|
||||||
)
|
)
|
||||||
|
|
||||||
const hostAppStore = useHostAppStore()
|
const result = await mutate({
|
||||||
|
|
||||||
const result = await createVersion.mutate({
|
|
||||||
input: {
|
input: {
|
||||||
modelId: args.modelId,
|
modelId: args.modelId,
|
||||||
objectId: args.referencedObjectId,
|
objectId: args.referencedObjectId,
|
||||||
sourceApplication: hostAppStore.hostAppName,
|
sourceApplication: args.sourceApplication || 'Archicad',
|
||||||
projectId: args.projectId
|
projectId: args.projectId
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return result?.data?.versionMutations?.create?.id
|
return result?.data?.versionMutations?.create?.id
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+56
-4
@@ -19,6 +19,9 @@ import type {
|
|||||||
ReceiveViaBrowserArgs,
|
ReceiveViaBrowserArgs,
|
||||||
CreateVersionArgs
|
CreateVersionArgs
|
||||||
} from '~/lib/bridge/server'
|
} from '~/lib/bridge/server'
|
||||||
|
import { useModelIngestion } from '../ingestion/composables/useModelIngestion'
|
||||||
|
import type { ISenderModelCard } from '../models/card/send'
|
||||||
|
import { useCheckGraphql } from '~/lib/core/composables/useCheckGraphql'
|
||||||
|
|
||||||
declare let sketchup: {
|
declare let sketchup: {
|
||||||
exec: (data: Record<string, unknown>) => void
|
exec: (data: Record<string, unknown>) => void
|
||||||
@@ -297,23 +300,71 @@ export class SketchupBridge extends BaseBridge {
|
|||||||
sourceApplication: 'sketchup',
|
sourceApplication: 'sketchup',
|
||||||
message: message || 'send from sketchup'
|
message: message || 'send from sketchup'
|
||||||
}
|
}
|
||||||
const versionId = await this.createVersion(args)
|
|
||||||
|
|
||||||
const hostAppStore = useHostAppStore()
|
const hostAppStore = useHostAppStore()
|
||||||
// TODO: Alignment needed
|
try {
|
||||||
|
const versionId = await this.createVersion(args)
|
||||||
hostAppStore.setModelSendResult({
|
hostAppStore.setModelSendResult({
|
||||||
modelCardId: args.modelCardId,
|
modelCardId: args.modelCardId,
|
||||||
versionId: versionId as string,
|
versionId: versionId as string,
|
||||||
sendConversionResults
|
sendConversionResults
|
||||||
})
|
})
|
||||||
|
} catch (err) {
|
||||||
|
hostAppStore.setHostAppError({
|
||||||
|
message: (err as Error).message || 'Unknown error occurred',
|
||||||
|
error: (err as Error).toString(),
|
||||||
|
stackTrace: (err as Error).stack || ''
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async createVersion(args: CreateVersionArgs) {
|
public async createVersion(args: CreateVersionArgs) {
|
||||||
const accountStore = useAccountStore()
|
|
||||||
const hostAppStore = useHostAppStore()
|
const hostAppStore = useHostAppStore()
|
||||||
|
const accountStore = useAccountStore()
|
||||||
const { accounts } = storeToRefs(accountStore)
|
const { accounts } = storeToRefs(accountStore)
|
||||||
const account = accounts.value.find((acc) => acc.accountInfo.id === args.accountId)
|
const account = accounts.value.find((acc) => acc.accountInfo.id === args.accountId)
|
||||||
|
const { completeIngestionWithVersion } = useModelIngestion()
|
||||||
|
|
||||||
|
const modelCard = hostAppStore.models.find(
|
||||||
|
(model) => model.modelCardId === args.modelCardId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!modelCard) {
|
||||||
|
throw new Error('Model card not found') // ctor
|
||||||
|
}
|
||||||
|
|
||||||
|
const { canCreateModelIngestion } = useCheckGraphql()
|
||||||
|
const canCreateIngestion = await canCreateModelIngestion(
|
||||||
|
modelCard.projectId,
|
||||||
|
modelCard.modelId,
|
||||||
|
modelCard.accountId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (canCreateIngestion.queryAvailable) {
|
||||||
|
const ingestionId = hostAppStore.activeIngestions[args.modelCardId]
|
||||||
|
if (!ingestionId) {
|
||||||
|
throw new Error(`Ingestion failed: Ingestion ID not found to create version.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await completeIngestionWithVersion(
|
||||||
|
modelCard as ISenderModelCard,
|
||||||
|
ingestionId,
|
||||||
|
args.referencedObjectId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (res?.statusData.__typename === 'ModelIngestionSuccessStatus') {
|
||||||
|
return res?.statusData.versionId
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res?.statusData.__typename === 'ModelIngestionFailedStatus') {
|
||||||
|
throw new Error(
|
||||||
|
`Ingestion failed: ${res?.statusData.errorReason || 'Unknown error'}.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
throw new Error(
|
||||||
|
`Ingestion status does not match with the expected types as success or failure.`
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// for the self hosters that does not have available graphql for ingestions
|
||||||
const createVersion = provideApolloClient((account as DUIAccount).client)(() =>
|
const createVersion = provideApolloClient((account as DUIAccount).client)(() =>
|
||||||
useMutation(createVersionMutation)
|
useMutation(createVersionMutation)
|
||||||
)
|
)
|
||||||
@@ -332,6 +383,7 @@ export class SketchupBridge extends BaseBridge {
|
|||||||
})
|
})
|
||||||
return result?.data?.versionMutations?.create?.id
|
return result?.data?.versionMutations?.create?.id
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public async create(): Promise<boolean> {
|
public async create(): Promise<boolean> {
|
||||||
// Initialization continues in the receiveCommandsAndInitializeBridge function,
|
// Initialization continues in the receiveCommandsAndInitializeBridge function,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ type Documents = {
|
|||||||
"\n query CanCreatePersonalProject {\n activeUser {\n permissions {\n canCreatePersonalProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": typeof types.CanCreatePersonalProjectDocument,
|
"\n query CanCreatePersonalProject {\n activeUser {\n permissions {\n canCreatePersonalProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": typeof types.CanCreatePersonalProjectDocument,
|
||||||
"\n query CanCreateProjectInWorkspace($workspaceId: String!) {\n workspace(id: $workspaceId) {\n permissions {\n canCreateProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": typeof types.CanCreateProjectInWorkspaceDocument,
|
"\n query CanCreateProjectInWorkspace($workspaceId: String!) {\n workspace(id: $workspaceId) {\n permissions {\n canCreateProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": typeof types.CanCreateProjectInWorkspaceDocument,
|
||||||
"\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n": typeof types.CanCreateModelInProjectDocument,
|
"\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n": typeof types.CanCreateModelInProjectDocument,
|
||||||
|
"\n query CanCreateVersion($projectId: String!, $modelId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateVersion {\n authorized\n code\n message\n errorMessage\n }\n }\n }\n }\n }\n": typeof types.CanCreateVersionDocument,
|
||||||
"\n query ActiveWorkspace {\n activeUser {\n activeWorkspace {\n id\n name\n }\n }\n }\n": typeof types.ActiveWorkspaceDocument,
|
"\n query ActiveWorkspace {\n activeUser {\n activeWorkspace {\n id\n name\n }\n }\n }\n": typeof types.ActiveWorkspaceDocument,
|
||||||
"\n fragment ProjectListProjectItem on Project {\n id\n name\n role\n updatedAt\n workspaceId\n workspace {\n id\n name\n slug\n role\n }\n models {\n totalCount\n }\n permissions {\n canLoad {\n authorized\n code\n message\n }\n canPublish {\n authorized\n code\n message\n }\n }\n }\n": typeof types.ProjectListProjectItemFragmentDoc,
|
"\n fragment ProjectListProjectItem on Project {\n id\n name\n role\n updatedAt\n workspaceId\n workspace {\n id\n name\n slug\n role\n }\n models {\n totalCount\n }\n permissions {\n canLoad {\n authorized\n code\n message\n }\n canPublish {\n authorized\n code\n message\n }\n }\n }\n": typeof types.ProjectListProjectItemFragmentDoc,
|
||||||
"\n query ProjectListQuery($limit: Int!, $filter: UserProjectsFilter, $cursor: String) {\n activeUser {\n id\n projects(limit: $limit, filter: $filter, cursor: $cursor) {\n totalCount\n cursor\n items {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": typeof types.ProjectListQueryDocument,
|
"\n query ProjectListQuery($limit: Int!, $filter: UserProjectsFilter, $cursor: String) {\n activeUser {\n id\n projects(limit: $limit, filter: $filter, cursor: $cursor) {\n totalCount\n cursor\n items {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": typeof types.ProjectListQueryDocument,
|
||||||
@@ -52,10 +53,17 @@ type Documents = {
|
|||||||
"\n subscription ProjectTriggeredAutomationsStatusUpdated($projectId: String!) {\n projectTriggeredAutomationsStatusUpdated(projectId: $projectId) {\n type\n version {\n id\n }\n model {\n id\n }\n project {\n id\n }\n run {\n ...AutomationRunItem\n }\n }\n }\n": typeof types.ProjectTriggeredAutomationsStatusUpdatedDocument,
|
"\n subscription ProjectTriggeredAutomationsStatusUpdated($projectId: String!) {\n projectTriggeredAutomationsStatusUpdated(projectId: $projectId) {\n type\n version {\n id\n }\n model {\n id\n }\n project {\n id\n }\n run {\n ...AutomationRunItem\n }\n }\n }\n": typeof types.ProjectTriggeredAutomationsStatusUpdatedDocument,
|
||||||
"\n subscription OnUserProjectsUpdated {\n userProjectsUpdated {\n id\n project {\n id\n visibility\n team {\n id\n role\n }\n }\n }\n }\n": typeof types.OnUserProjectsUpdatedDocument,
|
"\n subscription OnUserProjectsUpdated {\n userProjectsUpdated {\n id\n project {\n id\n visibility\n team {\n id\n role\n }\n }\n }\n }\n": typeof types.OnUserProjectsUpdatedDocument,
|
||||||
"\n subscription ProjectUpdated($projectId: String!) {\n projectUpdated(id: $projectId) {\n id\n project {\n visibility\n }\n }\n }\n": typeof types.ProjectUpdatedDocument,
|
"\n subscription ProjectUpdated($projectId: String!) {\n projectUpdated(id: $projectId) {\n id\n project {\n visibility\n }\n }\n }\n": typeof types.ProjectUpdatedDocument,
|
||||||
"\n subscription Subscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n": typeof types.SubscriptionDocument,
|
"\n subscription ModelViewingSubscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n": typeof types.ModelViewingSubscriptionDocument,
|
||||||
"\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\n }\n }\n": typeof types.ProjectCommentsUpdatedDocument,
|
"\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\n }\n }\n": typeof types.ProjectCommentsUpdatedDocument,
|
||||||
|
"\n mutation CreateModelIngestion($input: ModelIngestionCreateInput!) {\n projectMutations {\n modelIngestionMutations {\n create(input: $input) {\n id\n }\n }\n }\n }\n": typeof types.CreateModelIngestionDocument,
|
||||||
|
"\n mutation UpdateModelIngestionProgress($input: ModelIngestionUpdateInput!) {\n projectMutations {\n modelIngestionMutations {\n updateProgress(input: $input) {\n id\n }\n }\n }\n }\n": typeof types.UpdateModelIngestionProgressDocument,
|
||||||
|
"\n mutation CompleteModelIngestionWithVersion($input: ModelIngestionSuccessInput!) {\n projectMutations {\n modelIngestionMutations {\n completeWithVersion(input: $input) {\n id\n statusData {\n __typename\n ... on ModelIngestionProcessingStatus {\n status\n progressMessage\n progress\n }\n ... on ModelIngestionSuccessStatus {\n status\n versionId\n }\n ... on ModelIngestionFailedStatus {\n errorStacktrace\n errorReason\n status\n }\n ... on ModelIngestionCancelledStatus {\n cancellationMessage\n status\n }\n ... on ModelIngestionQueuedStatus {\n progressMessage\n status\n }\n }\n }\n }\n }\n }\n": typeof types.CompleteModelIngestionWithVersionDocument,
|
||||||
|
"\n mutation FailModelIngestionWithError($input: ModelIngestionFailedInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithError(input: $input) {\n id\n }\n }\n }\n }\n": typeof types.FailModelIngestionWithErrorDocument,
|
||||||
|
"\n mutation FailModelIngestionWithCancel($input: ModelIngestionCancelledInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithCancel(input: $input) {\n id\n }\n }\n }\n }\n": typeof types.FailModelIngestionWithCancelDocument,
|
||||||
|
"\n query CanCreateIngestion($modelId: String!, $projectId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateIngestion {\n authorized\n code\n message\n }\n }\n }\n }\n }\n": typeof types.CanCreateIngestionDocument,
|
||||||
"\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 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 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 subscription WorkspacePlanUsageUpdated($input: WorkspacePlanUsageSubscriptionInput!) {\n workspacePlanUsageUpdated(input: $input)\n }\n": typeof types.WorkspacePlanUsageUpdatedDocument,
|
||||||
};
|
};
|
||||||
const documents: Documents = {
|
const documents: Documents = {
|
||||||
"\n mutation SetActiveWorkspaceMutation($slug: String) {\n activeUserMutations {\n setActiveWorkspace(slug: $slug) {\n id\n }\n }\n }\n": types.SetActiveWorkspaceMutationDocument,
|
"\n mutation SetActiveWorkspaceMutation($slug: String) {\n activeUserMutations {\n setActiveWorkspace(slug: $slug) {\n id\n }\n }\n }\n": types.SetActiveWorkspaceMutationDocument,
|
||||||
@@ -77,6 +85,7 @@ const documents: Documents = {
|
|||||||
"\n query CanCreatePersonalProject {\n activeUser {\n permissions {\n canCreatePersonalProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": types.CanCreatePersonalProjectDocument,
|
"\n query CanCreatePersonalProject {\n activeUser {\n permissions {\n canCreatePersonalProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": types.CanCreatePersonalProjectDocument,
|
||||||
"\n query CanCreateProjectInWorkspace($workspaceId: String!) {\n workspace(id: $workspaceId) {\n permissions {\n canCreateProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": types.CanCreateProjectInWorkspaceDocument,
|
"\n query CanCreateProjectInWorkspace($workspaceId: String!) {\n workspace(id: $workspaceId) {\n permissions {\n canCreateProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": types.CanCreateProjectInWorkspaceDocument,
|
||||||
"\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n": types.CanCreateModelInProjectDocument,
|
"\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n": types.CanCreateModelInProjectDocument,
|
||||||
|
"\n query CanCreateVersion($projectId: String!, $modelId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateVersion {\n authorized\n code\n message\n errorMessage\n }\n }\n }\n }\n }\n": types.CanCreateVersionDocument,
|
||||||
"\n query ActiveWorkspace {\n activeUser {\n activeWorkspace {\n id\n name\n }\n }\n }\n": types.ActiveWorkspaceDocument,
|
"\n query ActiveWorkspace {\n activeUser {\n activeWorkspace {\n id\n name\n }\n }\n }\n": types.ActiveWorkspaceDocument,
|
||||||
"\n fragment ProjectListProjectItem on Project {\n id\n name\n role\n updatedAt\n workspaceId\n workspace {\n id\n name\n slug\n role\n }\n models {\n totalCount\n }\n permissions {\n canLoad {\n authorized\n code\n message\n }\n canPublish {\n authorized\n code\n message\n }\n }\n }\n": types.ProjectListProjectItemFragmentDoc,
|
"\n fragment ProjectListProjectItem on Project {\n id\n name\n role\n updatedAt\n workspaceId\n workspace {\n id\n name\n slug\n role\n }\n models {\n totalCount\n }\n permissions {\n canLoad {\n authorized\n code\n message\n }\n canPublish {\n authorized\n code\n message\n }\n }\n }\n": types.ProjectListProjectItemFragmentDoc,
|
||||||
"\n query ProjectListQuery($limit: Int!, $filter: UserProjectsFilter, $cursor: String) {\n activeUser {\n id\n projects(limit: $limit, filter: $filter, cursor: $cursor) {\n totalCount\n cursor\n items {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": types.ProjectListQueryDocument,
|
"\n query ProjectListQuery($limit: Int!, $filter: UserProjectsFilter, $cursor: String) {\n activeUser {\n id\n projects(limit: $limit, filter: $filter, cursor: $cursor) {\n totalCount\n cursor\n items {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": types.ProjectListQueryDocument,
|
||||||
@@ -96,10 +105,17 @@ const documents: Documents = {
|
|||||||
"\n subscription ProjectTriggeredAutomationsStatusUpdated($projectId: String!) {\n projectTriggeredAutomationsStatusUpdated(projectId: $projectId) {\n type\n version {\n id\n }\n model {\n id\n }\n project {\n id\n }\n run {\n ...AutomationRunItem\n }\n }\n }\n": types.ProjectTriggeredAutomationsStatusUpdatedDocument,
|
"\n subscription ProjectTriggeredAutomationsStatusUpdated($projectId: String!) {\n projectTriggeredAutomationsStatusUpdated(projectId: $projectId) {\n type\n version {\n id\n }\n model {\n id\n }\n project {\n id\n }\n run {\n ...AutomationRunItem\n }\n }\n }\n": types.ProjectTriggeredAutomationsStatusUpdatedDocument,
|
||||||
"\n subscription OnUserProjectsUpdated {\n userProjectsUpdated {\n id\n project {\n id\n visibility\n team {\n id\n role\n }\n }\n }\n }\n": types.OnUserProjectsUpdatedDocument,
|
"\n subscription OnUserProjectsUpdated {\n userProjectsUpdated {\n id\n project {\n id\n visibility\n team {\n id\n role\n }\n }\n }\n }\n": types.OnUserProjectsUpdatedDocument,
|
||||||
"\n subscription ProjectUpdated($projectId: String!) {\n projectUpdated(id: $projectId) {\n id\n project {\n visibility\n }\n }\n }\n": types.ProjectUpdatedDocument,
|
"\n subscription ProjectUpdated($projectId: String!) {\n projectUpdated(id: $projectId) {\n id\n project {\n visibility\n }\n }\n }\n": types.ProjectUpdatedDocument,
|
||||||
"\n subscription Subscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n": types.SubscriptionDocument,
|
"\n subscription ModelViewingSubscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n": types.ModelViewingSubscriptionDocument,
|
||||||
"\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\n }\n }\n": types.ProjectCommentsUpdatedDocument,
|
"\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\n }\n }\n": types.ProjectCommentsUpdatedDocument,
|
||||||
|
"\n mutation CreateModelIngestion($input: ModelIngestionCreateInput!) {\n projectMutations {\n modelIngestionMutations {\n create(input: $input) {\n id\n }\n }\n }\n }\n": types.CreateModelIngestionDocument,
|
||||||
|
"\n mutation UpdateModelIngestionProgress($input: ModelIngestionUpdateInput!) {\n projectMutations {\n modelIngestionMutations {\n updateProgress(input: $input) {\n id\n }\n }\n }\n }\n": types.UpdateModelIngestionProgressDocument,
|
||||||
|
"\n mutation CompleteModelIngestionWithVersion($input: ModelIngestionSuccessInput!) {\n projectMutations {\n modelIngestionMutations {\n completeWithVersion(input: $input) {\n id\n statusData {\n __typename\n ... on ModelIngestionProcessingStatus {\n status\n progressMessage\n progress\n }\n ... on ModelIngestionSuccessStatus {\n status\n versionId\n }\n ... on ModelIngestionFailedStatus {\n errorStacktrace\n errorReason\n status\n }\n ... on ModelIngestionCancelledStatus {\n cancellationMessage\n status\n }\n ... on ModelIngestionQueuedStatus {\n progressMessage\n status\n }\n }\n }\n }\n }\n }\n": types.CompleteModelIngestionWithVersionDocument,
|
||||||
|
"\n mutation FailModelIngestionWithError($input: ModelIngestionFailedInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithError(input: $input) {\n id\n }\n }\n }\n }\n": types.FailModelIngestionWithErrorDocument,
|
||||||
|
"\n mutation FailModelIngestionWithCancel($input: ModelIngestionCancelledInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithCancel(input: $input) {\n id\n }\n }\n }\n }\n": types.FailModelIngestionWithCancelDocument,
|
||||||
|
"\n query CanCreateIngestion($modelId: String!, $projectId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateIngestion {\n authorized\n code\n message\n }\n }\n }\n }\n }\n": types.CanCreateIngestionDocument,
|
||||||
"\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 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 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 subscription WorkspacePlanUsageUpdated($input: WorkspacePlanUsageSubscriptionInput!) {\n workspacePlanUsageUpdated(input: $input)\n }\n": types.WorkspacePlanUsageUpdatedDocument,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -192,6 +208,10 @@ export function graphql(source: "\n query CanCreateProjectInWorkspace($workspac
|
|||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* 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 CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n"): (typeof documents)["\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n"];
|
export function graphql(source: "\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n"): (typeof documents)["\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\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 CanCreateVersion($projectId: String!, $modelId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateVersion {\n authorized\n code\n message\n errorMessage\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query CanCreateVersion($projectId: String!, $modelId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateVersion {\n authorized\n code\n message\n errorMessage\n }\n }\n }\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
@@ -271,11 +291,35 @@ export function graphql(source: "\n subscription ProjectUpdated($projectId: Str
|
|||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n subscription Subscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n"): (typeof documents)["\n subscription Subscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n"];
|
export function graphql(source: "\n subscription ModelViewingSubscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n"): (typeof documents)["\n subscription ModelViewingSubscription($target: ViewerUpdateTrackingTarget!) {\n viewerUserActivityBroadcasted(target: $target) {\n userName\n userId\n sessionId\n user {\n name\n id\n avatar\n }\n status\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
export function graphql(source: "\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\n }\n }\n"): (typeof documents)["\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\n }\n }\n"];
|
export function graphql(source: "\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\n }\n }\n"): (typeof documents)["\n subscription ProjectCommentsUpdated($target: ViewerUpdateTrackingTarget!) {\n projectCommentsUpdated(target: $target) {\n comment {\n author {\n avatar\n id\n name\n }\n id\n hasParent\n parent {\n id\n }\n }\n type\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 mutation CreateModelIngestion($input: ModelIngestionCreateInput!) {\n projectMutations {\n modelIngestionMutations {\n create(input: $input) {\n id\n }\n }\n }\n }\n"): (typeof documents)["\n mutation CreateModelIngestion($input: ModelIngestionCreateInput!) {\n projectMutations {\n modelIngestionMutations {\n create(input: $input) {\n id\n }\n }\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 mutation UpdateModelIngestionProgress($input: ModelIngestionUpdateInput!) {\n projectMutations {\n modelIngestionMutations {\n updateProgress(input: $input) {\n id\n }\n }\n }\n }\n"): (typeof documents)["\n mutation UpdateModelIngestionProgress($input: ModelIngestionUpdateInput!) {\n projectMutations {\n modelIngestionMutations {\n updateProgress(input: $input) {\n id\n }\n }\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 mutation CompleteModelIngestionWithVersion($input: ModelIngestionSuccessInput!) {\n projectMutations {\n modelIngestionMutations {\n completeWithVersion(input: $input) {\n id\n statusData {\n __typename\n ... on ModelIngestionProcessingStatus {\n status\n progressMessage\n progress\n }\n ... on ModelIngestionSuccessStatus {\n status\n versionId\n }\n ... on ModelIngestionFailedStatus {\n errorStacktrace\n errorReason\n status\n }\n ... on ModelIngestionCancelledStatus {\n cancellationMessage\n status\n }\n ... on ModelIngestionQueuedStatus {\n progressMessage\n status\n }\n }\n }\n }\n }\n }\n"): (typeof documents)["\n mutation CompleteModelIngestionWithVersion($input: ModelIngestionSuccessInput!) {\n projectMutations {\n modelIngestionMutations {\n completeWithVersion(input: $input) {\n id\n statusData {\n __typename\n ... on ModelIngestionProcessingStatus {\n status\n progressMessage\n progress\n }\n ... on ModelIngestionSuccessStatus {\n status\n versionId\n }\n ... on ModelIngestionFailedStatus {\n errorStacktrace\n errorReason\n status\n }\n ... on ModelIngestionCancelledStatus {\n cancellationMessage\n status\n }\n ... on ModelIngestionQueuedStatus {\n progressMessage\n status\n }\n }\n }\n }\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 mutation FailModelIngestionWithError($input: ModelIngestionFailedInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithError(input: $input) {\n id\n }\n }\n }\n }\n"): (typeof documents)["\n mutation FailModelIngestionWithError($input: ModelIngestionFailedInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithError(input: $input) {\n id\n }\n }\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 mutation FailModelIngestionWithCancel($input: ModelIngestionCancelledInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithCancel(input: $input) {\n id\n }\n }\n }\n }\n"): (typeof documents)["\n mutation FailModelIngestionWithCancel($input: ModelIngestionCancelledInput!) {\n projectMutations {\n modelIngestionMutations {\n failWithCancel(input: $input) {\n id\n }\n }\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 CanCreateIngestion($modelId: String!, $projectId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateIngestion {\n authorized\n code\n message\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query CanCreateIngestion($modelId: String!, $projectId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n permissions {\n canCreateIngestion {\n authorized\n code\n message\n }\n }\n }\n }\n }\n"];
|
||||||
/**
|
/**
|
||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||||
*/
|
*/
|
||||||
@@ -284,6 +328,10 @@ export function graphql(source: "\n fragment IssuesItem on Issue {\n id\n
|
|||||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
* 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 IssuesList($projectId: String!) {\n project(id: $projectId) {\n id\n issues {\n totalCount\n items {\n ...IssuesItem\n }\n }\n }\n }\n"): (typeof documents)["\n query IssuesList($projectId: String!) {\n project(id: $projectId) {\n id\n issues {\n totalCount\n items {\n ...IssuesItem\n }\n }\n }\n }\n"];
|
export function graphql(source: "\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 documents)["\n query IssuesList($projectId: String!) {\n project(id: $projectId) {\n id\n issues {\n totalCount\n items {\n ...IssuesItem\n }\n }\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 subscription WorkspacePlanUsageUpdated($input: WorkspacePlanUsageSubscriptionInput!) {\n workspacePlanUsageUpdated(input: $input)\n }\n"): (typeof documents)["\n subscription WorkspacePlanUsageUpdated($input: WorkspacePlanUsageSubscriptionInput!) {\n workspacePlanUsageUpdated(input: $input)\n }\n"];
|
||||||
|
|
||||||
export function graphql(source: string) {
|
export function graphql(source: string) {
|
||||||
return (documents as any)[source] ?? {};
|
return (documents as any)[source] ?? {};
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,71 @@
|
|||||||
|
import { canCreateVersionQuery } from '~/lib/graphql/mutationsAndQueries'
|
||||||
|
import { canCreateModelIngestionQuery } from '~/lib/ingestion/graphql/queries'
|
||||||
|
import { useAccountStore } from '~/store/accounts'
|
||||||
|
|
||||||
|
// use this composable whenever we need to check against available graphqls over servers
|
||||||
|
export function useCheckGraphql() {
|
||||||
|
/**
|
||||||
|
* Checks the ingestions available for the server,
|
||||||
|
* if available, returns with respond by appending `queryAvailable = true`
|
||||||
|
* otherwise, returns fake result object with `queryAvailable = false`
|
||||||
|
*/
|
||||||
|
const canCreateModelIngestion = async (
|
||||||
|
projectId: string,
|
||||||
|
modelId: string,
|
||||||
|
accountId: string
|
||||||
|
) => {
|
||||||
|
const accountsStore = useAccountStore()
|
||||||
|
const client = accountsStore.getAccountClient(accountId)
|
||||||
|
try {
|
||||||
|
const result = await client.query({
|
||||||
|
query: canCreateModelIngestionQuery,
|
||||||
|
variables: {
|
||||||
|
projectId,
|
||||||
|
modelId
|
||||||
|
},
|
||||||
|
fetchPolicy: 'network-only'
|
||||||
|
})
|
||||||
|
return {
|
||||||
|
...result.data.project.model.permissions.canCreateIngestion,
|
||||||
|
queryAvailable: true
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
return { queryAvailable: false, authorized: false, message: undefined }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if user can create a version for the given model.
|
||||||
|
* Used to validate before starting a publish operation.
|
||||||
|
*/
|
||||||
|
const canCreateVersion = async (
|
||||||
|
projectId: string,
|
||||||
|
modelId: string,
|
||||||
|
accountId: string
|
||||||
|
) => {
|
||||||
|
const accountsStore = useAccountStore()
|
||||||
|
const client = accountsStore.getAccountClient(accountId)
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await client.query({
|
||||||
|
query: canCreateVersionQuery,
|
||||||
|
variables: {
|
||||||
|
projectId,
|
||||||
|
modelId
|
||||||
|
},
|
||||||
|
fetchPolicy: 'network-only'
|
||||||
|
})
|
||||||
|
|
||||||
|
return result.data.project.model.permissions.canCreateVersion
|
||||||
|
} catch (error) {
|
||||||
|
// If we can't check, allow the attempt - server will reject if not allowed
|
||||||
|
console.error('Failed to check canCreateVersion:', error)
|
||||||
|
return { authorized: true, message: null }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
canCreateVersion,
|
||||||
|
canCreateModelIngestion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -246,6 +246,23 @@ export const canCreateModelInProjectQuery = graphql(`
|
|||||||
}
|
}
|
||||||
`)
|
`)
|
||||||
|
|
||||||
|
export const canCreateVersionQuery = graphql(`
|
||||||
|
query CanCreateVersion($projectId: String!, $modelId: String!) {
|
||||||
|
project(id: $projectId) {
|
||||||
|
model(id: $modelId) {
|
||||||
|
permissions {
|
||||||
|
canCreateVersion {
|
||||||
|
authorized
|
||||||
|
code
|
||||||
|
message
|
||||||
|
errorMessage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
export const activeWorkspaceQuery = graphql(`
|
export const activeWorkspaceQuery = graphql(`
|
||||||
query ActiveWorkspace {
|
query ActiveWorkspace {
|
||||||
activeUser {
|
activeUser {
|
||||||
@@ -606,7 +623,7 @@ export const projectUpdatedSubscription = graphql(`
|
|||||||
`)
|
`)
|
||||||
|
|
||||||
export const modelViewingSubscription = graphql(`
|
export const modelViewingSubscription = graphql(`
|
||||||
subscription Subscription($target: ViewerUpdateTrackingTarget!) {
|
subscription ModelViewingSubscription($target: ViewerUpdateTrackingTarget!) {
|
||||||
viewerUserActivityBroadcasted(target: $target) {
|
viewerUserActivityBroadcasted(target: $target) {
|
||||||
userName
|
userName
|
||||||
userId
|
userId
|
||||||
|
|||||||
@@ -0,0 +1,227 @@
|
|||||||
|
import { provideApolloClient, useMutation } from '@vue/apollo-composable'
|
||||||
|
import { useAccountStore } from '~/store/accounts'
|
||||||
|
import { useHostAppStore } from '~/store/hostApp'
|
||||||
|
import {
|
||||||
|
completeModelIngestionWithVersion,
|
||||||
|
createModelIngestion,
|
||||||
|
updateModelIngestionProgress,
|
||||||
|
failModelIngestionWithError,
|
||||||
|
failModelIngestionWithCancel
|
||||||
|
} from '../graphql/mutations'
|
||||||
|
import type { SourceDataInput } from '~~/lib/common/generated/gql/graphql'
|
||||||
|
import type { ISenderModelCard } from '~/lib/models/card/send'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { ToastNotificationType } from '@speckle/ui-components'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* New way of creating versions.
|
||||||
|
* It is essential for server to track limits on versions.
|
||||||
|
* The flow is as follows:
|
||||||
|
* 0. Check if the user has enough limits to create a new version (this is handled outside of this composable)
|
||||||
|
* 1. Start a new ingestion
|
||||||
|
* 2. Update the ingestion with the new data when connector throws progress via 'setModelProgress' event
|
||||||
|
* 3. Complete the version with the root object id that passed by connector or server/sketchup bridges in JS
|
||||||
|
*/
|
||||||
|
export const useModelIngestion = () => {
|
||||||
|
const store = useHostAppStore()
|
||||||
|
|
||||||
|
const accountStore = useAccountStore()
|
||||||
|
|
||||||
|
const startIngestion = async (
|
||||||
|
senderModelCard: ISenderModelCard,
|
||||||
|
progressMessage: string,
|
||||||
|
sourceData: SourceDataInput
|
||||||
|
) => {
|
||||||
|
const { activeIngestions } = storeToRefs(store)
|
||||||
|
const client = accountStore.getAccountClient(senderModelCard.accountId)
|
||||||
|
const { mutate } = provideApolloClient(client)(() =>
|
||||||
|
useMutation(createModelIngestion)
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await mutate({
|
||||||
|
input: {
|
||||||
|
projectId: senderModelCard.projectId,
|
||||||
|
modelId: senderModelCard.modelId,
|
||||||
|
progressMessage,
|
||||||
|
sourceData,
|
||||||
|
maxIdleTimeoutSeconds: 7200 // 2h
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.errors?.length) {
|
||||||
|
const msg = res.errors[0].message
|
||||||
|
store.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Error',
|
||||||
|
description: msg
|
||||||
|
})
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
const ingestionId = res?.data?.projectMutations.modelIngestionMutations.create.id
|
||||||
|
if (ingestionId) {
|
||||||
|
activeIngestions.value[senderModelCard.modelCardId] = ingestionId
|
||||||
|
}
|
||||||
|
|
||||||
|
return res?.data?.projectMutations.modelIngestionMutations.create
|
||||||
|
}
|
||||||
|
|
||||||
|
const updateIngestion = async (
|
||||||
|
senderModelCard: ISenderModelCard,
|
||||||
|
ingestionId: string,
|
||||||
|
progressMessage: string,
|
||||||
|
progress?: number
|
||||||
|
) => {
|
||||||
|
const client = accountStore.getAccountClient(senderModelCard.accountId)
|
||||||
|
const { mutate } = provideApolloClient(client)(() =>
|
||||||
|
useMutation(updateModelIngestionProgress)
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await mutate({
|
||||||
|
input: {
|
||||||
|
projectId: senderModelCard.projectId,
|
||||||
|
ingestionId,
|
||||||
|
progressMessage,
|
||||||
|
progress
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.errors?.length) {
|
||||||
|
const msg = res.errors[0].message
|
||||||
|
store.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Error',
|
||||||
|
description: msg
|
||||||
|
})
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res?.data?.projectMutations.modelIngestionMutations.updateProgress
|
||||||
|
}
|
||||||
|
|
||||||
|
const failIngestion = async (
|
||||||
|
senderModelCard: ISenderModelCard,
|
||||||
|
ingestionId: string,
|
||||||
|
errorReason: string,
|
||||||
|
errorStacktrace?: string
|
||||||
|
) => {
|
||||||
|
const client = accountStore.getAccountClient(senderModelCard.accountId)
|
||||||
|
const { mutate } = provideApolloClient(client)(() =>
|
||||||
|
useMutation(failModelIngestionWithError)
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await mutate({
|
||||||
|
input: {
|
||||||
|
projectId: senderModelCard.projectId,
|
||||||
|
ingestionId,
|
||||||
|
errorReason,
|
||||||
|
errorStacktrace
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.errors?.length) {
|
||||||
|
const msg = res.errors[0].message
|
||||||
|
store.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Error',
|
||||||
|
description: msg
|
||||||
|
})
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { activeIngestions } = storeToRefs(store)
|
||||||
|
|
||||||
|
// clean the failed ingestion
|
||||||
|
activeIngestions.value = Object.fromEntries(
|
||||||
|
Object.entries(activeIngestions.value).filter(
|
||||||
|
([key]) => key !== senderModelCard.modelCardId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const cancelIngestion = async (
|
||||||
|
senderModelCard: ISenderModelCard,
|
||||||
|
ingestionId: string,
|
||||||
|
cancellationMessage: string = 'Cancelled by user'
|
||||||
|
) => {
|
||||||
|
const client = accountStore.getAccountClient(senderModelCard.accountId)
|
||||||
|
const { mutate } = provideApolloClient(client)(() =>
|
||||||
|
useMutation(failModelIngestionWithCancel)
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await mutate({
|
||||||
|
input: {
|
||||||
|
projectId: senderModelCard.projectId,
|
||||||
|
ingestionId,
|
||||||
|
cancellationMessage
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.errors?.length) {
|
||||||
|
const msg = res.errors[0].message
|
||||||
|
store.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Error',
|
||||||
|
description: msg
|
||||||
|
})
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { activeIngestions } = storeToRefs(store)
|
||||||
|
|
||||||
|
// clean the cancelled ingestion
|
||||||
|
activeIngestions.value = Object.fromEntries(
|
||||||
|
Object.entries(activeIngestions.value).filter(
|
||||||
|
([key]) => key !== senderModelCard.modelCardId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const completeIngestionWithVersion = async (
|
||||||
|
senderModelCard: ISenderModelCard,
|
||||||
|
ingestionId: string,
|
||||||
|
rootObjectId: string
|
||||||
|
) => {
|
||||||
|
const client = accountStore.getAccountClient(senderModelCard.accountId)
|
||||||
|
const { mutate } = provideApolloClient(client)(() =>
|
||||||
|
useMutation(completeModelIngestionWithVersion)
|
||||||
|
)
|
||||||
|
|
||||||
|
const res = await mutate({
|
||||||
|
input: {
|
||||||
|
projectId: senderModelCard.projectId,
|
||||||
|
ingestionId,
|
||||||
|
rootObjectId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (res?.errors?.length) {
|
||||||
|
const msg = res.errors[0].message
|
||||||
|
store.setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Ingestion Error',
|
||||||
|
description: msg
|
||||||
|
})
|
||||||
|
throw new Error(msg)
|
||||||
|
}
|
||||||
|
|
||||||
|
const { activeIngestions } = storeToRefs(store)
|
||||||
|
|
||||||
|
// clean the completed ingestion
|
||||||
|
activeIngestions.value = Object.fromEntries(
|
||||||
|
Object.entries(activeIngestions.value).filter(
|
||||||
|
([key]) => key !== senderModelCard.modelCardId
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return res?.data?.projectMutations.modelIngestionMutations.completeWithVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
startIngestion,
|
||||||
|
updateIngestion,
|
||||||
|
failIngestion,
|
||||||
|
cancelIngestion,
|
||||||
|
completeIngestionWithVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,86 @@
|
|||||||
|
import { graphql } from '~~/lib/common/generated/gql'
|
||||||
|
|
||||||
|
export const createModelIngestion = graphql(`
|
||||||
|
mutation CreateModelIngestion($input: ModelIngestionCreateInput!) {
|
||||||
|
projectMutations {
|
||||||
|
modelIngestionMutations {
|
||||||
|
create(input: $input) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
export const updateModelIngestionProgress = graphql(`
|
||||||
|
mutation UpdateModelIngestionProgress($input: ModelIngestionUpdateInput!) {
|
||||||
|
projectMutations {
|
||||||
|
modelIngestionMutations {
|
||||||
|
updateProgress(input: $input) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
export const completeModelIngestionWithVersion = graphql(`
|
||||||
|
mutation CompleteModelIngestionWithVersion($input: ModelIngestionSuccessInput!) {
|
||||||
|
projectMutations {
|
||||||
|
modelIngestionMutations {
|
||||||
|
completeWithVersion(input: $input) {
|
||||||
|
id
|
||||||
|
statusData {
|
||||||
|
__typename
|
||||||
|
... on ModelIngestionProcessingStatus {
|
||||||
|
status
|
||||||
|
progressMessage
|
||||||
|
progress
|
||||||
|
}
|
||||||
|
... on ModelIngestionSuccessStatus {
|
||||||
|
status
|
||||||
|
versionId
|
||||||
|
}
|
||||||
|
... on ModelIngestionFailedStatus {
|
||||||
|
errorStacktrace
|
||||||
|
errorReason
|
||||||
|
status
|
||||||
|
}
|
||||||
|
... on ModelIngestionCancelledStatus {
|
||||||
|
cancellationMessage
|
||||||
|
status
|
||||||
|
}
|
||||||
|
... on ModelIngestionQueuedStatus {
|
||||||
|
progressMessage
|
||||||
|
status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
export const failModelIngestionWithError = graphql(`
|
||||||
|
mutation FailModelIngestionWithError($input: ModelIngestionFailedInput!) {
|
||||||
|
projectMutations {
|
||||||
|
modelIngestionMutations {
|
||||||
|
failWithError(input: $input) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
export const failModelIngestionWithCancel = graphql(`
|
||||||
|
mutation FailModelIngestionWithCancel($input: ModelIngestionCancelledInput!) {
|
||||||
|
projectMutations {
|
||||||
|
modelIngestionMutations {
|
||||||
|
failWithCancel(input: $input) {
|
||||||
|
id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
import { graphql } from '~~/lib/common/generated/gql'
|
||||||
|
|
||||||
|
export const canCreateModelIngestionQuery = graphql(`
|
||||||
|
query CanCreateIngestion($modelId: String!, $projectId: String!) {
|
||||||
|
project(id: $projectId) {
|
||||||
|
model(id: $modelId) {
|
||||||
|
permissions {
|
||||||
|
canCreateIngestion {
|
||||||
|
authorized
|
||||||
|
code
|
||||||
|
message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
@@ -15,6 +15,7 @@ export type ModelCardNotification = {
|
|||||||
name: string
|
name: string
|
||||||
tooltipText?: string
|
tooltipText?: string
|
||||||
action: () => void
|
action: () => void
|
||||||
|
disabled?: boolean
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* If set, will display a view report button next to cta
|
* If set, will display a view report button next to cta
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import { graphql } from '~~/lib/common/generated/gql'
|
||||||
|
|
||||||
|
export const workspacePlanUsageUpdatedSubscription = graphql(`
|
||||||
|
subscription WorkspacePlanUsageUpdated($input: WorkspacePlanUsageSubscriptionInput!) {
|
||||||
|
workspacePlanUsageUpdated(input: $input)
|
||||||
|
}
|
||||||
|
`)
|
||||||
@@ -294,6 +294,14 @@ export const useAccountStore = defineStore('accountStore', () => {
|
|||||||
if (accountMatchWithServerUrl) return accountMatchWithServerUrl
|
if (accountMatchWithServerUrl) return accountMatchWithServerUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getAccountClient = (accountId: string) => {
|
||||||
|
return (
|
||||||
|
accounts.value.find(
|
||||||
|
(account) => account.accountInfo.id === accountId
|
||||||
|
) as DUIAccount
|
||||||
|
).client
|
||||||
|
}
|
||||||
|
|
||||||
const provideClients = () => {
|
const provideClients = () => {
|
||||||
provideApolloClients(apolloClients)
|
provideApolloClients(apolloClients)
|
||||||
}
|
}
|
||||||
@@ -320,6 +328,7 @@ export const useAccountStore = defineStore('accountStore', () => {
|
|||||||
return {
|
return {
|
||||||
isLoading,
|
isLoading,
|
||||||
accounts,
|
accounts,
|
||||||
|
getAccountClient,
|
||||||
defaultAccount,
|
defaultAccount,
|
||||||
activeAccount,
|
activeAccount,
|
||||||
userSelectedAccount,
|
userSelectedAccount,
|
||||||
|
|||||||
+145
-9
@@ -14,6 +14,7 @@ import type {
|
|||||||
SendFilterSelect
|
SendFilterSelect
|
||||||
} from '~/lib/models/card/send'
|
} from '~/lib/models/card/send'
|
||||||
import type { ToastNotification } from '@speckle/ui-components'
|
import type { ToastNotification } from '@speckle/ui-components'
|
||||||
|
import { ToastNotificationType } from '@speckle/ui-components'
|
||||||
import type { Nullable } from '@speckle/shared'
|
import type { Nullable } from '@speckle/shared'
|
||||||
import type { HostAppError } from '~/lib/bridge/errorHandler'
|
import type { HostAppError } from '~/lib/bridge/errorHandler'
|
||||||
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
||||||
@@ -28,6 +29,8 @@ import {
|
|||||||
import { provideApolloClient, useMutation } from '@vue/apollo-composable'
|
import { provideApolloClient, useMutation } from '@vue/apollo-composable'
|
||||||
import { createVersionMutation } from '~/lib/graphql/mutationsAndQueries'
|
import { createVersionMutation } from '~/lib/graphql/mutationsAndQueries'
|
||||||
import type { BaseBridge } from '~/lib/bridge/base'
|
import type { BaseBridge } from '~/lib/bridge/base'
|
||||||
|
import { useModelIngestion } from '~/lib/ingestion/composables/useModelIngestion'
|
||||||
|
import { useCheckGraphql } from '~/lib/core/composables/useCheckGraphql'
|
||||||
|
|
||||||
export type ProjectModelGroup = {
|
export type ProjectModelGroup = {
|
||||||
projectId: string
|
projectId: string
|
||||||
@@ -43,7 +46,13 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
const { $openUrl } = useNuxtApp()
|
const { $openUrl } = useNuxtApp()
|
||||||
const accountsStore = useAccountStore()
|
const accountsStore = useAccountStore()
|
||||||
const { checkUpdate } = useUpdateConnector()
|
const { checkUpdate } = useUpdateConnector()
|
||||||
|
const {
|
||||||
|
startIngestion,
|
||||||
|
updateIngestion,
|
||||||
|
failIngestion,
|
||||||
|
cancelIngestion,
|
||||||
|
completeIngestionWithVersion
|
||||||
|
} = useModelIngestion()
|
||||||
const isDistributedBySpeckle = ref<boolean>(true)
|
const isDistributedBySpeckle = ref<boolean>(true)
|
||||||
const latestAvailableVersion = ref<Version | null>(null)
|
const latestAvailableVersion = ref<Version | null>(null)
|
||||||
|
|
||||||
@@ -65,6 +74,9 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
// Different host apps can have different kind of ISendFilterSelect send filters, and we collect them here to generalize the component we use in `ListSelect`
|
// Different host apps can have different kind of ISendFilterSelect send filters, and we collect them here to generalize the component we use in `ListSelect`
|
||||||
const availableSelectSendFilters = ref<Record<string, SendFilterSelect>>({})
|
const availableSelectSendFilters = ref<Record<string, SendFilterSelect>>({})
|
||||||
|
|
||||||
|
// kvp for modelCardId - ingestionId
|
||||||
|
const activeIngestions = ref<Record<string, string>>({})
|
||||||
|
|
||||||
const dismissNotification = () => {
|
const dismissNotification = () => {
|
||||||
currentNotification.value = null
|
currentNotification.value = null
|
||||||
}
|
}
|
||||||
@@ -95,6 +107,11 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
isDistributedBySpeckle.value = val
|
isDistributedBySpeckle.value = val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shouldHandleIngestion = computed(() => {
|
||||||
|
const hostAppsThatUsesDUIForGraphql = ['sketchup', 'archicad', 'Vectorworks']
|
||||||
|
return hostAppsThatUsesDUIForGraphql.includes(hostAppName.value as string)
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model Card Operations
|
* Model Card Operations
|
||||||
*/
|
*/
|
||||||
@@ -281,6 +298,44 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
const account = accountStore.accounts.find(
|
const account = accountStore.accounts.find(
|
||||||
(acc) => acc.accountInfo.id === args.accountId
|
(acc) => acc.accountInfo.id === args.accountId
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Check if we have an ingestion ID for this model.
|
||||||
|
// If so, we are in the "New Business Model" flow and should use completeIngestionWithVersion.
|
||||||
|
const modelCard = documentModelStore.value.models.find(
|
||||||
|
(m) => m.modelId === args.modelId && m.projectId === args.projectId
|
||||||
|
) as ISenderModelCard
|
||||||
|
|
||||||
|
const { canCreateModelIngestion } = useCheckGraphql()
|
||||||
|
const canCreateIngestion = await canCreateModelIngestion(
|
||||||
|
args.projectId,
|
||||||
|
args.modelId,
|
||||||
|
args.accountId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (canCreateIngestion.queryAvailable) {
|
||||||
|
const ingestionId = modelCard
|
||||||
|
? activeIngestions.value[modelCard.modelCardId]
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
if (ingestionId && modelCard) {
|
||||||
|
try {
|
||||||
|
await completeIngestionWithVersion(
|
||||||
|
modelCard,
|
||||||
|
ingestionId,
|
||||||
|
args.referencedObjectId
|
||||||
|
)
|
||||||
|
} catch (err) {
|
||||||
|
console.error(`completeIngestionWithVersion failed: ${err}`)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setNotification({
|
||||||
|
type: ToastNotificationType.Danger,
|
||||||
|
title: 'Publish Error',
|
||||||
|
description: 'Could not complete publish: Ingestion ID missing.'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Fallback to legacy flow (Old Server)
|
||||||
try {
|
try {
|
||||||
const createVersion = provideApolloClient((account as DUIAccount).client)(() =>
|
const createVersion = provideApolloClient((account as DUIAccount).client)(() =>
|
||||||
useMutation(createVersionMutation)
|
useMutation(createVersionMutation)
|
||||||
@@ -296,6 +351,7 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(`triggerCreateVersion is failed: ${err}`)
|
console.error(`triggerCreateVersion is failed: ${err}`)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -318,10 +374,57 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
* Tells the host app to start sending a specific model card. This will reach inside the host application.
|
* Tells the host app to start sending a specific model card. This will reach inside the host application.
|
||||||
* @param modelId
|
* @param modelId
|
||||||
*/
|
*/
|
||||||
const sendModel = (modelCardId: string, actionSource: string) => {
|
const sendModel = async (modelCardId: string, actionSource: string) => {
|
||||||
const model = documentModelStore.value.models.find(
|
const model = documentModelStore.value.models.find(
|
||||||
(m) => m.modelCardId === modelCardId
|
(m) => m.modelCardId === modelCardId
|
||||||
) as ISenderModelCard
|
) as ISenderModelCard
|
||||||
|
const { canCreateModelIngestion, canCreateVersion } = useCheckGraphql()
|
||||||
|
const canCreateIngestion = await canCreateModelIngestion(
|
||||||
|
model.projectId,
|
||||||
|
model.modelId,
|
||||||
|
model.accountId
|
||||||
|
)
|
||||||
|
|
||||||
|
// for the connectors that don't have SDK to handle graqhql
|
||||||
|
if (shouldHandleIngestion.value && canCreateIngestion.queryAvailable) {
|
||||||
|
const sourceData = {
|
||||||
|
sourceApplicationSlug: hostAppName.value || 'unknown',
|
||||||
|
sourceApplicationVersion: hostAppVersion.value?.toString() || 'unknown'
|
||||||
|
}
|
||||||
|
if (canCreateIngestion.authorized) {
|
||||||
|
await startIngestion(model, 'Starting to publish', sourceData)
|
||||||
|
model.progress = { status: 'Converting the objects...' }
|
||||||
|
} else {
|
||||||
|
setNotification({
|
||||||
|
type: ToastNotificationType.Warning,
|
||||||
|
title: 'Cannot publish',
|
||||||
|
description: canCreateIngestion.message
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// for the self hosters that does not have available graphql for ingestions
|
||||||
|
const canCreate = await canCreateVersion(
|
||||||
|
model.projectId,
|
||||||
|
model.modelId,
|
||||||
|
model.accountId
|
||||||
|
)
|
||||||
|
if (!canCreate.authorized) {
|
||||||
|
setNotification({
|
||||||
|
type: ToastNotificationType.Warning,
|
||||||
|
title: 'Cannot publish',
|
||||||
|
description: canCreate.message || 'Workspace limits have been reached'
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
model.latestCreatedVersionId = undefined
|
||||||
|
model.error = undefined
|
||||||
|
model.progress = { status: 'Starting to send...' }
|
||||||
|
model.expired = false
|
||||||
|
model.report = undefined
|
||||||
|
|
||||||
if (model.expired) {
|
if (model.expired) {
|
||||||
// user sends via "Update" button
|
// user sends via "Update" button
|
||||||
void trackEvent(
|
void trackEvent(
|
||||||
@@ -346,11 +449,7 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
model.accountId
|
model.accountId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
model.latestCreatedVersionId = undefined
|
|
||||||
model.error = undefined
|
|
||||||
model.progress = { status: 'Starting to send...' }
|
|
||||||
model.expired = false
|
|
||||||
model.report = undefined
|
|
||||||
// You should stop asking why if you saw anything related autocad..
|
// You should stop asking why if you saw anything related autocad..
|
||||||
// It solves the press "escape" issue.
|
// It solves the press "escape" issue.
|
||||||
// Because probably we don't give enough time to acad complete it's previos task and it stucks.
|
// Because probably we don't give enough time to acad complete it's previos task and it stucks.
|
||||||
@@ -377,6 +476,14 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
model.error = undefined
|
model.error = undefined
|
||||||
void trackEvent('DUI3 Action', { name: 'Send Cancel' }, model.accountId)
|
void trackEvent('DUI3 Action', { name: 'Send Cancel' }, model.accountId)
|
||||||
model.latestCreatedVersionId = undefined
|
model.latestCreatedVersionId = undefined
|
||||||
|
|
||||||
|
// Cancel the ingestion if applicable
|
||||||
|
if (shouldHandleIngestion.value) {
|
||||||
|
const ingestionId = activeIngestions.value[modelCardId]
|
||||||
|
if (ingestionId) {
|
||||||
|
await cancelIngestion(model, ingestionId, 'Cancelled by user')
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
app.$sendBinding?.on('setModelsExpired', (modelCardIds) => {
|
app.$sendBinding?.on('setModelsExpired', (modelCardIds) => {
|
||||||
@@ -479,7 +586,7 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
app.$receiveBinding?.on('setModelReceiveResult', setModelReceiveResult)
|
app.$receiveBinding?.on('setModelReceiveResult', setModelReceiveResult)
|
||||||
|
|
||||||
// GENERIC STUFF
|
// GENERIC STUFF
|
||||||
const handleModelProgressEvents = (args: {
|
const handleModelProgressEvents = async (args: {
|
||||||
modelCardId: string
|
modelCardId: string
|
||||||
progress?: ModelCardProgress
|
progress?: ModelCardProgress
|
||||||
}) => {
|
}) => {
|
||||||
@@ -487,9 +594,24 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
(m) => m.modelCardId === args.modelCardId
|
(m) => m.modelCardId === args.modelCardId
|
||||||
) as IModelCard
|
) as IModelCard
|
||||||
model.progress = args.progress
|
model.progress = args.progress
|
||||||
|
|
||||||
|
if (
|
||||||
|
model.typeDiscriminator.includes('SenderModelCard') &&
|
||||||
|
shouldHandleIngestion.value // for the connectors that don't have SDK to handle graqhql
|
||||||
|
) {
|
||||||
|
const ingestionId = activeIngestions.value[args.modelCardId]
|
||||||
|
if (ingestionId) {
|
||||||
|
await updateIngestion(
|
||||||
|
model,
|
||||||
|
ingestionId,
|
||||||
|
args.progress?.status || 'Progressing',
|
||||||
|
args.progress?.progress || 0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const setModelError = (args: {
|
const setModelError = async (args: {
|
||||||
modelCardId: string
|
modelCardId: string
|
||||||
error: string | { errorMessage: string; dismissible?: boolean }
|
error: string | { errorMessage: string; dismissible?: boolean }
|
||||||
}) => {
|
}) => {
|
||||||
@@ -505,6 +627,19 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
dismissible: boolean
|
dismissible: boolean
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fail the ingestion if applicable
|
||||||
|
if (
|
||||||
|
model.typeDiscriminator.includes('SenderModelCard') &&
|
||||||
|
shouldHandleIngestion.value
|
||||||
|
) {
|
||||||
|
const ingestionId = activeIngestions.value[args.modelCardId]
|
||||||
|
if (ingestionId) {
|
||||||
|
const errorMessage =
|
||||||
|
typeof args.error === 'string' ? args.error : args.error.errorMessage
|
||||||
|
await failIngestion(model as ISenderModelCard, ingestionId, errorMessage)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: all bindings that need to send these model events should register.
|
// NOTE: all bindings that need to send these model events should register.
|
||||||
@@ -750,6 +885,7 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
|||||||
hostAppName,
|
hostAppName,
|
||||||
hostAppVersion,
|
hostAppVersion,
|
||||||
connectorVersion,
|
connectorVersion,
|
||||||
|
activeIngestions,
|
||||||
isConnectorUpToDate,
|
isConnectorUpToDate,
|
||||||
latestAvailableVersion,
|
latestAvailableVersion,
|
||||||
documentInfo,
|
documentInfo,
|
||||||
|
|||||||
Reference in New Issue
Block a user