Merge branch 'main' into andrew/show-admins-in-discoverable-workspace-card
This commit is contained in:
@@ -6,7 +6,7 @@ def speckle_image(package,original_package_name=None):
|
||||
original_package_name = package
|
||||
|
||||
package_dir = 'packages/{}'.format(original_package_name)
|
||||
if package == 'test-deployment' or package == 'monitor-deployment' or package == 'docker-compose-ingress':
|
||||
if package == 'test-deployment' or package == 'docker-compose-ingress':
|
||||
package_dir = 'utils/{}'.format(package)
|
||||
docker_build('speckle/speckle-{}'.format(package),
|
||||
context='../..',
|
||||
|
||||
@@ -66,14 +66,14 @@ helm_resource('minio',
|
||||
deps=['./values/minio.values.yaml'],
|
||||
labels=['speckle-dependencies'])
|
||||
|
||||
helm_resource('redis',
|
||||
release_name='redis',
|
||||
namespace='redis',
|
||||
chart='oci://registry-1.docker.io/bitnamicharts/redis',
|
||||
flags=['--version=18.7.1',
|
||||
'--values=./values/redis.values.yaml',
|
||||
helm_resource('valkey',
|
||||
release_name='valkey',
|
||||
namespace='valkey',
|
||||
chart='oci://registry-1.docker.io/bitnamicharts/valkey',
|
||||
flags=['--version=3.0.8',
|
||||
'--values=./values/valkey.values.yaml',
|
||||
'--kube-context=kind-speckle-server'],
|
||||
deps=['./values/redis.values.yaml'],
|
||||
deps=['./values/valkey.values.yaml'],
|
||||
labels=['speckle-dependencies'])
|
||||
|
||||
#FIXME this helm chart does not deploy any containers, so tilt incorrectly believes it never gets to a final state
|
||||
@@ -98,11 +98,11 @@ helm_resource('ingress-nginx',
|
||||
release_name='ingress-nginx',
|
||||
namespace='ingress-nginx',
|
||||
chart='ingress-nginx-repo/ingress-nginx',
|
||||
flags=['--version=^4.8.0',
|
||||
flags=['--version=4.8.0',
|
||||
'--values=./values/nginx.values.yaml',
|
||||
'--kube-context=kind-speckle-server'],
|
||||
deps=['./values/nginx.values.yaml'],
|
||||
resource_deps=['postgresql', 'minio', 'redis', 'ingress-nginx-repo'],
|
||||
resource_deps=['postgresql', 'minio', 'valkey', 'ingress-nginx-repo'],
|
||||
labels=['speckle-dependencies'])
|
||||
|
||||
# Uncomment the below, and comment out the other helm_resource('speckle-server'...) to use the speckle-server helm chart
|
||||
@@ -113,7 +113,7 @@ helm_resource('ingress-nginx',
|
||||
# namespace='speckle-server',
|
||||
# chart='speckle-server-repo/speckle-server',
|
||||
# deps=['./values/speckle-server.values.yaml'],
|
||||
# resource_deps=['postgresql', 'minio', 'redis', 'ingress-nginx','speckle-server-repo'],
|
||||
# resource_deps=['postgresql', 'minio', 'valkey', 'ingress-nginx','speckle-server-repo'],
|
||||
# flags=['--values=./values/speckle-server.values.yaml', '--devel'],
|
||||
# labels=['speckle-server'])
|
||||
|
||||
@@ -144,7 +144,7 @@ helm_resource('speckle-server',
|
||||
'webhook_service.image',
|
||||
],
|
||||
deps=['../../utils/helm', './values/speckle-server.values.yaml'],
|
||||
resource_deps=['postgresql', 'minio', 'redis', 'ingress-nginx'],
|
||||
resource_deps=['postgresql', 'minio', 'valkey', 'ingress-nginx'],
|
||||
labels=['speckle-server'])
|
||||
|
||||
# TODO this is not yet working as it is expecting the updated version of the test container which is not yet released as of 2.17.16
|
||||
|
||||
@@ -2,7 +2,7 @@ apiVersion: v1
|
||||
data:
|
||||
s3_secret_key: 'bWluaW9hZG1pbg=='
|
||||
session_secret: 'c3BvcmtsZXNzcHJlY2tsZXNzcGVrbGU='
|
||||
redis_url: 'cmVkaXM6Ly86cmVkaXNAcmVkaXMtbWFzdGVyLnJlZGlzLnN2Yy5jbHVzdGVyLmxvY2FsOjYzNzk='
|
||||
redis_url: 'cmVkaXM6Ly86dmFsa2V5QHZhbGtleS1wcmltYXJ5LnZhbGtleS5zdmMuY2x1c3Rlci5sb2NhbDo2Mzc5Cg=='
|
||||
postgres_url: 'cG9zdGdyZXNxbDovL3NwZWNrbGU6c3BlY2tsZUBwb3N0Z3Jlc3FsLnBvc3RncmVzLnN2Yy5jbHVzdGVyLmxvY2FsOjU0MzIvc3BlY2tsZQo='
|
||||
kind: Secret
|
||||
metadata:
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: 'redis'
|
||||
name: 'valkey'
|
||||
@@ -3,7 +3,8 @@ controller:
|
||||
hostNetwork: true
|
||||
admissionWebhooks:
|
||||
enabled: false
|
||||
# progressDeadlineSeconds: 600 #HACK helm chart was complaining that this was less than minReadySeconds https://github.com/kubernetes/ingress-nginx/blob/c72441585e1ab1a32df86e760613d36fa804315d/charts/ingress-nginx/templates/controller-deployment.yaml#L26
|
||||
tcp:
|
||||
5433: 'postgres/postgresql:5432'
|
||||
6380: 'redis/redis-master:6379'
|
||||
6380: 'valkey/valkey-primary:6379'
|
||||
9002: 'minio/minio:9000'
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
architecture: standalone
|
||||
auth:
|
||||
password: redis
|
||||
password: valkey
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
This monorepo is the home of the Speckle v2 web packages:
|
||||
|
||||
- [`packages/server`](https://github.com/specklesystems/speckle-server/blob/main/packages/server): the Server, a nodejs app. Core external dependencies are a Redis and Postgresql db.
|
||||
- [`packages/server`](https://github.com/specklesystems/speckle-server/blob/main/packages/server): the Server, a nodejs app.
|
||||
- [`packages/frontend-2`](https://github.com/specklesystems/speckle-server/blob/main/packages/frontend-2): the Frontend, a Nuxt/Vue app.
|
||||
- [`packages/viewer`](https://github.com/specklesystems/speckle-server/blob/main/packages/viewer): a threejs extension that allows you to display 3D data [](https://www.npmjs.com/package/@speckle/viewer)
|
||||
- [`packages/objectloader`](https://github.com/specklesystems/speckle-server/blob/main/packages/objectloader): a small js utility class that helps you stream an object and all its sub-components from the Speckle Server API. [](https://www.npmjs.com/package/@speckle/objectloader)
|
||||
|
||||
@@ -50,7 +50,7 @@ services:
|
||||
- '127.0.0.1:5402:5432'
|
||||
|
||||
redis:
|
||||
image: 'redis:7-alpine'
|
||||
image: 'valkey/valkey:8.1-alpine'
|
||||
restart: always
|
||||
volumes:
|
||||
- redis-data:/data
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<FormFileUploadZone
|
||||
ref="uploadZone"
|
||||
v-slot="{ isDraggingFiles, openFilePicker }"
|
||||
:disabled="isUploading || disabled"
|
||||
:disabled="isUploading || isDisabled"
|
||||
:size-limit="maxSizeInBytes"
|
||||
:accept="accept"
|
||||
class="flex items-center h-full"
|
||||
@@ -41,14 +41,10 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<p v-if="showEmptyState" class="text-foreground-2 text-heading-sm p-0 m-0">
|
||||
{{
|
||||
emptyStateVariant === 'modelsSection'
|
||||
? 'The project has no models, yet.'
|
||||
: 'No models, yet.'
|
||||
}}
|
||||
<p v-if="emptyStateHeading" :class="emptyStateHeadingClasses">
|
||||
{{ emptyStateHeading }}
|
||||
</p>
|
||||
<p :class="paragraphClasses">
|
||||
<p v-if="!isDisabled" :class="paragraphClasses">
|
||||
Use
|
||||
<NuxtLink :to="connectorsRoute" class="font-medium">
|
||||
<span class="underline">connectors</span>
|
||||
@@ -57,7 +53,7 @@
|
||||
{{ modelName ? 'this model' : 'this project' }}, or drag and drop a
|
||||
IFC/OBJ/STL file here.
|
||||
</p>
|
||||
<div v-if="showEmptyState" :class="buttonsClasses">
|
||||
<div v-if="showEmptyState && !isDisabled" :class="buttonsClasses">
|
||||
<FormButton :to="connectorsRoute" size="sm" color="outline">
|
||||
Install connectors
|
||||
</FormButton>
|
||||
@@ -76,13 +72,43 @@ import { useFileUploadProgressCore } from '~~/lib/form/composables/fileUpload'
|
||||
import { ExclamationTriangleIcon } from '@heroicons/vue/24/solid'
|
||||
import { connectorsRoute } from '~/lib/common/helpers/route'
|
||||
import type { Nullable } from '@speckle/shared'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import type {
|
||||
ProjectCardImportFileArea_ModelFragment,
|
||||
ProjectCardImportFileArea_ProjectFragment
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
|
||||
type EmptyStateVariants = 'modelGrid' | 'modelList' | 'modelsSection'
|
||||
|
||||
graphql(`
|
||||
fragment ProjectCardImportFileArea_Project on Project {
|
||||
id
|
||||
permissions {
|
||||
canCreateModel {
|
||||
...FullPermissionCheckResult
|
||||
}
|
||||
}
|
||||
...UseFileImport_Project
|
||||
}
|
||||
`)
|
||||
|
||||
graphql(`
|
||||
fragment ProjectCardImportFileArea_Model on Model {
|
||||
id
|
||||
name
|
||||
permissions {
|
||||
canCreateVersion {
|
||||
...FullPermissionCheckResult
|
||||
}
|
||||
}
|
||||
...UseFileImport_Model
|
||||
}
|
||||
`)
|
||||
|
||||
const props = defineProps<{
|
||||
projectId: string
|
||||
project: ProjectCardImportFileArea_ProjectFragment
|
||||
model?: ProjectCardImportFileArea_ModelFragment
|
||||
modelName?: string
|
||||
disabled?: boolean
|
||||
emptyStateVariant?: EmptyStateVariants
|
||||
}>()
|
||||
|
||||
@@ -105,10 +131,43 @@ const uploadZone = ref(
|
||||
}>
|
||||
)
|
||||
|
||||
const modelName = computed(() => props.modelName || props.model?.name)
|
||||
const accessCheck = computed(() => {
|
||||
return props.model
|
||||
? props.model.permissions.canCreateVersion
|
||||
: props.project.permissions.canCreateModel
|
||||
})
|
||||
const isDisabled = computed(() => !accessCheck.value.authorized)
|
||||
|
||||
const showEmptyState = computed(
|
||||
() =>
|
||||
props.emptyStateVariant !== 'modelGrid' && props.emptyStateVariant !== 'modelList'
|
||||
)
|
||||
const emptyStateHeading = computed(() => {
|
||||
if (showEmptyState.value) {
|
||||
return props.emptyStateVariant === 'modelsSection'
|
||||
? 'The project has no models, yet.'
|
||||
: 'No models, yet.'
|
||||
}
|
||||
|
||||
if (isDisabled.value) {
|
||||
return modelName.value
|
||||
? 'The model has no versions, yet.'
|
||||
: 'The project has no models, yet.'
|
||||
}
|
||||
|
||||
return undefined
|
||||
})
|
||||
|
||||
const emptyStateHeadingClasses = computed(() => {
|
||||
const classParts = ['text-foreground-2 text-heading-sm p-0 m-0 ']
|
||||
|
||||
if (isDisabled.value) {
|
||||
classParts.push('text-balance text-center')
|
||||
}
|
||||
|
||||
return classParts.join(' ')
|
||||
})
|
||||
|
||||
const containerClasses = computed(() => {
|
||||
const classParts = ['w-full flex justify-center items-center']
|
||||
|
||||
@@ -60,9 +60,8 @@
|
||||
<div v-else>
|
||||
<ProjectCardImportFileArea
|
||||
ref="importArea"
|
||||
:project-id="project.id"
|
||||
:model-name="project.model.name"
|
||||
:disabled="project.workspace?.readOnly"
|
||||
:project="project"
|
||||
:model="project.model"
|
||||
class="h-full w-full"
|
||||
/>
|
||||
</div>
|
||||
@@ -127,8 +126,10 @@ graphql(`
|
||||
...ProjectModelPageVersionsCardVersion
|
||||
}
|
||||
}
|
||||
...ProjectCardImportFileArea_Model
|
||||
}
|
||||
...ProjectsModelPageEmbed_Project
|
||||
...ProjectCardImportFileArea_Project
|
||||
}
|
||||
`)
|
||||
|
||||
|
||||
@@ -78,17 +78,16 @@
|
||||
</NuxtLink>
|
||||
</template>
|
||||
<div
|
||||
v-if="!isPendingModelFragment(model)"
|
||||
v-if="!isPendingModelFragment(model) && project"
|
||||
v-show="!previewUrl && !pendingVersion"
|
||||
class="h-48 w-full relative z-30"
|
||||
>
|
||||
<ProjectCardImportFileArea
|
||||
ref="importArea"
|
||||
empty-state-variant="modelGrid"
|
||||
:project-id="projectId"
|
||||
:model-name="model.name"
|
||||
:project="project"
|
||||
:model="model"
|
||||
class="w-full h-full"
|
||||
:disabled="!canCreateModel?.authorized"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@@ -140,6 +139,7 @@ graphql(`
|
||||
role
|
||||
visibility
|
||||
...ProjectPageModelsActions_Project
|
||||
...ProjectCardImportFileArea_Project
|
||||
permissions {
|
||||
canCreateModel {
|
||||
...FullPermissionCheckResult
|
||||
@@ -178,7 +178,6 @@ const importArea = ref(
|
||||
const showActionsMenu = ref(false)
|
||||
const hovered = ref(false)
|
||||
|
||||
const canCreateModel = computed(() => props.project?.permissions.canCreateModel)
|
||||
const containerClasses = computed(() => {
|
||||
const classParts = [
|
||||
'group rounded-xl bg-foundation border border-outline-3 hover:border-outline-5 w-full z-[0]'
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
/>
|
||||
<div v-else-if="!hideFileUpload">
|
||||
<ProjectCardImportFileArea
|
||||
:disabled="project?.workspace?.readOnly"
|
||||
:project-id="projectId"
|
||||
v-if="project"
|
||||
:project="project"
|
||||
class="h-36 col-span-4"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
/>
|
||||
<div v-else>
|
||||
<ProjectCardImportFileArea
|
||||
:project-id="projectId"
|
||||
:disabled="project?.workspace?.readOnly"
|
||||
v-if="project"
|
||||
:project="project"
|
||||
class="h-36 col-span-4"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
<ProjectCardImportFileArea
|
||||
v-if="!isPendingFileUpload(item)"
|
||||
ref="importArea"
|
||||
:project-id="project.id"
|
||||
:project="project"
|
||||
:model-name="item.fullName"
|
||||
:disabled="!canCreateModel.authorized"
|
||||
:model="item.model || undefined"
|
||||
class="hidden"
|
||||
/>
|
||||
<div
|
||||
@@ -78,9 +78,9 @@
|
||||
:empty-state-variant="
|
||||
props.gridOrList === GridListToggleValue.Grid ? 'modelGrid' : 'modelList'
|
||||
"
|
||||
:project-id="project.id"
|
||||
:project="project"
|
||||
:model-name="item.fullName"
|
||||
:disabled="!canCreateModel.authorized"
|
||||
:model="item.model || undefined"
|
||||
class="h-full w-full"
|
||||
/>
|
||||
</div>
|
||||
@@ -259,6 +259,7 @@ graphql(`
|
||||
fragment ProjectPageModelsStructureItem_Project on Project {
|
||||
id
|
||||
...ProjectPageModelsActions_Project
|
||||
...ProjectCardImportFileArea_Project
|
||||
permissions {
|
||||
canCreateModel {
|
||||
...FullPermissionCheckResult
|
||||
@@ -274,6 +275,7 @@ graphql(`
|
||||
fullName
|
||||
model {
|
||||
...ProjectPageLatestItemsModelItem
|
||||
...ProjectCardImportFileArea_Model
|
||||
}
|
||||
hasChildren
|
||||
updatedAt
|
||||
|
||||
@@ -109,11 +109,7 @@
|
||||
<ProjectCardImportFileArea
|
||||
v-if="hasNoModels"
|
||||
empty-state-variant="modelsSection"
|
||||
:project-id="project.id"
|
||||
:disabled="
|
||||
project?.workspace?.readOnly ||
|
||||
!project.permissions.canCreateModel.authorized
|
||||
"
|
||||
:project="project"
|
||||
class="h-28 col-span-4"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -53,8 +53,10 @@ type Documents = {
|
||||
"\n fragment InviteDialogWorkspace_Workspace on Workspace {\n id\n name\n domainBasedMembershipProtectionEnabled\n domains {\n domain\n id\n }\n }\n": typeof types.InviteDialogWorkspace_WorkspaceFragmentDoc,
|
||||
"\n fragment InviteDialogProject_Project on Project {\n id\n name\n workspaceId\n workspace {\n id\n name\n role\n domainBasedMembershipProtectionEnabled\n domains {\n domain\n id\n }\n }\n }\n": typeof types.InviteDialogProject_ProjectFragmentDoc,
|
||||
"\n query InviteDialogProjectRowProjectCollaborators(\n $projectId: String!\n $filter: InvitableCollaboratorsFilter\n ) {\n project(id: $projectId) {\n invitableCollaborators(filter: $filter) {\n items {\n user {\n id\n name\n }\n }\n }\n }\n }\n": typeof types.InviteDialogProjectRowProjectCollaboratorsDocument,
|
||||
"\n fragment ProjectCardImportFileArea_Project on Project {\n id\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Project\n }\n": typeof types.ProjectCardImportFileArea_ProjectFragmentDoc,
|
||||
"\n fragment ProjectCardImportFileArea_Model on Model {\n id\n name\n permissions {\n canCreateVersion {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Model\n }\n": typeof types.ProjectCardImportFileArea_ModelFragmentDoc,
|
||||
"\n fragment ProjectModelPageHeaderProject on Project {\n id\n name\n model(id: $modelId) {\n id\n name\n description\n }\n workspace {\n id\n slug\n name\n role\n }\n }\n": typeof types.ProjectModelPageHeaderProjectFragmentDoc,
|
||||
"\n fragment ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n }\n ...ProjectsModelPageEmbed_Project\n }\n": typeof types.ProjectModelPageVersionsPaginationFragmentDoc,
|
||||
"\n fragment ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n ...ProjectCardImportFileArea_Model\n }\n ...ProjectsModelPageEmbed_Project\n ...ProjectCardImportFileArea_Project\n }\n": typeof types.ProjectModelPageVersionsPaginationFragmentDoc,
|
||||
"\n fragment ProjectModelPageVersionsProject on Project {\n ...ProjectPageProjectHeader\n model(id: $modelId) {\n id\n name\n pendingImportedVersions {\n ...PendingFileUpload\n }\n }\n ...ProjectModelPageVersionsPagination\n ...ProjectsModelPageEmbed_Project\n workspace {\n id\n readOnly\n }\n }\n": typeof types.ProjectModelPageVersionsProjectFragmentDoc,
|
||||
"\n fragment ProjectModelPageDialogDeleteVersion on Version {\n id\n message\n }\n": typeof types.ProjectModelPageDialogDeleteVersionFragmentDoc,
|
||||
"\n fragment ProjectModelPageDialogEditMessageVersion on Version {\n id\n message\n }\n": typeof types.ProjectModelPageDialogEditMessageVersionFragmentDoc,
|
||||
@@ -80,11 +82,11 @@ type Documents = {
|
||||
"\n fragment ProjectDiscussionsPageResults_Project on Project {\n id\n }\n": typeof types.ProjectDiscussionsPageResults_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsActions on Model {\n id\n name\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n canCreateVersion {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageModelsActionsFragmentDoc,
|
||||
"\n fragment ProjectPageModelsActions_Project on Project {\n id\n workspace {\n id\n slug\n }\n ...ProjectsModelPageEmbed_Project\n }\n": typeof types.ProjectPageModelsActions_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageModelsCardProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageModelsCardProjectFragmentDoc,
|
||||
"\n fragment ProjectModelsPageHeader_Project on Project {\n id\n name\n sourceApps\n role\n models {\n totalCount\n }\n team {\n id\n user {\n ...FormUsersSelectItem\n }\n }\n workspace {\n id\n role\n slug\n name\n readOnly\n plan {\n name\n }\n }\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectModelsPageHeader_ProjectFragmentDoc,
|
||||
"\n fragment ProjectModelsPageResults_Project on Project {\n ...ProjectPageLatestItemsModels\n }\n": typeof types.ProjectModelsPageResults_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageModelsStructureItem_ProjectFragmentDoc,
|
||||
"\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n }\n hasChildren\n updatedAt\n }\n": typeof types.SingleLevelModelTreeItemFragmentDoc,
|
||||
"\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageModelsStructureItem_ProjectFragmentDoc,
|
||||
"\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\n }\n": typeof types.SingleLevelModelTreeItemFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardDeleteDialog on Model {\n id\n name\n }\n": typeof types.ProjectPageModelsCardDeleteDialogFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardRenameDialog on Model {\n id\n name\n description\n }\n": typeof types.ProjectPageModelsCardRenameDialogFragmentDoc,
|
||||
"\n query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\n }\n }\n": typeof types.ProjectPageSettingsGeneralDocument,
|
||||
@@ -186,6 +188,8 @@ type Documents = {
|
||||
"\n query ServerInfoBlobSizeLimit {\n serverInfo {\n configuration {\n blobSizeLimitBytes\n }\n }\n }\n": typeof types.ServerInfoBlobSizeLimitDocument,
|
||||
"\n query ServerInfoAllScopes {\n serverInfo {\n scopes {\n name\n description\n }\n }\n }\n": typeof types.ServerInfoAllScopesDocument,
|
||||
"\n query ProjectModelsSelectorValues($projectId: String!, $cursor: String) {\n project(id: $projectId) {\n id\n models(limit: 100, cursor: $cursor) {\n cursor\n totalCount\n items {\n ...CommonModelSelectorModel\n }\n }\n }\n }\n": typeof types.ProjectModelsSelectorValuesDocument,
|
||||
"\n fragment UseFileImport_Project on Project {\n id\n }\n": typeof types.UseFileImport_ProjectFragmentDoc,
|
||||
"\n fragment UseFileImport_Model on Model {\n id\n name\n }\n": typeof types.UseFileImport_ModelFragmentDoc,
|
||||
"\n query MainServerInfoData {\n serverInfo {\n adminContact\n canonicalUrl\n company\n description\n guestModeEnabled\n inviteOnly\n name\n termsOfService\n version\n automateUrl\n configuration {\n isEmailEnabled\n }\n }\n }\n": typeof types.MainServerInfoDataDocument,
|
||||
"\n mutation DeleteAccessToken($token: String!) {\n apiTokenRevoke(token: $token)\n }\n": typeof types.DeleteAccessTokenDocument,
|
||||
"\n mutation CreateAccessToken($token: ApiTokenCreateInput!) {\n apiTokenCreate(token: $token)\n }\n": typeof types.CreateAccessTokenDocument,
|
||||
@@ -216,11 +220,11 @@ type Documents = {
|
||||
"\n fragment ProjectPageTeamInternals_Project on Project {\n id\n role\n invitedTeam {\n id\n title\n role\n inviteId\n user {\n role\n ...LimitedUserAvatar\n }\n }\n team {\n role\n seatType\n workspaceRole\n user {\n id\n role\n ...LimitedUserAvatar\n }\n }\n }\n": typeof types.ProjectPageTeamInternals_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageTeamDialog on Project {\n id\n name\n role\n allowPublicComments\n visibility\n team {\n id\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n invitedTeam {\n id\n title\n inviteId\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n ...ProjectsPageTeamDialogManagePermissions_Project\n }\n": typeof types.ProjectPageTeamDialogFragmentDoc,
|
||||
"\n fragment ProjectDashboardItemNoModels on Project {\n id\n name\n createdAt\n updatedAt\n role\n team {\n id\n user {\n id\n name\n avatar\n }\n }\n ...ProjectPageModelsCardProject\n }\n": typeof types.ProjectDashboardItemNoModelsFragmentDoc,
|
||||
"\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n": typeof types.ProjectDashboardItemFragmentDoc,
|
||||
"\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n ...ProjectCardImportFileArea_Project\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n": typeof types.ProjectDashboardItemFragmentDoc,
|
||||
"\n fragment PendingFileUpload on FileUpload {\n id\n projectId\n modelName\n convertedStatus\n convertedMessage\n uploadDate\n convertedLastUpdate\n fileType\n fileName\n }\n": typeof types.PendingFileUploadFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageLatestItemsModelItemFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n ...ProjectCardImportFileArea_Model\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectPageLatestItemsModelItemFragmentDoc,
|
||||
"\n fragment ProjectUpdatableMetadata on Project {\n id\n name\n description\n visibility\n allowPublicComments\n permissions {\n canRead {\n ...FullPermissionCheckResult\n }\n canUpdate {\n ...FullPermissionCheckResult\n }\n canUpdateAllowPublicComments {\n ...FullPermissionCheckResult\n }\n canReadSettings {\n ...FullPermissionCheckResult\n }\n canReadWebhooks {\n ...FullPermissionCheckResult\n }\n canLeave {\n ...FullPermissionCheckResult\n }\n }\n }\n": typeof types.ProjectUpdatableMetadataFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n": typeof types.ProjectPageLatestItemsModelsFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n ...ProjectCardImportFileArea_Project\n }\n": typeof types.ProjectPageLatestItemsModelsFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n": typeof types.ProjectPageLatestItemsCommentsFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n }\n": typeof types.ProjectPageLatestItemsCommentItemFragmentDoc,
|
||||
"\n mutation CreateModel($input: CreateModelInput!) {\n modelMutations {\n create(input: $input) {\n ...ProjectPageLatestItemsModelItem\n }\n }\n }\n": typeof types.CreateModelDocument,
|
||||
@@ -468,8 +472,10 @@ const documents: Documents = {
|
||||
"\n fragment InviteDialogWorkspace_Workspace on Workspace {\n id\n name\n domainBasedMembershipProtectionEnabled\n domains {\n domain\n id\n }\n }\n": types.InviteDialogWorkspace_WorkspaceFragmentDoc,
|
||||
"\n fragment InviteDialogProject_Project on Project {\n id\n name\n workspaceId\n workspace {\n id\n name\n role\n domainBasedMembershipProtectionEnabled\n domains {\n domain\n id\n }\n }\n }\n": types.InviteDialogProject_ProjectFragmentDoc,
|
||||
"\n query InviteDialogProjectRowProjectCollaborators(\n $projectId: String!\n $filter: InvitableCollaboratorsFilter\n ) {\n project(id: $projectId) {\n invitableCollaborators(filter: $filter) {\n items {\n user {\n id\n name\n }\n }\n }\n }\n }\n": types.InviteDialogProjectRowProjectCollaboratorsDocument,
|
||||
"\n fragment ProjectCardImportFileArea_Project on Project {\n id\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Project\n }\n": types.ProjectCardImportFileArea_ProjectFragmentDoc,
|
||||
"\n fragment ProjectCardImportFileArea_Model on Model {\n id\n name\n permissions {\n canCreateVersion {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Model\n }\n": types.ProjectCardImportFileArea_ModelFragmentDoc,
|
||||
"\n fragment ProjectModelPageHeaderProject on Project {\n id\n name\n model(id: $modelId) {\n id\n name\n description\n }\n workspace {\n id\n slug\n name\n role\n }\n }\n": types.ProjectModelPageHeaderProjectFragmentDoc,
|
||||
"\n fragment ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n }\n ...ProjectsModelPageEmbed_Project\n }\n": types.ProjectModelPageVersionsPaginationFragmentDoc,
|
||||
"\n fragment ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n ...ProjectCardImportFileArea_Model\n }\n ...ProjectsModelPageEmbed_Project\n ...ProjectCardImportFileArea_Project\n }\n": types.ProjectModelPageVersionsPaginationFragmentDoc,
|
||||
"\n fragment ProjectModelPageVersionsProject on Project {\n ...ProjectPageProjectHeader\n model(id: $modelId) {\n id\n name\n pendingImportedVersions {\n ...PendingFileUpload\n }\n }\n ...ProjectModelPageVersionsPagination\n ...ProjectsModelPageEmbed_Project\n workspace {\n id\n readOnly\n }\n }\n": types.ProjectModelPageVersionsProjectFragmentDoc,
|
||||
"\n fragment ProjectModelPageDialogDeleteVersion on Version {\n id\n message\n }\n": types.ProjectModelPageDialogDeleteVersionFragmentDoc,
|
||||
"\n fragment ProjectModelPageDialogEditMessageVersion on Version {\n id\n message\n }\n": types.ProjectModelPageDialogEditMessageVersionFragmentDoc,
|
||||
@@ -495,11 +501,11 @@ const documents: Documents = {
|
||||
"\n fragment ProjectDiscussionsPageResults_Project on Project {\n id\n }\n": types.ProjectDiscussionsPageResults_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsActions on Model {\n id\n name\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n canCreateVersion {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageModelsActionsFragmentDoc,
|
||||
"\n fragment ProjectPageModelsActions_Project on Project {\n id\n workspace {\n id\n slug\n }\n ...ProjectsModelPageEmbed_Project\n }\n": types.ProjectPageModelsActions_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageModelsCardProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageModelsCardProjectFragmentDoc,
|
||||
"\n fragment ProjectModelsPageHeader_Project on Project {\n id\n name\n sourceApps\n role\n models {\n totalCount\n }\n team {\n id\n user {\n ...FormUsersSelectItem\n }\n }\n workspace {\n id\n role\n slug\n name\n readOnly\n plan {\n name\n }\n }\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectModelsPageHeader_ProjectFragmentDoc,
|
||||
"\n fragment ProjectModelsPageResults_Project on Project {\n ...ProjectPageLatestItemsModels\n }\n": types.ProjectModelsPageResults_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageModelsStructureItem_ProjectFragmentDoc,
|
||||
"\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n }\n hasChildren\n updatedAt\n }\n": types.SingleLevelModelTreeItemFragmentDoc,
|
||||
"\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageModelsStructureItem_ProjectFragmentDoc,
|
||||
"\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\n }\n": types.SingleLevelModelTreeItemFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardDeleteDialog on Model {\n id\n name\n }\n": types.ProjectPageModelsCardDeleteDialogFragmentDoc,
|
||||
"\n fragment ProjectPageModelsCardRenameDialog on Model {\n id\n name\n description\n }\n": types.ProjectPageModelsCardRenameDialogFragmentDoc,
|
||||
"\n query ProjectPageSettingsGeneral($projectId: String!) {\n project(id: $projectId) {\n id\n ...ProjectPageSettingsGeneralBlockProjectInfo_Project\n ...ProjectPageSettingsGeneralBlockAccess_Project\n ...ProjectPageSettingsGeneralBlockDiscussions_Project\n ...ProjectPageSettingsGeneralBlockLeave_Project\n ...ProjectPageSettingsGeneralBlockDelete_Project\n ...ProjectPageTeamInternals_Project\n }\n }\n": types.ProjectPageSettingsGeneralDocument,
|
||||
@@ -601,6 +607,8 @@ const documents: Documents = {
|
||||
"\n query ServerInfoBlobSizeLimit {\n serverInfo {\n configuration {\n blobSizeLimitBytes\n }\n }\n }\n": types.ServerInfoBlobSizeLimitDocument,
|
||||
"\n query ServerInfoAllScopes {\n serverInfo {\n scopes {\n name\n description\n }\n }\n }\n": types.ServerInfoAllScopesDocument,
|
||||
"\n query ProjectModelsSelectorValues($projectId: String!, $cursor: String) {\n project(id: $projectId) {\n id\n models(limit: 100, cursor: $cursor) {\n cursor\n totalCount\n items {\n ...CommonModelSelectorModel\n }\n }\n }\n }\n": types.ProjectModelsSelectorValuesDocument,
|
||||
"\n fragment UseFileImport_Project on Project {\n id\n }\n": types.UseFileImport_ProjectFragmentDoc,
|
||||
"\n fragment UseFileImport_Model on Model {\n id\n name\n }\n": types.UseFileImport_ModelFragmentDoc,
|
||||
"\n query MainServerInfoData {\n serverInfo {\n adminContact\n canonicalUrl\n company\n description\n guestModeEnabled\n inviteOnly\n name\n termsOfService\n version\n automateUrl\n configuration {\n isEmailEnabled\n }\n }\n }\n": types.MainServerInfoDataDocument,
|
||||
"\n mutation DeleteAccessToken($token: String!) {\n apiTokenRevoke(token: $token)\n }\n": types.DeleteAccessTokenDocument,
|
||||
"\n mutation CreateAccessToken($token: ApiTokenCreateInput!) {\n apiTokenCreate(token: $token)\n }\n": types.CreateAccessTokenDocument,
|
||||
@@ -631,11 +639,11 @@ const documents: Documents = {
|
||||
"\n fragment ProjectPageTeamInternals_Project on Project {\n id\n role\n invitedTeam {\n id\n title\n role\n inviteId\n user {\n role\n ...LimitedUserAvatar\n }\n }\n team {\n role\n seatType\n workspaceRole\n user {\n id\n role\n ...LimitedUserAvatar\n }\n }\n }\n": types.ProjectPageTeamInternals_ProjectFragmentDoc,
|
||||
"\n fragment ProjectPageTeamDialog on Project {\n id\n name\n role\n allowPublicComments\n visibility\n team {\n id\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n invitedTeam {\n id\n title\n inviteId\n role\n user {\n ...LimitedUserAvatar\n role\n }\n }\n ...ProjectsPageTeamDialogManagePermissions_Project\n }\n": types.ProjectPageTeamDialogFragmentDoc,
|
||||
"\n fragment ProjectDashboardItemNoModels on Project {\n id\n name\n createdAt\n updatedAt\n role\n team {\n id\n user {\n id\n name\n avatar\n }\n }\n ...ProjectPageModelsCardProject\n }\n": types.ProjectDashboardItemNoModelsFragmentDoc,
|
||||
"\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n": types.ProjectDashboardItemFragmentDoc,
|
||||
"\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n ...ProjectCardImportFileArea_Project\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n": types.ProjectDashboardItemFragmentDoc,
|
||||
"\n fragment PendingFileUpload on FileUpload {\n id\n projectId\n modelName\n convertedStatus\n convertedMessage\n uploadDate\n convertedLastUpdate\n fileType\n fileName\n }\n": types.PendingFileUploadFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageLatestItemsModelItemFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n ...ProjectCardImportFileArea_Model\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectPageLatestItemsModelItemFragmentDoc,
|
||||
"\n fragment ProjectUpdatableMetadata on Project {\n id\n name\n description\n visibility\n allowPublicComments\n permissions {\n canRead {\n ...FullPermissionCheckResult\n }\n canUpdate {\n ...FullPermissionCheckResult\n }\n canUpdateAllowPublicComments {\n ...FullPermissionCheckResult\n }\n canReadSettings {\n ...FullPermissionCheckResult\n }\n canReadWebhooks {\n ...FullPermissionCheckResult\n }\n canLeave {\n ...FullPermissionCheckResult\n }\n }\n }\n": types.ProjectUpdatableMetadataFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n": types.ProjectPageLatestItemsModelsFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n ...ProjectCardImportFileArea_Project\n }\n": types.ProjectPageLatestItemsModelsFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsComments on Project {\n id\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n }\n": types.ProjectPageLatestItemsCommentsFragmentDoc,
|
||||
"\n fragment ProjectPageLatestItemsCommentItem on Comment {\n id\n author {\n ...FormUsersSelectItem\n }\n screenshot\n rawText\n createdAt\n updatedAt\n archived\n repliesCount: replies(limit: 0) {\n totalCount\n }\n replyAuthors(limit: 4) {\n totalCount\n items {\n ...FormUsersSelectItem\n }\n }\n }\n": types.ProjectPageLatestItemsCommentItemFragmentDoc,
|
||||
"\n mutation CreateModel($input: CreateModelInput!) {\n modelMutations {\n create(input: $input) {\n ...ProjectPageLatestItemsModelItem\n }\n }\n }\n": types.CreateModelDocument,
|
||||
@@ -1014,6 +1022,14 @@ export function graphql(source: "\n fragment InviteDialogProject_Project on Pro
|
||||
* 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 InviteDialogProjectRowProjectCollaborators(\n $projectId: String!\n $filter: InvitableCollaboratorsFilter\n ) {\n project(id: $projectId) {\n invitableCollaborators(filter: $filter) {\n items {\n user {\n id\n name\n }\n }\n }\n }\n }\n"): (typeof documents)["\n query InviteDialogProjectRowProjectCollaborators(\n $projectId: String!\n $filter: InvitableCollaboratorsFilter\n ) {\n project(id: $projectId) {\n invitableCollaborators(filter: $filter) {\n items {\n user {\n id\n name\n }\n }\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment ProjectCardImportFileArea_Project on Project {\n id\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Project\n }\n"): (typeof documents)["\n fragment ProjectCardImportFileArea_Project on Project {\n id\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Project\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment ProjectCardImportFileArea_Model on Model {\n id\n name\n permissions {\n canCreateVersion {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Model\n }\n"): (typeof documents)["\n fragment ProjectCardImportFileArea_Model on Model {\n id\n name\n permissions {\n canCreateVersion {\n ...FullPermissionCheckResult\n }\n }\n ...UseFileImport_Model\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1021,7 +1037,7 @@ export function graphql(source: "\n fragment ProjectModelPageHeaderProject on P
|
||||
/**
|
||||
* 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 ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n }\n ...ProjectsModelPageEmbed_Project\n }\n"): (typeof documents)["\n fragment ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n }\n ...ProjectsModelPageEmbed_Project\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n ...ProjectCardImportFileArea_Model\n }\n ...ProjectsModelPageEmbed_Project\n ...ProjectCardImportFileArea_Project\n }\n"): (typeof documents)["\n fragment ProjectModelPageVersionsPagination on Project {\n id\n visibility\n model(id: $modelId) {\n id\n versions(limit: 16, cursor: $versionsCursor) {\n cursor\n totalCount\n items {\n ...ProjectModelPageVersionsCardVersion\n }\n }\n ...ProjectCardImportFileArea_Model\n }\n ...ProjectsModelPageEmbed_Project\n ...ProjectCardImportFileArea_Project\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1125,7 +1141,7 @@ export function graphql(source: "\n fragment ProjectPageModelsActions_Project o
|
||||
/**
|
||||
* 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 ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageModelsCardProject on Project {\n id\n role\n visibility\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1137,11 +1153,11 @@ export function graphql(source: "\n fragment ProjectModelsPageResults_Project o
|
||||
/**
|
||||
* 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 ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageModelsStructureItem_Project on Project {\n id\n ...ProjectPageModelsActions_Project\n ...ProjectCardImportFileArea_Project\n permissions {\n canCreateModel {\n ...FullPermissionCheckResult\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 fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n }\n hasChildren\n updatedAt\n }\n"): (typeof documents)["\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n }\n hasChildren\n updatedAt\n }\n"];
|
||||
export function graphql(source: "\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\n }\n"): (typeof documents)["\n fragment SingleLevelModelTreeItem on ModelsTreeItem {\n id\n name\n fullName\n model {\n ...ProjectPageLatestItemsModelItem\n ...ProjectCardImportFileArea_Model\n }\n hasChildren\n updatedAt\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1546,6 +1562,14 @@ export function graphql(source: "\n query ServerInfoAllScopes {\n serverInfo
|
||||
* 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 ProjectModelsSelectorValues($projectId: String!, $cursor: String) {\n project(id: $projectId) {\n id\n models(limit: 100, cursor: $cursor) {\n cursor\n totalCount\n items {\n ...CommonModelSelectorModel\n }\n }\n }\n }\n"): (typeof documents)["\n query ProjectModelsSelectorValues($projectId: String!, $cursor: String) {\n project(id: $projectId) {\n id\n models(limit: 100, cursor: $cursor) {\n cursor\n totalCount\n items {\n ...CommonModelSelectorModel\n }\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment UseFileImport_Project on Project {\n id\n }\n"): (typeof documents)["\n fragment UseFileImport_Project on Project {\n id\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
export function graphql(source: "\n fragment UseFileImport_Model on Model {\n id\n name\n }\n"): (typeof documents)["\n fragment UseFileImport_Model on Model {\n id\n name\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1669,7 +1693,7 @@ export function graphql(source: "\n fragment ProjectDashboardItemNoModels on Pr
|
||||
/**
|
||||
* 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 ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n"): (typeof documents)["\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n ...ProjectCardImportFileArea_Project\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n"): (typeof documents)["\n fragment ProjectDashboardItem on Project {\n id\n ...ProjectDashboardItemNoModels\n ...ProjectCardImportFileArea_Project\n models(limit: 4) {\n totalCount\n items {\n ...ProjectPageLatestItemsModelItem\n }\n }\n workspace {\n id\n slug\n name\n logo\n readOnly\n }\n pendingImportedModels(limit: 4) {\n ...PendingFileUpload\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1677,7 +1701,7 @@ export function graphql(source: "\n fragment PendingFileUpload on FileUpload {\
|
||||
/**
|
||||
* 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 ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n ...ProjectCardImportFileArea_Model\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsModelItem on Model {\n id\n name\n displayName\n versionCount: versions(limit: 0) {\n totalCount\n }\n commentThreadCount: commentThreads(limit: 0) {\n totalCount\n }\n pendingImportedVersions(limit: 1) {\n ...PendingFileUpload\n }\n previewUrl\n createdAt\n updatedAt\n ...ProjectPageModelsCardRenameDialog\n ...ProjectPageModelsCardDeleteDialog\n ...ProjectPageModelsActions\n ...ProjectCardImportFileArea_Model\n automationsStatus {\n ...AutomateRunsTriggerStatus_TriggeredAutomationsStatus\n }\n permissions {\n canUpdate {\n ...FullPermissionCheckResult\n }\n canDelete {\n ...FullPermissionCheckResult\n }\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
@@ -1685,7 +1709,7 @@ export function graphql(source: "\n fragment ProjectUpdatableMetadata on Projec
|
||||
/**
|
||||
* 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 ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n }\n"];
|
||||
export function graphql(source: "\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n ...ProjectCardImportFileArea_Project\n }\n"): (typeof documents)["\n fragment ProjectPageLatestItemsModels on Project {\n id\n role\n visibility\n workspace {\n id\n readOnly\n }\n modelCount: models(limit: 0) {\n totalCount\n }\n ...ProjectPageModelsStructureItem_Project\n ...ProjectCardImportFileArea_Project\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,12 +10,35 @@ import { importFile } from '~~/lib/core/api/fileImport'
|
||||
import { useAuthCookie } from '~~/lib/auth/composables/auth'
|
||||
import { BlobUploadStatus } from '~~/lib/core/api/blobStorage'
|
||||
import { useMixpanel } from '~~/lib/core/composables/mp'
|
||||
import { graphql } from '~/lib/common/generated/gql'
|
||||
import type {
|
||||
UseFileImport_ModelFragment,
|
||||
UseFileImport_ProjectFragment
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
|
||||
graphql(`
|
||||
fragment UseFileImport_Project on Project {
|
||||
id
|
||||
}
|
||||
`)
|
||||
|
||||
graphql(`
|
||||
fragment UseFileImport_Model on Model {
|
||||
id
|
||||
name
|
||||
}
|
||||
`)
|
||||
|
||||
export function useFileImport(params: {
|
||||
projectId: MaybeRef<string>
|
||||
project: MaybeRef<UseFileImport_ProjectFragment>
|
||||
model?: MaybeRef<MaybeNullOrUndefined<UseFileImport_ModelFragment>>
|
||||
/**
|
||||
* Sometimes we don't have a model, but we still want to specify a target model name (e.g. for
|
||||
* model list view uploads, where list items don't necessarily represent real models)
|
||||
*/
|
||||
modelName?: MaybeRef<MaybeNullOrUndefined<string>>
|
||||
}) {
|
||||
const { projectId, modelName } = params
|
||||
const { project, model } = params
|
||||
|
||||
const { maxSizeInBytes } = useServerFileUploadLimit()
|
||||
const authToken = useAuthCookie()
|
||||
@@ -25,6 +48,8 @@ export function useFileImport(params: {
|
||||
const upload = ref(null as Nullable<UploadFileItem>)
|
||||
const isUploading = ref(false)
|
||||
|
||||
const modelName = computed(() => unref(params.modelName) || unref(model)?.name)
|
||||
|
||||
let onFileUploadedCb: Optional<(file: UploadFileItem) => void> = undefined
|
||||
const onFileUploaded = (cb: (file: UploadFileItem) => void) => {
|
||||
onFileUploadedCb = cb
|
||||
@@ -58,8 +83,8 @@ export function useFileImport(params: {
|
||||
const res = await importFile(
|
||||
{
|
||||
file: upload.value.file,
|
||||
projectId: unref(projectId),
|
||||
modelName: unref(modelName) || undefined,
|
||||
projectId: unref(project).id,
|
||||
modelName: modelName.value || undefined,
|
||||
authToken: authToken.value,
|
||||
apiOrigin
|
||||
},
|
||||
@@ -75,7 +100,7 @@ export function useFileImport(params: {
|
||||
mp.track('Upload Action', {
|
||||
type: 'action',
|
||||
name: 'create',
|
||||
source: unref(modelName) ? 'model card' : 'empty card'
|
||||
source: modelName.value ? 'model card' : 'empty card'
|
||||
// extension
|
||||
})
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ export const projectDashboardItemFragment = graphql(`
|
||||
fragment ProjectDashboardItem on Project {
|
||||
id
|
||||
...ProjectDashboardItemNoModels
|
||||
...ProjectCardImportFileArea_Project
|
||||
models(limit: 4) {
|
||||
totalCount
|
||||
items {
|
||||
@@ -105,6 +106,7 @@ export const projectPageLatestItemsModelItemFragment = graphql(`
|
||||
...ProjectPageModelsCardRenameDialog
|
||||
...ProjectPageModelsCardDeleteDialog
|
||||
...ProjectPageModelsActions
|
||||
...ProjectCardImportFileArea_Model
|
||||
automationsStatus {
|
||||
...AutomateRunsTriggerStatus_TriggeredAutomationsStatus
|
||||
}
|
||||
@@ -162,6 +164,7 @@ export const projectPageLatestItemsModelsFragment = graphql(`
|
||||
totalCount
|
||||
}
|
||||
...ProjectPageModelsStructureItem_Project
|
||||
...ProjectCardImportFileArea_Project
|
||||
}
|
||||
`)
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ input WorkspaceUpdateInput {
|
||||
@deprecated(reason: "Always the reviewer role. Will be removed in the future.")
|
||||
domainBasedMembershipProtectionEnabled: Boolean
|
||||
discoverabilityEnabled: Boolean
|
||||
discoverabilityAutoJoinEnabled: Boolean
|
||||
}
|
||||
|
||||
input WorkspaceRoleUpdateInput {
|
||||
@@ -306,6 +307,10 @@ type Workspace {
|
||||
"""
|
||||
discoverabilityEnabled: Boolean!
|
||||
"""
|
||||
If true, allow users to automatically join discoverable workspaces (instead of requesting to join)
|
||||
"""
|
||||
discoverabilityAutoJoinEnabled: Boolean!
|
||||
"""
|
||||
Info about the workspace creation state
|
||||
"""
|
||||
creationState: WorkspaceCreationState
|
||||
@@ -390,6 +395,10 @@ type LimitedWorkspace {
|
||||
"""
|
||||
logo: String
|
||||
"""
|
||||
If true, the users with a matching domain may join the workspace directly
|
||||
"""
|
||||
discoverabilityAutoJoinEnabled: Boolean!
|
||||
"""
|
||||
Workspace members visible to people with verified email domain
|
||||
"""
|
||||
team(cursor: String, limit: Int! = 25): LimitedWorkspaceCollaboratorCollection
|
||||
|
||||
@@ -1224,6 +1224,8 @@ export type LimitedWorkspace = {
|
||||
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 */
|
||||
@@ -4503,6 +4505,8 @@ export type Workspace = {
|
||||
*/
|
||||
defaultRegion?: Maybe<ServerRegionItem>;
|
||||
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 */
|
||||
@@ -5144,6 +5148,7 @@ export type WorkspaceUpdateInput = {
|
||||
/** @deprecated Always the reviewer role. Will be removed in the future. */
|
||||
defaultProjectRole?: InputMaybe<Scalars['String']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
discoverabilityAutoJoinEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
discoverabilityEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
domainBasedMembershipProtectionEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
id: Scalars['String']['input'];
|
||||
@@ -6431,6 +6436,7 @@ export type LimitedUserResolvers<ContextType = GraphQLContext, ParentType extend
|
||||
export type LimitedWorkspaceResolvers<ContextType = GraphQLContext, ParentType extends ResolversParentTypes['LimitedWorkspace'] = ResolversParentTypes['LimitedWorkspace']> = {
|
||||
adminTeam?: Resolver<Array<ResolversTypes['LimitedWorkspaceCollaborator']>, ParentType, ContextType>;
|
||||
description?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
discoverabilityAutoJoinEnabled?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
|
||||
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
|
||||
logo?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
name?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
@@ -7466,6 +7472,7 @@ export type WorkspaceResolvers<ContextType = GraphQLContext, ParentType extends
|
||||
defaultProjectRole?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
|
||||
defaultRegion?: Resolver<Maybe<ResolversTypes['ServerRegionItem']>, ParentType, ContextType>;
|
||||
description?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
|
||||
discoverabilityAutoJoinEnabled?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
|
||||
discoverabilityEnabled?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
|
||||
domainBasedMembershipProtectionEnabled?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
|
||||
domains?: Resolver<Maybe<Array<ResolversTypes['WorkspaceDomain']>>, ParentType, ContextType>;
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
import crs from 'crypto-random-string'
|
||||
|
||||
/**
|
||||
* Returns a random email from example.org domain
|
||||
*/
|
||||
export function createRandomEmail() {
|
||||
return randomizeCase(`${crs({ length: 6 })}@example.org`)
|
||||
}
|
||||
|
||||
@@ -1204,6 +1204,8 @@ export type LimitedWorkspace = {
|
||||
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 */
|
||||
@@ -4483,6 +4485,8 @@ export type Workspace = {
|
||||
*/
|
||||
defaultRegion?: Maybe<ServerRegionItem>;
|
||||
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 */
|
||||
@@ -5124,6 +5128,7 @@ export type WorkspaceUpdateInput = {
|
||||
/** @deprecated Always the reviewer role. Will be removed in the future. */
|
||||
defaultProjectRole?: InputMaybe<Scalars['String']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
discoverabilityAutoJoinEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
discoverabilityEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
domainBasedMembershipProtectionEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
id: Scalars['String']['input'];
|
||||
|
||||
@@ -6,7 +6,6 @@ import {
|
||||
WorkspaceDomain
|
||||
} from '@/modules/workspacesCore/domain/types'
|
||||
import { Roles, WorkspaceRoles } from '@speckle/shared'
|
||||
import { pick } from 'lodash'
|
||||
|
||||
export const userEmailsCompliantWithWorkspaceDomains = ({
|
||||
userEmails,
|
||||
@@ -45,5 +44,12 @@ export const isWorkspaceRole = (role: string): role is WorkspaceRoles => {
|
||||
}
|
||||
|
||||
export const toLimitedWorkspace = (workspace: Workspace): LimitedWorkspace => {
|
||||
return pick(workspace, ['id', 'slug', 'name', 'description', 'logo'])
|
||||
return {
|
||||
id: workspace.id,
|
||||
slug: workspace.slug,
|
||||
name: workspace.name,
|
||||
description: workspace.description,
|
||||
logo: workspace.logo,
|
||||
discoverabilityAutoJoinEnabled: workspace.discoverabilityAutoJoinEnabled
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { WorkspaceEvents } from '@/modules/workspacesCore/domain/events'
|
||||
import {
|
||||
LimitedWorkspace,
|
||||
Workspace,
|
||||
WorkspaceAcl,
|
||||
WorkspaceDomain,
|
||||
@@ -45,7 +46,7 @@ export type UpsertWorkspace = (args: UpsertWorkspaceArgs) => Promise<void>
|
||||
export type GetUserDiscoverableWorkspaces = (args: {
|
||||
domains: string[]
|
||||
userId: string
|
||||
}) => Promise<Pick<Workspace, 'id' | 'name' | 'slug' | 'description' | 'logo'>[]>
|
||||
}) => Promise<LimitedWorkspace[]>
|
||||
|
||||
export type GetWorkspace = (args: {
|
||||
workspaceId: string
|
||||
|
||||
@@ -1136,7 +1136,20 @@ export = FF_WORKSPACES_MODULE_ENABLED
|
||||
sendWorkspaceJoinRequestReceivedEmail,
|
||||
getUserById: getUserFactory({ db }),
|
||||
getWorkspaceWithDomains: getWorkspaceWithDomainsFactory({ db }),
|
||||
getUserEmails: findEmailsByUserIdFactory({ db })
|
||||
getUserEmails: findEmailsByUserIdFactory({ db }),
|
||||
addOrUpdateWorkspaceRole: addOrUpdateWorkspaceRoleFactory({
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db }),
|
||||
getWorkspaceWithDomains: getWorkspaceWithDomainsFactory({ db }),
|
||||
findVerifiedEmailsByUserId: findVerifiedEmailsByUserIdFactory({ db }),
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db }),
|
||||
emitWorkspaceEvent: getEventBus().emit,
|
||||
ensureValidWorkspaceRoleSeat: ensureValidWorkspaceRoleSeatFactory({
|
||||
createWorkspaceSeat: createWorkspaceSeatFactory({ db }),
|
||||
getWorkspaceUserSeat: getWorkspaceUserSeatFactory({ db }),
|
||||
eventEmit: getEventBus().emit
|
||||
})
|
||||
}),
|
||||
getWorkspaceTeam: getWorkspaceCollaboratorsFactory({ db })
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {
|
||||
LimitedWorkspace,
|
||||
Workspace,
|
||||
WorkspaceAcl,
|
||||
WorkspaceDomain,
|
||||
@@ -102,6 +103,7 @@ export const getUserDiscoverableWorkspacesFactory =
|
||||
'slug',
|
||||
'description',
|
||||
'logo',
|
||||
'discoverabilityAutoJoinEnabled',
|
||||
tables
|
||||
.workspacesAcl(db)
|
||||
.select(knex.raw('count(*)::integer'))
|
||||
@@ -129,10 +131,10 @@ export const getUserDiscoverableWorkspacesFactory =
|
||||
.where('discoverabilityEnabled', true)
|
||||
.where('verified', true)
|
||||
.where('role', null)
|
||||
.orderBy([{ column: 'teamCount', order: 'desc' }, 'workspaces.id'])) as Pick<
|
||||
Workspace,
|
||||
'id' | 'name' | 'slug' | 'description' | 'logo'
|
||||
>[]
|
||||
.orderBy([
|
||||
{ column: 'teamCount', order: 'desc' },
|
||||
'workspaces.id'
|
||||
])) as LimitedWorkspace[]
|
||||
|
||||
return workspaces
|
||||
}
|
||||
@@ -300,6 +302,7 @@ export const upsertWorkspaceFactory =
|
||||
'updatedAt',
|
||||
'domainBasedMembershipProtectionEnabled',
|
||||
'discoverabilityEnabled',
|
||||
'discoverabilityAutoJoinEnabled',
|
||||
'isEmbedSpeckleBrandingHidden'
|
||||
])
|
||||
}
|
||||
|
||||
@@ -164,8 +164,9 @@ export const createWorkspaceFactory =
|
||||
updatedAt: new Date(),
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
discoverabilityEnabled: false,
|
||||
discoverabilityAutoJoinEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false
|
||||
}
|
||||
} satisfies Workspace
|
||||
await upsertWorkspace({ workspace })
|
||||
|
||||
// assign the creator as workspace administrator
|
||||
|
||||
@@ -4,7 +4,7 @@ import {
|
||||
GetWorkspaceRolesForUser,
|
||||
GetWorkspaces
|
||||
} from '@/modules/workspaces/domain/operations'
|
||||
import { Workspace } from '@/modules/workspacesCore/domain/types'
|
||||
import { LimitedWorkspace, Workspace } from '@/modules/workspacesCore/domain/types'
|
||||
|
||||
type GetDiscoverableWorkspaceForUserArgs = {
|
||||
userId: string
|
||||
@@ -20,9 +20,7 @@ export const getDiscoverableWorkspacesForUserFactory =
|
||||
}) =>
|
||||
async ({
|
||||
userId
|
||||
}: GetDiscoverableWorkspaceForUserArgs): Promise<
|
||||
Pick<Workspace, 'id' | 'name' | 'slug' | 'description' | 'logo'>[]
|
||||
> => {
|
||||
}: GetDiscoverableWorkspaceForUserArgs): Promise<LimitedWorkspace[]> => {
|
||||
const userEmails = await findEmailsByUserId({ userId })
|
||||
const userVerifiedDomains = userEmails
|
||||
.filter((email) => email.verified)
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
CreateWorkspaceJoinRequest,
|
||||
DenyWorkspaceJoinRequest,
|
||||
GetWorkspace,
|
||||
GetWorkspaceCollaborators,
|
||||
GetWorkspaceJoinRequest,
|
||||
GetWorkspaceWithDomains,
|
||||
SendWorkspaceJoinRequestApprovedEmail,
|
||||
@@ -50,14 +51,18 @@ export const requestToJoinWorkspaceFactory =
|
||||
({
|
||||
createWorkspaceJoinRequest,
|
||||
sendWorkspaceJoinRequestReceivedEmail,
|
||||
addOrUpdateWorkspaceRole,
|
||||
getUserById,
|
||||
getWorkspaceWithDomains,
|
||||
getWorkspaceTeam,
|
||||
getUserEmails
|
||||
}: {
|
||||
createWorkspaceJoinRequest: CreateWorkspaceJoinRequest
|
||||
sendWorkspaceJoinRequestReceivedEmail: SendWorkspaceJoinRequestReceivedEmail
|
||||
addOrUpdateWorkspaceRole: AddOrUpdateWorkspaceRole
|
||||
getUserById: GetUser
|
||||
getWorkspaceWithDomains: GetWorkspaceWithDomains
|
||||
getWorkspaceTeam: GetWorkspaceCollaborators
|
||||
getUserEmails: FindEmailsByUserId
|
||||
}) =>
|
||||
async ({ userId, workspaceId }: { userId: string; workspaceId: string }) => {
|
||||
@@ -84,6 +89,23 @@ export const requestToJoinWorkspaceFactory =
|
||||
throw new WorkspaceProtectedError()
|
||||
}
|
||||
|
||||
if (workspace.discoverabilityAutoJoinEnabled) {
|
||||
const [workspaceAdmin] = await getWorkspaceTeam({
|
||||
workspaceId,
|
||||
limit: 1,
|
||||
filter: {
|
||||
roles: [Roles.Workspace.Admin]
|
||||
}
|
||||
})
|
||||
await addOrUpdateWorkspaceRole({
|
||||
userId,
|
||||
workspaceId,
|
||||
role: Roles.Workspace.Member,
|
||||
updatedByUserId: workspaceAdmin.id
|
||||
})
|
||||
return true
|
||||
}
|
||||
|
||||
const joinRequest = await createWorkspaceJoinRequest({
|
||||
workspaceJoinRequest: {
|
||||
userId,
|
||||
|
||||
@@ -151,6 +151,7 @@ export type BasicTestWorkspace = {
|
||||
description?: string
|
||||
logo?: string
|
||||
discoverabilityEnabled?: boolean
|
||||
discoverabilityAutoJoinEnabled?: boolean
|
||||
domainBasedMembershipProtectionEnabled?: boolean
|
||||
}
|
||||
|
||||
@@ -326,13 +327,14 @@ export const createTestWorkspace = async (
|
||||
emitWorkspaceEvent: (...args) => getEventBus().emit(...args)
|
||||
})
|
||||
|
||||
if (workspace.discoverabilityEnabled) {
|
||||
if (workspace.discoverabilityEnabled || workspace.discoverabilityAutoJoinEnabled) {
|
||||
if (!domain) throw new Error('Domain is needed for discoverability')
|
||||
|
||||
await updateWorkspace({
|
||||
workspaceId: newWorkspace.id,
|
||||
workspaceInput: {
|
||||
discoverabilityEnabled: true
|
||||
discoverabilityEnabled: workspace.discoverabilityEnabled,
|
||||
discoverabilityAutoJoinEnabled: workspace.discoverabilityAutoJoinEnabled
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -8,8 +8,15 @@ import {
|
||||
WorkspaceNotDiscoverableError,
|
||||
WorkspaceNotFoundError
|
||||
} from '@/modules/workspaces/errors/workspace'
|
||||
import { getWorkspaceFactory } from '@/modules/workspaces/repositories/workspaces'
|
||||
import { UserWithOptionalRole } from '@/modules/core/repositories/users'
|
||||
import {
|
||||
getWorkspaceCollaboratorsFactory,
|
||||
getWorkspaceFactory,
|
||||
getWorkspaceRoleForUserFactory,
|
||||
getWorkspaceRolesFactory,
|
||||
getWorkspaceWithDomainsFactory,
|
||||
upsertWorkspaceRoleFactory
|
||||
} from '@/modules/workspaces/repositories/workspaces'
|
||||
import { getUserFactory, UserWithOptionalRole } from '@/modules/core/repositories/users'
|
||||
import {
|
||||
AddOrUpdateWorkspaceRole,
|
||||
CreateWorkspaceJoinRequest,
|
||||
@@ -35,7 +42,7 @@ import {
|
||||
} from '@/modules/workspacesCore/domain/types'
|
||||
import { WorkspaceJoinRequests } from '@/modules/workspacesCore/helpers/db'
|
||||
import { expectToThrow } from '@/test/assertionHelper'
|
||||
import { BasicTestUser, createTestUser } from '@/test/authHelper'
|
||||
import { BasicTestUser, createTestUser, createTestUsers } from '@/test/authHelper'
|
||||
import { Roles } from '@speckle/shared'
|
||||
import { expect } from 'chai'
|
||||
import cryptoRandomString from 'crypto-random-string'
|
||||
@@ -44,6 +51,17 @@ import {
|
||||
updateWorkspaceJoinRequestStatusFactory
|
||||
} from '@/modules/workspaces/repositories/workspaceJoinRequests'
|
||||
import { UserEmail } from '@/modules/core/domain/userEmails/types'
|
||||
import {
|
||||
findEmailsByUserIdFactory,
|
||||
findVerifiedEmailsByUserIdFactory
|
||||
} from '@/modules/core/repositories/userEmails'
|
||||
import { addOrUpdateWorkspaceRoleFactory } from '@/modules/workspaces/services/management'
|
||||
import { getEventBus } from '@/modules/shared/services/eventBus'
|
||||
import { ensureValidWorkspaceRoleSeatFactory } from '@/modules/workspaces/services/workspaceSeat'
|
||||
import {
|
||||
createWorkspaceSeatFactory,
|
||||
getWorkspaceUserSeatFactory
|
||||
} from '@/modules/gatekeeper/repositories/workspaceSeat'
|
||||
|
||||
const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
|
||||
@@ -109,7 +127,9 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
sendWorkspaceJoinRequestReceivedEmail: async () => Promise.resolve(),
|
||||
getUserById: async () => null,
|
||||
getWorkspaceWithDomains: async () => null,
|
||||
getUserEmails: async () => []
|
||||
getUserEmails: async () => [],
|
||||
addOrUpdateWorkspaceRole: async () => {},
|
||||
getWorkspaceTeam: async () => []
|
||||
})({ workspaceId: createRandomString(), userId: createRandomString() })
|
||||
)
|
||||
|
||||
@@ -124,7 +144,9 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
sendWorkspaceJoinRequestReceivedEmail: async () => Promise.resolve(),
|
||||
getUserById: async () => user as unknown as UserWithOptionalRole,
|
||||
getWorkspaceWithDomains: async () => null,
|
||||
getUserEmails: async () => []
|
||||
getUserEmails: async () => [],
|
||||
addOrUpdateWorkspaceRole: async () => {},
|
||||
getWorkspaceTeam: async () => []
|
||||
})({ workspaceId: createRandomString(), userId: createRandomString() })
|
||||
)
|
||||
|
||||
@@ -157,7 +179,9 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
getUserById: async () => user as unknown as UserWithOptionalRole,
|
||||
getWorkspaceWithDomains: async () =>
|
||||
workspace as unknown as WorkspaceWithDomains,
|
||||
getUserEmails: async () => []
|
||||
getUserEmails: async () => [],
|
||||
addOrUpdateWorkspaceRole: async () => {},
|
||||
getWorkspaceTeam: async () => []
|
||||
})({ workspaceId: createRandomString(), userId: createRandomString() })
|
||||
)
|
||||
|
||||
@@ -213,7 +237,9 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
domains: [domain]
|
||||
} as unknown as WorkspaceWithDomains),
|
||||
getUserEmails: async () =>
|
||||
[{ email: user.email, verified: true }] as unknown as UserEmail[]
|
||||
[{ email: user.email, verified: true }] as unknown as UserEmail[],
|
||||
addOrUpdateWorkspaceRole: async () => {},
|
||||
getWorkspaceTeam: async () => []
|
||||
})({ workspaceId: workspace.id, userId: user.id })
|
||||
).to.equal(true)
|
||||
|
||||
@@ -282,7 +308,9 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
domains: [domain]
|
||||
} as unknown as WorkspaceWithDomains),
|
||||
getUserEmails: async () =>
|
||||
[{ email: user.email, verified: true }] as unknown as UserEmail[]
|
||||
[{ email: user.email, verified: true }] as unknown as UserEmail[],
|
||||
addOrUpdateWorkspaceRole: async () => {},
|
||||
getWorkspaceTeam: async () => []
|
||||
})
|
||||
|
||||
expect(
|
||||
@@ -322,6 +350,64 @@ const { FF_WORKSPACES_MODULE_ENABLED } = getFeatureFlags()
|
||||
|
||||
expect(sendWorkspaceJoinRequestReceivedEmailCalls).to.have.length(1)
|
||||
})
|
||||
it('adds user to workspace if discoverable auto-join is enabled', async () => {
|
||||
const userA: BasicTestUser = {
|
||||
id: '',
|
||||
name: 'John Speckle',
|
||||
email: createRandomEmail(),
|
||||
role: Roles.Server.Admin,
|
||||
verified: true
|
||||
}
|
||||
const userB: BasicTestUser = {
|
||||
id: '',
|
||||
name: 'Jimothy Speckle',
|
||||
email: createRandomEmail(),
|
||||
verified: true
|
||||
}
|
||||
await createTestUsers([userA, userB])
|
||||
|
||||
const workspace: BasicTestWorkspace = {
|
||||
id: '',
|
||||
slug: '',
|
||||
ownerId: '',
|
||||
name: cryptoRandomString({ length: 6 }),
|
||||
description: cryptoRandomString({ length: 12 }),
|
||||
discoverabilityEnabled: true,
|
||||
discoverabilityAutoJoinEnabled: true
|
||||
}
|
||||
await createTestWorkspace(workspace, userA, { domain: 'example.org' })
|
||||
|
||||
await requestToJoinWorkspaceFactory({
|
||||
createWorkspaceJoinRequest: createWorkspaceJoinRequestFactory({ db }),
|
||||
sendWorkspaceJoinRequestReceivedEmail: async () => {},
|
||||
getUserById: getUserFactory({ db }),
|
||||
addOrUpdateWorkspaceRole: addOrUpdateWorkspaceRoleFactory({
|
||||
getWorkspaceRoles: getWorkspaceRolesFactory({ db }),
|
||||
getWorkspaceWithDomains: getWorkspaceWithDomainsFactory({ db }),
|
||||
findVerifiedEmailsByUserId: findVerifiedEmailsByUserIdFactory({ db }),
|
||||
upsertWorkspaceRole: upsertWorkspaceRoleFactory({ db }),
|
||||
emitWorkspaceEvent: getEventBus().emit,
|
||||
ensureValidWorkspaceRoleSeat: ensureValidWorkspaceRoleSeatFactory({
|
||||
createWorkspaceSeat: createWorkspaceSeatFactory({ db }),
|
||||
getWorkspaceUserSeat: getWorkspaceUserSeatFactory({ db }),
|
||||
eventEmit: getEventBus().emit
|
||||
})
|
||||
}),
|
||||
getWorkspaceWithDomains: getWorkspaceWithDomainsFactory({ db }),
|
||||
getWorkspaceTeam: getWorkspaceCollaboratorsFactory({ db }),
|
||||
getUserEmails: findEmailsByUserIdFactory({ db })
|
||||
})({
|
||||
userId: userB.id,
|
||||
workspaceId: workspace.id
|
||||
})
|
||||
|
||||
const workspaceRole = await getWorkspaceRoleForUserFactory({ db })({
|
||||
userId: userB.id,
|
||||
workspaceId: workspace.id
|
||||
})
|
||||
|
||||
expect(workspaceRole).to.not.be.null
|
||||
})
|
||||
})
|
||||
|
||||
describe('approveWorkspaceJoinRequestFactory, returns a function that ', () => {
|
||||
|
||||
@@ -259,6 +259,7 @@ describe('Workspace services', () => {
|
||||
updatedAt: new Date(),
|
||||
logo: null,
|
||||
discoverabilityEnabled: false,
|
||||
discoverabilityAutoJoinEnabled: false,
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false,
|
||||
domains: []
|
||||
@@ -1140,6 +1141,7 @@ describe('Workspace role services', () => {
|
||||
updatedAt: new Date(),
|
||||
description: null,
|
||||
discoverabilityEnabled: false,
|
||||
discoverabilityAutoJoinEnabled: false,
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false
|
||||
}
|
||||
@@ -1180,6 +1182,7 @@ describe('Workspace role services', () => {
|
||||
updatedAt: new Date(),
|
||||
description: null,
|
||||
discoverabilityEnabled: false,
|
||||
discoverabilityAutoJoinEnabled: false,
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false
|
||||
}
|
||||
|
||||
@@ -383,6 +383,7 @@ describe('Workspace SSO services', () => {
|
||||
logo: null,
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
discoverabilityEnabled: false,
|
||||
discoverabilityAutoJoinEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false,
|
||||
createdAt: new Date(),
|
||||
updatedAt: new Date()
|
||||
|
||||
@@ -29,13 +29,14 @@ export type Workspace = {
|
||||
logo: string | null
|
||||
domainBasedMembershipProtectionEnabled: boolean
|
||||
discoverabilityEnabled: boolean
|
||||
// TODO: Create new table/structure if embeds get more configuration
|
||||
discoverabilityAutoJoinEnabled: boolean
|
||||
// TODO: Create new table/structure if embeds get more workspace-level configuration
|
||||
isEmbedSpeckleBrandingHidden: boolean
|
||||
}
|
||||
|
||||
export type LimitedWorkspace = Pick<
|
||||
Workspace,
|
||||
'id' | 'slug' | 'name' | 'description' | 'logo'
|
||||
'id' | 'slug' | 'name' | 'description' | 'logo' | 'discoverabilityAutoJoinEnabled'
|
||||
>
|
||||
|
||||
export type WorkspaceWithDomains = Workspace & { domains: WorkspaceDomain[] }
|
||||
|
||||
@@ -10,6 +10,7 @@ export const Workspaces = buildTableHelper('workspaces', [
|
||||
'logo',
|
||||
'domainBasedMembershipProtectionEnabled',
|
||||
'discoverabilityEnabled',
|
||||
'discoverabilityAutoJoinEnabled',
|
||||
'isEmbedSpeckleBrandingHidden'
|
||||
])
|
||||
|
||||
|
||||
@@ -2,7 +2,11 @@ import { MutationsObjectGraphQLReturn } from '@/modules/core/helpers/graphTypes'
|
||||
import { LimitedUserRecord } from '@/modules/core/helpers/types'
|
||||
import { WorkspaceSsoProviderRecord } from '@/modules/workspaces/domain/sso/types'
|
||||
import { WorkspaceTeamMember } from '@/modules/workspaces/domain/types'
|
||||
import { Workspace, WorkspaceJoinRequest } from '@/modules/workspacesCore/domain/types'
|
||||
import {
|
||||
LimitedWorkspace,
|
||||
Workspace,
|
||||
WorkspaceJoinRequest
|
||||
} from '@/modules/workspacesCore/domain/types'
|
||||
import { WorkspaceRoles } from '@speckle/shared'
|
||||
|
||||
export type WorkspaceGraphQLReturn = Workspace
|
||||
@@ -37,10 +41,7 @@ export type PendingWorkspaceCollaboratorGraphQLReturn = {
|
||||
|
||||
export type WorkspaceCollaboratorGraphQLReturn = WorkspaceTeamMember
|
||||
|
||||
export type LimitedWorkspaceGraphQLReturn = Pick<
|
||||
Workspace,
|
||||
'id' | 'name' | 'slug' | 'description' | 'logo'
|
||||
>
|
||||
export type LimitedWorkspaceGraphQLReturn = LimitedWorkspace
|
||||
export type LimitedWorkspaceCollaboratorGraphQLReturn = WorkspaceTeamMember
|
||||
|
||||
export type WorkspacePermissionChecksGraphQLReturn = {
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
import { Knex } from 'knex'
|
||||
|
||||
export async function up(knex: Knex): Promise<void> {
|
||||
await knex.schema.alterTable('workspaces', (table) => {
|
||||
table.boolean('discoverabilityAutoJoinEnabled').notNullable().defaultTo(false)
|
||||
})
|
||||
}
|
||||
|
||||
export async function down(knex: Knex): Promise<void> {
|
||||
await knex.schema.alterTable('workspaces', (table) => {
|
||||
table.dropColumn('discoverabilityAutoJoinEnabled')
|
||||
})
|
||||
}
|
||||
@@ -1205,6 +1205,8 @@ export type LimitedWorkspace = {
|
||||
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 */
|
||||
@@ -4484,6 +4486,8 @@ export type Workspace = {
|
||||
*/
|
||||
defaultRegion?: Maybe<ServerRegionItem>;
|
||||
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 */
|
||||
@@ -5125,6 +5129,7 @@ export type WorkspaceUpdateInput = {
|
||||
/** @deprecated Always the reviewer role. Will be removed in the future. */
|
||||
defaultProjectRole?: InputMaybe<Scalars['String']['input']>;
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
discoverabilityAutoJoinEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
discoverabilityEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
domainBasedMembershipProtectionEnabled?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
id: Scalars['String']['input'];
|
||||
|
||||
@@ -15,6 +15,7 @@ export const createAndStoreTestWorkspaceFactory =
|
||||
logo: null,
|
||||
domainBasedMembershipProtectionEnabled: false,
|
||||
discoverabilityEnabled: false,
|
||||
discoverabilityAutoJoinEnabled: false,
|
||||
isEmbedSpeckleBrandingHidden: false,
|
||||
...workspaceOverrides
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user