refactor: centralized filter validation and generalized 'empty selection' checks
This commit is contained in:
@@ -217,7 +217,8 @@ const updateFilter = (filter: ISendFilter) => {
|
||||
}
|
||||
|
||||
const isSaveDisabled = computed(() => {
|
||||
return !store.validateSendFilter(newFilter.value || props.modelCard.sendFilter).valid
|
||||
const filterToCheck = newFilter.value || props.modelCard.sendFilter
|
||||
return !store.validateSendFilter(filterToCheck).valid
|
||||
})
|
||||
|
||||
const saveFilter = async () => {
|
||||
|
||||
@@ -1,6 +1,24 @@
|
||||
import { computed } from 'vue'
|
||||
import type {
|
||||
ISendFilter,
|
||||
SendFilterSelect,
|
||||
RevitCategoriesSendFilter,
|
||||
RevitViewsSendFilter
|
||||
} from '~/lib/models/card/send'
|
||||
import { ValidationHelpers } from '@speckle/ui-components'
|
||||
import type { GenericValidateFunction } from 'vee-validate'
|
||||
|
||||
export const isSelectFilter = (f: ISendFilter): f is SendFilterSelect =>
|
||||
f.type === 'Select' || 'selectedItems' in f
|
||||
|
||||
export const isRevitCategoriesFilter = (
|
||||
f: ISendFilter
|
||||
): f is RevitCategoriesSendFilter =>
|
||||
f.id === 'revitCategories' || f.id === 'archicadLayers'
|
||||
|
||||
export const isRevitViewsFilter = (f: ISendFilter): f is RevitViewsSendFilter =>
|
||||
f.id === 'revitViews'
|
||||
|
||||
export const isEmail = ValidationHelpers.isEmail
|
||||
|
||||
export const isOneOrMultipleEmails = ValidationHelpers.isOneOrMultipleEmails
|
||||
@@ -42,3 +60,42 @@ export function useModelNameValidationRules() {
|
||||
isValidModelName
|
||||
])
|
||||
}
|
||||
|
||||
export type FilterValidationResult = { valid: boolean; reason?: string }
|
||||
|
||||
export function validateFilter(
|
||||
filter: ISendFilter | undefined,
|
||||
context: { selectionCount: number }
|
||||
): FilterValidationResult {
|
||||
if (!filter) return { valid: false, reason: 'No filter selected' }
|
||||
|
||||
// Selection Filter check
|
||||
if (filter.name === 'Selection' || filter.id === 'selection') {
|
||||
return context.selectionCount > 0
|
||||
? { valid: true }
|
||||
: { valid: false, reason: 'No objects selected to publish' }
|
||||
}
|
||||
|
||||
// List-based filters (Rhino Layers, etc.)
|
||||
if (isSelectFilter(filter)) {
|
||||
return (filter.selectedItems?.length ?? 0) > 0
|
||||
? { valid: true }
|
||||
: { valid: false, reason: 'No items selected to publish' }
|
||||
}
|
||||
|
||||
// Category-based filters
|
||||
if (isRevitCategoriesFilter(filter)) {
|
||||
return (filter.selectedCategories?.length ?? 0) > 0
|
||||
? { valid: true }
|
||||
: { valid: false, reason: 'No categories selected to publish' }
|
||||
}
|
||||
|
||||
// View-based filters
|
||||
if (isRevitViewsFilter(filter)) {
|
||||
return filter.selectedView?.trim()
|
||||
? { valid: true }
|
||||
: { valid: false, reason: 'No view selected to publish' }
|
||||
}
|
||||
|
||||
return { valid: true }
|
||||
}
|
||||
|
||||
+7
-38
@@ -11,9 +11,10 @@ import type {
|
||||
ISendFilterSelectItem,
|
||||
ISenderModelCard,
|
||||
RevitViewsSendFilter,
|
||||
RevitCategoriesSendFilter,
|
||||
SendFilterSelect
|
||||
} from '~/lib/models/card/send'
|
||||
import { useSelectionStore } from '~/store/selection'
|
||||
import { validateFilter } from '~/lib/validation'
|
||||
import type { ToastNotification } from '@speckle/ui-components'
|
||||
import { ToastNotificationType } from '@speckle/ui-components'
|
||||
import type { Nullable } from '@speckle/shared'
|
||||
@@ -23,7 +24,6 @@ import { defineStore } from 'pinia'
|
||||
import type { CardSetting } from '~/lib/models/card/setting'
|
||||
import type { DUIAccount } from '~/store/accounts'
|
||||
import { useAccountStore } from '~/store/accounts'
|
||||
import { useSelectionStore } from '~/store/selection'
|
||||
import {
|
||||
useUpdateConnector,
|
||||
type Version
|
||||
@@ -370,43 +370,12 @@ export const useHostAppStore = defineStore('hostAppStore', () => {
|
||||
*/
|
||||
app.$sendBinding?.on('refreshSendFilters', () => void refreshSendFilters())
|
||||
|
||||
const validateSendFilter = (
|
||||
filter?: ISendFilter
|
||||
): { valid: boolean; reason?: string } => {
|
||||
if (!filter) return { valid: false, reason: 'No filter selected' }
|
||||
const validateSendFilter = (filter?: ISendFilter) => {
|
||||
const selectionStore = useSelectionStore()
|
||||
|
||||
if (filter.name === 'Selection' || filter.id === 'selection') {
|
||||
const selectionStore = useSelectionStore()
|
||||
if (
|
||||
!selectionStore.selectionInfo.selectedObjectIds ||
|
||||
selectionStore.selectionInfo.selectedObjectIds.length === 0
|
||||
) {
|
||||
return { valid: false, reason: 'No objects selected to publish' }
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.type === 'Select' || filter.id === 'navisworksSavedSets') {
|
||||
const f = filter as SendFilterSelect
|
||||
if (!f.selectedItems || f.selectedItems.length === 0) {
|
||||
return { valid: false, reason: 'No items selected to publish' }
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.id === 'revitCategories' || filter.id === 'archicadLayers') {
|
||||
const f = filter as RevitCategoriesSendFilter
|
||||
if (!f.selectedCategories || f.selectedCategories.length === 0) {
|
||||
return { valid: false, reason: 'No categories selected to publish' }
|
||||
}
|
||||
}
|
||||
|
||||
if (filter.id === 'revitViews') {
|
||||
const f = filter as RevitViewsSendFilter
|
||||
if (!f.selectedView || f.selectedView.trim() === '') {
|
||||
return { valid: false, reason: 'No view selected to publish' }
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: true }
|
||||
return validateFilter(filter, {
|
||||
selectionCount: selectionStore.selectionInfo.selectedObjectIds?.length ?? 0
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user