Align Receive Card Settings Expiration with Send Card Pattern
This commit is contained in:
@@ -17,6 +17,7 @@
|
||||
v-if="hasSettings"
|
||||
:model-card-id="props.modelCard.modelCardId"
|
||||
:settings="props.modelCard.settings"
|
||||
:default-settings="settingsDefaults as unknown as CardSetting[]"
|
||||
>
|
||||
<template #activator="{ toggle }">
|
||||
<button class="action action-normal" @click="toggle()">
|
||||
@@ -69,6 +70,8 @@ import {
|
||||
Bars3Icon
|
||||
} from '@heroicons/vue/24/outline'
|
||||
import type { IModelCard } from '~/lib/models/card'
|
||||
import type { CardSetting } from '~/lib/models/card/setting'
|
||||
import { useHostAppStore } from '~/store/hostApp'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { issuesListQuery } from '~/lib/issues/graphql/queries'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
@@ -76,6 +79,7 @@ import { storeToRefs } from 'pinia'
|
||||
import { useQuery } from '@vue/apollo-composable'
|
||||
|
||||
const { trackEvent } = useMixpanel()
|
||||
const store = useHostAppStore()
|
||||
|
||||
const openModelCardActionsDialog = ref(false)
|
||||
const emit = defineEmits(['view', 'view-versions', 'copy-model-link', 'remove'])
|
||||
@@ -85,6 +89,14 @@ const props = defineProps<{
|
||||
modelCard: IModelCard
|
||||
}>()
|
||||
|
||||
const isSender = computed(() =>
|
||||
props.modelCard.typeDiscriminator.includes('SenderModelCard')
|
||||
)
|
||||
|
||||
const settingsDefaults = computed(() =>
|
||||
isSender.value ? store.sendSettings : store.receiveSettings
|
||||
)
|
||||
|
||||
const hasSettings = computed(() => {
|
||||
return !!props.modelCard.settings
|
||||
})
|
||||
|
||||
@@ -103,11 +103,13 @@ import type { IReceiverModelCard } from '~/lib/models/card/receiver'
|
||||
import { versionDetailsQuery } from '~/lib/graphql/mutationsAndQueries'
|
||||
import type { VersionListItemFragment } from '~/lib/common/generated/gql/graphql'
|
||||
import { useMixpanel } from '~/lib/core/composables/mixpanel'
|
||||
import { useSettingsTracking } from '~/lib/core/composables/trackSettings'
|
||||
import { useInterval, watchOnce } from '@vueuse/core'
|
||||
import { useAccountStore } from '~~/store/accounts'
|
||||
import type { CardSetting } from '~/lib/models/card/setting'
|
||||
|
||||
const { trackEvent } = useMixpanel()
|
||||
const { trackSettingsChange } = useSettingsTracking()
|
||||
const app = useNuxtApp()
|
||||
const accountStore = useAccountStore()
|
||||
|
||||
@@ -157,17 +159,48 @@ const isExpired = computed(() => {
|
||||
return props.modelCard.latestVersionId !== props.modelCard.selectedVersionId
|
||||
})
|
||||
|
||||
const handleUpdateSettings = async (settings: CardSetting[]) => {
|
||||
await store.patchModel(props.modelCard.modelCardId, {
|
||||
settings
|
||||
})
|
||||
// Buffer settings changes while the version dialog is open, then apply on close.
|
||||
// This matches the send card's batch-then-save pattern (SendSettingsDialog).
|
||||
let pendingSettings: CardSetting[] | undefined
|
||||
let settingsWereChanged = false
|
||||
let versionWasSelected = false
|
||||
|
||||
const handleUpdateSettings = (settings: CardSetting[]) => {
|
||||
pendingSettings = settings
|
||||
settingsWereChanged = true
|
||||
}
|
||||
|
||||
watch(openVersionsDialog, async (isOpen) => {
|
||||
if (isOpen) {
|
||||
// Reset flags when dialog opens
|
||||
pendingSettings = undefined
|
||||
settingsWereChanged = false
|
||||
versionWasSelected = false
|
||||
return
|
||||
}
|
||||
|
||||
// Dialog closed — apply buffered settings if they changed
|
||||
// and the user didn't select a version (which triggers a fresh receive anyway)
|
||||
if (settingsWereChanged && pendingSettings && !versionWasSelected) {
|
||||
trackSettingsChange(
|
||||
'Load Card Settings Updated',
|
||||
pendingSettings,
|
||||
store.receiveSettings || []
|
||||
)
|
||||
|
||||
await store.patchModel(props.modelCard.modelCardId, {
|
||||
settings: pendingSettings,
|
||||
expired: true
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
// Cancels any in progress receive AND load selected version
|
||||
const handleVersionSelection = async (
|
||||
selectedVersion: VersionListItemFragment,
|
||||
latestVersion: VersionListItemFragment
|
||||
) => {
|
||||
versionWasSelected = true
|
||||
openVersionsDialog.value = false
|
||||
void trackEvent('DUI3 Action', {
|
||||
name: 'Load Card Version Change',
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
>
|
||||
<ModelSettings
|
||||
:expandable="false"
|
||||
:default-settings="(store.sendSettings as unknown as CardSetting[])"
|
||||
:default-settings="(props.defaultSettings ?? store.sendSettings) as unknown as CardSetting[]"
|
||||
:settings="props.settings"
|
||||
@update:settings="updateSettings"
|
||||
></ModelSettings>
|
||||
@@ -32,6 +32,7 @@ const { trackSettingsChange } = useSettingsTracking()
|
||||
const props = defineProps<{
|
||||
settings?: CardSetting[]
|
||||
modelCardId: string
|
||||
defaultSettings?: CardSetting[]
|
||||
}>()
|
||||
|
||||
const store = useHostAppStore()
|
||||
@@ -51,7 +52,7 @@ const saveSettings = async () => {
|
||||
trackSettingsChange(
|
||||
'Model Card Settings Updated',
|
||||
newSettings,
|
||||
store.sendSettings || []
|
||||
props.defaultSettings || store.sendSettings || []
|
||||
)
|
||||
|
||||
await store.patchModel(props.modelCardId, {
|
||||
|
||||
@@ -5342,6 +5342,8 @@ export type ServerAutomateInfo = {
|
||||
export type ServerConfiguration = {
|
||||
__typename?: 'ServerConfiguration';
|
||||
blobSizeLimitBytes: Scalars['Int']['output'];
|
||||
/** Origin URL of the dashboards service */
|
||||
dashboardsOrigin?: Maybe<Scalars['String']['output']>;
|
||||
/** Email verification code timeout in minutes */
|
||||
emailVerificationTimeoutMinutes: Scalars['Int']['output'];
|
||||
/** Active server-level feature flags */
|
||||
@@ -5464,6 +5466,7 @@ export enum ServerRole {
|
||||
ServerAdmin = 'SERVER_ADMIN',
|
||||
ServerArchivedUser = 'SERVER_ARCHIVED_USER',
|
||||
ServerGuest = 'SERVER_GUEST',
|
||||
ServerSupport = 'SERVER_SUPPORT',
|
||||
ServerUser = 'SERVER_USER'
|
||||
}
|
||||
|
||||
@@ -6987,6 +6990,13 @@ export type Workspace = {
|
||||
plan?: Maybe<WorkspacePlan>;
|
||||
/** Shows the plan prices localized for the given workspace */
|
||||
planPrices?: Maybe<WorkspacePaidPlanPrices>;
|
||||
/**
|
||||
* Bulk project activity data for the workspace timeline widget.
|
||||
* Returns versions created within a date window, grouped by project.
|
||||
* First call discovers top N projects; pass the returned cursor to load older data.
|
||||
* Internal API — may change without notice.
|
||||
*/
|
||||
projectActivityTimeline?: Maybe<WorkspaceProjectActivityTimelineResult>;
|
||||
projects: ProjectCollection;
|
||||
/** A Workspace is marked as readOnly if its trial period is finished or a paid plan is subscribed but payment has failed */
|
||||
readOnly: Scalars['Boolean']['output'];
|
||||
@@ -7048,6 +7058,11 @@ export type WorkspaceIssueLabelsArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type WorkspaceProjectActivityTimelineArgs = {
|
||||
input: WorkspaceProjectActivityTimelineInput;
|
||||
};
|
||||
|
||||
|
||||
export type WorkspaceProjectsArgs = {
|
||||
cursor?: InputMaybe<Scalars['String']['input']>;
|
||||
filter?: InputMaybe<WorkspaceProjectsFilter>;
|
||||
@@ -7186,6 +7201,7 @@ export enum WorkspaceFeatureName {
|
||||
DomainDiscoverability = 'domainDiscoverability',
|
||||
EmbedPrivateProjects = 'embedPrivateProjects',
|
||||
ExclusiveMembership = 'exclusiveMembership',
|
||||
Frontend3 = 'frontend3',
|
||||
HideSpeckleBranding = 'hideSpeckleBranding',
|
||||
Issues = 'issues',
|
||||
Markup = 'markup',
|
||||
@@ -7684,6 +7700,43 @@ export enum WorkspacePlans {
|
||||
Unlimited = 'unlimited'
|
||||
}
|
||||
|
||||
export type WorkspaceProjectActivityTimelineInput = {
|
||||
/**
|
||||
* Opaque cursor from a previous response. When provided, withProjectRoleOnly and projectLimit are ignored.
|
||||
* Encodes the locked-in project set and next date boundary.
|
||||
*/
|
||||
cursor?: InputMaybe<Scalars['String']['input']>;
|
||||
/**
|
||||
* Size of each date window in days. Default: 7.
|
||||
* Used for both discovery (now - N days) and pagination (cursor.before - N days).
|
||||
* Can change between pages — the cursor locks the project set and boundary,
|
||||
* while this controls how far back from that boundary to look.
|
||||
*/
|
||||
dateRangeDays?: InputMaybe<Scalars['Int']['input']>;
|
||||
/** Max projects to discover by updatedAt DESC. Default: 20. Ignored when cursor is provided. */
|
||||
projectLimit?: InputMaybe<Scalars['Int']['input']>;
|
||||
/**
|
||||
* Only return projects where the active user has an explicit project role.
|
||||
* Used on first call (discovery). Ignored when cursor is provided (as projects are pre-determined then).
|
||||
*/
|
||||
withProjectRoleOnly?: InputMaybe<Scalars['Boolean']['input']>;
|
||||
};
|
||||
|
||||
export type WorkspaceProjectActivityTimelineProjectGroup = {
|
||||
__typename?: 'WorkspaceProjectActivityTimelineProjectGroup';
|
||||
project: Project;
|
||||
/** Versions within the date range, ordered by createdAt DESC. */
|
||||
versions: Array<Version>;
|
||||
};
|
||||
|
||||
export type WorkspaceProjectActivityTimelineResult = {
|
||||
__typename?: 'WorkspaceProjectActivityTimelineResult';
|
||||
/** Opaque cursor for loading older data. Null when no more data is available. */
|
||||
cursor?: Maybe<Scalars['String']['output']>;
|
||||
/** Projects with their versions, ordered by most recent version DESC. */
|
||||
projectGroups: Array<WorkspaceProjectActivityTimelineProjectGroup>;
|
||||
};
|
||||
|
||||
export type WorkspaceProjectCreateInput = {
|
||||
description?: InputMaybe<Scalars['String']['input']>;
|
||||
name?: InputMaybe<Scalars['String']['input']>;
|
||||
|
||||
@@ -2,6 +2,9 @@ import legacy from '@vitejs/plugin-legacy'
|
||||
|
||||
// https://nuxt.com/docs/api/configuration/nuxt-config
|
||||
export default defineNuxtConfig({
|
||||
devServer: {
|
||||
port: 8082
|
||||
},
|
||||
typescript: {
|
||||
shim: false,
|
||||
strict: true
|
||||
|
||||
+1
-1
@@ -514,7 +514,7 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
app.$receiveBinding?.on('setModelsExpired', (modelCardIds) => {
|
||||
documentModelStore.value.models
|
||||
.filter((m) => modelCardIds.includes(m.modelCardId))
|
||||
.forEach((model: IReceiverModelCard) => {
|
||||
.forEach((model) => {
|
||||
model.error = undefined
|
||||
model.expired = true
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user