Skip to content

Commit

Permalink
Merge branch 'main' of github.com:specklesystems/speckle-server into …
Browse files Browse the repository at this point in the history
…alessandro/web-2357-create-workspace-join-request-table
  • Loading branch information
alemagio committed Jan 7, 2025
2 parents b1e4834 + c252339 commit 1886ec0
Show file tree
Hide file tree
Showing 167 changed files with 7,686 additions and 3,871 deletions.
3 changes: 3 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ jobs:
S3_REGION: '' # optional, defaults to 'us-east-1'
ENCRYPTION_KEYS_PATH: 'test/assets/automate/encryptionKeys.json'
FF_BILLING_INTEGRATION_ENABLED: 'true'
RATELIMITER_ENABLED: 'false'
steps:
- checkout
- restore_cache:
Expand Down Expand Up @@ -578,6 +579,7 @@ jobs:
S3_REGION: '' # optional, defaults to 'us-east-1'
ENCRYPTION_KEYS_PATH: 'test/assets/automate/encryptionKeys.json'
DISABLE_ALL_FFS: 'true'
RATELIMITER_ENABLED: 'false'

test-server-multiregion:
<<: *test-server-job
Expand Down Expand Up @@ -624,6 +626,7 @@ jobs:
FF_WORKSPACES_MODULE_ENABLED: 'true'
FF_WORKSPACES_MULTI_REGION_ENABLED: 'true'
RUN_TESTS_IN_MULTIREGION_MODE: true
RATELIMITER_ENABLED: 'false'

test-frontend-2:
docker: &docker-node-browsers-image
Expand Down
2 changes: 1 addition & 1 deletion packages/fileimport-service/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"@speckle/shared": "workspace:^",
"bcrypt": "^5.0.1",
"crypto-random-string": "^3.3.1",
"knex": "^2.4.1",
"knex": "^2.5.1",
"pg": "^8.7.3",
"pino": "^8.7.0",
"pino-http": "^8.0.0",
Expand Down
49 changes: 38 additions & 11 deletions packages/frontend-2/components/billing/Alert.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,29 @@
<template>
<div>
<CommonAlert v-if="!hasValidPlan" :color="alertColor" :actions="actions">
<template #title>
<template v-if="!hasValidPlan">
<div
v-if="condensed"
class="flex items-center justify-between rounded-md p-2 pl-3 text-body-3xs font-medium bg-info-lighter text-primary-focus gap-x-2"
>
{{ title }}
</template>
<template #description>
{{ description }}
</template>
</CommonAlert>
<FormButton
v-if="actions.length > 0"
size="sm"
:disabled="actions[0].disabled"
@click="actions[0].onClick"
>
{{ actions[0].title }}
</FormButton>
</div>
<CommonAlert v-else :color="alertColor" :actions="actions">
<template #title>
{{ title }}
</template>
<template #description>
{{ description }}
</template>
</CommonAlert>
</template>
</div>
</template>

