Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 65a9d3e485 | |||
| be631746b9 | |||
| 20c43f2108 | |||
| af0de85ef7 | |||
| 7c54845a05 | |||
| cbec244443 | |||
| a2a9ab1f4b | |||
| 2f87c34272 | |||
| 7fde35e639 | |||
| 97765d84ca | |||
| 9d15be73ad | |||
| 45f763a2ce | |||
| 3c6bda7af9 | |||
| 007794dae2 | |||
| f8912338cb | |||
| f932fa46a3 | |||
| 292d2bf0bb | |||
| 43340d9b52 | |||
| 4898a9e2e9 | |||
| 19b982e2e3 | |||
| e3cf896c14 | |||
| 34d855212f | |||
| 8d159547d4 | |||
| 0c3ee8b38f | |||
| c51f282644 | |||
| 1faea0aec2 | |||
| 5e97acf4c0 | |||
| 9c7413d630 | |||
| 89acd7ca80 | |||
| 2e51a2fb3c | |||
| 644754262c | |||
| b28129c30e | |||
| 305ad36cac | |||
| 554d0ee478 | |||
| 33fd9c65e3 | |||
| ebaee49fe8 | |||
| b877c1d321 | |||
| be4dc87b3e | |||
| 94ddc486aa | |||
| ac5984d184 | |||
| 8dae170592 | |||
| d6f371c7d2 | |||
| cbf9e8d578 | |||
| 6f10519e6f | |||
| 590b8b8872 | |||
| 2514b6c606 | |||
| af37112a5f | |||
| d224b33bc8 | |||
| 377cfc2f65 | |||
| fdd13170f5 | |||
| e70310654b | |||
| 8bb14d3389 | |||
| 93e4762b6a | |||
| 21a4bd4076 | |||
| 82c95aab58 | |||
| fe77ede49e | |||
| f70915f485 |
+1
-1
@@ -1,4 +1,4 @@
|
||||
HOST=0.0.0.0
|
||||
HOST=127.0.0.1
|
||||
PORT=8082
|
||||
|
||||
NUXT_PUBLIC_MIXPANEL_TOKEN_ID=acd87c5a50b56df91a795e999812a3a4
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,44 @@
|
||||
name: Linting
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
lint-and-build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '22.14.0'
|
||||
|
||||
- name: Enable Corepack and Install Correct Yarn Version
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare yarn@$(jq -r .packageManager package.json | cut -d'@' -f2) --activate
|
||||
yarn --version
|
||||
|
||||
- name: Cache node_modules
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
**/node_modules
|
||||
.yarn/cache
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install Dependencies
|
||||
run: yarn install --immutable
|
||||
|
||||
- name: Run Linter
|
||||
run: yarn lint
|
||||
|
||||
- name: Run generate
|
||||
run: yarn generate
|
||||
@@ -0,0 +1,35 @@
|
||||
node_modules
|
||||
build
|
||||
dist
|
||||
dist2
|
||||
dist-*
|
||||
coverage
|
||||
.nyc_output
|
||||
|
||||
.output
|
||||
.nuxt
|
||||
**/nuxt-modules/**/templates/*.js
|
||||
/lib/common/generated/**/*
|
||||
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
.yarn
|
||||
|
||||
# Profiler output
|
||||
events.json
|
||||
|
||||
# Prettier doesn't understand the syntax inside the Yaml files, because of the brackets
|
||||
utils/helm/speckle-server/templates
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
.venv
|
||||
venv
|
||||
|
||||
.*.{ts,js,vue,tsx,jsx}
|
||||
**/generated/**/*
|
||||
**/generated/graphql.ts
|
||||
|
||||
storybook-static
|
||||
.tshy
|
||||
.tshy-build
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"trailingComma": "none",
|
||||
"tabWidth": 2,
|
||||
"semi": false,
|
||||
"endOfLine": "auto",
|
||||
"bracketSpacing": true,
|
||||
"vueIndentScriptAndStyle": false,
|
||||
"htmlWhitespaceSensitivity": "ignore",
|
||||
"printWidth": 88,
|
||||
"singleQuote": true
|
||||
}
|
||||
Vendored
+16
-16
@@ -1,18 +1,18 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"Vue.volar",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"stylelint.vscode-stylelint",
|
||||
"cpylua.language-postcss",
|
||||
"graphql.vscode-graphql",
|
||||
"graphql.vscode-graphql-syntax"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": ["octref.vetur"]
|
||||
}
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"esbenp.prettier-vscode",
|
||||
"Vue.volar",
|
||||
"bradlc.vscode-tailwindcss",
|
||||
"stylelint.vscode-stylelint",
|
||||
"cpylua.language-postcss",
|
||||
"graphql.vscode-graphql",
|
||||
"graphql.vscode-graphql-syntax"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": ["octref.vetur"]
|
||||
}
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
nodeLinker: node-modules
|
||||
nodeLinker: node-modules
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# dui3
|
||||
# Speckle Connectors DUI
|
||||
|
||||
DUIv3 is a Speckle interface embedded inside the desktop connectors that allows users to interact with them - sync streams, manage servers etc. It's built in Vue 3 with Nuxt 3 and only supports client side rendering.
|
||||
DUI v3 is a Speckle interface embedded inside the desktop connectors that allows users to interact with them - sync streams, manage servers etc. It's built in Vue 3 with Nuxt 3 and only supports client side rendering.
|
||||
|
||||
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||
|
||||
@@ -15,12 +15,12 @@ yarn install
|
||||
|
||||
And create an `.env` file from `.env.example`.
|
||||
|
||||
## Development Server
|
||||
## Development
|
||||
|
||||
Start the development server on `http://localhost:3000`
|
||||
Start the development server on `http://localhost:8082`
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
yarn dev
|
||||
```
|
||||
|
||||
## Production
|
||||
@@ -28,13 +28,7 @@ npm run dev
|
||||
Build the application for production:
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
Locally preview production build:
|
||||
|
||||
```bash
|
||||
npm run preview
|
||||
yarn build
|
||||
```
|
||||
|
||||
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information...
|
||||
|
||||
@@ -13,15 +13,19 @@
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { useConfigStore } from '~/store/config'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const uiConfigStore = useConfigStore()
|
||||
const { isDarkTheme } = storeToRefs(uiConfigStore)
|
||||
const hostAppStore = useHostAppStore()
|
||||
const { connectorVersion, hostAppName, hostAppVersion } = storeToRefs(hostAppStore)
|
||||
|
||||
useHead({
|
||||
// Title suffix
|
||||
titleTemplate: (titleChunk) =>
|
||||
titleChunk ? `${titleChunk as string} - Speckle DUIv3` : 'Speckle DUIv3',
|
||||
title: computed(
|
||||
() =>
|
||||
`CNX: (hostApp: ${hostAppName.value}:v${hostAppVersion.value}),(version: ${connectorVersion.value})`
|
||||
),
|
||||
htmlAttrs: {
|
||||
lang: 'en',
|
||||
class: computed(() => (isDarkTheme.value ? `dark` : ``))
|
||||
@@ -50,6 +54,8 @@ onMounted(() => {
|
||||
uniqueEmails.add(email)
|
||||
}
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const { $intercom } = useNuxtApp() // needed her for initialisation
|
||||
})
|
||||
</script>
|
||||
<style></style>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/* stylelint-disable selector-id-pattern */
|
||||
@import '@speckle/ui-components/style.css';
|
||||
@import url('@speckle/ui-components/style.css');
|
||||
|
||||
@tailwind base;
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
import type { CodegenConfig } from '@graphql-codegen/cli'
|
||||
|
||||
const config: CodegenConfig = {
|
||||
schema: 'http://127.0.0.1:3000/graphql',
|
||||
schema: 'https://app.speckle.systems/graphql',
|
||||
documents: ['{lib,components,layouts,pages,middleware}/**/*.{vue,js,ts}'],
|
||||
ignoreNoDocuments: true, // for better experience with the watcher
|
||||
generates: {
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<script setup lang="ts">
|
||||
import type { DUIAccount } from '~~/store/accounts'
|
||||
import { TrashIcon } from '@heroicons/vue/24/outline'
|
||||
import { type BaseBridge } from '~/lib/bridge/base'
|
||||
import type { BaseBridge } from '~/lib/bridge/base'
|
||||
|
||||
const { $accountBinding } = useNuxtApp()
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
mount-menu-on-body
|
||||
>
|
||||
<template #something-selected="{ value }">
|
||||
<span>{{ value.name }}</span>
|
||||
<span>{{ isArray(value) ? value[0].name : value.name }}</span>
|
||||
</template>
|
||||
<template #option="{ item }">
|
||||
<div class="flex items-center">
|
||||
@@ -80,10 +80,11 @@ import {
|
||||
createAutomationMutation
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
import { provideApolloClient, useMutation, useQuery } from '@vue/apollo-composable'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useAccountStore, type DUIAccount } from '~/store/accounts'
|
||||
import type { ApolloError } from '@apollo/client/errors'
|
||||
import { formatVersionParams } from '~/lib/common/helpers/jsonSchema'
|
||||
import { useJsonFormsChangeHandler } from '~/lib/core/composables/jsonSchema'
|
||||
import { isArray } from 'lodash-es'
|
||||
|
||||
const props = defineProps<{
|
||||
projectId: string
|
||||
@@ -106,7 +107,7 @@ const toggleDialog = () => {
|
||||
showAutomateDialog.value = !showAutomateDialog.value
|
||||
}
|
||||
|
||||
const { mutate } = provideApolloClient(activeAccount.value.client)(() =>
|
||||
const { mutate } = provideApolloClient((activeAccount.value as DUIAccount).client)(() =>
|
||||
useMutation(createAutomationMutation)
|
||||
)
|
||||
|
||||
|
||||
@@ -9,7 +9,13 @@
|
||||
<Component :is="iconAndColor.icon" :class="`w-4 h-4 ${iconAndColor.color}`" />
|
||||
</div>
|
||||
<div :class="`text-xs ${iconAndColor.color}`">
|
||||
{{ result.category }}: {{ result.objectIds.length }} affected elements
|
||||
{{ result.category }}:
|
||||
{{
|
||||
'objectIds' in props.result
|
||||
? props.result.objectIds.length
|
||||
: props.result.objectAppIds.length
|
||||
}}
|
||||
affected elements
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="result.message" class="text-xs text-foreground-2 pl-5">
|
||||
@@ -19,16 +25,13 @@
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import {
|
||||
XMarkIcon,
|
||||
InformationCircleIcon,
|
||||
ExclamationTriangleIcon
|
||||
} from '@heroicons/vue/24/outline'
|
||||
import type { Automate } from '@speckle/shared'
|
||||
import { objectQuery } from '~/lib/graphql/mutationsAndQueries'
|
||||
import type { IModelCard } from '~/lib/models/card'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
|
||||
type ObjectResult = Automate.AutomateTypes.ResultsSchema['values']['objectResults'][0]
|
||||
|
||||
@@ -37,38 +40,12 @@ const props = defineProps<{
|
||||
result: ObjectResult
|
||||
functionId?: string
|
||||
}>()
|
||||
|
||||
const accStore = useAccountStore()
|
||||
const app = useNuxtApp()
|
||||
const projectAccount = computed(() =>
|
||||
accStore.accountWithFallback(props.modelCard.accountId, props.modelCard.serverUrl)
|
||||
)
|
||||
const clientId = projectAccount.value.accountInfo.id
|
||||
|
||||
const applicationIds = ref<string[]>([])
|
||||
|
||||
type Data = {
|
||||
applicationId?: string
|
||||
}
|
||||
|
||||
// Loop over each objectId to run the query and collect application IDs
|
||||
props.result.objectIds.forEach((objectId) => {
|
||||
const { result: objectResult } = useQuery(
|
||||
objectQuery,
|
||||
() => ({
|
||||
projectId: props.modelCard.projectId,
|
||||
objectId
|
||||
}),
|
||||
() => ({ clientId })
|
||||
)
|
||||
|
||||
watch(objectResult, (newValue) => {
|
||||
const data = newValue?.project.object?.data as Data | undefined
|
||||
const applicationId = data?.applicationId
|
||||
if (applicationId && !applicationIds.value.includes(applicationId)) {
|
||||
applicationIds.value.push(applicationId)
|
||||
}
|
||||
})
|
||||
const applicationIds = computed(() => {
|
||||
// Old schema ignore
|
||||
if ('objectIds' in props.result) return []
|
||||
return Object.values(props.result.objectAppIds).filter((id) => id !== null)
|
||||
})
|
||||
|
||||
const handleClick = async () => {
|
||||
|
||||
@@ -329,6 +329,7 @@ onUnmounted(() => {
|
||||
html.dialog-open {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
html.dialog-open body {
|
||||
overflow: hidden !important;
|
||||
}
|
||||
|
||||
@@ -17,9 +17,21 @@
|
||||
</div>
|
||||
<div class="flex items-center group">
|
||||
<FormButton
|
||||
v-if="notification.cta"
|
||||
v-if="notification.secondaryCta"
|
||||
v-tippy="notification.secondaryCta.tooltipText"
|
||||
size="sm"
|
||||
:color="notification.level === 'info' ? 'outline' : notification.level"
|
||||
color="outline"
|
||||
full-width
|
||||
class="mr-1"
|
||||
@click.stop="notification.secondaryCta.action"
|
||||
>
|
||||
{{ notification.secondaryCta.name }}
|
||||
</FormButton>
|
||||
<FormButton
|
||||
v-if="notification.cta"
|
||||
v-tippy="notification.cta.tooltipText"
|
||||
size="sm"
|
||||
color="primary"
|
||||
full-width
|
||||
@click.stop="notification.cta?.action"
|
||||
>
|
||||
@@ -59,6 +71,21 @@ if (props.notification.timeout) {
|
||||
useTimeoutFn(() => emit('dismiss'), props.notification.timeout)
|
||||
}
|
||||
|
||||
// const notificationButtonColor = (notificationLevel: ModelCardNotificationLevel) => {
|
||||
// switch (notificationLevel) {
|
||||
// case 'info':
|
||||
// return 'outline'
|
||||
// case 'danger':
|
||||
// return 'danger'
|
||||
// case 'success':
|
||||
// return 'primary'
|
||||
// case 'warning':
|
||||
// return 'danger'
|
||||
// default:
|
||||
// return 'outline'
|
||||
// }
|
||||
// }
|
||||
|
||||
const textClassColor = computed(() => {
|
||||
switch (props.notification.level) {
|
||||
case 'danger':
|
||||
|
||||
@@ -18,18 +18,24 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="opacity-0 group-hover:opacity-100 transition flex">
|
||||
<div
|
||||
:class="
|
||||
isPersonalProject ? '' : 'opacity-0 group-hover:opacity-100 transition flex'
|
||||
"
|
||||
>
|
||||
<button
|
||||
v-tippy="'Open project in browser'"
|
||||
class="hover:text-primary flex items-center space-x-2 p-2"
|
||||
v-tippy="projectNavigatorTippy"
|
||||
class="hover:text-primary flex items-center space-x-2 p-2 relative animate-pulse"
|
||||
>
|
||||
<ArrowTopRightOnSquareIcon
|
||||
class="w-4"
|
||||
@click.stop="
|
||||
$openUrl(projectUrl),
|
||||
trackEvent('DUI3 Action', { name: 'Project View' }, project.accountId)
|
||||
"
|
||||
/>
|
||||
<div class="relative w-4 h-4">
|
||||
<ArrowTopRightOnSquareIcon
|
||||
class="w-4 h-4"
|
||||
@click.stop="
|
||||
$openUrl(projectUrl),
|
||||
trackEvent('DUI3 Action', { name: 'Project View' }, project.accountId)
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
@@ -130,6 +136,13 @@ const projectAccount = computed(() =>
|
||||
accountStore.accountWithFallback(props.project.accountId, props.project.serverUrl)
|
||||
)
|
||||
|
||||
const isPersonalProject = computed(() => !projectDetails.value?.workspace)
|
||||
const projectNavigatorTippy = computed(() =>
|
||||
isPersonalProject.value
|
||||
? 'Move personal project into a workspace'
|
||||
: 'Open project in browser'
|
||||
)
|
||||
|
||||
const clientId = projectAccount.value.accountInfo.id
|
||||
|
||||
const { result: projectDetailsResult, refetch: refetchProjectDetails } = useQuery(
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
color="neutral"
|
||||
size="xs"
|
||||
hide-icon
|
||||
class="mb-2 mt-1"
|
||||
class="mt-1"
|
||||
>
|
||||
<template #description>
|
||||
<div class="flex items-center">
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import type { IDirectSelectionSendFilter, ISendFilter } from 'lib/models/card/send'
|
||||
import type { IDirectSelectionSendFilter, ISendFilter } from '~/lib/models/card/send'
|
||||
import { useHostAppStore } from '~~/store/hostApp'
|
||||
import { useSelectionStore } from '~~/store/selection'
|
||||
|
||||
|
||||
@@ -12,8 +12,11 @@
|
||||
full-width
|
||||
color="foundation"
|
||||
/>
|
||||
<FormButton color="outline" size="sm" @click="selectAllCategories">
|
||||
{{ allSelected ? 'Deselect all' : 'Select all' }}
|
||||
</FormButton>
|
||||
</div>
|
||||
<div class="flex space-y-1 flex-col">
|
||||
<div class="flex space-y-1 flex-col max-h-48 simple-scrollbar overflow-auto">
|
||||
<div
|
||||
v-for="cat in selectedCategoriesObjects.sort((a, b) =>
|
||||
a.name.localeCompare(b.name)
|
||||
@@ -93,6 +96,25 @@ const searchResults = computed(() => {
|
||||
|
||||
const selectedCategories = ref<string[]>(props.filter.selectedCategories || [])
|
||||
|
||||
const selectAllCategories = () => {
|
||||
if (allSelected.value) {
|
||||
selectedCategories.value = []
|
||||
return
|
||||
}
|
||||
availableCategories.value.forEach((cat) => {
|
||||
const index = selectedCategories.value.indexOf(cat.id)
|
||||
if (index !== -1) {
|
||||
return
|
||||
} else {
|
||||
selectedCategories.value.push(cat.id)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const allSelected = computed(() => {
|
||||
return availableCategories.value.length === selectedCategories.value.length
|
||||
})
|
||||
|
||||
const selectOrUnselectCategory = (id: string) => {
|
||||
const index = selectedCategories.value.indexOf(id)
|
||||
if (index !== -1) {
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
class="w-4 text-foreground-disabled group-hover:text-foreground-2"
|
||||
/>
|
||||
</HeaderButton>
|
||||
<HeaderButton v-tippy="'Send us feedback'" @click="showFeedbackDialog = true">
|
||||
<HeaderButton v-tippy="'Send us feedback'" @click="openFeedbackDialog()">
|
||||
<ChatBubbleLeftIcon
|
||||
class="w-4 text-foreground-disabled group-hover:text-foreground-2"
|
||||
/>
|
||||
@@ -99,4 +99,17 @@ app.$baseBinding.on('documentChanged', () => {
|
||||
showSendDialog.value = false
|
||||
showReceiveDialog.value = false
|
||||
})
|
||||
|
||||
const { $intercom } = useNuxtApp()
|
||||
|
||||
const openFeedbackDialog = () => {
|
||||
if (
|
||||
hostAppStore.hostAppName?.toLowerCase() === 'revit' &&
|
||||
hostAppStore.hostAppVersion?.includes('2022')
|
||||
) {
|
||||
showFeedbackDialog.value = true
|
||||
} else {
|
||||
$intercom.show()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -159,7 +159,7 @@
|
||||
>
|
||||
<UserAvatarGroup
|
||||
size="xs"
|
||||
:users="[latestCommentNotification.comment?.author]"
|
||||
:users="[latestCommentNotification.comment?.author as AvatarUserWithId]"
|
||||
/>
|
||||
<span class="line-clamp-1">
|
||||
{{ latestCommentNotification.comment?.author.name }} just left a
|
||||
@@ -208,6 +208,7 @@ import { useIntervalFn, useTimeoutFn } from '@vueuse/core'
|
||||
import type { ProjectCommentsUpdatedMessage } from '~/lib/common/generated/gql/graphql'
|
||||
import { useFunctionRunsStatusSummary } from '~/lib/automate/runStatus'
|
||||
import { CursorArrowRaysIcon, XCircleIcon } from '@heroicons/vue/24/outline'
|
||||
import type { AvatarUserWithId } from '@speckle/ui-components'
|
||||
|
||||
const app = useNuxtApp()
|
||||
const store = useHostAppStore()
|
||||
@@ -430,7 +431,8 @@ const { start: startCommentClearTimeout, stop: stopCommentClearTimeout } = useTi
|
||||
)
|
||||
|
||||
onCommentResult((res) => {
|
||||
latestCommentNotification.value = res.data?.projectCommentsUpdated
|
||||
latestCommentNotification.value = res.data
|
||||
?.projectCommentsUpdated as ProjectCommentsUpdatedMessage
|
||||
startCommentClearTimeout()
|
||||
})
|
||||
|
||||
|
||||
@@ -1,186 +0,0 @@
|
||||
<template>
|
||||
<div class="p-0">
|
||||
<slot name="activator" :toggle="toggleDialog"></slot>
|
||||
<CommonDialog
|
||||
v-model:open="showModelCreateDialog"
|
||||
:title="canCreateModelInWorkspace ? `Create new model` : errorMessage?.title"
|
||||
fullscreen="none"
|
||||
>
|
||||
<form v-if="canCreateModelInWorkspace" @submit="onSubmitCreateNewModel">
|
||||
<div class="text-body-2xs mb-2 ml-1">Model name</div>
|
||||
<FormTextInput
|
||||
v-model="newModelName"
|
||||
class="text-xs"
|
||||
autocomplete="off"
|
||||
name="name"
|
||||
label="Model name"
|
||||
color="foundation"
|
||||
:show-clear="!!newModelName"
|
||||
:placeholder="hostAppStore.documentInfo?.name"
|
||||
:rules="[
|
||||
ValidationHelpers.isRequired,
|
||||
ValidationHelpers.isStringOfLength({ minLength: 3 })
|
||||
]"
|
||||
full-width
|
||||
/>
|
||||
<div class="mt-4 flex justify-end items-center space-x-2 w-full">
|
||||
<FormButton size="sm" text @click="showModelCreateDialog = false">
|
||||
Cancel
|
||||
</FormButton>
|
||||
<FormButton size="sm" submit :disabled="isCreatingModel">Create</FormButton>
|
||||
</div>
|
||||
</form>
|
||||
<div v-else class="m-2">
|
||||
{{ errorMessage?.description }}
|
||||
<div class="flex mt-2 space-x-2 justify-end">
|
||||
<FormButton size="sm" color="outline" @click="showModelCreateDialog = false">
|
||||
Close
|
||||
</FormButton>
|
||||
<FormButton
|
||||
v-if="errorMessage?.cta"
|
||||
size="sm"
|
||||
submit
|
||||
@click="errorMessage?.cta?.action(), (showModelCreateDialog = false)"
|
||||
>
|
||||
{{ errorMessage?.cta?.name }}
|
||||
</FormButton>
|
||||
</div>
|
||||
</div>
|
||||
</CommonDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMutation, provideApolloClient, useQuery } from '@vue/apollo-composable'
|
||||
import type { ModelListModelItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { ValidationHelpers } from '@speckle/ui-components'
|
||||
import type { DUIAccount } from '~/store/accounts'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import {
|
||||
canCreateModelInProjectQuery,
|
||||
createModelMutation
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
|
||||
type WorkspacePermissionMessage = {
|
||||
title: string
|
||||
description: string
|
||||
cta?: {
|
||||
name: string
|
||||
action: () => void
|
||||
}
|
||||
}
|
||||
|
||||
const { $openUrl } = useNuxtApp()
|
||||
|
||||
const showModelCreateDialog = ref(false)
|
||||
const isCreatingModel = ref(false)
|
||||
|
||||
const props = defineProps<{
|
||||
projectId: string
|
||||
workspaceId?: string
|
||||
workspaceSlug?: string
|
||||
}>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'model:created', model: ModelListModelItemFragment): void
|
||||
}>()
|
||||
|
||||
const { trackEvent } = useMixpanel()
|
||||
const accountStore = useAccountStore()
|
||||
const hostAppStore = useHostAppStore()
|
||||
const { activeAccount } = storeToRefs(accountStore)
|
||||
|
||||
const accountId = computed(() => activeAccount.value.accountInfo.id)
|
||||
const newModelName = ref<string>()
|
||||
const errorMessage = ref<WorkspacePermissionMessage>()
|
||||
|
||||
const toggleDialog = () => {
|
||||
showModelCreateDialog.value = !showModelCreateDialog.value
|
||||
}
|
||||
|
||||
const account = computed(() => {
|
||||
return accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === accountId.value
|
||||
) as DUIAccount
|
||||
})
|
||||
|
||||
const canCreateModelInWorkspace = ref<boolean>()
|
||||
|
||||
const { result: canCreateModelInWorkspaceResult } = useQuery(
|
||||
canCreateModelInProjectQuery,
|
||||
() => ({ projectId: props.projectId }),
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
watch(canCreateModelInWorkspaceResult, (val) => {
|
||||
if (val?.project.permissions.canCreateModel.code !== 'OK') {
|
||||
switch (val?.project.permissions.canCreateModel.code) {
|
||||
case 'WorkspaceLimitsReached':
|
||||
errorMessage.value = {
|
||||
title: 'Plan limit reached',
|
||||
description:
|
||||
'The model limit for this workspace has been reached. Upgrade the workspace plan to create or move more models.',
|
||||
cta: {
|
||||
name: 'Explore Plans',
|
||||
action: () =>
|
||||
$openUrl(
|
||||
`${account.value.accountInfo.serverInfo.url}/settings/workspaces/${props.workspaceSlug}/billing`
|
||||
)
|
||||
}
|
||||
}
|
||||
break
|
||||
// TODO: we should add more cases later according to `code`
|
||||
default:
|
||||
errorMessage.value = {
|
||||
title: 'Workspace warning',
|
||||
description: val?.project.permissions.canCreateModel.message ?? 'error'
|
||||
}
|
||||
break
|
||||
}
|
||||
canCreateModelInWorkspace.value = false
|
||||
} else {
|
||||
canCreateModelInWorkspace.value = true
|
||||
}
|
||||
})
|
||||
|
||||
const createNewModel = async (name: string) => {
|
||||
isCreatingModel.value = true
|
||||
|
||||
void trackEvent('DUI3 Action', { name: 'Model Create' }, account.value.accountInfo.id)
|
||||
|
||||
const { mutate } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createModelMutation)
|
||||
)
|
||||
const res = await mutate({ input: { projectId: props.projectId, name } })
|
||||
if (res?.data?.modelMutations.create) {
|
||||
emit('model:created', res?.data?.modelMutations.create)
|
||||
// refetch() // Sorts the list with newly created model otherwise it will put the model at the bottom.
|
||||
// emit('next', res?.data?.modelMutations.create)
|
||||
} else {
|
||||
let errorMessage = 'Undefined error'
|
||||
if (res?.errors && res?.errors.length !== 0) {
|
||||
errorMessage = res?.errors[0].message
|
||||
}
|
||||
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create model',
|
||||
description: errorMessage
|
||||
})
|
||||
}
|
||||
isCreatingModel.value = false
|
||||
}
|
||||
|
||||
const { handleSubmit } = useForm<{ name: string }>()
|
||||
const onSubmitCreateNewModel = handleSubmit(() => {
|
||||
void createNewModel(newModelName.value as string)
|
||||
})
|
||||
</script>
|
||||
@@ -19,7 +19,7 @@
|
||||
color="subtle"
|
||||
class="block text-foreground-2 hover:text-foreground overflow-hidden max-w-full !justify-start"
|
||||
full-width
|
||||
:disabled="!!modelCard.progress || noReadAccess"
|
||||
:disabled="!!modelCard.progress || !canEdit"
|
||||
@click.stop="openVersionsDialog = true"
|
||||
>
|
||||
<span>
|
||||
@@ -178,7 +178,7 @@ const expiredNotification = computed(() => {
|
||||
if (props.modelCard.latestVersionId === props.modelCard.selectedVersionId) return
|
||||
const notification = {} as ModelCardNotification
|
||||
notification.dismissible = true
|
||||
notification.level = 'info'
|
||||
notification.level = 'success'
|
||||
notification.text = 'Newer version available!'
|
||||
notification.cta = {
|
||||
name: 'Update',
|
||||
@@ -203,13 +203,6 @@ const receiveResultNotificationText = computed(() => {
|
||||
return 'Model loaded!'
|
||||
})
|
||||
|
||||
const receiveResultNotificationLevel = computed(() => {
|
||||
if (failRate.value > 80) {
|
||||
return 'warning'
|
||||
}
|
||||
return 'info'
|
||||
})
|
||||
|
||||
const receiveResultNotification = computed(() => {
|
||||
if (
|
||||
!props.modelCard.bakedObjectIds ||
|
||||
@@ -219,7 +212,7 @@ const receiveResultNotification = computed(() => {
|
||||
|
||||
const notification = {} as ModelCardNotification
|
||||
notification.dismissible = true
|
||||
notification.level = receiveResultNotificationLevel.value
|
||||
notification.level = 'success'
|
||||
notification.text = receiveResultNotificationText.value
|
||||
notification.report = props.modelCard.report
|
||||
notification.cta = {
|
||||
@@ -269,10 +262,6 @@ const latestVersionCreatedAt = computed(() => {
|
||||
return dayjs(props.modelCard.latestVersionCreatedAt).from(dayjs())
|
||||
})
|
||||
|
||||
const noReadAccess = computed(() => {
|
||||
return props.canEdit
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
refetch()
|
||||
})
|
||||
|
||||
+118
-1
@@ -41,6 +41,44 @@
|
||||
</div>
|
||||
</CommonDialog>
|
||||
|
||||
<CommonDialog
|
||||
v-model:open="showSetMessageDialog"
|
||||
title="Version message"
|
||||
fullscreen="none"
|
||||
>
|
||||
<form @submit="setVersionMessage(versionMessage as string)">
|
||||
<div class="text-body-2xs mb-2 ml-1">
|
||||
Describe your latest changes to help keep track of design intent.
|
||||
</div>
|
||||
<FormTextArea
|
||||
v-model="versionMessage"
|
||||
class="text-xs"
|
||||
placeholder="Moved elements to prevent clash"
|
||||
autocomplete="off"
|
||||
name="name"
|
||||
label="Version message"
|
||||
color="foundation"
|
||||
:show-clear="!!versionMessage"
|
||||
:rules="[ValidationHelpers.isStringOfLength({ minLength: 3 })]"
|
||||
full-width
|
||||
/>
|
||||
<CommonLoadingBar v-if="isUpdatingVersionMessage" loading />
|
||||
<div class="mt-4 flex justify-end items-center space-x-2 w-full">
|
||||
<FormButton size="sm" text @click="showSetMessageDialog = false">
|
||||
Cancel
|
||||
</FormButton>
|
||||
<FormButton
|
||||
size="sm"
|
||||
submit
|
||||
:disabled="
|
||||
isUpdatingVersionMessage || !versionMessage || versionMessage.length < 3
|
||||
"
|
||||
>
|
||||
Save
|
||||
</FormButton>
|
||||
</div>
|
||||
</form>
|
||||
</CommonDialog>
|
||||
<template #states>
|
||||
<CommonModelNotification
|
||||
v-if="expiredNotification"
|
||||
@@ -74,6 +112,11 @@ import type { ISendFilter, ISenderModelCard } from '~/lib/models/card/send'
|
||||
import type { ProjectModelGroup } from '~/store/hostApp'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { ToastNotificationType, ValidationHelpers } from '@speckle/ui-components'
|
||||
import { provideApolloClient, useMutation } from '@vue/apollo-composable'
|
||||
import { useAccountStore, type DUIAccount } from '~/store/accounts'
|
||||
import { setVersionMessageMutation } from '~/lib/graphql/mutationsAndQueries'
|
||||
const hostAppStore = useHostAppStore()
|
||||
|
||||
const { trackEvent } = useMixpanel()
|
||||
const app = useNuxtApp()
|
||||
@@ -97,6 +140,7 @@ const sendOrCancel = () => {
|
||||
}
|
||||
if (props.modelCard.progress) store.sendModelCancel(props.modelCard.modelCardId)
|
||||
else store.sendModel(props.modelCard.modelCardId, 'ModelCardButton')
|
||||
hasSetVersionMessage.value = false
|
||||
}
|
||||
|
||||
let newFilter: ISendFilter
|
||||
@@ -120,9 +164,63 @@ const saveFilter = async () => {
|
||||
openFilterDialog.value = false
|
||||
}
|
||||
|
||||
const showSetMessageDialog = ref(false)
|
||||
const isUpdatingVersionMessage = ref(false)
|
||||
const hasSetVersionMessage = ref(false)
|
||||
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) => {
|
||||
if (!props.modelCard.latestCreatedVersionId) {
|
||||
return
|
||||
}
|
||||
|
||||
void trackEvent('DUI3 Action', {
|
||||
name: 'Set version message'
|
||||
})
|
||||
|
||||
isUpdatingVersionMessage.value = true
|
||||
const { mutate } = provideApolloClient(account.client)(() =>
|
||||
useMutation(setVersionMessageMutation)
|
||||
)
|
||||
|
||||
const res = await mutate({
|
||||
input: {
|
||||
projectId: props.project.projectId,
|
||||
versionId: props.modelCard.latestCreatedVersionId,
|
||||
message
|
||||
}
|
||||
})
|
||||
|
||||
if (res?.data?.versionMutations.update.id) {
|
||||
// seemed to noisy, and autoclose does not work for some reason.
|
||||
// nicer ux to just close the dialog
|
||||
// hostAppStore.setNotification({
|
||||
// type: ToastNotificationType.Info,
|
||||
// title: 'Version message saved',
|
||||
// autoClose: true
|
||||
// })
|
||||
hasSetVersionMessage.value = true
|
||||
} else {
|
||||
hostAppStore.setNotification({
|
||||
type: ToastNotificationType.Danger,
|
||||
title: 'Request failed',
|
||||
description: 'Failed to update version message.',
|
||||
autoClose: true
|
||||
})
|
||||
}
|
||||
showSetMessageDialog.value = false
|
||||
isUpdatingVersionMessage.value = false
|
||||
}
|
||||
|
||||
const saveFilterAndSend = async () => {
|
||||
await saveFilter()
|
||||
store.sendModel(props.modelCard.modelCardId, 'Filter')
|
||||
hasSetVersionMessage.value = false
|
||||
}
|
||||
|
||||
const expiredNotification = computed(() => {
|
||||
@@ -139,6 +237,7 @@ const expiredNotification = computed(() => {
|
||||
notification.cta = {
|
||||
name: ctaType,
|
||||
action: async () => {
|
||||
hasSetVersionMessage.value = false
|
||||
if (props.modelCard.progress) {
|
||||
await store.sendModelCancel(props.modelCard.modelCardId)
|
||||
}
|
||||
@@ -188,8 +287,26 @@ const latestVersionNotification = computed(() => {
|
||||
notification.level = sendResultNotificationLevel.value
|
||||
notification.text = sendResultNotificationText.value
|
||||
notification.report = props.modelCard.report
|
||||
|
||||
// NOTE: this prevents us displaying the set message button for non-updated
|
||||
// connectors that send over the root object id over instead of the commit id
|
||||
if (
|
||||
props.modelCard.latestCreatedVersionId.length === 10 &&
|
||||
!hasSetVersionMessage.value
|
||||
) {
|
||||
notification.secondaryCta = {
|
||||
name: 'Set message',
|
||||
tooltipText: 'Describe your changes',
|
||||
action: () => {
|
||||
showSetMessageDialog.value = true
|
||||
versionMessage.value = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
notification.cta = {
|
||||
name: 'View version',
|
||||
name: 'View',
|
||||
tooltipText: 'Check your model in the browser!',
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-member-access
|
||||
action: () => cardBase.value?.viewModel()
|
||||
}
|
||||
|
||||
@@ -1,220 +0,0 @@
|
||||
<template>
|
||||
<div class="p-0">
|
||||
<slot name="activator" :toggle="toggleDialog"></slot>
|
||||
<CommonDialog
|
||||
v-model:open="showProjectCreateDialog"
|
||||
:title="`Create new project`"
|
||||
fullscreen="none"
|
||||
>
|
||||
<form @submit="onSubmitCreateNewProject">
|
||||
<div class="text-body-2xs mb-2 ml-1">Project name</div>
|
||||
<FormTextInput
|
||||
v-model="newProjectName"
|
||||
class="text-xs"
|
||||
placeholder="A Beautiful Home, A Small Bridge..."
|
||||
autocomplete="off"
|
||||
name="name"
|
||||
label="Project name"
|
||||
color="foundation"
|
||||
:show-clear="!!newProjectName"
|
||||
:rules="[
|
||||
ValidationHelpers.isRequired,
|
||||
ValidationHelpers.isStringOfLength({ minLength: 3 })
|
||||
]"
|
||||
full-width
|
||||
/>
|
||||
<div class="mt-4 flex justify-end items-center space-x-2 w-full">
|
||||
<FormButton size="sm" text @click="showProjectCreateDialog = false">
|
||||
Cancel
|
||||
</FormButton>
|
||||
<FormButton
|
||||
size="sm"
|
||||
submit
|
||||
:disabled="isCreatingProject || !canCreateProject"
|
||||
>
|
||||
Create
|
||||
</FormButton>
|
||||
</div>
|
||||
</form>
|
||||
</CommonDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMutation, provideApolloClient, useQuery } from '@vue/apollo-composable'
|
||||
import type { ProjectListProjectItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import {
|
||||
canCreatePersonalProjectQuery,
|
||||
canCreateProjectInWorkspaceQuery,
|
||||
createProjectInWorkspaceMutation,
|
||||
createProjectMutation
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
import type { DUIAccount } from '~/store/accounts'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { ValidationHelpers } from '@speckle/ui-components'
|
||||
|
||||
const showProjectCreateDialog = ref(false)
|
||||
const isCreatingProject = ref(false)
|
||||
|
||||
const props = defineProps<{ workspaceId?: string }>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'project:created', result: ProjectListProjectItemFragment): void
|
||||
}>()
|
||||
|
||||
const { trackEvent } = useMixpanel()
|
||||
const accountStore = useAccountStore()
|
||||
const hostAppStore = useHostAppStore()
|
||||
const { activeAccount } = storeToRefs(accountStore)
|
||||
|
||||
const accountId = computed(() => activeAccount.value.accountInfo.id)
|
||||
const newProjectName = ref<string>()
|
||||
|
||||
const errorMessageForWorkspace = ref<string>()
|
||||
const errorMessageForPersonalProject = ref<string>()
|
||||
|
||||
const toggleDialog = () => {
|
||||
showProjectCreateDialog.value = !showProjectCreateDialog.value
|
||||
}
|
||||
|
||||
const account = computed(() => {
|
||||
return accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === accountId.value
|
||||
) as DUIAccount
|
||||
})
|
||||
|
||||
const canCreateProject = computed(() =>
|
||||
props.workspaceId === 'personalProject'
|
||||
? canCreatePersonalProject.value
|
||||
: canCreateProjectInWorkspace.value
|
||||
)
|
||||
|
||||
const { result: canCreatePersonalProjectResult } = useQuery(
|
||||
canCreatePersonalProjectQuery,
|
||||
() => ({}),
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
watch(canCreatePersonalProjectResult, (val) => {
|
||||
if (val?.activeUser?.permissions.canCreatePersonalProject.code !== 'OK') {
|
||||
errorMessageForPersonalProject.value =
|
||||
val?.activeUser?.permissions.canCreatePersonalProject.message
|
||||
}
|
||||
})
|
||||
|
||||
const canCreatePersonalProject = computed(() => {
|
||||
try {
|
||||
return (
|
||||
canCreatePersonalProjectResult.value?.activeUser?.permissions
|
||||
.canCreatePersonalProject.code === 'OK'
|
||||
)
|
||||
} catch {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
const { result: canCreateProjectInWorkspaceResult } = useQuery(
|
||||
canCreateProjectInWorkspaceQuery,
|
||||
() => ({ workspaceId: props.workspaceId ?? 'null' }), // TODO: i do not know the potential cause here
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
watch(canCreateProjectInWorkspaceResult, (val) => {
|
||||
if (val?.workspace.permissions.canCreateProject.code !== 'OK') {
|
||||
errorMessageForWorkspace.value = val?.workspace.permissions.canCreateProject.message
|
||||
}
|
||||
})
|
||||
|
||||
const canCreateProjectInWorkspace = computed(() => {
|
||||
try {
|
||||
return (
|
||||
canCreateProjectInWorkspaceResult.value?.workspace.permissions.canCreateProject
|
||||
.code === 'OK'
|
||||
)
|
||||
} catch {
|
||||
return true
|
||||
}
|
||||
})
|
||||
|
||||
const { handleSubmit } = useForm<{ name: string }>()
|
||||
const onSubmitCreateNewProject = handleSubmit(() => {
|
||||
// TODO: Chat with Fabians
|
||||
// This works, but if we use handleSubmit(args) > args.name -> it is undefined in Production on netlify, but works fine on local dev
|
||||
void createNewProject(newProjectName.value as string)
|
||||
})
|
||||
|
||||
const createNewProject = async (name: string) => {
|
||||
isCreatingProject.value = true
|
||||
|
||||
if (props.workspaceId !== 'personalProject' && props.workspaceId !== undefined) {
|
||||
createNewProjectInWorkspace(name)
|
||||
isCreatingProject.value = false
|
||||
return
|
||||
}
|
||||
|
||||
void trackEvent(
|
||||
'DUI3 Action',
|
||||
{ name: 'Project Create', workspace: false },
|
||||
account.value.accountInfo.id
|
||||
)
|
||||
const { mutate } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createProjectMutation)
|
||||
)
|
||||
const res = await mutate({ input: { name } })
|
||||
if (res?.data?.projectMutations.create) {
|
||||
emit('project:created', res?.data?.projectMutations.create)
|
||||
} else {
|
||||
let errorMessage = 'Undefined error'
|
||||
if (res?.errors && res?.errors.length !== 0) {
|
||||
errorMessage = res?.errors[0].message
|
||||
}
|
||||
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create project',
|
||||
description: errorMessage
|
||||
})
|
||||
}
|
||||
isCreatingProject.value = false
|
||||
}
|
||||
|
||||
const createNewProjectInWorkspace = async (name: string) => {
|
||||
void trackEvent(
|
||||
'DUI3 Action',
|
||||
{ name: 'Project Create', workspace: true },
|
||||
account.value.accountInfo.id
|
||||
)
|
||||
const { mutate } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createProjectInWorkspaceMutation)
|
||||
)
|
||||
const res = await mutate({
|
||||
input: { name, workspaceId: props.workspaceId as string }
|
||||
})
|
||||
if (res?.data?.workspaceMutations.projects.create) {
|
||||
emit('project:created', res?.data?.workspaceMutations.projects.create)
|
||||
} else {
|
||||
let errorMessage = 'Undefined error'
|
||||
if (res?.errors && res?.errors.length !== 0) {
|
||||
errorMessage = res?.errors[0].message
|
||||
}
|
||||
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create project',
|
||||
description: errorMessage
|
||||
})
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,141 +0,0 @@
|
||||
<template>
|
||||
<div class="p-0">
|
||||
<slot name="activator" :toggle="toggleDialog"></slot>
|
||||
<CommonDialog
|
||||
v-model:open="showProjectCreateDialog"
|
||||
:title="`Create new project`"
|
||||
fullscreen="none"
|
||||
>
|
||||
<form @submit="onSubmitCreateNewProject">
|
||||
<div class="text-body-2xs mb-2 ml-1">Project name</div>
|
||||
<FormTextInput
|
||||
v-model="newProjectName"
|
||||
class="text-xs"
|
||||
placeholder="A Beautiful Home, A Small Bridge..."
|
||||
autocomplete="off"
|
||||
name="name"
|
||||
label="Project name"
|
||||
color="foundation"
|
||||
:show-clear="!!newProjectName"
|
||||
:rules="[
|
||||
ValidationHelpers.isRequired,
|
||||
ValidationHelpers.isStringOfLength({ minLength: 3 })
|
||||
]"
|
||||
full-width
|
||||
/>
|
||||
<div class="mt-4 flex justify-end items-center space-x-2 w-full">
|
||||
<FormButton size="sm" text @click="showProjectCreateDialog = false">
|
||||
Cancel
|
||||
</FormButton>
|
||||
<FormButton
|
||||
size="sm"
|
||||
submit
|
||||
:disabled="isCreatingProject || !canCreatePersonalProject"
|
||||
>
|
||||
Create
|
||||
</FormButton>
|
||||
</div>
|
||||
</form>
|
||||
</CommonDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMutation, provideApolloClient, useQuery } from '@vue/apollo-composable'
|
||||
import type { ProjectListProjectItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import {
|
||||
canCreatePersonalProjectQuery,
|
||||
createProjectMutation
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
import type { DUIAccount } from '~/store/accounts'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { ValidationHelpers } from '@speckle/ui-components'
|
||||
|
||||
const showProjectCreateDialog = ref(false)
|
||||
const isCreatingProject = ref(false)
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'project:created', result: ProjectListProjectItemFragment): void
|
||||
}>()
|
||||
|
||||
const { trackEvent } = useMixpanel()
|
||||
const accountStore = useAccountStore()
|
||||
const hostAppStore = useHostAppStore()
|
||||
const { activeAccount } = storeToRefs(accountStore)
|
||||
|
||||
const accountId = computed(() => activeAccount.value.accountInfo.id)
|
||||
const newProjectName = ref<string>()
|
||||
|
||||
const errorMessage = ref<string>()
|
||||
|
||||
const toggleDialog = () => {
|
||||
showProjectCreateDialog.value = !showProjectCreateDialog.value
|
||||
}
|
||||
|
||||
const account = computed(() => {
|
||||
return accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === accountId.value
|
||||
) as DUIAccount
|
||||
})
|
||||
|
||||
const canCreatePersonalProject = ref<boolean>(false)
|
||||
|
||||
const { result: canCreatePersonalProjectResult } = useQuery(
|
||||
canCreatePersonalProjectQuery,
|
||||
() => ({}),
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
watch(canCreatePersonalProjectResult, (val) => {
|
||||
if (val?.activeUser?.permissions.canCreatePersonalProject.code !== 'OK') {
|
||||
errorMessage.value = val?.activeUser?.permissions.canCreatePersonalProject.message
|
||||
canCreatePersonalProject.value = false
|
||||
} else {
|
||||
canCreatePersonalProject.value = true
|
||||
}
|
||||
})
|
||||
|
||||
const { handleSubmit } = useForm<{ name: string }>()
|
||||
const onSubmitCreateNewProject = handleSubmit(() => {
|
||||
// TODO: Chat with Fabians
|
||||
// This works, but if we use handleSubmit(args) > args.name -> it is undefined in Production on netlify, but works fine on local dev
|
||||
void createNewProject(newProjectName.value as string)
|
||||
})
|
||||
|
||||
const createNewProject = async (name: string) => {
|
||||
isCreatingProject.value = true
|
||||
|
||||
void trackEvent(
|
||||
'DUI3 Action',
|
||||
{ name: 'Project Create', workspace: false },
|
||||
account.value.accountInfo.id
|
||||
)
|
||||
const { mutate } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createProjectMutation)
|
||||
)
|
||||
const res = await mutate({ input: { name } })
|
||||
if (res?.data?.projectMutations.create) {
|
||||
emit('project:created', res?.data?.projectMutations.create)
|
||||
} else {
|
||||
let errorMessage = 'Undefined error'
|
||||
if (res?.errors && res?.errors.length !== 0) {
|
||||
errorMessage = res?.errors[0].message
|
||||
}
|
||||
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create project',
|
||||
description: errorMessage
|
||||
})
|
||||
}
|
||||
isCreatingProject.value = false
|
||||
}
|
||||
</script>
|
||||
@@ -1,198 +0,0 @@
|
||||
<template>
|
||||
<div class="p-0">
|
||||
<slot name="activator" :toggle="toggleDialog"></slot>
|
||||
<CommonDialog
|
||||
v-model:open="showProjectCreateDialog"
|
||||
:title="canCreateProjectInWorkspace ? `Create new project` : errorMessage?.title"
|
||||
fullscreen="none"
|
||||
>
|
||||
<form v-if="canCreateProjectInWorkspace" @submit="onSubmitCreateNewProject">
|
||||
<div class="text-body-2xs mb-2 ml-1">Project name</div>
|
||||
<FormTextInput
|
||||
v-model="newProjectName"
|
||||
class="text-xs"
|
||||
placeholder="A Beautiful Home, A Small Bridge..."
|
||||
autocomplete="off"
|
||||
name="name"
|
||||
label="Project name"
|
||||
color="foundation"
|
||||
:show-clear="!!newProjectName"
|
||||
:rules="[
|
||||
ValidationHelpers.isRequired,
|
||||
ValidationHelpers.isStringOfLength({ minLength: 3 })
|
||||
]"
|
||||
full-width
|
||||
/>
|
||||
<div class="mt-4 flex justify-end items-center space-x-2 w-full">
|
||||
<FormButton
|
||||
size="sm"
|
||||
color="outline"
|
||||
@click="showProjectCreateDialog = false"
|
||||
>
|
||||
Cancel
|
||||
</FormButton>
|
||||
<FormButton size="sm" submit :disabled="isCreatingProject">Create</FormButton>
|
||||
</div>
|
||||
</form>
|
||||
<div v-else class="m-2">
|
||||
{{ errorMessage?.description }}
|
||||
<div class="flex mt-2 space-x-2 justify-end">
|
||||
<FormButton
|
||||
size="sm"
|
||||
color="outline"
|
||||
@click="showProjectCreateDialog = false"
|
||||
>
|
||||
Close
|
||||
</FormButton>
|
||||
<FormButton
|
||||
v-if="errorMessage?.cta"
|
||||
size="sm"
|
||||
submit
|
||||
@click="errorMessage?.cta?.action(), (showProjectCreateDialog = false)"
|
||||
>
|
||||
{{ errorMessage?.cta?.name }}
|
||||
</FormButton>
|
||||
</div>
|
||||
</div>
|
||||
</CommonDialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useMutation, provideApolloClient, useQuery } from '@vue/apollo-composable'
|
||||
import type {
|
||||
ProjectListProjectItemFragment,
|
||||
WorkspaceListWorkspaceItemFragment
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
import {
|
||||
canCreateProjectInWorkspaceQuery,
|
||||
createProjectInWorkspaceMutation
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
import type { DUIAccount } from '~/store/accounts'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { ValidationHelpers } from '@speckle/ui-components'
|
||||
|
||||
type WorkspacePermissionMessage = {
|
||||
title: string
|
||||
description: string
|
||||
cta?: {
|
||||
name: string
|
||||
action: () => void
|
||||
}
|
||||
}
|
||||
|
||||
const { $openUrl } = useNuxtApp()
|
||||
|
||||
const showProjectCreateDialog = ref(false)
|
||||
const isCreatingProject = ref(false)
|
||||
|
||||
const props = defineProps<{ workspace?: WorkspaceListWorkspaceItemFragment }>()
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'project:created', result: ProjectListProjectItemFragment): void
|
||||
}>()
|
||||
|
||||
const { trackEvent } = useMixpanel()
|
||||
const accountStore = useAccountStore()
|
||||
const hostAppStore = useHostAppStore()
|
||||
const { activeAccount } = storeToRefs(accountStore)
|
||||
|
||||
const accountId = computed(() => activeAccount.value.accountInfo.id)
|
||||
const newProjectName = ref<string>()
|
||||
|
||||
const errorMessage = ref<WorkspacePermissionMessage>()
|
||||
|
||||
const toggleDialog = () => {
|
||||
showProjectCreateDialog.value = !showProjectCreateDialog.value
|
||||
}
|
||||
|
||||
const account = computed(() => {
|
||||
return accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === accountId.value
|
||||
) as DUIAccount
|
||||
})
|
||||
|
||||
const canCreateProjectInWorkspace = ref<boolean>()
|
||||
|
||||
const { result: canCreateProjectInWorkspaceResult } = useQuery(
|
||||
canCreateProjectInWorkspaceQuery,
|
||||
() => ({ workspaceId: props.workspace?.id ?? 'null' }), // TODO: i do not know the potential cause here
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
watch(canCreateProjectInWorkspaceResult, (val) => {
|
||||
if (val?.workspace.permissions.canCreateProject.code !== 'OK') {
|
||||
switch (val?.workspace.permissions.canCreateProject.code) {
|
||||
case 'WorkspaceLimitsReached':
|
||||
errorMessage.value = {
|
||||
title: 'Plan limit reached',
|
||||
description:
|
||||
'The project limit for this workspace has been reached. Upgrade the workspace plan to create or move more projects.',
|
||||
cta: {
|
||||
name: 'Explore Plans',
|
||||
action: () =>
|
||||
$openUrl(
|
||||
`${account.value.accountInfo.serverInfo.url}/settings/workspaces/${props.workspace?.slug}/billing`
|
||||
)
|
||||
}
|
||||
}
|
||||
break
|
||||
// TODO: we should add more cases later according to `code`
|
||||
default:
|
||||
errorMessage.value = {
|
||||
title: 'Workspace warning',
|
||||
description: val?.workspace.permissions.canCreateProject.message ?? 'error'
|
||||
}
|
||||
break
|
||||
}
|
||||
canCreateProjectInWorkspace.value = false
|
||||
} else {
|
||||
canCreateProjectInWorkspace.value = true
|
||||
}
|
||||
})
|
||||
|
||||
const { handleSubmit } = useForm<{ name: string }>()
|
||||
const onSubmitCreateNewProject = handleSubmit(() => {
|
||||
// TODO: Chat with Fabians
|
||||
// This works, but if we use handleSubmit(args) > args.name -> it is undefined in Production on netlify, but works fine on local dev
|
||||
void createNewProjectInWorkspace(newProjectName.value as string)
|
||||
})
|
||||
|
||||
const createNewProjectInWorkspace = async (name: string) => {
|
||||
isCreatingProject.value = true
|
||||
void trackEvent(
|
||||
'DUI3 Action',
|
||||
{ name: 'Project Create', workspace: true },
|
||||
account.value.accountInfo.id
|
||||
)
|
||||
const { mutate } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createProjectInWorkspaceMutation)
|
||||
)
|
||||
const res = await mutate({
|
||||
input: { name, workspaceId: props.workspace?.id as string }
|
||||
})
|
||||
if (res?.data?.workspaceMutations.projects.create) {
|
||||
emit('project:created', res?.data?.workspaceMutations.projects.create)
|
||||
} else {
|
||||
let errorMessage = 'Undefined error'
|
||||
if (res?.errors && res?.errors.length !== 0) {
|
||||
errorMessage = res?.errors[0].message
|
||||
}
|
||||
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create project',
|
||||
description: errorMessage
|
||||
})
|
||||
}
|
||||
isCreatingProject.value = false
|
||||
}
|
||||
</script>
|
||||
@@ -12,6 +12,7 @@
|
||||
<WizardProjectSelector
|
||||
:is-sender="false"
|
||||
:show-new-project="false"
|
||||
:url-parse-error="urlParseError"
|
||||
@next="selectProject"
|
||||
@search-text-update="updateSearchText"
|
||||
/>
|
||||
@@ -39,7 +40,7 @@
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="urlParseError" class="p-2 text-xs text-danger">{{ urlParseError }}</div>
|
||||
<div v-if="urlParseError" class="p-2 text-danger">{{ urlParseError }}</div>
|
||||
</CommonDialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
|
||||
@@ -75,7 +75,7 @@ import {
|
||||
} from '@heroicons/vue/24/solid'
|
||||
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import type { IModelCard } from 'lib/models/card'
|
||||
import type { IModelCard } from '~/lib/models/card'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
|
||||
const app = useNuxtApp()
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<WizardProjectSelector
|
||||
is-sender
|
||||
disable-no-write-access-projects
|
||||
:url-parse-error="urlParseError"
|
||||
@next="selectProject"
|
||||
@search-text-update="updateSearchText"
|
||||
/>
|
||||
@@ -37,7 +38,7 @@
|
||||
<FormButton full-width @click="addModel">Publish</FormButton>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="urlParseError" class="p-2 text-xs text-danger">
|
||||
<div v-if="urlParseError" class="p-2 text-danger">
|
||||
{{ urlParseError }}
|
||||
</div>
|
||||
</CommonDialog>
|
||||
|
||||
@@ -13,22 +13,51 @@
|
||||
full-width
|
||||
color="foundation"
|
||||
/>
|
||||
<ModelCreateDialog
|
||||
:project-id="project.id"
|
||||
:workspace-id="workspaceId"
|
||||
:workspace-slug="workspaceSlug"
|
||||
@model:created="(result: ModelListModelItemFragment) => handleModelCreated(result)"
|
||||
<div
|
||||
v-tippy="
|
||||
canCreateModelResult?.project.permissions.canCreateModel.authorized
|
||||
? 'Create new model'
|
||||
: canCreateModelResult?.project.permissions.canCreateModel.message
|
||||
"
|
||||
>
|
||||
<template #activator="{ toggle }">
|
||||
<button
|
||||
v-tippy="'New model'"
|
||||
class="p-1.5 bg-foundation hover:bg-primary-muted rounded text-foreground border"
|
||||
@click="toggle()"
|
||||
<FormButton
|
||||
color="outline"
|
||||
:disabled="
|
||||
!canCreateModelResult?.project.permissions.canCreateModel.authorized
|
||||
"
|
||||
:class="`p-1.5 bg-foundation hover:bg-primary-muted rounded text-foreground border`"
|
||||
@click="showNewModelDialog = true"
|
||||
>
|
||||
<PlusIcon class="w-4 -mx-2" />
|
||||
</FormButton>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="
|
||||
canCreateModelResult &&
|
||||
!canCreateModelResult.project.permissions.canCreateModel.authorized
|
||||
"
|
||||
>
|
||||
<CommonAlert title="Cannot create new models" color="info" hide-icon>
|
||||
<template #description>
|
||||
{{ canCreateModelResult.project.permissions.canCreateModel.message }}
|
||||
|
||||
<FormButton
|
||||
v-if="workspaceSlug"
|
||||
full-width
|
||||
color="primary"
|
||||
size="sm"
|
||||
class="mt-2"
|
||||
@click="
|
||||
$openUrl(
|
||||
`${account.accountInfo.serverInfo.url}/settings/workspaces/${workspaceSlug}/billing`
|
||||
)
|
||||
"
|
||||
>
|
||||
<PlusIcon class="w-4" />
|
||||
</button>
|
||||
Explore Plans
|
||||
</FormButton>
|
||||
</template>
|
||||
</ModelCreateDialog>
|
||||
</CommonAlert>
|
||||
</div>
|
||||
<div class="relative grid grid-cols-1 gap-2">
|
||||
<CommonLoadingBar v-if="loading" loading />
|
||||
@@ -37,6 +66,7 @@
|
||||
v-for="model in models"
|
||||
:key="model.id"
|
||||
:model="model"
|
||||
:token="token"
|
||||
@click="handleModelSelect(model)"
|
||||
/>
|
||||
|
||||
@@ -77,6 +107,20 @@
|
||||
</template>
|
||||
</CommonDialog>
|
||||
<FormButton
|
||||
v-if="
|
||||
models?.length === 0 &&
|
||||
!!searchText &&
|
||||
canCreateModelResult?.project.permissions.canCreateModel?.authorized
|
||||
"
|
||||
full-width
|
||||
color="outline"
|
||||
:disabled="isCreatingModel"
|
||||
@click="createNewModel(searchText)"
|
||||
>
|
||||
Create "{{ searchText }}"
|
||||
</FormButton>
|
||||
<FormButton
|
||||
v-else
|
||||
color="outline"
|
||||
full-width
|
||||
:disabled="hasReachedEnd"
|
||||
@@ -91,7 +135,7 @@
|
||||
title="Create new model"
|
||||
fullscreen="none"
|
||||
>
|
||||
<form @submit="onSubmit">
|
||||
<form @submit="createNewModel(newModelName as string)">
|
||||
<FormTextInput
|
||||
v-model="newModelName"
|
||||
:rules="rules"
|
||||
@@ -107,7 +151,9 @@
|
||||
<FormButton size="sm" text @click="showNewModelDialog = false">
|
||||
Cancel
|
||||
</FormButton>
|
||||
<FormButton size="sm" submit :disabled="isCreatingModel">Create</FormButton>
|
||||
<FormButton size="sm" submit :disabled="isCreatingModel || !newModelName">
|
||||
Create
|
||||
</FormButton>
|
||||
</div>
|
||||
</form>
|
||||
</CommonDialog>
|
||||
@@ -122,10 +168,10 @@ import type {
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
import { useModelNameValidationRules } from '~/lib/validation'
|
||||
import {
|
||||
canCreateModelInProjectQuery,
|
||||
createModelMutation,
|
||||
projectModelsQuery
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
import { useForm } from 'vee-validate'
|
||||
import type { DUIAccount } from '~/store/accounts'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
@@ -152,13 +198,20 @@ const props = withDefaults(
|
||||
|
||||
const accountStore = useAccountStore()
|
||||
|
||||
const account = computed(
|
||||
() =>
|
||||
accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === props.accountId
|
||||
) as DUIAccount
|
||||
)
|
||||
|
||||
const showNewModelDialog = ref(false)
|
||||
const showSelectionHasProblemsDialog = ref(false)
|
||||
|
||||
const searchText = ref<string>()
|
||||
const newModelName = ref<string>()
|
||||
const newModelName = ref<string>(hostAppStore.documentInfo?.name ?? 'unnamed model')
|
||||
|
||||
watch(searchText, () => (newModelName.value = searchText.value))
|
||||
watch(searchText, () => (newModelName.value = searchText.value as string))
|
||||
|
||||
let selectedModel: ModelListModelItemFragment | undefined = undefined
|
||||
const existingModelProblem = ref(false)
|
||||
@@ -187,12 +240,6 @@ const confirmModelSelection = () => {
|
||||
}
|
||||
|
||||
const rules = useModelNameValidationRules()
|
||||
const { handleSubmit } = useForm<{ name: string }>()
|
||||
const onSubmit = handleSubmit(() => {
|
||||
// TODO: Chat with Fabians
|
||||
// This works, but if we use handleSubmit(args) > args.name -> it is undefined in Production on netlify, but works fine on local dev
|
||||
void createNewModel(newModelName.value as string)
|
||||
})
|
||||
|
||||
const handleModelCreated = (result: ModelListModelItemFragment) => {
|
||||
refetch() // Sorts the list with newly created project otherwise it will put the project at the bottom.
|
||||
@@ -200,21 +247,30 @@ const handleModelCreated = (result: ModelListModelItemFragment) => {
|
||||
}
|
||||
|
||||
const isCreatingModel = ref(false)
|
||||
|
||||
const createNewModel = async (name: string) => {
|
||||
if (!canCreateModelResult.value?.project.permissions.canCreateModel.authorized) {
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create model',
|
||||
description:
|
||||
canCreateModelResult.value?.project.permissions.canCreateModel.message
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
isCreatingModel.value = true
|
||||
const account = accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === props.accountId
|
||||
) as DUIAccount
|
||||
|
||||
void trackEvent('DUI3 Action', { name: 'Model Create' }, account.accountInfo.id)
|
||||
void trackEvent('DUI3 Action', { name: 'Model Create' }, account.value.accountInfo.id)
|
||||
|
||||
const { mutate } = provideApolloClient(account.client)(() =>
|
||||
const { mutate } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createModelMutation)
|
||||
)
|
||||
const res = await mutate({ input: { projectId: props.project.id, name } })
|
||||
if (res?.data?.modelMutations.create) {
|
||||
refetch() // Sorts the list with newly created model otherwise it will put the model at the bottom.
|
||||
emit('next', res?.data?.modelMutations.create)
|
||||
// emit('next', res?.data?.modelMutations.create)
|
||||
handleModelCreated(res?.data?.modelMutations.create)
|
||||
} else {
|
||||
let errorMessage = 'Undefined error'
|
||||
if (res?.errors && res?.errors.length !== 0) {
|
||||
@@ -230,6 +286,15 @@ const createNewModel = async (name: string) => {
|
||||
isCreatingModel.value = false
|
||||
}
|
||||
|
||||
const { result: canCreateModelResult } = useQuery(
|
||||
canCreateModelInProjectQuery,
|
||||
() => ({ projectId: props.project.id }),
|
||||
() => ({
|
||||
clientId: props.accountId,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
const {
|
||||
result: projectModelsResult,
|
||||
loading,
|
||||
@@ -247,6 +312,7 @@ const {
|
||||
() => ({ clientId: props.accountId, debounce: 500, fetchPolicy: 'cache-and-network' })
|
||||
)
|
||||
|
||||
const token = computed(() => account.value.accountInfo.token)
|
||||
const models = computed(() => projectModelsResult.value?.project.models.items)
|
||||
const totalCount = computed(() => projectModelsResult.value?.project.models.totalCount)
|
||||
const hasReachedEnd = ref(false)
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
class="px-3 py-1 rounded-md shadow transition overflow-hidden bg-foundation border-foundation-2 hover:shadow-md border-1 group"
|
||||
>
|
||||
<div class="flex flex-col sm:flex-row sm:gap-2 text-foreground">
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="text-body-xs">
|
||||
<h1
|
||||
class="mb-1 text-sm font-semibold w-full inline-block py-1 bg-clip-text"
|
||||
>
|
||||
Move your projects to a workspace
|
||||
</h1>
|
||||
<p class="mb-2">
|
||||
<span class="text-sm">➊</span>
|
||||
<span class="text-xs">
|
||||
We are making workspaces the default way to work in Speckle.
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<p class="mb-1">
|
||||
<span class="text-sm">➋</span>
|
||||
<span class="text-xs">
|
||||
Introducing
|
||||
<FormButton
|
||||
text
|
||||
link
|
||||
external
|
||||
size="sm"
|
||||
class="font-semibold"
|
||||
@click="$openUrl(`https://www.speckle.systems/pricing`)"
|
||||
>
|
||||
new pricing
|
||||
</FormButton>
|
||||
including limits to the free plan.
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<FormButton
|
||||
text
|
||||
color="primary"
|
||||
size="sm"
|
||||
:class="showMore ? `mb-1` : ``"
|
||||
:icon-right="showMore ? ChevronUpIcon : ChevronDownIcon"
|
||||
@click="showMore = !showMore"
|
||||
>
|
||||
{{ showMore ? 'Show less' : 'Show timeline' }}
|
||||
</FormButton>
|
||||
|
||||
<div v-show="showMore">
|
||||
<hr />
|
||||
<h3 class="font-medium text-warning-darker my-1">By June 1st 2025</h3>
|
||||
<p class="text-xs mb-1">Move your projects to a workspace to:</p>
|
||||
<ul class="list-disc list-inside pl-2 mb-2">
|
||||
<li>
|
||||
<span class="text-xs font-medium">
|
||||
Create new projects and models
|
||||
</span>
|
||||
<span class="text-xs">
|
||||
(will be disabled for personal projects; existing projects and
|
||||
models stay editable)
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text-xs font-medium">
|
||||
Invite new project collaborators
|
||||
</span>
|
||||
<span class="text-xs">
|
||||
(new invites will be unavailable for personal projects)
|
||||
</span>
|
||||
</li>
|
||||
<li>
|
||||
<span class="text-xs font-medium">
|
||||
Preserve version and comment history
|
||||
</span>
|
||||
<span class="text-xs">
|
||||
(history is reduced to 7 days for personal projects)
|
||||
</span>
|
||||
</li>
|
||||
</ul>
|
||||
<h3 class="font-medium text-warning-darker">By Janury 1st 2026</h3>
|
||||
<span class="text-xs mb-1">
|
||||
All projects will be archived if not moved into a workspace. Don't
|
||||
worry, we'll give you plenty of reminders before then.
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ChevronUpIcon, ChevronDownIcon } from '@heroicons/vue/20/solid'
|
||||
|
||||
const { $openUrl } = useNuxtApp()
|
||||
const showMore = ref(false)
|
||||
</script>
|
||||
@@ -1,11 +1,9 @@
|
||||
<template>
|
||||
<div class="space-y-2">
|
||||
<div class="space-y-2 relative">
|
||||
<div
|
||||
v-if="workspacesEnabled && workspaces"
|
||||
class="flex items-center space-x-2 bg-foundation -mx-3 -mt-2 px-3 py-2 shadow-sm border-b"
|
||||
>
|
||||
<div v-if="workspacesEnabled && workspaces" class="flex items-center space-x-2">
|
||||
<div class="flex-grow min-w-0">
|
||||
<!-- NO WORKSPACE YET -->
|
||||
<div v-if="workspaces.length === 0">
|
||||
<FormButton
|
||||
full-width
|
||||
@@ -43,23 +41,13 @@
|
||||
</template>
|
||||
</WorkspaceMenu>
|
||||
</div>
|
||||
<div class="px-0.5 shrink-0">
|
||||
<div class="shrink-0 pt-1 px-1">
|
||||
<AccountsMenu
|
||||
:current-selected-account-id="accountId"
|
||||
@select="(e) => selectAccount(e)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- we can message to user about the non-workspace scenario -->
|
||||
<!-- <div v-if="workspaces && workspaces.length === 0">
|
||||
<CommonAlert size="xs" :color="'warning'">
|
||||
<template #description>
|
||||
You are listing legacy personal projects which will be deprecated end of
|
||||
2025. We suggest you to move your personal projects into a workspace before
|
||||
then.
|
||||
</template>
|
||||
</CommonAlert>
|
||||
</div> -->
|
||||
<div class="space-y-2">
|
||||
<div class="flex items-center space-x-1 justify-between">
|
||||
<FormTextInput
|
||||
@@ -72,36 +60,58 @@
|
||||
color="foundation"
|
||||
/>
|
||||
<div class="flex justify-between items-center space-x-2">
|
||||
<ProjectCreateWorkspaceDialog
|
||||
v-if="selectedWorkspace && selectedWorkspace.id !== 'personalProject'"
|
||||
:workspace="selectedWorkspace"
|
||||
@project:created="(result : ProjectListProjectItemFragment) => handleProjectCreated(result)"
|
||||
<div
|
||||
v-tippy="
|
||||
canCreateProject
|
||||
? 'Create new project'
|
||||
: canCreateProjectPermissionCheck?.message
|
||||
"
|
||||
>
|
||||
<template #activator="{ toggle }">
|
||||
<button
|
||||
v-tippy="'New project in workspace'"
|
||||
class="p-1.5 bg-foundation hover:bg-primary-muted rounded text-foreground border"
|
||||
@click="toggle()"
|
||||
>
|
||||
<PlusIcon class="w-4" />
|
||||
</button>
|
||||
</template>
|
||||
</ProjectCreateWorkspaceDialog>
|
||||
<!-- TODO: once we deprecate personal projects, else block is bye bye -->
|
||||
<ProjectCreatePersonalDialog
|
||||
v-else
|
||||
@project:created="(result : ProjectListProjectItemFragment) => handleProjectCreated(result)"
|
||||
<FormButton
|
||||
color="outline"
|
||||
:disabled="!canCreateProject"
|
||||
:class="`p-1.5 bg-foundation hover:bg-primary-muted rounded text-foreground border`"
|
||||
@click="showProjectCreateDialog = true"
|
||||
>
|
||||
<PlusIcon class="w-4 -mx-2" />
|
||||
</FormButton>
|
||||
</div>
|
||||
<CommonDialog
|
||||
v-model:open="showProjectCreateDialog"
|
||||
:title="`Create new project`"
|
||||
fullscreen="none"
|
||||
>
|
||||
<template #activator="{ toggle }">
|
||||
<button
|
||||
v-tippy="'New personal project'"
|
||||
class="p-1.5 bg-foundation hover:bg-primary-muted rounded text-foreground border"
|
||||
@click="toggle()"
|
||||
>
|
||||
<PlusIcon class="w-4" />
|
||||
</button>
|
||||
</template>
|
||||
</ProjectCreatePersonalDialog>
|
||||
<form @submit="createProject(newProjectName as string)">
|
||||
<div class="text-body-2xs mb-2 ml-1">Project name</div>
|
||||
<FormTextInput
|
||||
v-model="newProjectName"
|
||||
class="text-xs"
|
||||
placeholder="A Beautiful Home, A Small Bridge..."
|
||||
autocomplete="off"
|
||||
name="name"
|
||||
label="Project name"
|
||||
color="foundation"
|
||||
:show-clear="!!newProjectName"
|
||||
:rules="[
|
||||
ValidationHelpers.isRequired,
|
||||
ValidationHelpers.isStringOfLength({ minLength: 3 })
|
||||
]"
|
||||
full-width
|
||||
/>
|
||||
<div class="mt-4 flex justify-end items-center space-x-2 w-full">
|
||||
<FormButton size="sm" text @click="showProjectCreateDialog = false">
|
||||
Cancel
|
||||
</FormButton>
|
||||
<FormButton
|
||||
size="sm"
|
||||
submit
|
||||
:disabled="isCreatingProject || !newProjectName"
|
||||
>
|
||||
Create
|
||||
</FormButton>
|
||||
</div>
|
||||
</form>
|
||||
</CommonDialog>
|
||||
<div v-if="!workspacesEnabled || !workspaces" class="mt-1">
|
||||
<AccountsMenu
|
||||
:current-selected-account-id="accountId"
|
||||
@@ -110,9 +120,34 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<CommonLoadingBar v-if="loading" loading />
|
||||
<div
|
||||
v-if="
|
||||
canCreateProjectPermissionCheck &&
|
||||
!canCreateProjectPermissionCheck.authorized
|
||||
"
|
||||
>
|
||||
<CommonAlert color="info" hide-icon>
|
||||
<template #description>
|
||||
{{ canCreateProjectPermissionCheck.message }}
|
||||
<FormButton
|
||||
v-if="showUpgradeButton"
|
||||
full-width
|
||||
class="mt-2"
|
||||
color="primary"
|
||||
size="sm"
|
||||
@click="upgradeButtonAction()"
|
||||
>
|
||||
Upgrade now
|
||||
</FormButton>
|
||||
</template>
|
||||
</CommonAlert>
|
||||
</div>
|
||||
|
||||
<WizardPersonalProjectsWarning v-if="isPersonalProjectsAsWorkspace" />
|
||||
|
||||
<CommonLoadingBar v-if="loading || isCreatingProject" loading />
|
||||
</div>
|
||||
<div class="grid grid-cols-1 gap-2 relative z-0">
|
||||
<div v-if="!urlParseError" class="grid grid-cols-1 gap-2 relative z-0">
|
||||
<WizardListProjectCard
|
||||
v-for="project in projects"
|
||||
:key="project.id"
|
||||
@@ -120,7 +155,27 @@
|
||||
:is-sender="isSender"
|
||||
@click="handleProjectCardClick(project)"
|
||||
/>
|
||||
<p v-if="projects?.length === 0 && !!searchText" class="text-sm">
|
||||
No projects found
|
||||
</p>
|
||||
<FormButton
|
||||
v-if="
|
||||
projects?.length === 0 &&
|
||||
!!searchText &&
|
||||
canCreateProjectPermissionCheck?.authorized
|
||||
"
|
||||
full-width
|
||||
color="outline"
|
||||
:disabled="isCreatingProject"
|
||||
class="block truncate overflow-hidden"
|
||||
@click="createProject(searchText)"
|
||||
>
|
||||
Create "{{
|
||||
searchText.length > 10 ? searchText.substring(0, 10) + '...' : searchText
|
||||
}}"
|
||||
</FormButton>
|
||||
<FormButton
|
||||
v-else
|
||||
full-width
|
||||
:disabled="hasReachedEnd"
|
||||
color="outline"
|
||||
@@ -140,19 +195,25 @@ import type { DUIAccount } from '~/store/accounts'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import {
|
||||
activeWorkspaceQuery,
|
||||
canCreatePersonalProjectQuery,
|
||||
createProjectInWorkspaceMutation,
|
||||
createProjectMutation,
|
||||
projectsListQuery,
|
||||
serverInfoQuery,
|
||||
setActiveWorkspaceMutation,
|
||||
workspacesListQuery
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
import { useMutation, provideApolloClient, useQuery } from '@vue/apollo-composable'
|
||||
import { ValidationHelpers } from '@speckle/ui-components'
|
||||
import type {
|
||||
ProjectListProjectItemFragment,
|
||||
WorkspaceListWorkspaceItemFragment
|
||||
} from 'lib/common/generated/gql/graphql'
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { useConfigStore } from '~/store/config'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
|
||||
const hostAppStore = useHostAppStore()
|
||||
const { trackEvent } = useMixpanel()
|
||||
const { $openUrl } = useNuxtApp()
|
||||
|
||||
@@ -174,6 +235,7 @@ const props = withDefaults(
|
||||
* For the send wizard - not allowing selecting projects we can't write to.
|
||||
*/
|
||||
disableNoWriteAccessProjects?: boolean
|
||||
urlParseError?: string
|
||||
}>(),
|
||||
{
|
||||
showNewProject: true,
|
||||
@@ -210,7 +272,11 @@ const handleProjectCreated = (result: ProjectListProjectItemFragment) => {
|
||||
const { result: serverInfoResult, refetch: refetchServerInfo } = useQuery(
|
||||
serverInfoQuery,
|
||||
() => ({}),
|
||||
() => ({ clientId: accountId.value, debounce: 500, fetchPolicy: 'network-only' })
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
const workspacesEnabled = computed(
|
||||
@@ -222,7 +288,11 @@ const { result: workspacesResult, refetch: refetchWorkspaces } = useQuery(
|
||||
() => ({
|
||||
limit: 100
|
||||
}),
|
||||
() => ({ clientId: accountId.value, debounce: 500, fetchPolicy: 'network-only' })
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
const workspaces = computed(() => workspacesResult.value?.activeUser?.workspaces.items)
|
||||
@@ -230,7 +300,11 @@ const workspaces = computed(() => workspacesResult.value?.activeUser?.workspaces
|
||||
const { result: activeWorkspaceResult, refetch: refetchActiveWorkspace } = useQuery(
|
||||
activeWorkspaceQuery,
|
||||
() => ({}),
|
||||
() => ({ clientId: accountId.value, debounce: 500, fetchPolicy: 'network-only' })
|
||||
() => ({
|
||||
clientId: accountId.value,
|
||||
debounce: 500,
|
||||
fetchPolicy: 'network-only'
|
||||
})
|
||||
)
|
||||
|
||||
const activeWorkspace = computed(() => {
|
||||
@@ -243,15 +317,30 @@ const activeWorkspace = computed(() => {
|
||||
return previouslySelectedWorkspace
|
||||
}
|
||||
}
|
||||
// fallback to activeWorkspace query result
|
||||
return activeWorkspaceResult.value?.activeUser
|
||||
|
||||
const activeWorkspace = activeWorkspaceResult.value?.activeUser
|
||||
?.activeWorkspace as WorkspaceListWorkspaceItemFragment
|
||||
|
||||
// fallback to activeWorkspace query result
|
||||
if (activeWorkspace) {
|
||||
return activeWorkspace
|
||||
}
|
||||
|
||||
// if activeWorkspace is null will mean that it is personal projects - this fallback wont be the case soon
|
||||
return {
|
||||
id: 'personalProject',
|
||||
name: 'Personal Projects'
|
||||
} as WorkspaceListWorkspaceItemFragment
|
||||
})
|
||||
|
||||
const selectedWorkspace = ref<WorkspaceListWorkspaceItemFragment | undefined>(
|
||||
activeWorkspace.value
|
||||
)
|
||||
|
||||
const isPersonalProjectsAsWorkspace = computed(
|
||||
() => selectedWorkspace.value?.id === 'personalProject'
|
||||
)
|
||||
|
||||
watch(
|
||||
workspaces,
|
||||
(newItems) => {
|
||||
@@ -320,12 +409,11 @@ const {
|
||||
limit: 10, // stupid hack, increased it since we do manual filter to be able to see more project, see below TODO note, once we have `personalOnly` filter, decrease back to 10
|
||||
filter: {
|
||||
search: (searchText.value || '').trim() || null,
|
||||
workspaceId:
|
||||
selectedWorkspace.value?.id === 'personalProject'
|
||||
? null
|
||||
: selectedWorkspace.value?.id,
|
||||
workspaceId: isPersonalProjectsAsWorkspace.value
|
||||
? null
|
||||
: selectedWorkspace.value?.id,
|
||||
includeImplicitAccess: true,
|
||||
personalOnly: selectedWorkspace.value?.id === 'personalProject'
|
||||
personalOnly: isPersonalProjectsAsWorkspace.value
|
||||
}
|
||||
}),
|
||||
() => ({
|
||||
@@ -337,7 +425,7 @@ const {
|
||||
)
|
||||
|
||||
const projects = computed(() =>
|
||||
selectedWorkspace.value?.id === 'personalProject' // TODO: we need to replace this logic with `personalOnly` filter when it is implemented into app.speckle.systems
|
||||
isPersonalProjectsAsWorkspace.value // TODO: we need to replace this logic with `personalOnly` filter when it is implemented into app.speckle.systems
|
||||
? projectsResult.value?.activeUser?.projects.items.filter(
|
||||
(i) => i.workspaceId === null
|
||||
)
|
||||
@@ -361,6 +449,156 @@ watch(projectsResult, (newVal) => {
|
||||
}
|
||||
})
|
||||
|
||||
const { result: canCreatePersonalProjectResult } = useQuery(
|
||||
canCreatePersonalProjectQuery,
|
||||
{},
|
||||
() => ({
|
||||
clientId: accountId.value
|
||||
})
|
||||
)
|
||||
|
||||
const canCreateProject = computed(() => {
|
||||
// If a workspace is selected, return that permission check
|
||||
if (selectedWorkspace.value && selectedWorkspace.value.permissions) {
|
||||
return selectedWorkspace.value.permissions.canCreateProject.authorized //as boolean
|
||||
}
|
||||
// Otherwise, check for personal projects
|
||||
if (canCreatePersonalProjectResult) {
|
||||
return canCreatePersonalProjectResult.value?.activeUser?.permissions
|
||||
.canCreatePersonalProject.authorized
|
||||
}
|
||||
// To be always safe, default to false
|
||||
return false
|
||||
})
|
||||
|
||||
const canCreateProjectPermissionCheck = computed(() => {
|
||||
if (selectedWorkspace.value && selectedWorkspace.value.permissions) {
|
||||
return selectedWorkspace.value.permissions.canCreateProject
|
||||
}
|
||||
if (canCreatePersonalProjectResult) {
|
||||
return canCreatePersonalProjectResult.value?.activeUser?.permissions
|
||||
.canCreatePersonalProject
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
const upgradeButtonAction = () => {
|
||||
if (!canCreateProjectPermissionCheck.value) return
|
||||
if (canCreateProjectPermissionCheck.value.code === 'WorkspaceNoEditorSeat') {
|
||||
// open url to workspace/settings/users
|
||||
$openUrl(
|
||||
`${account.value.accountInfo.serverInfo.url}/settings/workspaces/${selectedWorkspace.value?.slug}/members`
|
||||
)
|
||||
return
|
||||
}
|
||||
if (canCreateProjectPermissionCheck.value.code === 'WorkspaceLimitsReached') {
|
||||
// open url to workspace/billing
|
||||
$openUrl(
|
||||
`${account.value.accountInfo.serverInfo.url}/settings/workspaces/${selectedWorkspace.value?.slug}/billing`
|
||||
)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
const showUpgradeButton = computed(() => {
|
||||
if (!canCreateProjectPermissionCheck.value) return false
|
||||
if (
|
||||
canCreateProjectPermissionCheck.value.code === 'WorkspaceNoEditorSeat' ||
|
||||
canCreateProjectPermissionCheck.value.code === 'WorkspaceLimitsReached'
|
||||
) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
const isCreatingProject = ref(false)
|
||||
const showProjectCreateDialog = ref(false)
|
||||
|
||||
const createProject = (name: string) => {
|
||||
if (
|
||||
canCreateProjectPermissionCheck.value &&
|
||||
!canCreateProjectPermissionCheck.value.authorized
|
||||
) {
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create project',
|
||||
description: canCreateProjectPermissionCheck.value.message as string
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (isPersonalProjectsAsWorkspace.value || !selectedWorkspace.value) {
|
||||
return void createNewPersonalProject(name)
|
||||
} else {
|
||||
return void createNewWorkspaceProject(name)
|
||||
}
|
||||
}
|
||||
|
||||
const account = computed(() => {
|
||||
return accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === accountId.value
|
||||
) as DUIAccount
|
||||
})
|
||||
|
||||
const createNewWorkspaceProject = async (name: string) => {
|
||||
isCreatingProject.value = true
|
||||
void trackEvent(
|
||||
'DUI3 Action',
|
||||
{ name: 'Project Create', workspace: true },
|
||||
accountId.value
|
||||
)
|
||||
const { mutate, onError } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createProjectInWorkspaceMutation)
|
||||
)
|
||||
|
||||
onError((err) => {
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create project',
|
||||
description: err.cause?.message ?? err.message ?? 'Unknown error'
|
||||
})
|
||||
})
|
||||
|
||||
const res = await mutate({
|
||||
input: { name, workspaceId: selectedWorkspace.value?.id as string }
|
||||
})
|
||||
|
||||
if (res?.data?.workspaceMutations.projects.create) {
|
||||
handleProjectCreated(res?.data?.workspaceMutations.projects.create)
|
||||
}
|
||||
isCreatingProject.value = false
|
||||
}
|
||||
|
||||
const createNewPersonalProject = async (name: string) => {
|
||||
isCreatingProject.value = true
|
||||
|
||||
void trackEvent(
|
||||
'DUI3 Action',
|
||||
{ name: 'Project Create', workspace: false },
|
||||
account.value.accountInfo.id
|
||||
)
|
||||
|
||||
const { mutate, onError } = provideApolloClient(account.value.client)(() =>
|
||||
useMutation(createProjectMutation)
|
||||
)
|
||||
|
||||
onError((err) => {
|
||||
hostAppStore.setNotification({
|
||||
type: 1,
|
||||
title: 'Failed to create project',
|
||||
description: err.cause?.message ?? err.message ?? 'Unknown error'
|
||||
})
|
||||
})
|
||||
|
||||
const res = await mutate({ input: { name } })
|
||||
|
||||
if (res?.data?.projectMutations.create) {
|
||||
return handleProjectCreated(res?.data?.projectMutations.create)
|
||||
}
|
||||
|
||||
isCreatingProject.value = false
|
||||
}
|
||||
|
||||
const loadMore = () => {
|
||||
fetchMore({
|
||||
variables: { cursor: projectsResult.value?.activeUser?.projects.cursor },
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="text-body-2xs mb-2 ml-1">Project workspace</div>
|
||||
<FormSelectBase
|
||||
key="name"
|
||||
v-model="selectedWorkspace"
|
||||
clearable
|
||||
label="Workspaces"
|
||||
placeholder="Nothing selected"
|
||||
name="Workspaces"
|
||||
:items="workspaces"
|
||||
:disabled-item-predicate="userCantCreateWorkspace"
|
||||
mount-menu-on-body
|
||||
>
|
||||
<template #something-selected="{ value }">
|
||||
<span>{{ value.name }}</span>
|
||||
</template>
|
||||
<template #option="{ item }">
|
||||
<div
|
||||
v-tippy="{
|
||||
content: item.readOnly
|
||||
? 'This workspace is read-only.'
|
||||
: item.role === 'workspace:guest'
|
||||
? 'You do not have write access on this workspace.'
|
||||
: undefined,
|
||||
disabled: !(item.readOnly || item.role === 'workspace:guest')
|
||||
}"
|
||||
class="flex items-center"
|
||||
>
|
||||
<span class="truncate">{{ item.name }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</FormSelectBase>
|
||||
<div
|
||||
v-if="selectedWorkspace"
|
||||
class="text-body-sm caption rounded p-2 bg-blue-500/10 my-2"
|
||||
>
|
||||
Project will be created in the selected workspace.
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed } from 'vue'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
import { workspacesListQuery } from '~/lib/graphql/mutationsAndQueries'
|
||||
import type { WorkspaceListWorkspaceItemFragment } from 'lib/common/generated/gql/graphql'
|
||||
import { storeToRefs } from 'pinia'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(
|
||||
e: 'update:selectedWorkspace',
|
||||
value: WorkspaceListWorkspaceItemFragment | undefined
|
||||
): void
|
||||
}>()
|
||||
|
||||
const accountStore = useAccountStore()
|
||||
const { activeAccount } = storeToRefs(accountStore)
|
||||
const accountId = computed(() => activeAccount.value.accountInfo.id)
|
||||
|
||||
const searchText = ref<string>()
|
||||
|
||||
const { result: workspacesResult } = useQuery(
|
||||
workspacesListQuery,
|
||||
() => ({
|
||||
limit: 5,
|
||||
filter: {
|
||||
search: (searchText.value || '').trim() || null
|
||||
}
|
||||
}),
|
||||
() => ({ clientId: accountId.value, debounce: 500, fetchPolicy: 'network-only' })
|
||||
)
|
||||
|
||||
const workspaces = computed(() => workspacesResult.value?.activeUser?.workspaces.items)
|
||||
const selectedWorkspace = ref<WorkspaceListWorkspaceItemFragment>()
|
||||
|
||||
watch(selectedWorkspace, (newVal) => {
|
||||
emit('update:selectedWorkspace', newVal)
|
||||
})
|
||||
|
||||
// Utility function to check if the user cannot create a workspace
|
||||
const userCantCreateWorkspace = (item: WorkspaceListWorkspaceItemFragment) =>
|
||||
(!!item?.role && item.role === 'workspace:guest') || !!item.readOnly
|
||||
</script>
|
||||
@@ -4,9 +4,15 @@
|
||||
>
|
||||
<div class="flex items-center space-x-2 max-[275px]:space-x-0">
|
||||
<div class="max-[275px]:hidden">
|
||||
<div v-if="model.previewUrl" class="h-12 w-12">
|
||||
<div
|
||||
v-if="model.versions.totalCount === 0"
|
||||
class="h-12 w-12 bg-blue-500/10 rounded flex items-center justify-center"
|
||||
>
|
||||
<CubeTransparentIcon class="w-5 h-5 text-foreground-2" />
|
||||
</div>
|
||||
<div v-else-if="previewUrl" class="h-12 w-12">
|
||||
<img
|
||||
:src="model.previewUrl"
|
||||
:src="previewUrl"
|
||||
alt="preview image for model"
|
||||
class="h-12 w-12 object-cover"
|
||||
/>
|
||||
@@ -15,7 +21,7 @@
|
||||
v-else
|
||||
class="h-12 w-12 bg-blue-500/10 rounded flex items-center justify-center"
|
||||
>
|
||||
<CubeTransparentIcon class="w-5 h-5 text-foreground-2" />
|
||||
<CommonLoadingIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div class="min-w-0 w-full">
|
||||
@@ -52,9 +58,16 @@ import { ClockIcon } from '@heroicons/vue/24/outline'
|
||||
import type { SourceAppName } from '@speckle/shared'
|
||||
import { SourceApps } from '@speckle/shared'
|
||||
import type { ModelListModelItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { computedAsync } from '@vueuse/core'
|
||||
import { usePreviewUrl } from '~/lib/core/composables/previewUrl'
|
||||
|
||||
const props = defineProps<{
|
||||
model: ModelListModelItemFragment
|
||||
/**
|
||||
* Token to retrieve preview url
|
||||
* @note by convention we pass around `accountId` but it doesn't make sense to get token for every model card. more efficient with this way.
|
||||
*/
|
||||
token: string
|
||||
}>()
|
||||
|
||||
const folderPath = computed(() => {
|
||||
@@ -68,6 +81,11 @@ const updatedAgo = computed(() => {
|
||||
return dayjs(props.model.updatedAt).from(dayjs())
|
||||
})
|
||||
|
||||
const previewUrl = computedAsync(async () => {
|
||||
if (props.model.previewUrl === null) return
|
||||
return await usePreviewUrl(props.token, props.model.previewUrl)
|
||||
})
|
||||
|
||||
const sourceApp = computed(() => {
|
||||
if (props.model.versions.items.length === 0) return
|
||||
const version = props.model.versions.items[0]
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
>
|
||||
<UserAvatar
|
||||
v-tippy="`Authored by ${version.authorUser?.name}`"
|
||||
:user="version.authorUser"
|
||||
:user="{ avatar: version.authorUser?.avatar, name: version.authorUser?.name as string }"
|
||||
size="sm"
|
||||
class="absolute inset-1"
|
||||
/>
|
||||
@@ -24,7 +24,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else class="flex items-center justify-center w-full h-24">
|
||||
<img :src="version.previewUrl" alt="version preview" />
|
||||
<div v-if="previewUrl">
|
||||
<img :src="previewUrl" alt="preview image for version" />
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="h-12 w-12 bg-blue-500/10 rounded flex items-center justify-center"
|
||||
>
|
||||
<CommonLoadingIcon />
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-1.5 border-t dark:border-gray-700">
|
||||
<div class="flex space-x-2 items-center min-w-0">
|
||||
@@ -100,9 +108,14 @@ import dayjs from 'dayjs'
|
||||
import type { SourceAppName } from '@speckle/shared'
|
||||
import { SourceApps } from '@speckle/shared'
|
||||
import type { VersionListItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { useAccountStore, type DUIAccount } from '~/store/accounts'
|
||||
import { computedAsync } from '@vueuse/core'
|
||||
import { usePreviewUrl } from '~/lib/core/composables/previewUrl'
|
||||
// import { objectQuery } from '~/lib/graphql/mutationsAndQueries'
|
||||
// import { useQuery } from '@vue/apollo-composable'
|
||||
|
||||
const accountStore = useAccountStore()
|
||||
|
||||
const props = defineProps<{
|
||||
version: VersionListItemFragment
|
||||
index: number
|
||||
@@ -120,6 +133,18 @@ const createdAgo = computed(() => {
|
||||
|
||||
const isLimited = computed(() => props.version.referencedObject === null)
|
||||
|
||||
const token = computed(() => {
|
||||
const account = accountStore.accounts.find(
|
||||
(acc) => acc.accountInfo.id === props.accountId
|
||||
) as DUIAccount
|
||||
return account.accountInfo.token
|
||||
})
|
||||
|
||||
const previewUrl = computedAsync(async () => {
|
||||
if (props.version.previewUrl === null) return
|
||||
return await usePreviewUrl(token.value, props.version.previewUrl)
|
||||
})
|
||||
|
||||
// NOTE!!!: This logic somehow caused regression on versionList fetchMore, but we do not know exactly why yet.
|
||||
// const { result: objectQueryResult } = useQuery(
|
||||
// objectQuery,
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
@select="
|
||||
$emit('workspace:selected', workspace), (showWorkspaceSelectorDialog = false)
|
||||
"
|
||||
></WorkspaceListItem>
|
||||
/>
|
||||
</CommonDialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -34,7 +34,7 @@ defineEmits<{
|
||||
}>()
|
||||
|
||||
const workspacesWithPersonalProjects = computed(() => [
|
||||
...props.workspaces,
|
||||
...props.workspaces.filter((w) => w.creationState?.completed !== false),
|
||||
{
|
||||
id: 'personalProject',
|
||||
name: 'Personal Projects'
|
||||
|
||||
+53
-7
@@ -1,7 +1,19 @@
|
||||
import { omit } from 'lodash-es'
|
||||
import { baseConfigs, globals, getESMDirname } from '../../eslint.config.mjs'
|
||||
import withNuxt from './.nuxt/eslint.config.mjs'
|
||||
import pluginVueA11y from 'eslint-plugin-vuejs-accessibility'
|
||||
import globals from 'globals'
|
||||
import { fileURLToPath } from 'url'
|
||||
import { dirname } from 'path'
|
||||
import prettierConfig from 'eslint-config-prettier'
|
||||
import js from '@eslint/js'
|
||||
|
||||
/**
|
||||
* Feed in import.meta.url in your .mjs module to get the equivalent of __dirname
|
||||
* @param {string} importMetaUrl
|
||||
*/
|
||||
export const getESMDirname = (importMetaUrl) => {
|
||||
return dirname(fileURLToPath(importMetaUrl))
|
||||
}
|
||||
|
||||
const configs = await withNuxt([
|
||||
{
|
||||
@@ -62,6 +74,7 @@ const configs = await withNuxt([
|
||||
'@typescript-eslint/require-await': 'error',
|
||||
'no-undef': 'off',
|
||||
|
||||
'@typescript-eslint/no-empty-object-type': 'off', // too restrictive
|
||||
'@typescript-eslint/unified-signatures': 'off', // DX sucks in vue event definitions
|
||||
'@typescript-eslint/no-dynamic-delete': 'off', // too restrictive
|
||||
'@typescript-eslint/restrict-template-expressions': 'off', // too restrictive
|
||||
@@ -78,10 +91,7 @@ const configs = await withNuxt([
|
||||
{
|
||||
files: ['**/*.vue'],
|
||||
rules: {
|
||||
'vue/component-tags-order': [
|
||||
'error',
|
||||
{ order: ['docs', 'template', 'script', 'style'] }
|
||||
],
|
||||
'vue/block-order': ['error', { order: ['docs', 'template', 'script', 'style'] }],
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'vue/component-name-in-template-casing': [
|
||||
@@ -116,10 +126,46 @@ const configs = await withNuxt([
|
||||
'./lib/common/generated/**/*',
|
||||
'storybook-static',
|
||||
'.nuxt/**',
|
||||
'.output/**'
|
||||
'.output/**',
|
||||
'**/dist/**',
|
||||
'**/dist-*/**',
|
||||
'**/public/**',
|
||||
'**/events.json',
|
||||
'**/generated/**/*'
|
||||
]
|
||||
},
|
||||
...baseConfigs
|
||||
{
|
||||
files: ['**/*.mjs'],
|
||||
languageOptions: {
|
||||
sourceType: 'module'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.cjs'],
|
||||
languageOptions: {
|
||||
sourceType: 'commonjs'
|
||||
}
|
||||
},
|
||||
{
|
||||
files: ['**/*.{js,mjs,cjs}', '**/.*.{js,mjs,cjs}'],
|
||||
...js.configs.recommended
|
||||
},
|
||||
prettierConfig,
|
||||
{
|
||||
rules: {
|
||||
camelcase: [
|
||||
1,
|
||||
{
|
||||
properties: 'always'
|
||||
}
|
||||
],
|
||||
'no-var': 'error',
|
||||
'no-alert': 'error',
|
||||
eqeqeq: 'error',
|
||||
'prefer-const': 'warn',
|
||||
'object-shorthand': 'warn'
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
export default configs
|
||||
|
||||
@@ -1,136 +0,0 @@
|
||||
import { ApolloClient, gql } from '@apollo/client/core'
|
||||
import { ApolloClients } from '@vue/apollo-composable'
|
||||
import type { ComputedRef, Ref } from 'vue'
|
||||
import type { Account } from '~/lib/bindings/definitions/IBasicConnectorBinding'
|
||||
import { resolveClientConfig } from '~/lib/core/configs/apollo'
|
||||
|
||||
export type DUIAccount = {
|
||||
/** account info coming from the host app */
|
||||
accountInfo: Account
|
||||
/** the graphql client; a bit superflous */
|
||||
client?: ApolloClient<unknown>
|
||||
/** whether an intial serverinfo query succeeded. */
|
||||
isValid: boolean
|
||||
}
|
||||
|
||||
export type DUIAccountsState = {
|
||||
accounts: Ref<DUIAccount[]>
|
||||
validAccounts: ComputedRef<DUIAccount[]>
|
||||
refreshAccounts: () => Promise<void>
|
||||
defaultAccount: ComputedRef<DUIAccount | undefined>
|
||||
loading: Ref<boolean>
|
||||
}
|
||||
|
||||
const AccountsInjectionKey = 'DUI_ACCOUNTS_STATE'
|
||||
|
||||
/**
|
||||
* Use this composable to set up the account bindings and graphql clients at the top of the app.
|
||||
* TODO: Properly handle cases when user was not connected to the internet,
|
||||
* and then actually got connected.
|
||||
*/
|
||||
export function useAccountsSetup(): DUIAccountsState {
|
||||
const app = useNuxtApp()
|
||||
const $baseBinding = app.$baseBinding
|
||||
|
||||
const accounts = ref<DUIAccount[]>([])
|
||||
|
||||
const apolloClients = {} as Record<string, ApolloClient<unknown>>
|
||||
|
||||
// Tries to connect to the accounts and sets their is valid prop to false if fails.
|
||||
const testAccounts = async (accs: DUIAccount[]) => {
|
||||
const accountTestQuery = gql`
|
||||
query AcccountTestQuery {
|
||||
serverInfo {
|
||||
version
|
||||
name
|
||||
company
|
||||
}
|
||||
}
|
||||
`
|
||||
for (const acc of accs) {
|
||||
if (!acc.client) continue
|
||||
try {
|
||||
await acc.client.query({ query: accountTestQuery })
|
||||
acc.isValid = true
|
||||
} catch {
|
||||
// TODO: properly dispose and kill this client. It's unclear how to do it.
|
||||
acc.isValid = false
|
||||
// NOTE: we do not want to delete the client, as we might want to "refresh" in
|
||||
// case the user was not connected to the interweb.
|
||||
// acc.client.disableNetworkFetches = true
|
||||
// acc.client.stop()
|
||||
// delete acc.client
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const loading = ref(false)
|
||||
|
||||
// Matches local accounts coming from the host app to app state.
|
||||
const refreshAccounts = async () => {
|
||||
loading.value = true
|
||||
|
||||
const accs = await $baseBinding.getAccounts()
|
||||
// We create a whole new list of accounts that will replace the old list. This way we ensure we drop
|
||||
// out of scope old accounts that not exist anymore (TODO: test), and we don't need to do complex diffing.
|
||||
const newAccs = [] as DUIAccount[]
|
||||
for (const acc of accs) {
|
||||
const existing = accounts.value.find((a) => a.accountInfo.id === acc.id)
|
||||
if (existing) {
|
||||
newAccs.push(existing as DUIAccount)
|
||||
continue
|
||||
}
|
||||
|
||||
const client = new ApolloClient(
|
||||
resolveClientConfig({
|
||||
httpEndpoint: new URL('/graphql', acc.serverInfo.url).href,
|
||||
authToken: () => acc.token
|
||||
})
|
||||
)
|
||||
|
||||
apolloClients[acc.id] = client
|
||||
|
||||
newAccs.push({
|
||||
accountInfo: acc,
|
||||
client,
|
||||
isValid: true
|
||||
})
|
||||
}
|
||||
// We test accounts here so we try to prevent the app from querying/using invalid accounts.
|
||||
await testAccounts(newAccs)
|
||||
// Once we have tested the new accounts, finally set them.
|
||||
accounts.value = newAccs
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
void refreshAccounts() // Promise that we do not want to await (convention with void)
|
||||
|
||||
const defaultAccount = computed(() =>
|
||||
accounts.value.find((acc) => acc.accountInfo.isDefault)
|
||||
)
|
||||
|
||||
const validAccounts = computed(() => {
|
||||
return accounts.value.filter((a) => a.isValid)
|
||||
})
|
||||
|
||||
const accState = {
|
||||
accounts,
|
||||
defaultAccount,
|
||||
validAccounts,
|
||||
refreshAccounts,
|
||||
loading
|
||||
}
|
||||
|
||||
app.vueApp.provide(ApolloClients, apolloClients)
|
||||
provide(AccountsInjectionKey, accState)
|
||||
|
||||
return accState // as DUIAccountsState
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this composable to access the users' local accounts and their corresponding graphql client.
|
||||
*/
|
||||
export function useInjectedAccounts(): DUIAccountsState {
|
||||
const state = inject(AccountsInjectionKey) as DUIAccountsState
|
||||
return state
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
import type { IBinding, IBindingSharedEvents } from 'lib/bindings/definitions/IBinding'
|
||||
import type {
|
||||
IBinding,
|
||||
IBindingSharedEvents
|
||||
} from '~/lib/bindings/definitions/IBinding'
|
||||
|
||||
export const IAccountBindingKey = 'accountsBinding'
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ConversionResult } from 'lib/conversions/conversionResult'
|
||||
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
||||
import type { IModelCardSharedEvents } from '~/lib/models/card'
|
||||
import type { CardSetting } from '~/lib/models/card/setting'
|
||||
import type {
|
||||
|
||||
@@ -5,7 +5,7 @@ import type {
|
||||
} from '~~/lib/bindings/definitions/IBinding'
|
||||
import type { CardSetting } from '~/lib/models/card/setting'
|
||||
import type { IModelCardSharedEvents } from '~/lib/models/card'
|
||||
import type { ConversionResult } from 'lib/conversions/conversionResult'
|
||||
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
||||
import type { CreateVersionArgs } from '~/lib/bridge/server'
|
||||
|
||||
export const ISendBindingKey = 'sendBinding'
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
import { ArchicadBridge } from '~/lib/bridge/server'
|
||||
import { BaseBridge } from '~/lib/bridge/base'
|
||||
import type { IRawBridge } from '~/lib/bridge/definitions'
|
||||
|
||||
/**
|
||||
* A generic bridge class for Webivew2 or CefSharp.
|
||||
*/
|
||||
export class GenericBridge extends BaseBridge {
|
||||
private bridge: IRawBridge
|
||||
private archicadBridge: ArchicadBridge | undefined
|
||||
private requests = {} as Record<
|
||||
string,
|
||||
{
|
||||
methodName: string
|
||||
resolve: (value: unknown) => void
|
||||
reject: (reason: string | Error) => void
|
||||
rejectTimerId: number
|
||||
}
|
||||
>
|
||||
// TOTHINK: as this is a fast timeout, it forces us for long await methods in .net to return results via events. Kind-of not cool, and i'd be in favour of bumping it to "endless", or remove it altogether
|
||||
// An example is the send or receive operations: they can take fucking long :D
|
||||
private TIMEOUT_MS = 1000 * 60 // 60 sec
|
||||
|
||||
constructor(object: IRawBridge, isArchicadBridge: boolean = false) {
|
||||
super()
|
||||
this.bridge = object
|
||||
if (isArchicadBridge) {
|
||||
this.archicadBridge = new ArchicadBridge(this.emitter)
|
||||
}
|
||||
}
|
||||
|
||||
public async create(): Promise<boolean> {
|
||||
// NOTE: GetMethods is a call to the .NET side.
|
||||
|
||||
try {
|
||||
this.availableMethodNames = await this.bridge.GetBindingsMethodNames()
|
||||
} catch {
|
||||
console.warn(`Failed to get method names from binding.`)
|
||||
return false
|
||||
}
|
||||
|
||||
// NOTE: hoisting original calls as lowerCasedMethodNames, but using the UpperCasedName for the .NET call
|
||||
// This allows us to follow js convetions and keep .NET ones too (eg. bindings.sayHi('') => public string SayHi(string name) {}
|
||||
for (const methodName of this.availableMethodNames) {
|
||||
const lowercasedMethodName = lowercaseMethodName(methodName)
|
||||
const hoistTarget = this as unknown as Record<string, object>
|
||||
hoistTarget[lowercasedMethodName] = (...args: unknown[]) =>
|
||||
this.runMethod(methodName, args)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private async emitResponseReady(eventName: string, requestId: string) {
|
||||
this.registerPromise(eventName, requestId)
|
||||
const data = await this.bridge.GetCallResult(requestId)
|
||||
const request = this.requests[requestId]
|
||||
try {
|
||||
const parsedData = data ? (JSON.parse(data) as Record<string, unknown>) : null
|
||||
|
||||
if (parsedData === null) {
|
||||
throw new Error(`Data is not parsed successfuly on ${eventName}`)
|
||||
}
|
||||
|
||||
if (this.archicadBridge) {
|
||||
this.archicadBridge.emit(eventName, parsedData, this.runMethod.bind(this))
|
||||
} else {
|
||||
this.emitter.emit(eventName, parsedData)
|
||||
}
|
||||
|
||||
request.resolve(parsedData)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
request.reject(e as Error)
|
||||
} finally {
|
||||
window.clearTimeout(request.rejectTimerId)
|
||||
delete this.requests[requestId]
|
||||
}
|
||||
}
|
||||
|
||||
async runMethod(
|
||||
methodName: string,
|
||||
args: unknown[],
|
||||
shouldTimeout: boolean = true
|
||||
): Promise<unknown> {
|
||||
const requestId = (Math.random() + 1).toString(36).substring(2) + '_' + methodName
|
||||
const preserializedArgs = args.map((a) => JSON.stringify(a))
|
||||
|
||||
this.bridge.RunMethod(methodName, requestId, JSON.stringify(preserializedArgs))
|
||||
|
||||
return this.registerPromise(methodName, requestId, shouldTimeout)
|
||||
}
|
||||
|
||||
private async registerPromise(
|
||||
methodName: string,
|
||||
requestId: string,
|
||||
shouldTimeout: boolean = true
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.requests[requestId] = {
|
||||
methodName,
|
||||
resolve,
|
||||
reject,
|
||||
rejectTimerId: window.setTimeout(
|
||||
() => {
|
||||
reject(
|
||||
`.NET response timed out for call to ${methodName} - did not receive anything back in good time (${this.TIMEOUT_MS}ms).`
|
||||
)
|
||||
delete this.requests[requestId]
|
||||
},
|
||||
shouldTimeout ? this.TIMEOUT_MS : 3600000
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private async responseReady(requestId: string) {
|
||||
if (!this.requests[requestId])
|
||||
throw new Error(
|
||||
`.NET Bridge found no request to resolve with the id of ${requestId}. Something is weird!`
|
||||
)
|
||||
|
||||
const request = this.requests[requestId]
|
||||
const data = await this.bridge.GetCallResult(requestId)
|
||||
try {
|
||||
const parsedData = data ? (JSON.parse(data) as Record<string, unknown>) : null // TODO: check if data is undefined
|
||||
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (parsedData && parsedData.hasOwnProperty('error')) {
|
||||
console.error(data)
|
||||
this.emitter.emit('errorOnResponse', data)
|
||||
throw new Error(
|
||||
`Failed to run ${requestId}. The host app error is logged above.`
|
||||
)
|
||||
}
|
||||
request.resolve(parsedData)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
request.reject(e as Error)
|
||||
} finally {
|
||||
window.clearTimeout(request.rejectTimerId)
|
||||
delete this.requests[requestId]
|
||||
}
|
||||
}
|
||||
|
||||
public showDevTools() {
|
||||
this.bridge.ShowDevTools()
|
||||
}
|
||||
|
||||
public openUrl(url: string) {
|
||||
this.bridge.OpenUrl(url)
|
||||
}
|
||||
}
|
||||
|
||||
const lowercaseMethodName = (name: string) =>
|
||||
name.charAt(0).toLowerCase() + name.slice(1)
|
||||
+105
-19
@@ -1,30 +1,47 @@
|
||||
import { ArchicadBridge } from '~/lib/bridge/server'
|
||||
import { BaseBridge } from '~/lib/bridge/base'
|
||||
import type { IRawBridge } from '~/lib/bridge/definitions'
|
||||
|
||||
/**
|
||||
* A generic bridge class for Webivew2 or CefSharp.
|
||||
*/
|
||||
export class GenericBridge extends BaseBridge {
|
||||
private bridge: IRawBridge
|
||||
private archicadBridge: ArchicadBridge | undefined
|
||||
private requests = {} as Record<
|
||||
string,
|
||||
{
|
||||
methodName: string
|
||||
resolve: (value: unknown) => void
|
||||
reject: (reason: string | Error) => void
|
||||
rejectTimerId: number
|
||||
}
|
||||
>
|
||||
// TOTHINK: as this is a fast timeout, it forces us for long await methods in .net to return results via events. Kind-of not cool, and i'd be in favour of bumping it to "endless", or remove it altogether
|
||||
// An example is the send or receive operations: they can take fucking long :D
|
||||
private TIMEOUT_MS = 1000 * 60 // 60 sec
|
||||
|
||||
constructor(object: IRawBridge) {
|
||||
constructor(object: IRawBridge, isArchicadBridge: boolean = false) {
|
||||
super()
|
||||
this.bridge = object
|
||||
if (isArchicadBridge) {
|
||||
this.archicadBridge = new ArchicadBridge(this.emitter)
|
||||
}
|
||||
}
|
||||
|
||||
public async create(): Promise<boolean> {
|
||||
// NOTE: GetMethods is a call to the .NET side.
|
||||
let availableMethodNames = [] as string[]
|
||||
|
||||
try {
|
||||
availableMethodNames = await this.bridge.GetBindingsMethodNames()
|
||||
this.availableMethodNames = await this.bridge.GetBindingsMethodNames()
|
||||
} catch {
|
||||
console.warn(`Failed to get method names.`)
|
||||
console.warn(`Failed to get method names from binding.`)
|
||||
return false
|
||||
}
|
||||
|
||||
// NOTE: hoisting original calls as lowerCasedMethodNames, but using the UpperCasedName for the .NET call
|
||||
// This allows us to follow js convetions and keep .NET ones too (eg. bindings.sayHi('') => public string SayHi(string name) {}
|
||||
for (const methodName of availableMethodNames) {
|
||||
for (const methodName of this.availableMethodNames) {
|
||||
const lowercasedMethodName = lowercaseMethodName(methodName)
|
||||
const hoistTarget = this as unknown as Record<string, object>
|
||||
hoistTarget[lowercasedMethodName] = (...args: unknown[]) =>
|
||||
@@ -34,27 +51,96 @@ export class GenericBridge extends BaseBridge {
|
||||
return true
|
||||
}
|
||||
|
||||
private async runMethod(methodName: string, args: unknown[]): Promise<unknown> {
|
||||
private async emitResponseReady(eventName: string, requestId: string) {
|
||||
this.registerPromise(eventName, requestId)
|
||||
const data = await this.bridge.GetCallResult(requestId)
|
||||
const request = this.requests[requestId]
|
||||
try {
|
||||
const parsedData = data ? (JSON.parse(data) as Record<string, unknown>) : null
|
||||
|
||||
if (parsedData === null) {
|
||||
throw new Error(`Data is not parsed successfuly on ${eventName}`)
|
||||
}
|
||||
|
||||
if (this.archicadBridge) {
|
||||
this.archicadBridge.emit(eventName, parsedData, this.runMethod.bind(this))
|
||||
} else {
|
||||
this.emitter.emit(eventName, parsedData)
|
||||
}
|
||||
|
||||
request.resolve(parsedData)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
request.reject(e as Error)
|
||||
} finally {
|
||||
window.clearTimeout(request.rejectTimerId)
|
||||
delete this.requests[requestId]
|
||||
}
|
||||
}
|
||||
|
||||
async runMethod(
|
||||
methodName: string,
|
||||
args: unknown[],
|
||||
shouldTimeout: boolean = true
|
||||
): Promise<unknown> {
|
||||
const requestId = (Math.random() + 1).toString(36).substring(2) + '_' + methodName
|
||||
const preserializedArgs = args.map((a) => JSON.stringify(a))
|
||||
|
||||
// NOTE: RunMethod is a call to the .NET side.
|
||||
const result = await this.bridge.RunMethod(
|
||||
methodName,
|
||||
JSON.stringify(preserializedArgs)
|
||||
)
|
||||
this.bridge.RunMethod(methodName, requestId, JSON.stringify(preserializedArgs))
|
||||
|
||||
const parsed = result ? (JSON.parse(result) as Record<string, unknown>) : null
|
||||
return this.registerPromise(methodName, requestId, shouldTimeout)
|
||||
}
|
||||
|
||||
if (parsed && parsed['error']) {
|
||||
console.error(parsed)
|
||||
private async registerPromise(
|
||||
methodName: string,
|
||||
requestId: string,
|
||||
shouldTimeout: boolean = true
|
||||
) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.requests[requestId] = {
|
||||
methodName,
|
||||
resolve,
|
||||
reject,
|
||||
rejectTimerId: window.setTimeout(
|
||||
() => {
|
||||
reject(
|
||||
`.NET response timed out for call to ${methodName} - did not receive anything back in good time (${this.TIMEOUT_MS}ms).`
|
||||
)
|
||||
delete this.requests[requestId]
|
||||
},
|
||||
shouldTimeout ? this.TIMEOUT_MS : 3600000
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private async responseReady(requestId: string) {
|
||||
if (!this.requests[requestId])
|
||||
throw new Error(
|
||||
`Failed to run ${methodName} with args ${JSON.stringify(
|
||||
args
|
||||
)}. The host app error is logged above.`
|
||||
`.NET Bridge found no request to resolve with the id of ${requestId}. Something is weird!`
|
||||
)
|
||||
}
|
||||
|
||||
return parsed
|
||||
const request = this.requests[requestId]
|
||||
const data = await this.bridge.GetCallResult(requestId)
|
||||
try {
|
||||
const parsedData = data ? (JSON.parse(data) as Record<string, unknown>) : null // TODO: check if data is undefined
|
||||
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (parsedData && parsedData.hasOwnProperty('error')) {
|
||||
console.error(data)
|
||||
this.emitter.emit('errorOnResponse', data)
|
||||
throw new Error(
|
||||
`Failed to run ${requestId}. The host app error is logged above.`
|
||||
)
|
||||
}
|
||||
request.resolve(parsedData)
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
request.reject(e as Error)
|
||||
} finally {
|
||||
window.clearTimeout(request.rejectTimerId)
|
||||
delete this.requests[requestId]
|
||||
}
|
||||
}
|
||||
|
||||
public showDevTools() {
|
||||
|
||||
@@ -189,7 +189,7 @@ export class ArchicadBridge {
|
||||
const body: ArchicadReceiveRequest = {
|
||||
accountId: eventPayload.accountId,
|
||||
projectId: eventPayload.projectId,
|
||||
referencedObject: result.data.project.model.version.referencedObject,
|
||||
referencedObject: result.data.project.model.version.referencedObject as string,
|
||||
xmlConverterPath: eventPayload.xmlConverterPath
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ export class ArchicadBridge {
|
||||
serverUrl: account?.accountInfo.serverInfo.url as string,
|
||||
token: account?.accountInfo.token as string,
|
||||
streamId: eventPayload.projectId,
|
||||
objectId: result.data.project.model.version.referencedObject
|
||||
objectId: result.data.project.model.version.referencedObject as string
|
||||
})
|
||||
|
||||
const updateProgress = (e: {
|
||||
@@ -313,7 +313,7 @@ export class ArchicadBridge {
|
||||
})
|
||||
|
||||
// CONVERSION WILL START AFTER THAT
|
||||
await runMethod('afterGetObjects', args as unknown as unknown[])
|
||||
await runMethod('afterGetObjects', args as unknown as unknown[], false)
|
||||
}
|
||||
|
||||
private queuedPromises = {} as Record<string, Promise<Response>[]>
|
||||
@@ -373,7 +373,7 @@ export class ArchicadBridge {
|
||||
this.queuedPromises[modelCardId] = []
|
||||
console.log(`🚀 Upload is completed in ${(performance.now() - start) / 1000} s!`)
|
||||
const args = [eventPayload.modelCardId, referencedObjectId]
|
||||
await runMethod('afterSendObjects', args as unknown as unknown[])
|
||||
await runMethod('afterSendObjects', args as unknown as unknown[], false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,7 +86,7 @@ export class SketchupBridge extends BaseBridge {
|
||||
}
|
||||
|
||||
// NOTE: Overriden emit as we do not need to parse the data back - the Sketchup bridge already parses it for us.
|
||||
emit(eventName: string, payload: string): void {
|
||||
override emit(eventName: string, payload: string): void {
|
||||
const eventPayload = payload as unknown as Record<string, unknown>
|
||||
|
||||
if (eventName === 'sendViaBrowser')
|
||||
@@ -124,7 +124,7 @@ export class SketchupBridge extends BaseBridge {
|
||||
serverUrl: account?.accountInfo.serverInfo.url as string,
|
||||
token: account?.accountInfo.token as string,
|
||||
streamId: eventPayload.projectId,
|
||||
objectId: result.data.project.model.version.referencedObject
|
||||
objectId: result.data.project.model.version.referencedObject as string
|
||||
})
|
||||
|
||||
const updateProgress = (e: {
|
||||
|
||||
@@ -11,17 +11,59 @@ import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-
|
||||
* 3. It does not support dead code elimination, so it will add unused operations.
|
||||
*
|
||||
* Therefore it is highly recommended to use the babel or swc plugin for production.
|
||||
* Learn more about it here: https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#reducing-bundle-size
|
||||
*/
|
||||
const documents = {
|
||||
"\n query AcccountTestQuery {\n serverInfo {\n version\n name\n company\n }\n }\n ": types.AcccountTestQueryDocument,
|
||||
type Documents = {
|
||||
"\n mutation SetActiveWorkspaceMutation($slug: String) {\n activeUserMutations {\n setActiveWorkspace(slug: $slug)\n }\n }\n": typeof types.SetActiveWorkspaceMutationDocument,
|
||||
"\n mutation VersionMutations($input: CreateVersionInput!) {\n versionMutations {\n create(input: $input) {\n id\n }\n }\n }\n": typeof types.VersionMutationsDocument,
|
||||
"\n mutation Update($input: UpdateVersionInput!) {\n versionMutations {\n update(input: $input) {\n id\n }\n }\n }\n": typeof types.UpdateDocument,
|
||||
"\n mutation MarkReceivedVersion($input: MarkReceivedVersionInput!) {\n versionMutations {\n markReceived(input: $input)\n }\n }\n": typeof types.MarkReceivedVersionDocument,
|
||||
"\n mutation CreateModel($input: CreateModelInput!) {\n modelMutations {\n create(input: $input) {\n ...ModelListModelItem\n }\n }\n }\n": typeof types.CreateModelDocument,
|
||||
"\n mutation CreateProject($input: ProjectCreateInput) {\n projectMutations {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n": typeof types.CreateProjectDocument,
|
||||
"\n mutation CreateProjectInWorkspace($input: WorkspaceProjectCreateInput!) {\n workspaceMutations {\n projects {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": typeof types.CreateProjectInWorkspaceDocument,
|
||||
"\n mutation StreamAccessRequestCreate($input: String!) {\n streamAccessRequestCreate(streamId: $input) {\n id\n }\n }\n": typeof types.StreamAccessRequestCreateDocument,
|
||||
"\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logo\n role\n readOnly\n creationState {\n completed\n }\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n": typeof types.WorkspaceListWorkspaceItemFragmentDoc,
|
||||
"\n fragment AutomateFunctionItem on AutomateFunction {\n name\n isFeatured\n id\n creator {\n name\n }\n releases {\n items {\n inputSchema\n }\n }\n }\n": typeof types.AutomateFunctionItemFragmentDoc,
|
||||
"\n mutation CreateAutomation($projectId: ID!, $input: ProjectAutomationCreateInput!) {\n projectMutations {\n automationMutations(projectId: $projectId) {\n create(input: $input) {\n id\n name\n }\n }\n }\n }\n": typeof types.CreateAutomationDocument,
|
||||
"\n fragment AutomateFunctionRunItem on AutomateFunctionRun {\n id\n status\n statusMessage\n results\n contextView\n function {\n id\n name\n logo\n }\n }\n": typeof types.AutomateFunctionRunItemFragmentDoc,
|
||||
"\n fragment AutomationRunItem on AutomateRun {\n id\n status\n automation {\n id\n name\n }\n functionRuns {\n ...AutomateFunctionRunItem\n }\n }\n": typeof types.AutomationRunItemFragmentDoc,
|
||||
"\n query AutomationStatus($projectId: String!, $modelId: String!) {\n project(id: $projectId) {\n model(id: $modelId) {\n automationsStatus {\n id\n status\n automationRuns {\n ...AutomationRunItem\n }\n }\n }\n }\n }\n": typeof types.AutomationStatusDocument,
|
||||
"\n query WorkspaceListQuery(\n $limit: Int!\n $filter: UserWorkspacesFilter\n $cursor: String\n ) {\n activeUser {\n id\n workspaces(limit: $limit, filter: $filter, cursor: $cursor) {\n totalCount\n cursor\n items {\n ...WorkspaceListWorkspaceItem\n }\n }\n }\n }\n": typeof types.WorkspaceListQueryDocument,
|
||||
"\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 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 ActiveWorkspace {\n activeUser {\n activeWorkspace {\n ...WorkspaceListWorkspaceItem\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 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 fragment ModelListModelItem on Model {\n displayName\n name\n id\n previewUrl\n updatedAt\n versions(limit: 1) {\n totalCount\n items {\n ...VersionListItem\n }\n }\n }\n": typeof types.ModelListModelItemFragmentDoc,
|
||||
"\n query ProjectModels(\n $projectId: String!\n $cursor: String\n $limit: Int!\n $filter: ProjectModelsFilter\n ) {\n project(id: $projectId) {\n id\n models(cursor: $cursor, limit: $limit, filter: $filter) {\n totalCount\n cursor\n items {\n ...ModelListModelItem\n }\n }\n }\n }\n": typeof types.ProjectModelsDocument,
|
||||
"\n fragment VersionListItem on Version {\n id\n referencedObject\n message\n sourceApplication\n authorUser {\n avatar\n id\n name\n }\n createdAt\n previewUrl\n }\n": typeof types.VersionListItemFragmentDoc,
|
||||
"\n query ModelVersions(\n $modelId: String!\n $projectId: String!\n $limit: Int!\n $cursor: String\n $filter: ModelVersionsFilter\n ) {\n project(id: $projectId) {\n id\n model(id: $modelId) {\n id\n versions(limit: $limit, cursor: $cursor, filter: $filter) {\n totalCount\n cursor\n items {\n ...VersionListItem\n }\n }\n }\n }\n }\n": typeof types.ModelVersionsDocument,
|
||||
"\n query ObjectQuery($projectId: String!, $objectId: String!) {\n project(id: $projectId) {\n object(id: $objectId) {\n id\n data\n }\n }\n }\n": typeof types.ObjectQueryDocument,
|
||||
"\n query ProjectAddByUrlQueryWithVersion(\n $projectId: String!\n $modelId: String!\n $versionId: String!\n ) {\n project(id: $projectId) {\n ...ProjectListProjectItem\n model(id: $modelId) {\n ...ModelListModelItem\n version(id: $versionId) {\n ...VersionListItem\n }\n }\n }\n }\n": typeof types.ProjectAddByUrlQueryWithVersionDocument,
|
||||
"\n query ProjectAddByUrlQueryWithoutVersion($projectId: String!, $modelId: String!) {\n project(id: $projectId) {\n ...ProjectListProjectItem\n model(id: $modelId) {\n ...ModelListModelItem\n }\n }\n }\n": typeof types.ProjectAddByUrlQueryWithoutVersionDocument,
|
||||
"\n query ProjectDetails($projectId: String!) {\n project(id: $projectId) {\n id\n role\n name\n workspace {\n name\n slug\n readOnly\n role\n }\n team {\n user {\n avatar\n id\n name\n }\n }\n visibility\n permissions {\n canLoad {\n authorized\n code\n message\n }\n canPublish {\n authorized\n code\n message\n }\n }\n }\n }\n": typeof types.ProjectDetailsDocument,
|
||||
"\n query AutomateFunctions {\n automateFunctions {\n items {\n ...AutomateFunctionItem\n }\n }\n }\n": typeof types.AutomateFunctionsDocument,
|
||||
"\n query ModelDetails($modelId: String!, $projectId: String!) {\n project(id: $projectId) {\n id\n name\n model(id: $modelId) {\n id\n displayName\n name\n versions {\n totalCount\n items {\n id\n }\n }\n author {\n id\n name\n avatar\n }\n }\n }\n }\n": typeof types.ModelDetailsDocument,
|
||||
"\n query VersionDetails($projectId: String!, $versionId: String!, $modelId: String!) {\n project(id: $projectId) {\n id\n name\n model(id: $modelId) {\n id\n name\n versions(limit: 1) {\n items {\n id\n createdAt\n sourceApplication\n authorUser {\n id\n }\n }\n }\n version(id: $versionId) {\n id\n referencedObject\n message\n sourceApplication\n createdAt\n previewUrl\n }\n }\n }\n }\n": typeof types.VersionDetailsDocument,
|
||||
"\n query ServerInfo {\n serverInfo {\n workspaces {\n workspacesEnabled\n }\n }\n }\n": typeof types.ServerInfoDocument,
|
||||
"\n subscription OnProjectVersionsUpdate($projectId: String!) {\n projectVersionsUpdated(id: $projectId) {\n id\n type\n version {\n id\n createdAt\n message\n sourceApplication\n authorUser {\n id\n name\n avatar\n }\n model {\n id\n name\n displayName\n }\n }\n }\n }\n": typeof types.OnProjectVersionsUpdateDocument,
|
||||
"\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 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 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,
|
||||
};
|
||||
const documents: Documents = {
|
||||
"\n mutation SetActiveWorkspaceMutation($slug: String) {\n activeUserMutations {\n setActiveWorkspace(slug: $slug)\n }\n }\n": types.SetActiveWorkspaceMutationDocument,
|
||||
"\n mutation VersionMutations($input: CreateVersionInput!) {\n versionMutations {\n create(input: $input) {\n id\n }\n }\n }\n": types.VersionMutationsDocument,
|
||||
"\n mutation Update($input: UpdateVersionInput!) {\n versionMutations {\n update(input: $input) {\n id\n }\n }\n }\n": types.UpdateDocument,
|
||||
"\n mutation MarkReceivedVersion($input: MarkReceivedVersionInput!) {\n versionMutations {\n markReceived(input: $input)\n }\n }\n": types.MarkReceivedVersionDocument,
|
||||
"\n mutation CreateModel($input: CreateModelInput!) {\n modelMutations {\n create(input: $input) {\n ...ModelListModelItem\n }\n }\n }\n": types.CreateModelDocument,
|
||||
"\n mutation CreateProject($input: ProjectCreateInput) {\n projectMutations {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n": types.CreateProjectDocument,
|
||||
"\n mutation CreateProjectInWorkspace($input: WorkspaceProjectCreateInput!) {\n workspaceMutations {\n projects {\n create(input: $input) {\n ...ProjectListProjectItem\n }\n }\n }\n }\n": types.CreateProjectInWorkspaceDocument,
|
||||
"\n mutation StreamAccessRequestCreate($input: String!) {\n streamAccessRequestCreate(streamId: $input) {\n id\n }\n }\n": types.StreamAccessRequestCreateDocument,
|
||||
"\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logo\n role\n readOnly\n }\n": types.WorkspaceListWorkspaceItemFragmentDoc,
|
||||
"\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logo\n role\n readOnly\n creationState {\n completed\n }\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n": types.WorkspaceListWorkspaceItemFragmentDoc,
|
||||
"\n fragment AutomateFunctionItem on AutomateFunction {\n name\n isFeatured\n id\n creator {\n name\n }\n releases {\n items {\n inputSchema\n }\n }\n }\n": types.AutomateFunctionItemFragmentDoc,
|
||||
"\n mutation CreateAutomation($projectId: ID!, $input: ProjectAutomationCreateInput!) {\n projectMutations {\n automationMutations(projectId: $projectId) {\n create(input: $input) {\n id\n name\n }\n }\n }\n }\n": types.CreateAutomationDocument,
|
||||
"\n fragment AutomateFunctionRunItem on AutomateFunctionRun {\n id\n status\n statusMessage\n results\n contextView\n function {\n id\n name\n logo\n }\n }\n": types.AutomateFunctionRunItemFragmentDoc,
|
||||
@@ -68,10 +110,6 @@ const documents = {
|
||||
*/
|
||||
export function graphql(source: string): unknown;
|
||||
|
||||
/**
|
||||
* 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 AcccountTestQuery {\n serverInfo {\n version\n name\n company\n }\n }\n "): (typeof documents)["\n query AcccountTestQuery {\n serverInfo {\n version\n name\n company\n }\n }\n "];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -80,6 +118,10 @@ export function graphql(source: "\n mutation SetActiveWorkspaceMutation($slug:
|
||||
* 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 VersionMutations($input: CreateVersionInput!) {\n versionMutations {\n create(input: $input) {\n id\n }\n }\n }\n"): (typeof documents)["\n mutation VersionMutations($input: CreateVersionInput!) {\n versionMutations {\n create(input: $input) {\n id\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 Update($input: UpdateVersionInput!) {\n versionMutations {\n update(input: $input) {\n id\n }\n }\n }\n"): (typeof documents)["\n mutation Update($input: UpdateVersionInput!) {\n versionMutations {\n update(input: $input) {\n id\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -103,7 +145,7 @@ export function graphql(source: "\n mutation StreamAccessRequestCreate($input:
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logo\n role\n readOnly\n }\n"): (typeof documents)["\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logo\n role\n readOnly\n }\n"];
|
||||
export function graphql(source: "\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logo\n role\n readOnly\n creationState {\n completed\n }\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n"): (typeof documents)["\n fragment WorkspaceListWorkspaceItem on Workspace {\n id\n slug\n name\n description\n createdAt\n updatedAt\n logo\n role\n readOnly\n creationState {\n completed\n }\n permissions {\n canCreateProject {\n authorized\n code\n message\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
@@ -1191,8 +1191,12 @@ export type LimitedUserWorkspaceRoleArgs = {
|
||||
/** Workspace metadata visible to non-workspace members. */
|
||||
export type LimitedWorkspace = {
|
||||
__typename?: 'LimitedWorkspace';
|
||||
/** Workspace admins ordered by join date */
|
||||
adminTeam: Array<LimitedWorkspaceCollaborator>;
|
||||
/** Workspace description */
|
||||
description?: Maybe<Scalars['String']['output']>;
|
||||
/** If true, the users with a matching domain may join the workspace directly */
|
||||
discoverabilityAutoJoinEnabled: Scalars['Boolean']['output'];
|
||||
/** Workspace id */
|
||||
id: Scalars['ID']['output'];
|
||||
/** Optional base64 encoded workspace logo image */
|
||||
@@ -2022,6 +2026,9 @@ export type Project = {
|
||||
commentThreads: ProjectCommentCollection;
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
description?: Maybe<Scalars['String']['output']>;
|
||||
/** Public project-level configuration for embedded viewer */
|
||||
embedOptions: ProjectEmbedOptions;
|
||||
hasAccessToFeature: Scalars['Boolean']['output'];
|
||||
id: Scalars['ID']['output'];
|
||||
invitableCollaborators: WorkspaceCollaboratorCollection;
|
||||
/** Collaborators who have been invited, but not yet accepted. */
|
||||
@@ -2060,7 +2067,7 @@ export type Project = {
|
||||
versions: VersionCollection;
|
||||
/** Return metadata about resources being requested in the viewer */
|
||||
viewerResources: Array<ViewerResourceGroup>;
|
||||
visibility: SimpleProjectVisibility;
|
||||
visibility: ProjectVisibility;
|
||||
webhooks: WebhookCollection;
|
||||
workspace?: Maybe<Workspace>;
|
||||
workspaceId?: Maybe<Scalars['String']['output']>;
|
||||
@@ -2103,6 +2110,11 @@ export type ProjectCommentThreadsArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type ProjectHasAccessToFeatureArgs = {
|
||||
featureName: WorkspaceFeatureName;
|
||||
};
|
||||
|
||||
|
||||
export type ProjectInvitableCollaboratorsArgs = {
|
||||
cursor?: InputMaybe<Scalars['String']['input']>;
|
||||
filter?: InputMaybe<InvitableCollaboratorsFilter>;
|
||||
@@ -2353,6 +2365,11 @@ export type ProjectCreateInput = {
|
||||
visibility?: InputMaybe<ProjectVisibility>;
|
||||
};
|
||||
|
||||
export type ProjectEmbedOptions = {
|
||||
__typename?: 'ProjectEmbedOptions';
|
||||
hideSpeckleBranding: Scalars['Boolean']['output'];
|
||||
};
|
||||
|
||||
export type ProjectFileImportUpdatedMessage = {
|
||||
__typename?: 'ProjectFileImportUpdatedMessage';
|
||||
/** Upload ID */
|
||||
@@ -2573,6 +2590,7 @@ export type ProjectPermissionChecks = {
|
||||
canCreateComment: PermissionCheckResult;
|
||||
canCreateModel: PermissionCheckResult;
|
||||
canDelete: PermissionCheckResult;
|
||||
canInvite: PermissionCheckResult;
|
||||
canLeave: PermissionCheckResult;
|
||||
canLoad: PermissionCheckResult;
|
||||
canMoveToWorkspace: PermissionCheckResult;
|
||||
@@ -2671,9 +2689,14 @@ export enum ProjectVersionsUpdatedMessageType {
|
||||
}
|
||||
|
||||
export enum ProjectVisibility {
|
||||
/** Only accessible to explicit collaborators */
|
||||
Private = 'PRIVATE',
|
||||
/** Accessible to everyone (even non-logged in users) */
|
||||
Public = 'PUBLIC',
|
||||
Unlisted = 'UNLISTED'
|
||||
/** Legacy - same as public */
|
||||
Unlisted = 'UNLISTED',
|
||||
/** Accessible to everyone in the project's workspace */
|
||||
Workspace = 'WORKSPACE'
|
||||
}
|
||||
|
||||
export type Query = {
|
||||
@@ -3219,12 +3242,6 @@ export type SetPrimaryUserEmailInput = {
|
||||
id: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
/** Visibility without the "discoverable" option */
|
||||
export enum SimpleProjectVisibility {
|
||||
Private = 'PRIVATE',
|
||||
Unlisted = 'UNLISTED'
|
||||
}
|
||||
|
||||
export type SmartTextEditorValue = {
|
||||
__typename?: 'SmartTextEditorValue';
|
||||
/** File attachments, if any */
|
||||
@@ -3300,6 +3317,7 @@ export type Stream = {
|
||||
/**
|
||||
* Whether the stream (if public) can be found on public stream exploration pages
|
||||
* and searches
|
||||
* @deprecated Discoverability as a feature has been removed.
|
||||
*/
|
||||
isDiscoverable: Scalars['Boolean']['output'];
|
||||
/** Whether the stream can be viewed by non-contributors */
|
||||
@@ -4094,12 +4112,14 @@ export type UserMeta = {
|
||||
__typename?: 'UserMeta';
|
||||
legacyProjectsExplainerCollapsed: Scalars['Boolean']['output'];
|
||||
newWorkspaceExplainerDismissed: Scalars['Boolean']['output'];
|
||||
speckleConBannerDismissed: Scalars['Boolean']['output'];
|
||||
};
|
||||
|
||||
export type UserMetaMutations = {
|
||||
__typename?: 'UserMetaMutations';
|
||||
setLegacyProjectsExplainerCollapsed: Scalars['Boolean']['output'];
|
||||
setNewWorkspaceExplainerDismissed: Scalars['Boolean']['output'];
|
||||
setSpeckleConBannerDismissed: Scalars['Boolean']['output'];
|
||||
};
|
||||
|
||||
|
||||
@@ -4112,6 +4132,11 @@ export type UserMetaMutationsSetNewWorkspaceExplainerDismissedArgs = {
|
||||
value: Scalars['Boolean']['input'];
|
||||
};
|
||||
|
||||
|
||||
export type UserMetaMutationsSetSpeckleConBannerDismissedArgs = {
|
||||
value: Scalars['Boolean']['input'];
|
||||
};
|
||||
|
||||
export type UserProjectCollection = {
|
||||
__typename?: 'UserProjectCollection';
|
||||
cursor?: Maybe<Scalars['String']['output']>;
|
||||
@@ -4178,6 +4203,7 @@ export type UserUpdateInput = {
|
||||
};
|
||||
|
||||
export type UserWorkspacesFilter = {
|
||||
completed?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
search?: InputMaybe<Scalars['String']['input']>;
|
||||
};
|
||||
|
||||
@@ -4436,13 +4462,19 @@ export type Workspace = {
|
||||
* region.
|
||||
*/
|
||||
defaultRegion?: Maybe<ServerRegionItem>;
|
||||
/** The default seat assigned to users that join a workspace. Used during workspace discovery or on invites without seat types. */
|
||||
defaultSeatType: WorkspaceSeatType;
|
||||
description?: Maybe<Scalars['String']['output']>;
|
||||
/** If true, allow users to automatically join discoverable workspaces (instead of requesting to join) */
|
||||
discoverabilityAutoJoinEnabled: Scalars['Boolean']['output'];
|
||||
/** Enable/Disable discovery of the workspace */
|
||||
discoverabilityEnabled: Scalars['Boolean']['output'];
|
||||
/** Enable/Disable restriction to invite users to workspace as Guests only */
|
||||
domainBasedMembershipProtectionEnabled: Scalars['Boolean']['output'];
|
||||
/** Verified workspace domains */
|
||||
domains?: Maybe<Array<WorkspaceDomain>>;
|
||||
/** Workspace-level configuration for models in embedded viewer */
|
||||
embedOptions: WorkspaceEmbedOptions;
|
||||
hasAccessToFeature: Scalars['Boolean']['output'];
|
||||
id: Scalars['ID']['output'];
|
||||
/** Only available to workspace owners/members */
|
||||
@@ -4534,6 +4566,7 @@ export type WorkspaceBillingMutationsUpgradePlanArgs = {
|
||||
/** Overridden by `WorkspaceCollaboratorGraphQLReturn` */
|
||||
export type WorkspaceCollaborator = {
|
||||
__typename?: 'WorkspaceCollaborator';
|
||||
email?: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['ID']['output'];
|
||||
/** Date that the user joined the workspace. */
|
||||
joinDate: Scalars['DateTime']['output'];
|
||||
@@ -4594,8 +4627,14 @@ export type WorkspaceDomainDeleteInput = {
|
||||
workspaceId: Scalars['ID']['input'];
|
||||
};
|
||||
|
||||
export type WorkspaceEmbedOptions = {
|
||||
__typename?: 'WorkspaceEmbedOptions';
|
||||
hideSpeckleBranding: Scalars['Boolean']['output'];
|
||||
};
|
||||
|
||||
export enum WorkspaceFeatureName {
|
||||
DomainBasedSecurityPolicies = 'domainBasedSecurityPolicies',
|
||||
HideSpeckleBranding = 'hideSpeckleBranding',
|
||||
OidcSso = 'oidcSso',
|
||||
WorkspaceDataRegionSpecificity = 'workspaceDataRegionSpecificity'
|
||||
}
|
||||
@@ -4671,6 +4710,7 @@ export type WorkspaceInviteUseInput = {
|
||||
export type WorkspaceJoinRequest = {
|
||||
__typename?: 'WorkspaceJoinRequest';
|
||||
createdAt: Scalars['DateTime']['output'];
|
||||
email?: Maybe<Scalars['String']['output']>;
|
||||
id: Scalars['String']['output'];
|
||||
status: WorkspaceJoinRequestStatus;
|
||||
user: LimitedUser;
|
||||
@@ -4721,7 +4761,6 @@ export type WorkspaceMutations = {
|
||||
/** Dismiss a workspace from the discoverable list, behind the scene a join request is created with the status "dismissed" */
|
||||
dismiss: Scalars['Boolean']['output'];
|
||||
invites: WorkspaceInviteMutations;
|
||||
join: Workspace;
|
||||
leave: Scalars['Boolean']['output'];
|
||||
projects: WorkspaceProjectMutations;
|
||||
requestToJoin: Scalars['Boolean']['output'];
|
||||
@@ -4729,6 +4768,7 @@ export type WorkspaceMutations = {
|
||||
setDefaultRegion: Workspace;
|
||||
update: Workspace;
|
||||
updateCreationState: Scalars['Boolean']['output'];
|
||||
updateEmbedOptions: WorkspaceEmbedOptions;
|
||||
updateRole: Workspace;
|
||||
updateSeatType: Workspace;
|
||||
};
|
||||
@@ -4764,11 +4804,6 @@ export type WorkspaceMutationsDismissArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type WorkspaceMutationsJoinArgs = {
|
||||
input: JoinWorkspaceInput;
|
||||
};
|
||||
|
||||
|
||||
export type WorkspaceMutationsLeaveArgs = {
|
||||
id: Scalars['ID']['input'];
|
||||
};
|
||||
@@ -4795,6 +4830,11 @@ export type WorkspaceMutationsUpdateCreationStateArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type WorkspaceMutationsUpdateEmbedOptionsArgs = {
|
||||
input: WorkspaceUpdateEmbedOptionsInput;
|
||||
};
|
||||
|
||||
|
||||
export type WorkspaceMutationsUpdateRoleArgs = {
|
||||
input: WorkspaceRoleUpdateInput;
|
||||
};
|
||||
@@ -4821,7 +4861,10 @@ export enum WorkspacePaymentMethod {
|
||||
export type WorkspacePermissionChecks = {
|
||||
__typename?: 'WorkspacePermissionChecks';
|
||||
canCreateProject: PermissionCheckResult;
|
||||
canEditEmbedOptions: PermissionCheckResult;
|
||||
canInvite: PermissionCheckResult;
|
||||
canMoveProjectToWorkspace: PermissionCheckResult;
|
||||
canReadMemberEmail: PermissionCheckResult;
|
||||
};
|
||||
|
||||
|
||||
@@ -5052,8 +5095,15 @@ export type WorkspaceTeamFilter = {
|
||||
seatType?: InputMaybe<WorkspaceSeatType>;
|
||||
};
|
||||
|
||||
export type WorkspaceUpdateEmbedOptionsInput = {
|
||||
hideSpeckleBranding: Scalars['Boolean']['input'];
|
||||
workspaceId: Scalars['String']['input'];
|
||||
};
|
||||
|
||||
export type WorkspaceUpdateInput = {
|
||||
defaultSeatType?: InputMaybe<WorkspaceSeatType>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
discoverabilityAutoJoinEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
discoverabilityEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
domainBasedMembershipProtectionEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
id: Scalars['String']['input'];
|
||||
@@ -5077,11 +5127,6 @@ export type WorkspaceUpdatedMessage = {
|
||||
workspace: Workspace;
|
||||
};
|
||||
|
||||
export type AcccountTestQueryQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type AcccountTestQueryQuery = { __typename?: 'Query', serverInfo: { __typename?: 'ServerInfo', version?: string | null, name: string, company?: string | null } };
|
||||
|
||||
export type SetActiveWorkspaceMutationMutationVariables = Exact<{
|
||||
slug?: InputMaybe<Scalars['String']['input']>;
|
||||
}>;
|
||||
@@ -5096,6 +5141,13 @@ export type VersionMutationsMutationVariables = Exact<{
|
||||
|
||||
export type VersionMutationsMutation = { __typename?: 'Mutation', versionMutations: { __typename?: 'VersionMutations', create: { __typename?: 'Version', id: string } } };
|
||||
|
||||
export type UpdateMutationVariables = Exact<{
|
||||
input: UpdateVersionInput;
|
||||
}>;
|
||||
|
||||
|
||||
export type UpdateMutation = { __typename?: 'Mutation', versionMutations: { __typename?: 'VersionMutations', update: { __typename?: 'Version', id: string } } };
|
||||
|
||||
export type MarkReceivedVersionMutationVariables = Exact<{
|
||||
input: MarkReceivedVersionInput;
|
||||
}>;
|
||||
@@ -5131,7 +5183,7 @@ export type StreamAccessRequestCreateMutationVariables = Exact<{
|
||||
|
||||
export type StreamAccessRequestCreateMutation = { __typename?: 'Mutation', streamAccessRequestCreate: { __typename?: 'StreamAccessRequest', id: string } };
|
||||
|
||||
export type WorkspaceListWorkspaceItemFragment = { __typename?: 'Workspace', id: string, slug: string, name: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, role?: string | null, readOnly: boolean };
|
||||
export type WorkspaceListWorkspaceItemFragment = { __typename?: 'Workspace', id: string, slug: string, name: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, role?: string | null, readOnly: boolean, creationState?: { __typename?: 'WorkspaceCreationState', completed: boolean } | null, permissions: { __typename?: 'WorkspacePermissionChecks', canCreateProject: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string } } };
|
||||
|
||||
export type AutomateFunctionItemFragment = { __typename?: 'AutomateFunction', name: string, isFeatured: boolean, id: string, creator?: { __typename?: 'LimitedUser', name: string } | null, releases: { __typename?: 'AutomateFunctionReleaseCollection', items: Array<{ __typename?: 'AutomateFunctionRelease', inputSchema?: {} | null }> } };
|
||||
|
||||
@@ -5162,7 +5214,7 @@ export type WorkspaceListQueryQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type WorkspaceListQueryQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', id: string, workspaces: { __typename?: 'WorkspaceCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'Workspace', id: string, slug: string, name: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, role?: string | null, readOnly: boolean }> } } | null };
|
||||
export type WorkspaceListQueryQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', id: string, workspaces: { __typename?: 'WorkspaceCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'Workspace', id: string, slug: string, name: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, role?: string | null, readOnly: boolean, creationState?: { __typename?: 'WorkspaceCreationState', completed: boolean } | null, permissions: { __typename?: 'WorkspacePermissionChecks', canCreateProject: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string } } }> } } | null };
|
||||
|
||||
export type CanCreatePersonalProjectQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -5186,7 +5238,7 @@ export type CanCreateModelInProjectQuery = { __typename?: 'Query', project: { __
|
||||
export type ActiveWorkspaceQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ActiveWorkspaceQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', activeWorkspace?: { __typename?: 'Workspace', id: string, slug: string, name: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, role?: string | null, readOnly: boolean } | null } | null };
|
||||
export type ActiveWorkspaceQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', activeWorkspace?: { __typename?: 'Workspace', id: string, slug: string, name: string, description?: string | null, createdAt: string, updatedAt: string, logo?: string | null, role?: string | null, readOnly: boolean, creationState?: { __typename?: 'WorkspaceCreationState', completed: boolean } | null, permissions: { __typename?: 'WorkspacePermissionChecks', canCreateProject: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string } } } | null } | null };
|
||||
|
||||
export type ProjectListProjectItemFragment = { __typename?: 'Project', id: string, name: string, role?: string | null, updatedAt: string, workspaceId?: string | null, workspace?: { __typename?: 'Workspace', id: string, name: string, slug: string, role?: string | null } | null, models: { __typename?: 'ModelCollection', totalCount: number }, permissions: { __typename?: 'ProjectPermissionChecks', canLoad: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string }, canPublish: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string } } };
|
||||
|
||||
@@ -5254,7 +5306,7 @@ export type ProjectDetailsQueryVariables = Exact<{
|
||||
}>;
|
||||
|
||||
|
||||
export type ProjectDetailsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, role?: string | null, name: string, visibility: SimpleProjectVisibility, workspace?: { __typename?: 'Workspace', name: string, slug: string, readOnly: boolean, role?: string | null } | null, team: Array<{ __typename?: 'ProjectCollaborator', user: { __typename?: 'LimitedUser', avatar?: string | null, id: string, name: string } }>, permissions: { __typename?: 'ProjectPermissionChecks', canLoad: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string }, canPublish: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string } } } };
|
||||
export type ProjectDetailsQuery = { __typename?: 'Query', project: { __typename?: 'Project', id: string, role?: string | null, name: string, visibility: ProjectVisibility, workspace?: { __typename?: 'Workspace', name: string, slug: string, readOnly: boolean, role?: string | null } | null, team: Array<{ __typename?: 'ProjectCollaborator', user: { __typename?: 'LimitedUser', avatar?: string | null, id: string, name: string } }>, permissions: { __typename?: 'ProjectPermissionChecks', canLoad: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string }, canPublish: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string } } } };
|
||||
|
||||
export type AutomateFunctionsQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
@@ -5300,14 +5352,14 @@ export type ProjectTriggeredAutomationsStatusUpdatedSubscription = { __typename?
|
||||
export type OnUserProjectsUpdatedSubscriptionVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type OnUserProjectsUpdatedSubscription = { __typename?: 'Subscription', userProjectsUpdated: { __typename?: 'UserProjectsUpdatedMessage', id: string, project?: { __typename?: 'Project', id: string, visibility: SimpleProjectVisibility, team: Array<{ __typename?: 'ProjectCollaborator', id: string, role: string }> } | null } };
|
||||
export type OnUserProjectsUpdatedSubscription = { __typename?: 'Subscription', userProjectsUpdated: { __typename?: 'UserProjectsUpdatedMessage', id: string, project?: { __typename?: 'Project', id: string, visibility: ProjectVisibility, team: Array<{ __typename?: 'ProjectCollaborator', id: string, role: string }> } | null } };
|
||||
|
||||
export type ProjectUpdatedSubscriptionVariables = Exact<{
|
||||
projectId: Scalars['String']['input'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ProjectUpdatedSubscription = { __typename?: 'Subscription', projectUpdated: { __typename?: 'ProjectUpdatedMessage', id: string, project?: { __typename?: 'Project', visibility: SimpleProjectVisibility } | null } };
|
||||
export type ProjectUpdatedSubscription = { __typename?: 'Subscription', projectUpdated: { __typename?: 'ProjectUpdatedMessage', id: string, project?: { __typename?: 'Project', visibility: ProjectVisibility } | null } };
|
||||
|
||||
export type SubscriptionSubscriptionVariables = Exact<{
|
||||
target: ViewerUpdateTrackingTarget;
|
||||
@@ -5323,16 +5375,16 @@ export type ProjectCommentsUpdatedSubscriptionVariables = Exact<{
|
||||
|
||||
export type ProjectCommentsUpdatedSubscription = { __typename?: 'Subscription', projectCommentsUpdated: { __typename?: 'ProjectCommentsUpdatedMessage', type: ProjectCommentsUpdatedMessageType, comment?: { __typename?: 'Comment', id: string, hasParent: boolean, author: { __typename?: 'LimitedUser', avatar?: string | null, id: string, name: string }, parent?: { __typename?: 'Comment', id: string } | null } | null } };
|
||||
|
||||
export const WorkspaceListWorkspaceItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}}]}}]} as unknown as DocumentNode<WorkspaceListWorkspaceItemFragment, unknown>;
|
||||
export const WorkspaceListWorkspaceItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}},{"kind":"Field","name":{"kind":"Name","value":"creationState"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"completed"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreateProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]} as unknown as DocumentNode<WorkspaceListWorkspaceItemFragment, unknown>;
|
||||
export const AutomateFunctionItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunction"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"creator"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"releases"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"inputSchema"}}]}}]}}]}}]} as unknown as DocumentNode<AutomateFunctionItemFragment, unknown>;
|
||||
export const AutomateFunctionRunItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionRunItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}},{"kind":"Field","name":{"kind":"Name","value":"results"}},{"kind":"Field","name":{"kind":"Name","value":"contextView"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}}]}}]}}]} as unknown as DocumentNode<AutomateFunctionRunItemFragment, unknown>;
|
||||
export const AutomationRunItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationRunItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"automation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionRunItem"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionRunItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}},{"kind":"Field","name":{"kind":"Name","value":"results"}},{"kind":"Field","name":{"kind":"Name","value":"contextView"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}}]}}]}}]} as unknown as DocumentNode<AutomationRunItemFragment, unknown>;
|
||||
export const ProjectListProjectItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectListProjectItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}},{"kind":"Field","name":{"kind":"Name","value":"models"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canLoad"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canPublish"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectListProjectItemFragment, unknown>;
|
||||
export const VersionListItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"VersionListItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}}]}}]} as unknown as DocumentNode<VersionListItemFragment, unknown>;
|
||||
export const ModelListModelItemFragmentDoc = {"kind":"Document","definitions":[{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ModelListModelItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"VersionListItem"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"VersionListItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}}]}}]} as unknown as DocumentNode<ModelListModelItemFragment, unknown>;
|
||||
export const AcccountTestQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AcccountTestQuery"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"serverInfo"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"company"}}]}}]}}]} as unknown as DocumentNode<AcccountTestQueryQuery, AcccountTestQueryQueryVariables>;
|
||||
export const SetActiveWorkspaceMutationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"SetActiveWorkspaceMutation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"slug"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUserMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"setActiveWorkspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"slug"},"value":{"kind":"Variable","name":{"kind":"Name","value":"slug"}}}]}]}}]}}]} as unknown as DocumentNode<SetActiveWorkspaceMutationMutation, SetActiveWorkspaceMutationMutationVariables>;
|
||||
export const VersionMutationsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"VersionMutations"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateVersionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode<VersionMutationsMutation, VersionMutationsMutationVariables>;
|
||||
export const UpdateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"Update"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateVersionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"update"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]}}]} as unknown as DocumentNode<UpdateMutation, UpdateMutationVariables>;
|
||||
export const MarkReceivedVersionDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"MarkReceivedVersion"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"MarkReceivedVersionInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"versionMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"markReceived"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]}}]} as unknown as DocumentNode<MarkReceivedVersionMutation, MarkReceivedVersionMutationVariables>;
|
||||
export const CreateModelDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateModel"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateModelInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"modelMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ModelListModelItem"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"VersionListItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ModelListModelItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"VersionListItem"}}]}}]}}]}}]} as unknown as DocumentNode<CreateModelMutation, CreateModelMutationVariables>;
|
||||
export const CreateProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectCreateInput"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectListProjectItem"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectListProjectItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}},{"kind":"Field","name":{"kind":"Name","value":"models"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canLoad"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canPublish"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]} as unknown as DocumentNode<CreateProjectMutation, CreateProjectMutationVariables>;
|
||||
@@ -5340,11 +5392,11 @@ export const CreateProjectInWorkspaceDocument = {"kind":"Document","definitions"
|
||||
export const StreamAccessRequestCreateDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"StreamAccessRequestCreate"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"streamAccessRequestCreate"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"streamId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}}]}}]}}]} as unknown as DocumentNode<StreamAccessRequestCreateMutation, StreamAccessRequestCreateMutationVariables>;
|
||||
export const CreateAutomationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateAutomation"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ID"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectAutomationCreateInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"projectMutations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"automationMutations"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"projectId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"create"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]} as unknown as DocumentNode<CreateAutomationMutation, CreateAutomationMutationVariables>;
|
||||
export const AutomationStatusDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"AutomationStatus"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"model"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"automationsStatus"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"automationRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomationRunItem"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomateFunctionRunItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateFunctionRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"statusMessage"}},{"kind":"Field","name":{"kind":"Name","value":"results"}},{"kind":"Field","name":{"kind":"Name","value":"contextView"}},{"kind":"Field","name":{"kind":"Name","value":"function"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"AutomationRunItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"AutomateRun"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"status"}},{"kind":"Field","name":{"kind":"Name","value":"automation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"functionRuns"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"AutomateFunctionRunItem"}}]}}]}}]} as unknown as DocumentNode<AutomationStatusQuery, AutomationStatusQueryVariables>;
|
||||
export const WorkspaceListQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"WorkspaceListQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UserWorkspacesFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}}]}}]} as unknown as DocumentNode<WorkspaceListQueryQuery, WorkspaceListQueryQueryVariables>;
|
||||
export const WorkspaceListQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"WorkspaceListQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UserWorkspacesFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"workspaces"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}},{"kind":"Field","name":{"kind":"Name","value":"creationState"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"completed"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreateProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]} as unknown as DocumentNode<WorkspaceListQueryQuery, WorkspaceListQueryQueryVariables>;
|
||||
export const CanCreatePersonalProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CanCreatePersonalProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreatePersonalProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}}]}}]}}]}}]} as unknown as DocumentNode<CanCreatePersonalProjectQuery, CanCreatePersonalProjectQueryVariables>;
|
||||
export const CanCreateProjectInWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CanCreateProjectInWorkspace"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"workspace"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"workspaceId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreateProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"payload"}}]}}]}}]}}]}}]} as unknown as DocumentNode<CanCreateProjectInWorkspaceQuery, CanCreateProjectInWorkspaceQueryVariables>;
|
||||
export const CanCreateModelInProjectDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"CanCreateModelInProject"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreateModel"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]}}]} as unknown as DocumentNode<CanCreateModelInProjectQuery, CanCreateModelInProjectQueryVariables>;
|
||||
export const ActiveWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ActiveWorkspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeWorkspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}}]}}]} as unknown as DocumentNode<ActiveWorkspaceQuery, ActiveWorkspaceQueryVariables>;
|
||||
export const ActiveWorkspaceDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ActiveWorkspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeWorkspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"WorkspaceListWorkspaceItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Workspace"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"readOnly"}},{"kind":"Field","name":{"kind":"Name","value":"creationState"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"completed"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canCreateProject"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]} as unknown as DocumentNode<ActiveWorkspaceQuery, ActiveWorkspaceQueryVariables>;
|
||||
export const ProjectListQueryDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectListQuery"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"UserProjectsFilter"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"projects"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ProjectListProjectItem"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ProjectListProjectItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Project"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"workspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"workspace"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"slug"}},{"kind":"Field","name":{"kind":"Name","value":"role"}}]}},{"kind":"Field","name":{"kind":"Name","value":"models"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"canLoad"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}},{"kind":"Field","name":{"kind":"Name","value":"canPublish"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"authorized"}},{"kind":"Field","name":{"kind":"Name","value":"code"}},{"kind":"Field","name":{"kind":"Name","value":"message"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectListQueryQuery, ProjectListQueryQueryVariables>;
|
||||
export const ProjectModelsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ProjectModels"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ProjectModelsFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"models"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ModelListModelItem"}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"VersionListItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ModelListModelItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Model"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"displayName"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"IntValue","value":"1"}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"VersionListItem"}}]}}]}}]}}]} as unknown as DocumentNode<ProjectModelsQuery, ProjectModelsQueryVariables>;
|
||||
export const ModelVersionsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ModelVersions"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"limit"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"Int"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"filter"}},"type":{"kind":"NamedType","name":{"kind":"Name","value":"ModelVersionsFilter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"project"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"projectId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"model"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"modelId"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"versions"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"limit"},"value":{"kind":"Variable","name":{"kind":"Name","value":"limit"}}},{"kind":"Argument","name":{"kind":"Name","value":"cursor"},"value":{"kind":"Variable","name":{"kind":"Name","value":"cursor"}}},{"kind":"Argument","name":{"kind":"Name","value":"filter"},"value":{"kind":"Variable","name":{"kind":"Name","value":"filter"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"totalCount"}},{"kind":"Field","name":{"kind":"Name","value":"cursor"}},{"kind":"Field","name":{"kind":"Name","value":"items"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"VersionListItem"}}]}}]}}]}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"VersionListItem"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"Version"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"referencedObject"}},{"kind":"Field","name":{"kind":"Name","value":"message"}},{"kind":"Field","name":{"kind":"Name","value":"sourceApplication"}},{"kind":"Field","name":{"kind":"Name","value":"authorUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"avatar"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"previewUrl"}}]}}]} as unknown as DocumentNode<ModelVersionsQuery, ModelVersionsQueryVariables>;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @param previewUrl url that server returns but does not return the corresponding image if the project is private
|
||||
* @param token auth token to get proper image over url
|
||||
*/
|
||||
export async function usePreviewUrl(
|
||||
token: string,
|
||||
previewUrl?: string
|
||||
): Promise<string | undefined> {
|
||||
if (!previewUrl) return previewUrl
|
||||
const res = await fetch(previewUrl, {
|
||||
headers: { Authorization: `Bearer ${token}` }
|
||||
})
|
||||
|
||||
if (!res.ok) return previewUrl //
|
||||
const blob = await res.blob()
|
||||
return URL.createObjectURL(blob)
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { ToastNotification } from '@speckle/ui-components'
|
||||
import { ToastNotificationType } from '@speckle/ui-components'
|
||||
import { useConfigStore } from '~/store/config'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
|
||||
type Versions = {
|
||||
@@ -18,31 +17,13 @@ export type Version = {
|
||||
|
||||
export function useUpdateConnector() {
|
||||
const hostApp = useHostAppStore()
|
||||
const config = useConfigStore()
|
||||
const { $openUrl } = useNuxtApp()
|
||||
|
||||
const versions = ref<Version[]>([])
|
||||
const latestAvailableVersion = ref<Version | null>(null)
|
||||
|
||||
const isUpToDate = computed(
|
||||
() => hostApp.connectorVersion === latestAvailableVersion.value?.Number
|
||||
)
|
||||
|
||||
async function checkUpdate() {
|
||||
try {
|
||||
await getVersions()
|
||||
if (!isUpToDate.value && !config.isDevMode) {
|
||||
const notification: ToastNotification = {
|
||||
type: ToastNotificationType.Success,
|
||||
title: `New connector update available`,
|
||||
description: latestAvailableVersion.value?.Number.replace('+0', ''), // TODO: currently versions end with "+0" Alan will have a look
|
||||
cta: {
|
||||
title: `Update`,
|
||||
onClick: () => downloadLatestVersion()
|
||||
}
|
||||
}
|
||||
hostApp.setNotification(notification)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
const notification: ToastNotification = {
|
||||
@@ -74,9 +55,5 @@ export function useUpdateConnector() {
|
||||
hostApp.setLatestAvailableVersion(sortedVersions[0])
|
||||
}
|
||||
|
||||
function downloadLatestVersion() {
|
||||
$openUrl(latestAvailableVersion.value?.Url as string)
|
||||
}
|
||||
|
||||
return { checkUpdate }
|
||||
}
|
||||
|
||||
@@ -18,6 +18,16 @@ export const createVersionMutation = graphql(`
|
||||
}
|
||||
`)
|
||||
|
||||
export const setVersionMessageMutation = graphql(`
|
||||
mutation Update($input: UpdateVersionInput!) {
|
||||
versionMutations {
|
||||
update(input: $input) {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const markReceivedVersionMutation = graphql(`
|
||||
mutation MarkReceivedVersion($input: MarkReceivedVersionInput!) {
|
||||
versionMutations {
|
||||
@@ -77,6 +87,16 @@ export const workspaceListFragment = graphql(`
|
||||
logo
|
||||
role
|
||||
readOnly
|
||||
creationState {
|
||||
completed
|
||||
}
|
||||
permissions {
|
||||
canCreateProject {
|
||||
authorized
|
||||
code
|
||||
message
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
import crs from 'crypto-random-string'
|
||||
import type { AutomationRunItemFragment } from 'lib/common/generated/gql/graphql'
|
||||
import type { ConversionResult } from 'lib/conversions/conversionResult'
|
||||
import type { CardSetting } from 'lib/models/card/setting'
|
||||
import type { AutomationRunItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
||||
import type { CardSetting } from '~/lib/models/card/setting'
|
||||
import type { IDiscriminatedObject } from '~~/lib/bindings/definitions/common'
|
||||
import { DiscriminatedObject } from '~~/lib/bindings/definitions/common'
|
||||
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
import type { ConversionResult } from 'lib/conversions/conversionResult'
|
||||
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
||||
|
||||
export type ModelCardNotificationLevel = 'info' | 'danger' | 'warning' | 'success'
|
||||
|
||||
export type ModelCardNotification = {
|
||||
modelCardId: string
|
||||
text: string
|
||||
level: 'info' | 'danger' | 'warning' | 'success'
|
||||
level: ModelCardNotificationLevel
|
||||
secondaryCta?: {
|
||||
name: string
|
||||
tooltipText?: string
|
||||
action: () => void
|
||||
}
|
||||
cta?: {
|
||||
name: string
|
||||
tooltipText?: string
|
||||
action: () => void
|
||||
}
|
||||
/**
|
||||
|
||||
+3
-4
@@ -17,9 +17,6 @@ export default defineNuxtConfig({
|
||||
// lodash: 'lodash-es'
|
||||
},
|
||||
|
||||
// pinia: {
|
||||
// autoImports: ['defineStore', 'storeToRefs']
|
||||
// },
|
||||
runtimeConfig: {
|
||||
public: {
|
||||
mixpanelApiHost: 'UNDEFINED',
|
||||
@@ -29,7 +26,8 @@ export default defineNuxtConfig({
|
||||
speckleUserId: process.env.SPECKLE_USER_ID,
|
||||
speckleUrl: process.env.SPECKLE_URL,
|
||||
speckleSampleProjectId: process.env.SPECKLE_SAMPLE_PROJECT_ID,
|
||||
speckleSampleModelId: process.env.SPECKLE_SAMPLE_MODEL_ID
|
||||
speckleSampleModelId: process.env.SPECKLE_SAMPLE_MODEL_ID,
|
||||
intercomAppId: ''
|
||||
}
|
||||
},
|
||||
vite: {
|
||||
@@ -53,6 +51,7 @@ export default defineNuxtConfig({
|
||||
]
|
||||
},
|
||||
ssr: false,
|
||||
devtools: { enabled: false },
|
||||
build: {
|
||||
transpile: [
|
||||
/^@apollo\/client/,
|
||||
|
||||
+16
-14
@@ -15,7 +15,7 @@
|
||||
"postinstall": "nuxt prepare",
|
||||
"lint:js": "eslint .",
|
||||
"lint:tsc": "vue-tsc --noEmit",
|
||||
"lint:prettier": "prettier --config ../../.prettierrc --ignore-path ../../.prettierignore --check .",
|
||||
"lint:prettier": "prettier --config .prettierrc --ignore-path .prettierignore --check .",
|
||||
"lint:css": "stylelint \"**/*.{css,vue}\"",
|
||||
"lint": "yarn lint:js && yarn lint:tsc && yarn lint:prettier && yarn lint:css",
|
||||
"lint:ci": "yarn lint:tsc && yarn lint:css",
|
||||
@@ -26,16 +26,17 @@
|
||||
"@apollo/client": "^3.7.14",
|
||||
"@headlessui/vue": "^1.7.13",
|
||||
"@heroicons/vue": "^2.0.12",
|
||||
"@intercom/messenger-js-sdk": "^0.0.14",
|
||||
"@jsonforms/core": "3.1.0",
|
||||
"@jsonforms/vue": "3.1.0",
|
||||
"@jsonforms/vue-vanilla": "3.1.0",
|
||||
"@pinia/nuxt": "^0.4.11",
|
||||
"@speckle/objectloader": "^2.24.0",
|
||||
"@speckle/objectsender": "^2.24.0",
|
||||
"@speckle/shared": "^2.24.0",
|
||||
"@speckle/tailwind-theme": "2.24.1-alpha.0",
|
||||
"@speckle/ui-components": "^2.24.0",
|
||||
"@speckle/ui-components-nuxt": "^2.24.0",
|
||||
"@speckle/objectloader": "^2.25.0",
|
||||
"@speckle/objectsender": "^2.25.0",
|
||||
"@speckle/shared": "^2.25.0",
|
||||
"@speckle/tailwind-theme": "2.25.0",
|
||||
"@speckle/ui-components": "^2.25.0",
|
||||
"@speckle/ui-components-nuxt": "^2.25.0",
|
||||
"@vue/apollo-composable": "^4.0.0-beta.5",
|
||||
"@vueuse/core": "^9.13.0",
|
||||
"apollo-upload-client": "^17.0.0",
|
||||
@@ -55,11 +56,11 @@
|
||||
"devDependencies": {
|
||||
"@graphql-codegen/cli": "^5.0.5",
|
||||
"@graphql-codegen/client-preset": "^4.3.0",
|
||||
"@nuxt/eslint": "^0.3.13",
|
||||
"@nuxt/eslint": "^1.3.1",
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
"@parcel/watcher": "^2.5.1",
|
||||
"@types/apollo-upload-client": "^17.0.1",
|
||||
"@types/eslint": "^8.56.10",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/lodash-es": "^4.17.6",
|
||||
"@types/node": "^18",
|
||||
"@typescript-eslint/eslint-plugin": "^8.20.0",
|
||||
@@ -77,10 +78,9 @@
|
||||
"postcss-html": "^1.8.0",
|
||||
"postcss-nesting": "^13.0.1",
|
||||
"prettier": "^2.8.7",
|
||||
"stylelint": "^15.10.1",
|
||||
"stylelint-config-prettier": "^9.0.3",
|
||||
"stylelint-config-recommended-vue": "^1.4.0",
|
||||
"stylelint-config-standard": "^26.0.0",
|
||||
"stylelint": "^16.19.1",
|
||||
"stylelint-config-recommended-vue": "^1.6.0",
|
||||
"stylelint-config-standard": "^38.0.0",
|
||||
"tailwindcss": "^3.4.17",
|
||||
"type-fest": "^3.5.1",
|
||||
"typescript": "^5.7.3",
|
||||
@@ -89,7 +89,9 @@
|
||||
},
|
||||
"resolutions": {
|
||||
"core-js": "3.22.4",
|
||||
"core-js-compat/semver": "^7.5.4"
|
||||
"core-js-compat/semver": "^7.5.4",
|
||||
"@babel/plugin-transform-classes/globals": "13.13.0",
|
||||
"@babel/traverse/globals": "13.13.0"
|
||||
},
|
||||
"packageManager": "yarn@4.9.1"
|
||||
}
|
||||
|
||||
+1
-1
@@ -102,7 +102,7 @@
|
||||
</div>
|
||||
</LayoutPanel>
|
||||
</div>
|
||||
<div v-if="accounts.length !== 0 && !hasNoModelCards" class="space-y-2">
|
||||
<div v-if="accounts.length !== 0 && !hasNoModelCards" class="space-y-2 pb-24">
|
||||
<div v-for="project in store.projectModelGroups" :key="project.projectId">
|
||||
<CommonProjectModelGroup :project="project" />
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -79,7 +79,7 @@
|
||||
</p>
|
||||
</div>
|
||||
<FormButton
|
||||
color="card"
|
||||
:color="'outline'"
|
||||
full-width
|
||||
class="sticky top-10 top-16"
|
||||
@click="runTests()"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { IRawBridge } from '~/lib/bridge/definitions'
|
||||
import { GenericBridge } from '~/lib/bridge/generic-v2'
|
||||
import { GenericBridge } from '~/lib/bridge/generic'
|
||||
import { SketchupBridge } from '~/lib/bridge/sketchup'
|
||||
|
||||
import type { IBasicConnectorBinding } from '~/lib/bindings/definitions/IBasicConnectorBinding'
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
import { watch, computed, ref } from 'vue'
|
||||
import Intercom, {
|
||||
shutdown,
|
||||
show,
|
||||
hide,
|
||||
update,
|
||||
trackEvent
|
||||
} from '@intercom/messenger-js-sdk'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { storeToRefs } from 'pinia'
|
||||
|
||||
const disabledRoutes: string[] = []
|
||||
|
||||
export const useIntercom = () => {
|
||||
const route = useRoute()
|
||||
|
||||
const accountStore = useAccountStore()
|
||||
const { activeAccount } = storeToRefs(accountStore)
|
||||
|
||||
const isInitialized = ref(false)
|
||||
|
||||
const isRouteBlacklisted = computed(() => {
|
||||
return disabledRoutes.some((disabledRoute) => route.path.includes(disabledRoute))
|
||||
})
|
||||
|
||||
const shouldEnableIntercom = computed(() => !isRouteBlacklisted.value)
|
||||
|
||||
const bootIntercom = () => {
|
||||
if (!shouldEnableIntercom.value || isInitialized.value || !activeAccount.value)
|
||||
return
|
||||
|
||||
isInitialized.value = true
|
||||
Intercom({
|
||||
/* eslint-disable camelcase */
|
||||
app_id: 'hoiaq4wn', // note: needs to be harcoded as this is statically served
|
||||
user_id: activeAccount.value.accountInfo.userInfo.id || '',
|
||||
name: activeAccount.value.accountInfo.userInfo.name || '',
|
||||
email: activeAccount.value.accountInfo.userInfo.email || ''
|
||||
})
|
||||
window.Intercom = Intercom
|
||||
}
|
||||
|
||||
const showIntercom = () => {
|
||||
if (!isInitialized.value) return
|
||||
show()
|
||||
}
|
||||
|
||||
const hideIntercom = () => {
|
||||
if (!isInitialized.value) return
|
||||
hide()
|
||||
}
|
||||
|
||||
const shutdownIntercom = () => {
|
||||
if (!isInitialized.value) return
|
||||
shutdown()
|
||||
isInitialized.value = false
|
||||
}
|
||||
|
||||
const trackIntercom = (event: string, metadata?: Record<string, unknown>) => {
|
||||
if (!isInitialized.value) return
|
||||
trackEvent(event, metadata)
|
||||
}
|
||||
|
||||
const updateConnectorDetails = (
|
||||
hostAppName: string,
|
||||
hostAppVersion: string,
|
||||
connectorVersion: string
|
||||
) => {
|
||||
update({
|
||||
page_title: `CNX: (hostApp: ${hostAppName}:v${hostAppVersion}),(version: ${connectorVersion})`
|
||||
})
|
||||
}
|
||||
|
||||
// On route change, check if we need to shutodwn or boot Intercom
|
||||
watch(route, () => {
|
||||
if (isRouteBlacklisted.value) {
|
||||
shutdownIntercom()
|
||||
} else {
|
||||
bootIntercom()
|
||||
}
|
||||
})
|
||||
|
||||
watch(activeAccount, (newValue) => {
|
||||
if (newValue) {
|
||||
if (!isInitialized.value) {
|
||||
bootIntercom() // if active account changed and itercom is not initialised, do it
|
||||
return // we do not need to update, as that's done by default in the init
|
||||
}
|
||||
update({
|
||||
user_id: activeAccount.value.accountInfo.userInfo.id || '',
|
||||
name: activeAccount.value.accountInfo.userInfo.name,
|
||||
email: activeAccount.value.accountInfo.userInfo.email
|
||||
})
|
||||
} else {
|
||||
if (isInitialized.value) {
|
||||
shutdownIntercom()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
show: showIntercom,
|
||||
hide: hideIntercom,
|
||||
shutdown: shutdownIntercom,
|
||||
track: trackIntercom,
|
||||
updateConnectorDetails
|
||||
}
|
||||
}
|
||||
|
||||
export default defineNuxtPlugin(() => {
|
||||
return {
|
||||
provide: {
|
||||
intercom: useIntercom()
|
||||
}
|
||||
}
|
||||
})
|
||||
+2
-3
@@ -15,7 +15,6 @@ import { onError, type ErrorResponse } from '@apollo/client/link/error'
|
||||
import { getMainDefinition } from '@apollo/client/utilities'
|
||||
import { setContext } from '@apollo/client/link/context'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import type { ToastNotification } from '@speckle/ui-components'
|
||||
import { ToastNotificationType } from '@speckle/ui-components'
|
||||
|
||||
export type DUIAccount = {
|
||||
@@ -86,7 +85,7 @@ export const useAccountStore = defineStore('accountStore', () => {
|
||||
try {
|
||||
await acc.client.query({ query: accountTestQuery })
|
||||
acc.isValid = true
|
||||
} catch (error) {
|
||||
} catch {
|
||||
// TODO: properly dispose and kill this client. It's unclear how to do it.
|
||||
acc.isValid = false
|
||||
// NOTE: we do not want to delete the client, as we might want to "refresh" in
|
||||
@@ -116,7 +115,7 @@ export const useAccountStore = defineStore('accountStore', () => {
|
||||
if (res.graphQLErrors) {
|
||||
if (
|
||||
res.graphQLErrors?.some(
|
||||
(err) => err.extensions.code === 'SSO_SESSION_MISSING_OR_EXPIRED_ERROR'
|
||||
(err) => err.extensions?.code === 'SSO_SESSION_MISSING_OR_EXPIRED_ERROR'
|
||||
)
|
||||
) {
|
||||
hostAppStore.setNotification({
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import type { ConnectorConfig } from 'lib/bindings/definitions/IConfigBinding'
|
||||
import type { ConnectorConfig } from '~/lib/bindings/definitions/IConfigBinding'
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useConfigStore = defineStore('configStore', () => {
|
||||
|
||||
+25
-5
@@ -2,7 +2,7 @@ import type {
|
||||
DocumentInfo,
|
||||
DocumentModelStore
|
||||
} from '~/lib/bindings/definitions/IBasicConnectorBinding'
|
||||
import type { IModelCard, ModelCardProgress } from 'lib/models/card'
|
||||
import type { IModelCard, ModelCardProgress } from '~/lib/models/card'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import type { IReceiverModelCard } from '~/lib/models/card/receiver'
|
||||
import type {
|
||||
@@ -12,11 +12,11 @@ import type {
|
||||
ISenderModelCard,
|
||||
RevitViewsSendFilter,
|
||||
SendFilterSelect
|
||||
} from 'lib/models/card/send'
|
||||
} from '~/lib/models/card/send'
|
||||
import type { ToastNotification } from '@speckle/ui-components'
|
||||
import type { Nullable } from '@speckle/shared'
|
||||
import type { HostAppError } from '~/lib/bridge/errorHandler'
|
||||
import type { ConversionResult } from 'lib/conversions/conversionResult'
|
||||
import type { ConversionResult } from '~/lib/conversions/conversionResult'
|
||||
import { defineStore } from 'pinia'
|
||||
import type { CardSetting } from '~/lib/models/card/setting'
|
||||
import type { DUIAccount } from '~/store/accounts'
|
||||
@@ -489,7 +489,10 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
if (typeof args.error === 'string') {
|
||||
model.error = { errorMessage: args.error as string, dismissible: true }
|
||||
} else {
|
||||
model.error = args.error as { errorMessage: string; dismissible: boolean }
|
||||
model.error = args.error as {
|
||||
errorMessage: string
|
||||
dismissible: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -674,7 +677,7 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
'documentChanged',
|
||||
() =>
|
||||
setTimeout(async () => {
|
||||
void trackEvent('DUI3 Action', { name: 'Document changed' })
|
||||
// void trackEvent('DUI3 Action', { name: 'Document changed' }) // noisy
|
||||
void refreshDocumentInfo()
|
||||
await refreshDocumentModelStore() // need to awaited since upgrading the card settings need documentModelStore in place
|
||||
void refreshSendFilters()
|
||||
@@ -691,6 +694,23 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
await refreshSendFilters()
|
||||
await getSendSettings()
|
||||
tryToUpgradeModelCardSettings(sendSettings.value || [], 'SenderModelCard')
|
||||
|
||||
// Intercom shenanningans below
|
||||
// Do not poke intercom in ancient revit version
|
||||
if (
|
||||
hostAppName.value?.toLowerCase() === 'revit' &&
|
||||
hostAppVersion.value?.includes('2022')
|
||||
)
|
||||
return
|
||||
|
||||
// guards against intercom being sometimes slower to init
|
||||
setTimeout(() => {
|
||||
app.$intercom.updateConnectorDetails(
|
||||
hostAppName.value as string,
|
||||
hostAppVersion.value as string,
|
||||
connectorVersion.value as string
|
||||
)
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
initializeApp()
|
||||
|
||||
+2
-6
@@ -1,9 +1,5 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'stylelint-config-standard',
|
||||
'stylelint-config-recommended-vue',
|
||||
'stylelint-config-prettier'
|
||||
],
|
||||
extends: ['stylelint-config-standard', 'stylelint-config-recommended-vue'],
|
||||
// add your custom config here
|
||||
// https://stylelint.io/user-guide/configuration
|
||||
rules: {
|
||||
@@ -14,7 +10,7 @@ module.exports = {
|
||||
ignoreAtRules: ['tailwind', 'apply', 'variants', 'responsive', 'screen']
|
||||
}
|
||||
],
|
||||
'declaration-block-trailing-semicolon': null,
|
||||
'at-rule-no-deprecated': [true, { ignoreAtRules: ['apply'] }],
|
||||
'no-descending-specificity': null
|
||||
},
|
||||
overrides: [
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
import {plugin as speckleThemePlugin} from '@speckle/tailwind-theme'
|
||||
import { plugin as speckleThemePlugin } from '@speckle/tailwind-theme'
|
||||
import { tailwindContentEntries as themeEntries } from '@speckle/tailwind-theme/tailwind-configure'
|
||||
import { tailwindContentEntries as uiLibEntries } from '@speckle/ui-components/tailwind-configure'
|
||||
import formsPlugin from '@tailwindcss/forms'
|
||||
|
||||
Reference in New Issue
Block a user