Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 3 additions & 27 deletions src/platform/assets/components/AssetBrowserModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
size="md"
class="!h-10 [&>span]:hidden md:[&>span]:inline"
:label="$t('assetBrowser.uploadModel')"
:on-click="handleUploadClick"
:on-click="showUploadDialog"
>
<template #icon>
<i class="icon-[lucide--package-plus]" />
Expand Down Expand Up @@ -70,17 +70,14 @@ import IconTextButton from '@/components/button/IconTextButton.vue'
import SearchBox from '@/components/input/SearchBox.vue'
import BaseModalLayout from '@/components/widget/layout/BaseModalLayout.vue'
import LeftSidePanel from '@/components/widget/panel/LeftSidePanel.vue'
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import AssetFilterBar from '@/platform/assets/components/AssetFilterBar.vue'
import AssetGrid from '@/platform/assets/components/AssetGrid.vue'
import UploadModelDialog from '@/platform/assets/components/UploadModelDialog.vue'
import UploadModelDialogHeader from '@/platform/assets/components/UploadModelDialogHeader.vue'
import type { AssetDisplayItem } from '@/platform/assets/composables/useAssetBrowser'
import { useAssetBrowser } from '@/platform/assets/composables/useAssetBrowser'
import { useModelUpload } from '@/platform/assets/composables/useModelUpload'
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
import { assetService } from '@/platform/assets/services/assetService'
import { formatCategoryLabel } from '@/platform/assets/utils/categoryLabel'
import { useDialogStore } from '@/stores/dialogStore'
import { useModelToNodeStore } from '@/stores/modelToNodeStore'
import { OnCloseKey } from '@/types/widgetTypes'

Expand All @@ -95,7 +92,6 @@ const props = defineProps<{
}>()

const { t } = useI18n()
const dialogStore = useDialogStore()

const emit = defineEmits<{
'asset-select': [asset: AssetDisplayItem]
Expand Down Expand Up @@ -189,25 +185,5 @@ function handleAssetSelectAndEmit(asset: AssetDisplayItem) {
props.onSelect?.(asset)
}

const { flags } = useFeatureFlags()
const isUploadButtonEnabled = computed(() => flags.modelUploadButtonEnabled)

function handleUploadClick() {
dialogStore.showDialog({
key: 'upload-model',
headerComponent: UploadModelDialogHeader,
component: UploadModelDialog,
props: {
onUploadSuccess: async () => {
await execute()
}
},
dialogComponentProps: {
pt: {
header: 'py-0! pl-0!',
content: 'p-0!'
}
}
})
}
const { isUploadButtonEnabled, showUploadDialog } = useModelUpload(execute)
</script>
35 changes: 35 additions & 0 deletions src/platform/assets/composables/useModelUpload.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { useFeatureFlags } from '@/composables/useFeatureFlags'
import UploadModelDialog from '@/platform/assets/components/UploadModelDialog.vue'
import UploadModelDialogHeader from '@/platform/assets/components/UploadModelDialogHeader.vue'
import type { AssetItem } from '@/platform/assets/schemas/assetSchema'
import { useDialogStore } from '@/stores/dialogStore'
import type { UseAsyncStateReturn } from '@vueuse/core'
import { computed } from 'vue'

export function useModelUpload(
execute?: UseAsyncStateReturn<AssetItem[], [], true>['execute']
) {
const dialogStore = useDialogStore()
const { flags } = useFeatureFlags()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: Is it better for feature flags to be accessed same way everywhere or passed through via the state-threading/DI/prop-drilling type of pattern?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They're universal, so they should be accessed directly. DI/Prop drilling is for things that are contextual and where the context can be derived from the DOM/component hierarchy.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So in theory, this compostable shouldn't re expose a computer version of the flags?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the importance isn't that it's a flag, it's whether the behavior here should be exposed.
Putting the flag check into the composable means that each consumer only needs to know the value, not how to get it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case, the importance isn't that it's a flag, it's whether the behavior here should be exposed.
Putting the flag check into the composable means that each consumer only needs to know the value, not how to get it.

const isUploadButtonEnabled = computed(() => flags.modelUploadButtonEnabled)

function showUploadDialog() {
dialogStore.showDialog({
key: 'upload-model',
headerComponent: UploadModelDialogHeader,
component: UploadModelDialog,
props: {
onUploadSuccess: async () => {
await execute?.()
}
},
dialogComponentProps: {
pt: {
header: 'py-0! pl-0!',
content: 'p-0!'
}
}
})
}
return { isUploadButtonEnabled, showUploadDialog }
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import IconTextButton from '@/components/button/IconTextButton.vue'
import { useModelUpload } from '@/platform/assets/composables/useModelUpload'
import { cn } from '@/utils/tailwindUtil'

import type { FilterOption, OptionId } from './types'
Expand All @@ -8,10 +10,12 @@ defineProps<{
}>()

const filterSelected = defineModel<OptionId>('filterSelected')

const { isUploadButtonEnabled, showUploadDialog } = useModelUpload()
</script>

<template>
<div class="text-secondary mb-4 flex gap-1 px-4">
<div class="text-secondary mb-4 flex gap-1 px-4 justify-between">
<div
v-for="option in filterOptions"
:key="option.id"
Expand All @@ -30,5 +34,15 @@ const filterSelected = defineModel<OptionId>('filterSelected')
>
{{ option.name }}
</div>
<IconTextButton
v-if="isUploadButtonEnabled"
:label="$t('g.import')"
type="secondary"
@click="showUploadDialog"
>
<template #icon>
<i class="icon-[lucide--folder-input]" />
</template>
</IconTextButton>
</div>
</template>