Expand Down Expand Up @@ -39,6 +55,7 @@ graphql(`
const props = defineProps<{
workspace: BillingAlert_WorkspaceFragment
actions?: Array<AlertAction>
condensed?: boolean
}>()
const { billingPortalRedirect } = useBillingActions()
Expand All @@ -62,9 +79,17 @@ const trialDaysLeft = computed(() => {
})
const title = computed(() => {
if (isTrial.value) {
return `You have ${trialDaysLeft.value} day${
trialDaysLeft.value !== 1 ? 's' : ''
} left on your free trial`
if (trialDaysLeft.value === 0) {
return 'Final day of free trial'
}
if (props.condensed) {
return `${trialDaysLeft.value} day${
trialDaysLeft.value !== 1 ? 's' : ''
} left in trial`
} else
return `You have ${trialDaysLeft.value} day${
trialDaysLeft.value !== 1 ? 's' : ''
} left on your free trial`
}
switch (planStatus.value) {
case WorkspacePlanStatuses.CancelationScheduled:
Expand Down Expand Up @@ -98,6 +123,8 @@ const description = computed(() => {
return ''
}
})
const hasValidPlan = computed(() => planStatus.value === WorkspacePlanStatuses.Valid)
const alertColor = computed<AlertColor>(() => {
switch (planStatus.value) {
case WorkspacePlanStatuses.PaymentFailed:
Expand All @@ -110,6 +137,7 @@ const alertColor = computed<AlertColor>(() => {
return 'neutral'
}
})
const actions = computed((): AlertAction[] => {
const actions: Array<AlertAction> = props.actions ?? []
Expand All @@ -129,5 +157,4 @@ const actions = computed((): AlertAction[] => {
return actions
})
const hasValidPlan = computed(() => planStatus.value === WorkspacePlanStatuses.Valid)
</script>
5 changes: 3 additions & 2 deletions packages/frontend-2/components/dashboard/Sidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@
v-if="isWorkspacesEnabled"
collapsible
title="Workspaces"
:plus-click="isNotGuest ? handlePlusClick : undefined"
plus-text="Create workspace"
:icon-click="isNotGuest ? handlePlusClick : undefined"
icon-text="Create workspace"
>
<NuxtLink :to="workspacesRoute" @click="handleIntroducingWorkspacesClick">
<LayoutSidebarMenuGroupItem
Expand All @@ -83,6 +83,7 @@
:active="isActive(item.to)"
:tag="
item.plan.status === WorkspacePlanStatuses.Trial ||
item.plan.status === WorkspacePlanStatuses.Expired ||
!item.plan.status
? 'TRIAL'
: undefined
Expand Down
41 changes: 41 additions & 0 deletions packages/frontend-2/components/invite/dialog/CancelInvite.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<template>
<LayoutDialog v-model:open="isOpen" :buttons="dialogButtons" max-width="md">
<template #header>Cancel invite</template>
<p class="text-foreground text-body-xs">
Are you sure you want to cancel the invite for
<span class="font-medium">{{ email }}</span>
<span>?</span>
</p>
</LayoutDialog>
</template>
<script setup lang="ts">
import type { LayoutDialogButton } from '@speckle/ui-components'
const emit = defineEmits<{
(e: 'onCancelInvite'): void
}>()
defineProps<{
email: string
}>()
const isOpen = defineModel<boolean>('open', { required: true })
const dialogButtons = computed((): LayoutDialogButton[] => [
{
text: 'Close',
props: { color: 'outline' },
onClick: () => (isOpen.value = false)
},
{
text: 'Cancel invite',
props: {
submit: true
},
onClick: () => {
emit('onCancelInvite')
isOpen.value = false
}
}
])
</script>
69 changes: 44 additions & 25 deletions packages/frontend-2/components/invite/dialog/Server.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ import { PlusIcon, TrashIcon } from '@heroicons/vue/24/outline'
import type { InviteServerForm, InviteServerItem } from '~~/lib/invites/helpers/types'
import { emptyInviteServerItem } from '~~/lib/invites/helpers/constants'
import { isEmail } from '~~/lib/common/helpers/validation'
import { useGlobalToast } from '~~/lib/common/composables/toast'
const isOpen = defineModel<boolean>('open', { required: true })
Expand All @@ -105,6 +106,7 @@ const anyMutationsLoading = useMutationLoading()
const { isAdmin } = useActiveUser()
const { isGuestMode } = useServerInfo()
const mixpanel = useMixpanel()
const { triggerNotification } = useGlobalToast()
const allowServerRoleSelect = computed(() => isAdmin.value || isGuestMode.value)
const dialogButtons = computed((): LayoutDialogButton[] => [
Expand Down Expand Up @@ -133,35 +135,52 @@ const removeInviteItem = (index: number) => {
removeInvite(index)
}
const onSubmit = handleSubmit(() => {
const onSubmit = handleSubmit(async () => {
const invites = fields.value.filter((invite) => invite.value.email)
invites.forEach(async (invite) => {
invite.value.project
? await inviteUserToProject(invite.value.project.id, [
{
email: invite.value.email,
serverRole: invite.value.serverRole
}
])
: await inviteUserToServer([
{
email: invite.value.email,
serverRole: invite.value.serverRole
}
])
})
try {
await Promise.all(
invites.map((invite) =>
invite.value.project
? inviteUserToProject(
invite.value.project.id,
[{ email: invite.value.email, serverRole: invite.value.serverRole }],
{ hideToasts: true }
)
: inviteUserToServer(
[{ email: invite.value.email, serverRole: invite.value.serverRole }],
{ hideToasts: true }
)
)
)
mixpanel.track('Invite Action', {
type: 'server invite',
name: 'send',
multiple: fields.value.length !== 1,
count: fields.value.length,
hasProject: !!fields.value.some((invite) => invite.value.project),
to: 'email'
})
triggerNotification({
type: ToastNotificationType.Success,
title:
invites.length > 1
? 'Invites successfully send'
: `Invite successfully sent to ${invites[0].value.email}`
})
isOpen.value = false
mixpanel.track('Invite Action', {
type: 'server invite',
name: 'send',
multiple: fields.value.length !== 1,
count: fields.value.length,
hasProject: !!fields.value.some((invite) => invite.value.project),
to: 'email'
})
isOpen.value = false
} catch {
triggerNotification({
type: ToastNotificationType.Danger,
title:
invites.length > 1
? 'One or more invites failed to send'
: `Failed to send invite to ${invites[0].value.email}`
})
}
})
watch(isOpen, (newVal, oldVal) => {
Expand Down
23 changes: 4 additions & 19 deletions packages/frontend-2/components/project/CardImportFileArea.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
<FormFileUploadZone
ref="uploadZone"
v-slot="{ isDraggingFiles }"
:disabled="isUploading"
:disabled="isUploading || disabled"
:size-limit="maxSizeInBytes"
:accept="accept"
class="flex items-center h-full"
@files-selected="triggerAction"
@files-selected="onFilesSelected"
>
<div
class="w-full h-full border-dashed border rounded-md p-4 flex items-center justify-center text-sm"
Expand Down Expand Up @@ -42,12 +42,6 @@
file here.
</span>
</div>
<WorkspaceRegionStaticDataDisclaimer
v-if="showRegionStaticDataDisclaimer"
v-model:open="showRegionStaticDataDisclaimer"
:variant="RegionStaticDataDisclaimerVariant.UploadModel"
@confirm="onConfirmHandler"
/>
</FormFileUploadZone>
</template>
<script setup lang="ts">
Expand All @@ -56,30 +50,21 @@ import { useFileUploadProgressCore } from '~~/lib/form/composables/fileUpload'
import { ExclamationTriangleIcon } from '@heroicons/vue/24/solid'
import { downloadManagerUrl } from '~/lib/common/helpers/route'
import type { Nullable } from '@speckle/shared'
import {
useWorkspaceCustomDataResidencyDisclaimerQuery,
RegionStaticDataDisclaimerVariant
} from '~/lib/workspaces/composables/region'
const props = defineProps<{
projectId: string
modelName?: string
disabled?: boolean
}>()
const {
maxSizeInBytes,
onFilesSelected: onFilesSelectedInternal,
onFilesSelected,
accept,
upload: fileUpload,
isUploading
} = useFileImport(toRefs(props))
const { showRegionStaticDataDisclaimer, triggerAction, onConfirmHandler } =
useWorkspaceCustomDataResidencyDisclaimerQuery({
projectId: computed(() => props.projectId),
onConfirmAction: onFilesSelectedInternal
})
const { errorMessage, progressBarClasses, progressBarStyle } =
useFileUploadProgressCore({
item: fileUpload
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
<template>
<div class="text-foreground-2 text-sm flex flex-col items-center space-y-1">
<div
class="text-foreground-2 text-body-xs flex flex-col items-center justify-center space-y-1"
>
<template
v-if="
[
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
ref="importArea"
:project-id="project.id"
:model-name="project.model.name"
:disabled="project.workspace?.readOnly"
class="h-full w-full"
/>
</div>
Expand Down Expand Up @@ -140,6 +141,10 @@ graphql(`
}
...ProjectModelPageVersionsPagination
...ProjectsModelPageEmbed_Project
workspace {
id
readOnly
}
}
`)
Expand Down
Loading

0 comments on commit 1886ec0

Please sign in to comment.