Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 016dbd97da | |||
| e55c0ca7dd | |||
| 8ef79f7a7c | |||
| 79951f7cf7 | |||
| cf70ddc79b | |||
| 4e16813c75 | |||
| ee4e7576ad | |||
| 3ba11c983b | |||
| d92dcf5342 | |||
| 55afedab68 | |||
| a8d948ec71 |
@@ -49,6 +49,7 @@ const applicationIds = computed(() => {
|
||||
})
|
||||
|
||||
const handleClick = async () => {
|
||||
if (applicationIds.value.length === 0) return
|
||||
await app.$baseBinding.highlightObjects(applicationIds.value)
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
</div>
|
||||
<div class="relative group flex items-center">
|
||||
<FormButton
|
||||
v-if="app.$receiveBinding"
|
||||
v-tippy="'Load a model from Speckle into this file'"
|
||||
color="outline"
|
||||
size="sm"
|
||||
@@ -52,10 +53,11 @@
|
||||
{{ hostAppStore.connectorVersion }}
|
||||
</div>
|
||||
<HeaderButton
|
||||
v-if="hostAppStore.isDistributedBySpeckle"
|
||||
v-tippy="'Documentation and help'"
|
||||
@click="
|
||||
app.$openUrl(
|
||||
`https://www.speckle.systems/connectors/${hostAppStore.hostAppName}?utm=dui`
|
||||
`https://docs.speckle.systems/connectors/${hostAppStore.hostAppName}?utm=dui`
|
||||
)
|
||||
"
|
||||
>
|
||||
|
||||
@@ -12,78 +12,27 @@
|
||||
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.
|
||||
Personal projects are being phased out. Move your projects to a
|
||||
workspace to create new projects and models, invite new project
|
||||
collaborators, and view comments and versions older than 7 days. By
|
||||
January 1st 2026, all projects will be archived if not moved into a
|
||||
workspace.
|
||||
</span>
|
||||
</p>
|
||||
|
||||
<FormButton
|
||||
text
|
||||
color="primary"
|
||||
size="sm"
|
||||
:class="showMore ? `mb-1` : ``"
|
||||
:icon-right="showMore ? ChevronUpIcon : ChevronDownIcon"
|
||||
@click="showMore = !showMore"
|
||||
class="mb-2"
|
||||
@click="
|
||||
$openUrl(
|
||||
`${accountStore.activeAccount.accountInfo.serverInfo.url}/projects`
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ showMore ? 'Show less' : 'Show timeline' }}
|
||||
Move projects
|
||||
</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>
|
||||
@@ -92,8 +41,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ChevronUpIcon, ChevronDownIcon } from '@heroicons/vue/20/solid'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
|
||||
const accountStore = useAccountStore()
|
||||
const { $openUrl } = useNuxtApp()
|
||||
const showMore = ref(false)
|
||||
</script>
|
||||
|
||||
@@ -36,6 +36,18 @@
|
||||
<div class="min-w-0 truncate flex-grow text-left">
|
||||
<span>{{ selectedWorkspace.name }}</span>
|
||||
</div>
|
||||
<button
|
||||
v-if="selectedWorkspace.slug"
|
||||
v-tippy="'Open workspace in browser'"
|
||||
class="transition mr-1 opacity-70 hover:opacity-100"
|
||||
@click.stop="
|
||||
$openUrl(
|
||||
`${accountStore.activeAccount.accountInfo.serverInfo.url}/workspaces/${selectedWorkspace.slug}`
|
||||
)
|
||||
"
|
||||
>
|
||||
<ArrowTopRightOnSquareIcon class="w-3.5" />
|
||||
</button>
|
||||
<ChevronDownIcon class="h-3 w-3 shrink-0" />
|
||||
</button>
|
||||
</template>
|
||||
|
||||
@@ -21,11 +21,27 @@
|
||||
<span>{{ workspace.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
v-if="workspace.slug"
|
||||
v-tippy="'Open workspace in browser'"
|
||||
class="hidden transition mr-1 opacity-70 group-hover:block"
|
||||
@click.stop="
|
||||
$openUrl(
|
||||
`${accountStore.activeAccount.accountInfo.serverInfo.url}/workspaces/${workspace.slug}`
|
||||
)
|
||||
"
|
||||
>
|
||||
<ArrowTopRightOnSquareIcon class="w-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
</button>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { WorkspaceListWorkspaceItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/outline'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
|
||||
const accountStore = useAccountStore()
|
||||
|
||||
defineProps<{
|
||||
workspace: WorkspaceListWorkspaceItemFragment
|
||||
|
||||
@@ -29,6 +29,7 @@ type Documents = {
|
||||
"\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 ActiveUser {\n activeUser {\n role\n id\n name\n }\n }\n": typeof types.ActiveUserDocument,
|
||||
"\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,
|
||||
@@ -70,6 +71,7 @@ const documents: Documents = {
|
||||
"\n fragment AutomationRunItem on AutomateRun {\n id\n status\n automation {\n id\n name\n }\n functionRuns {\n ...AutomateFunctionRunItem\n }\n }\n": 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": 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": types.WorkspaceListQueryDocument,
|
||||
"\n query ActiveUser {\n activeUser {\n role\n id\n name\n }\n }\n": types.ActiveUserDocument,
|
||||
"\n query CanCreatePersonalProject {\n activeUser {\n permissions {\n canCreatePersonalProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": types.CanCreatePersonalProjectDocument,
|
||||
"\n query CanCreateProjectInWorkspace($workspaceId: String!) {\n workspace(id: $workspaceId) {\n permissions {\n canCreateProject {\n authorized\n code\n message\n payload\n }\n }\n }\n }\n": types.CanCreateProjectInWorkspaceDocument,
|
||||
"\n query CanCreateModelInProject($projectId: String!) {\n project(id: $projectId) {\n permissions {\n canCreateModel {\n authorized\n code\n message\n }\n }\n }\n }\n": types.CanCreateModelInProjectDocument,
|
||||
@@ -170,6 +172,10 @@ export function graphql(source: "\n query AutomationStatus($projectId: String!,
|
||||
* 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 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 documents)["\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"];
|
||||
/**
|
||||
* 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 ActiveUser {\n activeUser {\n role\n id\n name\n }\n }\n"): (typeof documents)["\n query ActiveUser {\n activeUser {\n role\n id\n name\n }\n }\n"];
|
||||
/**
|
||||
* The graphql function is used to parse GraphQL queries into a document that can be used by GraphQL clients.
|
||||
*/
|
||||
|
||||
@@ -4644,6 +4644,8 @@ export type WorkspaceInviteCreateInput = {
|
||||
email?: InputMaybe<Scalars['String']['input']>;
|
||||
/** Defaults to the member role, if not specified */
|
||||
role?: InputMaybe<WorkspaceRole>;
|
||||
/** The workspace seat type to assign to the user upon accepting the invite. */
|
||||
seatType?: InputMaybe<WorkspaceSeatType>;
|
||||
/** Defaults to User, if not specified */
|
||||
serverRole?: InputMaybe<ServerRole>;
|
||||
/** Either this or email must be filled */
|
||||
@@ -4902,6 +4904,7 @@ export type WorkspacePlanUsage = {
|
||||
|
||||
export enum WorkspacePlans {
|
||||
Academia = 'academia',
|
||||
Enterprise = 'enterprise',
|
||||
Free = 'free',
|
||||
Pro = 'pro',
|
||||
ProUnlimited = 'proUnlimited',
|
||||
@@ -4924,6 +4927,11 @@ export type WorkspaceProjectInviteCreateInput = {
|
||||
email?: InputMaybe<Scalars['String']['input']>;
|
||||
/** Defaults to the contributor role, if not specified */
|
||||
role?: InputMaybe<Scalars['String']['input']>;
|
||||
/**
|
||||
* The workspace seat type to assign to the user upon accepting the invite
|
||||
* (if user is a workspace member already, the seat type will be updated)
|
||||
*/
|
||||
seatType?: InputMaybe<WorkspaceSeatType>;
|
||||
/** Can only be specified if guest mode is on or if the user is an admin */
|
||||
serverRole?: InputMaybe<Scalars['String']['input']>;
|
||||
/** Either this or email must be filled */
|
||||
@@ -5216,6 +5224,11 @@ 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, creationState?: { __typename?: 'WorkspaceCreationState', completed: boolean } | null, permissions: { __typename?: 'WorkspacePermissionChecks', canCreateProject: { __typename?: 'PermissionCheckResult', authorized: boolean, code: string, message: string } } }> } } | null };
|
||||
|
||||
export type ActiveUserQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ActiveUserQuery = { __typename?: 'Query', activeUser?: { __typename?: 'User', role?: string | null, id: string, name: string } | null };
|
||||
|
||||
export type CanCreatePersonalProjectQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
@@ -5393,6 +5406,7 @@ export const StreamAccessRequestCreateDocument = {"kind":"Document","definitions
|
||||
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"}},{"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 ActiveUserDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"ActiveUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"activeUser"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"role"}},{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]} as unknown as DocumentNode<ActiveUserQuery, ActiveUserQueryVariables>;
|
||||
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>;
|
||||
|
||||
@@ -7,7 +7,8 @@ import type {
|
||||
} from '~/lib/common/generated/gql/graphql'
|
||||
import {
|
||||
projectAddByUrlQueryWithoutVersion,
|
||||
projectAddByUrlQueryWithVersion
|
||||
projectAddByUrlQueryWithVersion,
|
||||
userInfoAndServerRoleQuery
|
||||
} from '~/lib/graphql/mutationsAndQueries'
|
||||
import { omit } from 'lodash-es'
|
||||
import { useDebounceFn } from '@vueuse/core'
|
||||
@@ -60,6 +61,7 @@ export function useAddByUrl() {
|
||||
|
||||
const { projectId, modelId, versionId } = params
|
||||
const apollo = (acc as DUIAccount).client
|
||||
const userInfoRes = await apollo.query({ query: userInfoAndServerRoleQuery })
|
||||
|
||||
let project: ProjectListProjectItemFragment | undefined = undefined,
|
||||
model: ModelListModelItemFragment | undefined = undefined,
|
||||
@@ -113,7 +115,7 @@ export function useAddByUrl() {
|
||||
? project.permissions.canPublish.authorized
|
||||
: project.permissions.canLoad.authorized
|
||||
|
||||
if (!hasAccess) {
|
||||
if (!hasAccess && userInfoRes.data.activeUser?.role !== 'server:admin') {
|
||||
urlParseError.value = errorMessage
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2,6 +2,16 @@ import type { ToastNotification } from '@speckle/ui-components'
|
||||
import { ToastNotificationType } from '@speckle/ui-components'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
|
||||
export class UpdateError extends Error {
|
||||
constructor(message: string) {
|
||||
super(message)
|
||||
this.name = 'FetchError'
|
||||
|
||||
// Required when extending Error in TypeScript
|
||||
Object.setPrototypeOf(this, new.target.prototype)
|
||||
}
|
||||
}
|
||||
|
||||
type Versions = {
|
||||
Versions: Version[]
|
||||
}
|
||||
@@ -35,24 +45,39 @@ export function useUpdateConnector() {
|
||||
}
|
||||
|
||||
async function getVersions() {
|
||||
const response = await fetch(
|
||||
`https://releases.speckle.dev/manager2/feeds/${hostApp.hostAppName?.toLowerCase()}-v3.json`,
|
||||
{
|
||||
method: 'GET'
|
||||
try {
|
||||
// End point to get list of versions that deployed by Speckle's pipeline
|
||||
const response = await fetch(
|
||||
`https://releases.speckle.dev/manager2/feeds/${hostApp.hostAppName?.toLowerCase()}-v3.json`,
|
||||
{
|
||||
method: 'GET'
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
// It is the only way to understand the connector is distributed by Speckle or not.
|
||||
throw new UpdateError('Failed to fetch versions')
|
||||
}
|
||||
)
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Failed to fetch versions')
|
||||
const data = (await response.json()) as unknown as Versions
|
||||
const sortedVersions = data.Versions.sort(function (a: Version, b: Version) {
|
||||
return new Date(b.Date).getTime() - new Date(a.Date).getTime()
|
||||
})
|
||||
versions.value = sortedVersions
|
||||
latestAvailableVersion.value = sortedVersions[0]
|
||||
hostApp.setLatestAvailableVersion(sortedVersions[0])
|
||||
} catch (err) {
|
||||
if (err instanceof TypeError && err.message === 'Failed to fetch') {
|
||||
// When user has network issue in between, actually it is not so likely because regardless user need network to be able to render netlify page
|
||||
throw new Error('Network error')
|
||||
} else if (err instanceof UpdateError) {
|
||||
// We set the flag to use it in relavant places, hide some documentation related buttons etc..
|
||||
hostApp.setIsDistributedBySpeckle(false)
|
||||
} else {
|
||||
// Rest of the possibilites that we trigger toast
|
||||
throw new Error('Unknown error occurred')
|
||||
}
|
||||
}
|
||||
|
||||
const data = (await response.json()) as unknown as Versions
|
||||
const sortedVersions = data.Versions.sort(function (a: Version, b: Version) {
|
||||
return new Date(b.Date).getTime() - new Date(a.Date).getTime()
|
||||
})
|
||||
versions.value = sortedVersions
|
||||
latestAvailableVersion.value = sortedVersions[0]
|
||||
hostApp.setLatestAvailableVersion(sortedVersions[0])
|
||||
}
|
||||
|
||||
return { checkUpdate }
|
||||
|
||||
@@ -193,6 +193,16 @@ export const workspacesListQuery = graphql(`
|
||||
}
|
||||
`)
|
||||
|
||||
export const userInfoAndServerRoleQuery = graphql(`
|
||||
query ActiveUser {
|
||||
activeUser {
|
||||
role
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
`)
|
||||
|
||||
export const canCreatePersonalProjectQuery = graphql(`
|
||||
query CanCreatePersonalProject {
|
||||
activeUser {
|
||||
|
||||
+27
-12
@@ -11,11 +11,23 @@
|
||||
class="fixed h-screen w-screen flex items-center justify-center pr-2 pointer-events-none"
|
||||
>
|
||||
<LayoutPanel fancy-glow class="transition pointer-events-auto w-[90%]">
|
||||
<h1
|
||||
class="text-heading-lg w-full bg-gradient-to-r from-blue-500 via-blue-400 to-blue-600 inline-block py-1 text-transparent bg-clip-text"
|
||||
>
|
||||
Hello!
|
||||
</h1>
|
||||
<div class="flex">
|
||||
<h1
|
||||
class="text-heading-lg w-full bg-gradient-to-r from-blue-500 via-blue-400 to-blue-600 inline-block py-1 text-transparent bg-clip-text"
|
||||
>
|
||||
Hello!
|
||||
</h1>
|
||||
<button
|
||||
v-if="accountStore.activeAccount"
|
||||
v-tippy="'Open web app'"
|
||||
class="transition mr-1 opacity-70 hover:opacity-100"
|
||||
@click.stop="
|
||||
$openUrl(accountStore.activeAccount.accountInfo.serverInfo.url)
|
||||
"
|
||||
>
|
||||
<ArrowTopRightOnSquareIcon class="w-4" />
|
||||
</button>
|
||||
</div>
|
||||
<!-- Returning null from host app is blocked by CI for now, hence host app send here empty documentInfo, we check it's id whether null or not. -->
|
||||
<div v-if="!!store.documentInfo?.id">
|
||||
<div class="text-foreground-2 text-body-sm">
|
||||
@@ -57,7 +69,10 @@
|
||||
</div>
|
||||
</div>
|
||||
<!-- TEMPORARY MESSAGE TO USER! will be deleted -->
|
||||
<div class="mt-2 bg-highlight-1 rounded-md p-2">
|
||||
<div
|
||||
v-if="store.isDistributedBySpeckle"
|
||||
class="mt-2 bg-highlight-1 rounded-md p-2"
|
||||
>
|
||||
<h1
|
||||
class="text-heading-sm w-full bg-gradient-to-r from-blue-500 via-blue-400 to-blue-600 inline-block py-1 text-transparent bg-clip-text"
|
||||
>
|
||||
@@ -74,15 +89,14 @@
|
||||
full-width
|
||||
@click="
|
||||
app.$openUrl(
|
||||
`https://speckle.systems/connectors/${store.hostAppName}`
|
||||
`https://docs.speckle.systems/connectors/${store.hostAppName}?utm=dui`
|
||||
)
|
||||
"
|
||||
>
|
||||
<span class="capitalize">{{ store.hostAppName }} </span>
|
||||
documentation
|
||||
Getting started
|
||||
</FormButton>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<FormButton
|
||||
text
|
||||
size="sm"
|
||||
@@ -98,7 +112,7 @@
|
||||
<span class="text-foreground-2 text-body-3xs truncate line-clamp-1">
|
||||
New connectors announcement
|
||||
</span>
|
||||
</FormButton>
|
||||
</FormButton> -->
|
||||
</div>
|
||||
</LayoutPanel>
|
||||
</div>
|
||||
@@ -153,7 +167,8 @@ import { storeToRefs } from 'pinia'
|
||||
import {
|
||||
ArrowDownTrayIcon,
|
||||
ArrowUpTrayIcon,
|
||||
ArrowPathIcon
|
||||
ArrowPathIcon,
|
||||
ArrowTopRightOnSquareIcon
|
||||
} from '@heroicons/vue/24/solid'
|
||||
import { useAccountStore } from '~~/store/accounts'
|
||||
import { useHostAppStore } from '~~/store/hostApp'
|
||||
|
||||
@@ -43,6 +43,7 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
const accountsStore = useAccountStore()
|
||||
const { checkUpdate } = useUpdateConnector()
|
||||
|
||||
const isDistributedBySpeckle = ref<boolean>(true)
|
||||
const latestAvailableVersion = ref<Version | null>(null)
|
||||
|
||||
const currentNotification = ref<Nullable<ToastNotification>>(null)
|
||||
@@ -85,6 +86,10 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
hostAppError.value = error
|
||||
}
|
||||
|
||||
const setIsDistributedBySpeckle = (val: boolean) => {
|
||||
isDistributedBySpeckle.value = val
|
||||
}
|
||||
|
||||
/**
|
||||
* Model Card Operations
|
||||
*/
|
||||
@@ -734,6 +739,8 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
availableViews,
|
||||
navisworksAvailableSavedSets,
|
||||
availableSelectSendFilters,
|
||||
isDistributedBySpeckle,
|
||||
setIsDistributedBySpeckle,
|
||||
setNotification,
|
||||
setModelError,
|
||||
setLatestAvailableVersion,
|
||||
|
||||
Reference in New Issue
Block a user