feat(ComboWidget): add ability to have mapped inputs (#6585)

## Summary

1. Add a `getOptionLabel` option to `ComboWidget` so users of it can map
of custom labels to widget values. (e.g., `"My Photo" ->
"my_photo_1235.png"`).
2. Utilize this ability in Cloud environment to map user uploaded
filenames to their corresponding input asset.
3. Copious unit tests to make sure I didn't (AFAIK) break anything
during the refactoring portion of development.
4. Bonus: Scope model browser to only show in cloud distributions until
it's released elsewhere; should prevent some undesired UI behavior if a
user accidentally enables the assetAPI.

## Review Focus

Widget code: please double check the work there.

## Screenshots (if applicable)



https://github.com/user-attachments/assets/a94b3203-c87f-4285-b692-479996859a5a


┆Issue is synchronized with this [Notion
page](https://www.notion.so/PR-6585-Feat-input-mapping-2a26d73d365081faa667e49892c8d45a)
by [Unito](https://www.unito.io)
This commit is contained in:
Arjan Singh
2025-11-05 11:33:00 -08:00
committed by GitHub
parent 265f1257e7
commit a2ef569b9c
9 changed files with 1804 additions and 106 deletions

View File

@@ -1,5 +1,6 @@
import { useAsyncState } from '@vueuse/core'
import { defineStore } from 'pinia'
import { computed } from 'vue'
import {
mapInputFileToAssetItem,
@@ -12,6 +13,8 @@ import { api } from '@/scripts/api'
import { TaskItemImpl } from './queueStore'
const INPUT_LIMIT = 100
/**
* Fetch input files from the internal API (OSS version)
*/
@@ -36,7 +39,9 @@ async function fetchInputFilesFromAPI(): Promise<AssetItem[]> {
* Fetch input files from cloud service
*/
async function fetchInputFilesFromCloud(): Promise<AssetItem[]> {
return await assetService.getAssetsByTag('input', false)
return await assetService.getAssetsByTag('input', false, {
limit: INPUT_LIMIT
})
}
/**
@@ -117,6 +122,30 @@ export const useAssetsStore = defineStore('assets', () => {
}
})
/**
* Map of asset hash filename to asset item for O(1) lookup
* Cloud assets use asset_hash for the hash-based filename
*/
const inputAssetsByFilename = computed(() => {
const map = new Map<string, AssetItem>()
for (const asset of inputAssets.value) {
// Use asset_hash as the key (hash-based filename)
if (asset.asset_hash) {
map.set(asset.asset_hash, asset)
}
}
return map
})
/**
* Get human-readable name for input asset filename
* @param filename Hash-based filename (e.g., "72e786ff...efb7.png")
* @returns Human-readable asset name or original filename if not found
*/
function getInputName(filename: string): string {
return inputAssetsByFilename.value.get(filename)?.name ?? filename
}
return {
// States
inputAssets,
@@ -128,6 +157,10 @@ export const useAssetsStore = defineStore('assets', () => {
// Actions
updateInputs,
updateHistory
updateHistory,
// Input mapping helpers
inputAssetsByFilename,
getInputName
}
})