@cobaltcore-dev/aurora 0.10.0 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -1
- package/dist/client/AuroraApp.d.ts +2 -0
- package/dist/client/AuthProvider-DZqOvceF.mjs +64 -0
- package/dist/client/AuthProvider-DZqOvceF.mjs.map +1 -0
- package/dist/client/ContentHeader-DsuZD8fa.mjs +110 -0
- package/dist/client/ContentHeader-DsuZD8fa.mjs.map +1 -0
- package/dist/client/{DeleteFlavorModal-C3m7bQJu.mjs → DeleteFlavorModal-RnbspW_2.mjs} +135 -135
- package/dist/client/{DeleteFlavorModal-C3m7bQJu.mjs.map → DeleteFlavorModal-RnbspW_2.mjs.map} +1 -1
- package/dist/client/{DeleteVersionsModal-CyYZfB8d.mjs → DeleteVersionsModal-CsBJzXoW.mjs} +57 -57
- package/dist/client/{DeleteVersionsModal-CyYZfB8d.mjs.map → DeleteVersionsModal-CsBJzXoW.mjs.map} +1 -1
- package/dist/client/{EditSecurityGroupModal-DKusxfta.mjs → EditSecurityGroupModal-BPv3d7am.mjs} +15 -15
- package/dist/client/{EditSecurityGroupModal-DKusxfta.mjs.map → EditSecurityGroupModal-BPv3d7am.mjs.map} +1 -1
- package/dist/client/{FiltersInput-GzR4D0q6.mjs → FiltersInput-CViamP59.mjs} +2 -2
- package/dist/client/{FiltersInput-GzR4D0q6.mjs.map → FiltersInput-CViamP59.mjs.map} +1 -1
- package/dist/client/{FloatingIpActionModals-CRvROJ3H.mjs → FloatingIpActionModals-DTn3HFei.mjs} +45 -45
- package/dist/client/{FloatingIpActionModals-CRvROJ3H.mjs.map → FloatingIpActionModals-DTn3HFei.mjs.map} +1 -1
- package/dist/client/{ImageToastNotifications-BuDXpTkl.mjs → ImageToastNotifications-CFKQZTgf.mjs} +261 -261
- package/dist/client/{ImageToastNotifications-BuDXpTkl.mjs.map → ImageToastNotifications-CFKQZTgf.mjs.map} +1 -1
- package/dist/client/{RouteError-DVAiT0mT.mjs → RouteError-BebIhFpQ.mjs} +2 -2
- package/dist/client/{RouteError-DVAiT0mT.mjs.map → RouteError-BebIhFpQ.mjs.map} +1 -1
- package/dist/client/{SortInput-DLcusjGZ.mjs → SortInput-D0Vb864D.mjs} +2 -2
- package/dist/client/{SortInput-DLcusjGZ.mjs.map → SortInput-D0Vb864D.mjs.map} +1 -1
- package/dist/client/{_auth-DXJkv9QO.mjs → _auth-DnImOqR-.mjs} +2 -2
- package/dist/client/_auth-DnImOqR-.mjs.map +1 -0
- package/dist/client/{_flavorId-Dy7EYQum.mjs → _flavorId-C9SZd1jL.mjs} +8 -8
- package/dist/client/{_flavorId-Dy7EYQum.mjs.map → _flavorId-C9SZd1jL.mjs.map} +1 -1
- package/dist/client/{_flavorId-DsD2VTKA.mjs → _flavorId-DINgWoeV.mjs} +38 -38
- package/dist/client/{_flavorId-DsD2VTKA.mjs.map → _flavorId-DINgWoeV.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-j17rCQqG2.mjs → _floatingIpId-BACLbMzi2.mjs} +32 -32
- package/dist/client/{_floatingIpId-j17rCQqG2.mjs.map → _floatingIpId-BACLbMzi2.mjs.map} +1 -1
- package/dist/client/{_floatingIpId-BjVbeNw_.mjs → _floatingIpId-BzVMOv97.mjs} +2 -2
- package/dist/client/{_floatingIpId-BjVbeNw_.mjs.map → _floatingIpId-BzVMOv97.mjs.map} +1 -1
- package/dist/client/_imageId-DCvaU7-S.mjs +534 -0
- package/dist/client/_imageId-DCvaU7-S.mjs.map +1 -0
- package/dist/client/{_pcaId-Bo7yHkNW.mjs → _pcaId-B3PqECyO.mjs} +115 -115
- package/dist/client/{_pcaId-Bo7yHkNW.mjs.map → _pcaId-B3PqECyO.mjs.map} +1 -1
- package/dist/client/{_pcaId-CKkCVC7b.mjs → _pcaId-DAJEt3ZI.mjs} +2 -2
- package/dist/client/{_pcaId-CKkCVC7b.mjs.map → _pcaId-DAJEt3ZI.mjs.map} +1 -1
- package/dist/client/{_projectId-CARHuZTU.mjs → _projectId-B2hG5peP.mjs} +3 -3
- package/dist/client/_projectId-B2hG5peP.mjs.map +1 -0
- package/dist/client/{_projectId-CY8W0IF6.mjs → _projectId-BnWXWTBR.mjs} +3 -3
- package/dist/client/{_projectId-CY8W0IF6.mjs.map → _projectId-BnWXWTBR.mjs.map} +1 -1
- package/dist/client/{_projectId-Dbck_MFa.mjs → _projectId-DRr9rLST.mjs} +66 -66
- package/dist/client/{_projectId-Dbck_MFa.mjs.map → _projectId-DRr9rLST.mjs.map} +1 -1
- package/dist/client/{_projectId-B_2sZKk-.mjs → _projectId-DU8qRiZk.mjs} +2 -2
- package/dist/client/_projectId-DU8qRiZk.mjs.map +1 -0
- package/dist/client/{_securityGroupId-gSEZbBII.mjs → _securityGroupId-Cj9IotMJ.mjs} +2 -2
- package/dist/client/{_securityGroupId-gSEZbBII.mjs.map → _securityGroupId-Cj9IotMJ.mjs.map} +1 -1
- package/dist/client/{_securityGroupId-CkN0CGVg.mjs → _securityGroupId-ClJiFh4R.mjs} +267 -267
- package/dist/client/{_securityGroupId-CkN0CGVg.mjs.map → _securityGroupId-ClJiFh4R.mjs.map} +1 -1
- package/dist/client/_storageType-BrHDa2bD.mjs +3005 -0
- package/dist/client/_storageType-BrHDa2bD.mjs.map +1 -0
- package/dist/client/{_storageType-6k8lUnQo.mjs → _storageType-CSLH93js.mjs} +2 -2
- package/dist/client/{_storageType-6k8lUnQo.mjs.map → _storageType-CSLH93js.mjs.map} +1 -1
- package/dist/client/_storageType-zeSZe--V.mjs.map +1 -1
- package/dist/client/{about-Nsxkyh9U.mjs → about-BnU297yB.mjs} +2 -2
- package/dist/client/about-BnU297yB.mjs.map +1 -0
- package/dist/client/{aurora-DDzsst74.mjs → aurora-6RsAZtnz.mjs} +2 -2
- package/dist/client/aurora-6RsAZtnz.mjs.map +1 -0
- package/dist/client/{build-BdRRmNf5.mjs → build-DF7MTyXG.mjs} +3582 -3114
- package/dist/client/{build-BdRRmNf5.mjs.map → build-DF7MTyXG.mjs.map} +1 -1
- package/dist/client/{constants-PMXUGI4Q.mjs → constants-BskfpGYY.mjs} +16 -16
- package/dist/client/{constants-PMXUGI4Q.mjs.map → constants-BskfpGYY.mjs.map} +1 -1
- package/dist/client/{flavors-p2TKcqP-.mjs → flavors-DAbtRoep.mjs} +151 -151
- package/dist/client/{flavors-p2TKcqP-.mjs.map → flavors-DAbtRoep.mjs.map} +1 -1
- package/dist/client/{flavors-BclEwobO.mjs → flavors-DODudzrA.mjs} +2 -2
- package/dist/client/{flavors-BclEwobO.mjs.map → flavors-DODudzrA.mjs.map} +1 -1
- package/dist/client/flavors-DWMZ6TuJ.mjs.map +1 -1
- package/dist/client/{floatingips-ph0ZxJw8.mjs → floatingips-DJW9ftN_.mjs} +83 -83
- package/dist/client/floatingips-DJW9ftN_.mjs.map +1 -0
- package/dist/client/{hooks-dSArr2Ca.mjs → hooks-CMgoYcDG.mjs} +1 -1
- package/dist/client/{images-CXdghaMW.mjs → images-BbLnuYrL.mjs} +2 -2
- package/dist/client/{images-CXdghaMW.mjs.map → images-BbLnuYrL.mjs.map} +1 -1
- package/dist/client/{images-Dbjo4yKn.mjs → images-C3JyPwer.mjs} +2 -2
- package/dist/client/images-C3JyPwer.mjs.map +1 -0
- package/dist/client/{images-BblnyWJq.mjs → images-Cp6V1nF5.mjs} +455 -455
- package/dist/client/{images-BblnyWJq.mjs.map → images-Cp6V1nF5.mjs.map} +1 -1
- package/dist/client/images-NBf2bV43.mjs.map +1 -1
- package/dist/client/index.js +257 -257
- package/dist/client/index.js.map +1 -1
- package/dist/client/network-DuZm76BZ.mjs.map +1 -1
- package/dist/client/{objects-B9Jh3SMG.mjs → objects-Bw96WXOs.mjs} +2 -2
- package/dist/client/{objects-B9Jh3SMG.mjs.map → objects-Bw96WXOs.mjs.map} +1 -1
- package/dist/client/{objects-Bw25cE1m.mjs → objects-DUmK3WgA.mjs} +1458 -1430
- package/dist/client/objects-DUmK3WgA.mjs.map +1 -0
- package/dist/client/objects-o2Cj_ndZ.mjs.map +1 -1
- package/dist/client/{pca-DUrQ_tIg.mjs → pca-DKeGzbww.mjs} +2 -2
- package/dist/client/{pca-DUrQ_tIg.mjs.map → pca-DKeGzbww.mjs.map} +1 -1
- package/dist/client/{pca-CiLPHmK7.mjs → pca-Dc_tdh4-.mjs} +47 -47
- package/dist/client/{pca-CiLPHmK7.mjs.map → pca-Dc_tdh4-.mjs.map} +1 -1
- package/dist/client/{projects-DNd3UTas.mjs → projects-CRL37ftA.mjs} +16 -16
- package/dist/client/{projects-DNd3UTas.mjs.map → projects-CRL37ftA.mjs.map} +1 -1
- package/dist/client/{projects-B5topuei.mjs → projects-DUWOgB3m.mjs} +2 -2
- package/dist/client/{projects-B5topuei.mjs.map → projects-DUWOgB3m.mjs.map} +1 -1
- package/dist/client/{projects-CHYn7L5e.mjs → projects-DpXQYfKc.mjs} +2 -2
- package/dist/client/projects-DpXQYfKc.mjs.map +1 -0
- package/dist/client/{securitygroups-CcA2TpAt.mjs → securitygroups-CWWFSjjj.mjs} +94 -94
- package/dist/client/securitygroups-CWWFSjjj.mjs.map +1 -0
- package/dist/client/{useListWithFiltering-CVzhMyEA.mjs → useListWithFiltering-C9k7xWqz.mjs} +7 -7
- package/dist/client/{useListWithFiltering-CVzhMyEA.mjs.map → useListWithFiltering-C9k7xWqz.mjs.map} +1 -1
- package/dist/server/index.js +697 -406
- package/package.json +3 -3
- package/dist/client/AuthProvider-Co4d0WzB.mjs +0 -100
- package/dist/client/AuthProvider-Co4d0WzB.mjs.map +0 -1
- package/dist/client/ContentHeader-D4jlOG-9.mjs +0 -96
- package/dist/client/ContentHeader-D4jlOG-9.mjs.map +0 -1
- package/dist/client/_auth-DXJkv9QO.mjs.map +0 -1
- package/dist/client/_imageId-BjfhqAje.mjs +0 -534
- package/dist/client/_imageId-BjfhqAje.mjs.map +0 -1
- package/dist/client/_projectId-B_2sZKk-.mjs.map +0 -1
- package/dist/client/_projectId-CARHuZTU.mjs.map +0 -1
- package/dist/client/_storageType-CLTxXjQZ.mjs +0 -3048
- package/dist/client/_storageType-CLTxXjQZ.mjs.map +0 -1
- package/dist/client/about-Nsxkyh9U.mjs.map +0 -1
- package/dist/client/aurora-DDzsst74.mjs.map +0 -1
- package/dist/client/floatingips-ph0ZxJw8.mjs.map +0 -1
- package/dist/client/images-Dbjo4yKn.mjs.map +0 -1
- package/dist/client/objects-Bw25cE1m.mjs.map +0 -1
- package/dist/client/projects-CHYn7L5e.mjs.map +0 -1
- package/dist/client/securitygroups-CcA2TpAt.mjs.map +0 -1
package/dist/client/{useListWithFiltering-CVzhMyEA.mjs.map → useListWithFiltering-C9k7xWqz.mjs.map}
RENAMED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useListWithFiltering-CVzhMyEA.mjs","names":["useCallback","useRef","useEffect","SearchInput","Stack","TabNavigation","TabNavigationItem","SelectedFilters","FiltersInput","SortInput","ListToolbar","filterSettings","onFilter","sortSettings","onSort","searchTerm","onSearch","searchInputProps","actions","tabs","totalCount","filteredCount","itemName","lastUpdated","useLingui","debounceTimerRef","undefined","current","clearTimeout","formatLastUpdated","date","dateObj","Date","toLocaleString","showCountInfo","handleFilterDelete","filterToRemove","selectedFilters","filter","name","value","handleSelect","selectedFilter","filterExists","some","supportsMultiValue","filters","find","filterName","newSelected","handleSearch","searchValue","handleSearchInput","event","currentTarget","window","setTimeout","handleSearchClear","filtersProps","onChange","sortProps","options","sortBy","sortDirection","onSortByChange","param","onSortDirectionChange","direction","searchProps","placeholder","t","onInput","onClear","div","className","activeItem","onActiveItemChange","items","map","item","label","alignment","gap","length","onDelete","span","formattedDate","startTransition","useState","useListWithFiltering","defaultSortKey","defaultSortDir","sortOptions","filterSettings","initialFilterSettings","searchTerm","setSearchTerm","handleSearchChange","term","searchValue","sortSettings","setSortSettings","options","sortBy","sortDirection","handleSortChange","newSortSettings","settings","toString","setFilterSettings","handleFilterChange","newFilterSettings"],"sources":["../../src/client/components/ListToolbar/index.tsx","../../src/client/utils/useListWithFiltering.ts"],"sourcesContent":["import { ReactNode, useCallback, useRef, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n SearchInput,\n SearchInputProps,\n Stack,\n TabNavigation,\n TabNavigationItem,\n} from \"@cloudoperators/juno-ui-components\"\nimport { SelectedFilters } from \"./SelectedFilters\"\nimport { FiltersInput } from \"./FiltersInput\"\nimport { SortInput } from \"./SortInput\"\nimport { FilterSettings, SelectedFilter, SortSettings } from \"./types\"\n\nexport type ListToolbarProps = {\n filterSettings?: FilterSettings\n onFilter?: (filterSettings: FilterSettings) => void\n sortSettings?: SortSettings\n onSort?: (sortSettings: SortSettings) => void\n searchTerm?: string\n onSearch?: (searchTerm: string) => void\n searchInputProps?: Omit<SearchInputProps, \"value\" | \"onSearch\" | \"onClear\" | \"onInput\">\n actions?: ReactNode\n tabs?: {\n items: Array<{ label: string; value: string }>\n activeItem: string\n onActiveItemChange: (value: ReactNode) => void\n }\n // Count information\n totalCount?: number\n itemName?: string // e.g. \"items\", \"users\", \"projects\" - used in count display\n filteredCount?: number\n // Last updated timestamp\n lastUpdated?: Date | string\n}\n\nexport const ListToolbar = ({\n filterSettings,\n onFilter,\n sortSettings,\n onSort,\n searchTerm,\n onSearch,\n searchInputProps = {},\n actions,\n tabs,\n totalCount,\n filteredCount,\n itemName = \"items\",\n lastUpdated,\n}: ListToolbarProps) => {\n const { t } = useLingui()\n\n const debounceTimerRef = useRef<number | undefined>(undefined)\n\n useEffect(() => {\n return () => {\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n }\n }, [])\n\n // Format last updated time\n const formatLastUpdated = (date: Date | string | undefined): string => {\n if (!date) return \"\"\n const dateObj = typeof date === \"string\" ? new Date(date) : date\n return dateObj.toLocaleString()\n }\n\n const showCountInfo = totalCount !== undefined && filteredCount !== undefined\n\n const handleFilterDelete = useCallback(\n (filterToRemove: SelectedFilter) => {\n if (!onFilter || !filterSettings) return\n onFilter({\n ...filterSettings,\n selectedFilters: filterSettings.selectedFilters?.filter(\n (filter) => !(filter.name === filterToRemove.name && filter.value === filterToRemove.value)\n ),\n })\n },\n [filterSettings, onFilter]\n )\n\n const handleSelect = (selectedFilter: SelectedFilter) => {\n if (!onFilter || !filterSettings) return\n const filterExists = filterSettings.selectedFilters?.some(\n (filter) => filter.name === selectedFilter.name && filter.value === selectedFilter.value\n )\n if (filterExists) return\n\n const supportsMultiValue = filterSettings.filters.find(\n (filter) => selectedFilter.name === filter.filterName\n )?.supportsMultiValue\n\n const newSelected = supportsMultiValue\n ? [...(filterSettings.selectedFilters || []), selectedFilter]\n : [\n ...(filterSettings.selectedFilters || []).filter((filter) => filter.name !== selectedFilter.name),\n selectedFilter,\n ]\n\n onFilter({ ...filterSettings, selectedFilters: newSelected })\n }\n\n const handleSearch = useCallback(\n (value: string | number | string[] | undefined) => {\n const searchValue = typeof value === \"string\" ? value : \"\"\n\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n\n onSearch?.(searchValue)\n },\n [onSearch]\n )\n\n const handleSearchInput = useCallback(\n (event: React.FormEvent<HTMLInputElement>) => {\n const searchValue = event.currentTarget.value\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)\n debounceTimerRef.current = window.setTimeout(() => onSearch?.(searchValue), 500)\n },\n [onSearch]\n )\n\n const handleSearchClear = useCallback(() => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)\n onSearch?.(\"\")\n }, [onSearch])\n\n const filtersProps = filterSettings && onFilter ? { filters: filterSettings.filters, onChange: handleSelect } : null\n const sortProps =\n sortSettings && onSort\n ? {\n options: sortSettings.options,\n sortBy: sortSettings.sortBy,\n sortDirection: sortSettings.sortDirection || \"asc\",\n onSortByChange: (param: string | number | string[] | undefined) =>\n onSort({ ...sortSettings, sortBy: param, sortDirection: sortSettings.sortDirection || \"asc\" }),\n onSortDirectionChange: (direction: \"asc\" | \"desc\") => onSort({ ...sortSettings, sortDirection: direction }),\n }\n : null\n\n const searchProps: (SearchInputProps & { \"data-testid\"?: string }) | null = onSearch\n ? {\n placeholder: t`Search...`,\n \"data-testid\": \"searchbar\",\n value: searchTerm,\n onInput: handleSearchInput,\n onClear: handleSearchClear,\n onSearch: handleSearch,\n ...searchInputProps,\n }\n : null\n\n return (\n <>\n {tabs && (\n <div className=\"w-full\">\n <TabNavigation activeItem={tabs.activeItem} onActiveItemChange={tabs.onActiveItemChange}>\n {tabs.items.map((item) => (\n <TabNavigationItem key={item.value} label={item.label} value={item.value} />\n ))}\n </TabNavigation>\n </div>\n )}\n <Stack alignment=\"center\" gap=\"6\" className=\"bg-theme-background-lvl-1 flex w-full flex-col p-4\">\n {actions && (\n <Stack direction=\"horizontal\" className=\"w-full justify-end\">\n {actions}\n </Stack>\n )}\n\n <div className=\"flex w-full flex-col items-stretch gap-4 md:flex-row md:items-center\">\n {filtersProps && (\n <div className=\"w-full md:w-auto md:min-w-37.5\">\n <FiltersInput {...filtersProps} />\n </div>\n )}\n {sortProps && (\n <div className=\"w-full md:w-auto md:min-w-45\">\n <SortInput {...sortProps} />\n </div>\n )}\n {searchProps && (\n <div className=\"w-full md:ml-auto md:w-auto md:min-w-25\">\n <SearchInput {...searchProps} />\n </div>\n )}\n </div>\n\n {filterSettings?.selectedFilters && filterSettings.selectedFilters.length > 0 && onFilter && (\n <div className=\"w-full\">\n <SelectedFilters\n selectedFilters={filterSettings.selectedFilters}\n onDelete={handleFilterDelete}\n onClear={() => onFilter({ ...filterSettings, selectedFilters: [] })}\n />\n </div>\n )}\n {/* Count and Last Updated Info */}\n {(showCountInfo || lastUpdated) && (\n <div className=\"text-theme-secondary flex w-full items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n {showCountInfo && (\n <span>\n <Trans>\n Showing {filteredCount} of {totalCount} {itemName}\n </Trans>\n </span>\n )}\n {lastUpdated &&\n (() => {\n const formattedDate = formatLastUpdated(lastUpdated)\n return (\n <span>\n <Trans>Last updated: {formattedDate}</Trans>\n </span>\n )\n })()}\n </div>\n </div>\n )}\n </Stack>\n </>\n )\n}\n","import { startTransition, useState } from \"react\"\nimport { FilterSettings, SortOption, SortSettings } from \"@/client/components/ListToolbar/types\"\n\n/**\n * Sort direction enumeration\n * Used across all sort-enabled list views\n */\nexport type SortDirection = \"asc\" | \"desc\"\n\n/**\n * Generic required sort settings with guaranteed non-optional properties\n * Used by components to maintain a fully-defined sort state\n *\n * Type parameter K is the sort key type (string literal union of allowed sort fields)\n *\n * @example\n * // For floating IPs\n * type FloatingIpListSortSettings = ListSortConfig<FloatingIpsSortKey>\n *\n * // For security groups\n * type SecurityGroupListSortSettings = ListSortConfig<\"name\" | \"project_id\">\n */\nexport type ListSortConfig<T extends string = string> = {\n /**\n * Array of available sort options to display in the UI\n */\n options: SortOption[]\n /**\n * The currently selected sort field (guaranteed to be one of the available options)\n */\n sortBy: T\n /**\n * The currently active sort direction (guaranteed to be either \"asc\" or \"desc\")\n */\n sortDirection: SortDirection\n}\n\n/**\n * Configuration options for the useListWithFiltering hook\n */\nexport interface UseListWithFilteringOptions<T extends string> {\n /** Default sort key to use on initial render */\n defaultSortKey: T\n /** Default sort direction to use on initial render */\n defaultSortDir: SortDirection\n /** Available sort options to display in the sort dropdown */\n sortOptions: Array<{ label: string; value: string }>\n /** Initial filter settings configuration */\n filterSettings: FilterSettings\n}\n\n/**\n * Return value from the useListWithFiltering hook\n */\nexport interface UseListWithFilteringReturn<T extends string> {\n // State\n searchTerm: string\n sortSettings: ListSortConfig<T>\n filterSettings: FilterSettings\n\n // Handlers\n handleSearchChange: (term: string | number | string[] | undefined) => void\n handleSortChange: (newSortSettings: SortSettings) => void\n handleFilterChange: (newFilterSettings: FilterSettings) => void\n}\n\n/**\n * Custom hook to manage common list view state: search, sort, and filter\n *\n * Extracts shared logic from list components to ensure consistent behavior\n * across all list pages and reduce code duplication.\n *\n * @example\n * ```tsx\n * const listState = useListWithFiltering({\n * defaultSortKey: \"name\",\n * defaultSortDir: \"asc\",\n * sortOptions: [\n * { label: t`Name`, value: \"name\" },\n * { label: t`Created`, value: \"created_at\" },\n * ],\n * filterSettings: {\n * filters: [\n * { displayName: t`Status`, filterName: \"status\", values: [\"active\", \"inactive\"] }\n * ]\n * }\n * })\n * ```\n */\nexport function useListWithFiltering<T extends string>({\n defaultSortKey,\n defaultSortDir,\n sortOptions,\n filterSettings: initialFilterSettings,\n}: UseListWithFilteringOptions<T>): UseListWithFilteringReturn<T> {\n // Search\n const [searchTerm, setSearchTerm] = useState(\"\")\n const handleSearchChange = (term: string | number | string[] | undefined) => {\n const searchValue = typeof term === \"string\" ? term : \"\"\n startTransition(() => setSearchTerm(searchValue))\n }\n\n // Sort\n const [sortSettings, setSortSettings] = useState<ListSortConfig<T>>({\n options: sortOptions,\n sortBy: defaultSortKey,\n sortDirection: defaultSortDir,\n })\n const handleSortChange = (newSortSettings: SortSettings) => {\n const settings: ListSortConfig<T> = {\n options: newSortSettings.options ?? sortSettings.options,\n sortBy: (newSortSettings.sortBy?.toString() as T) || defaultSortKey,\n sortDirection: (newSortSettings.sortDirection as SortDirection) || defaultSortDir,\n }\n setSortSettings(settings)\n }\n\n // Filter\n const [filterSettings, setFilterSettings] = useState<FilterSettings>(initialFilterSettings)\n const handleFilterChange = (newFilterSettings: FilterSettings) => {\n startTransition(() => setFilterSettings(newFilterSettings))\n }\n\n return {\n searchTerm,\n sortSettings,\n filterSettings,\n handleSearchChange,\n handleSortChange,\n handleFilterChange,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"useListWithFiltering-C9k7xWqz.mjs","names":["useCallback","useRef","useEffect","SearchInput","Stack","TabNavigation","TabNavigationItem","SelectedFilters","FiltersInput","SortInput","ListToolbar","filterSettings","onFilter","sortSettings","onSort","searchTerm","onSearch","searchInputProps","actions","tabs","totalCount","filteredCount","itemName","lastUpdated","useLingui","debounceTimerRef","undefined","current","clearTimeout","formatLastUpdated","date","dateObj","Date","toLocaleString","showCountInfo","handleFilterDelete","filterToRemove","selectedFilters","filter","name","value","handleSelect","selectedFilter","filterExists","some","supportsMultiValue","filters","find","filterName","newSelected","handleSearch","searchValue","handleSearchInput","event","currentTarget","window","setTimeout","handleSearchClear","filtersProps","onChange","sortProps","options","sortBy","sortDirection","onSortByChange","param","onSortDirectionChange","direction","searchProps","placeholder","t","onInput","onClear","div","className","activeItem","onActiveItemChange","items","map","item","label","alignment","gap","length","onDelete","span","formattedDate","startTransition","useState","useListWithFiltering","defaultSortKey","defaultSortDir","sortOptions","filterSettings","initialFilterSettings","searchTerm","setSearchTerm","handleSearchChange","term","searchValue","sortSettings","setSortSettings","options","sortBy","sortDirection","handleSortChange","newSortSettings","settings","toString","setFilterSettings","handleFilterChange","newFilterSettings"],"sources":["../../src/client/components/ListToolbar/index.tsx","../../src/client/utils/useListWithFiltering.ts"],"sourcesContent":["import { ReactNode, useCallback, useRef, useEffect } from \"react\"\nimport { Trans, useLingui } from \"@lingui/react/macro\"\nimport {\n SearchInput,\n SearchInputProps,\n Stack,\n TabNavigation,\n TabNavigationItem,\n} from \"@cloudoperators/juno-ui-components\"\nimport { SelectedFilters } from \"./SelectedFilters\"\nimport { FiltersInput } from \"./FiltersInput\"\nimport { SortInput } from \"./SortInput\"\nimport { FilterSettings, SelectedFilter, SortSettings } from \"./types\"\n\nexport type ListToolbarProps = {\n filterSettings?: FilterSettings\n onFilter?: (filterSettings: FilterSettings) => void\n sortSettings?: SortSettings\n onSort?: (sortSettings: SortSettings) => void\n searchTerm?: string\n onSearch?: (searchTerm: string) => void\n searchInputProps?: Omit<SearchInputProps, \"value\" | \"onSearch\" | \"onClear\" | \"onInput\">\n actions?: ReactNode\n tabs?: {\n items: Array<{ label: string; value: string }>\n activeItem: string\n onActiveItemChange: (value: ReactNode) => void\n }\n // Count information\n totalCount?: number\n itemName?: string // e.g. \"items\", \"users\", \"projects\" - used in count display\n filteredCount?: number\n // Last updated timestamp\n lastUpdated?: Date | string\n}\n\nexport const ListToolbar = ({\n filterSettings,\n onFilter,\n sortSettings,\n onSort,\n searchTerm,\n onSearch,\n searchInputProps = {},\n actions,\n tabs,\n totalCount,\n filteredCount,\n itemName = \"items\",\n lastUpdated,\n}: ListToolbarProps) => {\n const { t } = useLingui()\n\n const debounceTimerRef = useRef<number | undefined>(undefined)\n\n useEffect(() => {\n return () => {\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n }\n }, [])\n\n // Format last updated time\n const formatLastUpdated = (date: Date | string | undefined): string => {\n if (!date) return \"\"\n const dateObj = typeof date === \"string\" ? new Date(date) : date\n return dateObj.toLocaleString()\n }\n\n const showCountInfo = totalCount !== undefined && filteredCount !== undefined\n\n const handleFilterDelete = useCallback(\n (filterToRemove: SelectedFilter) => {\n if (!onFilter || !filterSettings) return\n onFilter({\n ...filterSettings,\n selectedFilters: filterSettings.selectedFilters?.filter(\n (filter) => !(filter.name === filterToRemove.name && filter.value === filterToRemove.value)\n ),\n })\n },\n [filterSettings, onFilter]\n )\n\n const handleSelect = (selectedFilter: SelectedFilter) => {\n if (!onFilter || !filterSettings) return\n const filterExists = filterSettings.selectedFilters?.some(\n (filter) => filter.name === selectedFilter.name && filter.value === selectedFilter.value\n )\n if (filterExists) return\n\n const supportsMultiValue = filterSettings.filters.find(\n (filter) => selectedFilter.name === filter.filterName\n )?.supportsMultiValue\n\n const newSelected = supportsMultiValue\n ? [...(filterSettings.selectedFilters || []), selectedFilter]\n : [\n ...(filterSettings.selectedFilters || []).filter((filter) => filter.name !== selectedFilter.name),\n selectedFilter,\n ]\n\n onFilter({ ...filterSettings, selectedFilters: newSelected })\n }\n\n const handleSearch = useCallback(\n (value: string | number | string[] | undefined) => {\n const searchValue = typeof value === \"string\" ? value : \"\"\n\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current)\n }\n\n onSearch?.(searchValue)\n },\n [onSearch]\n )\n\n const handleSearchInput = useCallback(\n (event: React.FormEvent<HTMLInputElement>) => {\n const searchValue = event.currentTarget.value\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)\n debounceTimerRef.current = window.setTimeout(() => onSearch?.(searchValue), 500)\n },\n [onSearch]\n )\n\n const handleSearchClear = useCallback(() => {\n if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current)\n onSearch?.(\"\")\n }, [onSearch])\n\n const filtersProps = filterSettings && onFilter ? { filters: filterSettings.filters, onChange: handleSelect } : null\n const sortProps =\n sortSettings && onSort\n ? {\n options: sortSettings.options,\n sortBy: sortSettings.sortBy,\n sortDirection: sortSettings.sortDirection || \"asc\",\n onSortByChange: (param: string | number | string[] | undefined) =>\n onSort({ ...sortSettings, sortBy: param, sortDirection: sortSettings.sortDirection || \"asc\" }),\n onSortDirectionChange: (direction: \"asc\" | \"desc\") => onSort({ ...sortSettings, sortDirection: direction }),\n }\n : null\n\n const searchProps: (SearchInputProps & { \"data-testid\"?: string }) | null = onSearch\n ? {\n placeholder: t`Search...`,\n \"data-testid\": \"searchbar\",\n value: searchTerm,\n onInput: handleSearchInput,\n onClear: handleSearchClear,\n onSearch: handleSearch,\n ...searchInputProps,\n }\n : null\n\n return (\n <>\n {tabs && (\n <div className=\"w-full\">\n <TabNavigation activeItem={tabs.activeItem} onActiveItemChange={tabs.onActiveItemChange}>\n {tabs.items.map((item) => (\n <TabNavigationItem key={item.value} label={item.label} value={item.value} />\n ))}\n </TabNavigation>\n </div>\n )}\n <Stack alignment=\"center\" gap=\"6\" className=\"bg-theme-background-lvl-1 flex w-full flex-col p-4\">\n {actions && (\n <Stack direction=\"horizontal\" className=\"w-full justify-end\">\n {actions}\n </Stack>\n )}\n\n <div className=\"flex w-full flex-col items-stretch gap-4 md:flex-row md:items-center\">\n {filtersProps && (\n <div className=\"w-full md:w-auto md:min-w-37.5\">\n <FiltersInput {...filtersProps} />\n </div>\n )}\n {sortProps && (\n <div className=\"w-full md:w-auto md:min-w-45\">\n <SortInput {...sortProps} />\n </div>\n )}\n {searchProps && (\n <div className=\"w-full md:ml-auto md:w-auto md:min-w-25\">\n <SearchInput {...searchProps} />\n </div>\n )}\n </div>\n\n {filterSettings?.selectedFilters && filterSettings.selectedFilters.length > 0 && onFilter && (\n <div className=\"w-full\">\n <SelectedFilters\n selectedFilters={filterSettings.selectedFilters}\n onDelete={handleFilterDelete}\n onClear={() => onFilter({ ...filterSettings, selectedFilters: [] })}\n />\n </div>\n )}\n {/* Count and Last Updated Info */}\n {(showCountInfo || lastUpdated) && (\n <div className=\"text-theme-secondary flex w-full items-center justify-between text-sm\">\n <div className=\"flex items-center gap-2\">\n {showCountInfo && (\n <span>\n <Trans>\n Showing {filteredCount} of {totalCount} {itemName}\n </Trans>\n </span>\n )}\n {lastUpdated &&\n (() => {\n const formattedDate = formatLastUpdated(lastUpdated)\n return (\n <span>\n <Trans>Last updated: {formattedDate}</Trans>\n </span>\n )\n })()}\n </div>\n </div>\n )}\n </Stack>\n </>\n )\n}\n","import { startTransition, useState } from \"react\"\nimport { FilterSettings, SortOption, SortSettings } from \"@/client/components/ListToolbar/types\"\n\n/**\n * Sort direction enumeration\n * Used across all sort-enabled list views\n */\nexport type SortDirection = \"asc\" | \"desc\"\n\n/**\n * Generic required sort settings with guaranteed non-optional properties\n * Used by components to maintain a fully-defined sort state\n *\n * Type parameter K is the sort key type (string literal union of allowed sort fields)\n *\n * @example\n * // For floating IPs\n * type FloatingIpListSortSettings = ListSortConfig<FloatingIpsSortKey>\n *\n * // For security groups\n * type SecurityGroupListSortSettings = ListSortConfig<\"name\" | \"project_id\">\n */\nexport type ListSortConfig<T extends string = string> = {\n /**\n * Array of available sort options to display in the UI\n */\n options: SortOption[]\n /**\n * The currently selected sort field (guaranteed to be one of the available options)\n */\n sortBy: T\n /**\n * The currently active sort direction (guaranteed to be either \"asc\" or \"desc\")\n */\n sortDirection: SortDirection\n}\n\n/**\n * Configuration options for the useListWithFiltering hook\n */\nexport interface UseListWithFilteringOptions<T extends string> {\n /** Default sort key to use on initial render */\n defaultSortKey: T\n /** Default sort direction to use on initial render */\n defaultSortDir: SortDirection\n /** Available sort options to display in the sort dropdown */\n sortOptions: Array<{ label: string; value: string }>\n /** Initial filter settings configuration */\n filterSettings: FilterSettings\n}\n\n/**\n * Return value from the useListWithFiltering hook\n */\nexport interface UseListWithFilteringReturn<T extends string> {\n // State\n searchTerm: string\n sortSettings: ListSortConfig<T>\n filterSettings: FilterSettings\n\n // Handlers\n handleSearchChange: (term: string | number | string[] | undefined) => void\n handleSortChange: (newSortSettings: SortSettings) => void\n handleFilterChange: (newFilterSettings: FilterSettings) => void\n}\n\n/**\n * Custom hook to manage common list view state: search, sort, and filter\n *\n * Extracts shared logic from list components to ensure consistent behavior\n * across all list pages and reduce code duplication.\n *\n * @example\n * ```tsx\n * const listState = useListWithFiltering({\n * defaultSortKey: \"name\",\n * defaultSortDir: \"asc\",\n * sortOptions: [\n * { label: t`Name`, value: \"name\" },\n * { label: t`Created`, value: \"created_at\" },\n * ],\n * filterSettings: {\n * filters: [\n * { displayName: t`Status`, filterName: \"status\", values: [\"active\", \"inactive\"] }\n * ]\n * }\n * })\n * ```\n */\nexport function useListWithFiltering<T extends string>({\n defaultSortKey,\n defaultSortDir,\n sortOptions,\n filterSettings: initialFilterSettings,\n}: UseListWithFilteringOptions<T>): UseListWithFilteringReturn<T> {\n // Search\n const [searchTerm, setSearchTerm] = useState(\"\")\n const handleSearchChange = (term: string | number | string[] | undefined) => {\n const searchValue = typeof term === \"string\" ? term : \"\"\n startTransition(() => setSearchTerm(searchValue))\n }\n\n // Sort\n const [sortSettings, setSortSettings] = useState<ListSortConfig<T>>({\n options: sortOptions,\n sortBy: defaultSortKey,\n sortDirection: defaultSortDir,\n })\n const handleSortChange = (newSortSettings: SortSettings) => {\n const settings: ListSortConfig<T> = {\n options: newSortSettings.options ?? sortSettings.options,\n sortBy: (newSortSettings.sortBy?.toString() as T) || defaultSortKey,\n sortDirection: (newSortSettings.sortDirection as SortDirection) || defaultSortDir,\n }\n setSortSettings(settings)\n }\n\n // Filter\n const [filterSettings, setFilterSettings] = useState<FilterSettings>(initialFilterSettings)\n const handleFilterChange = (newFilterSettings: FilterSettings) => {\n startTransition(() => setFilterSettings(newFilterSettings))\n }\n\n return {\n searchTerm,\n sortSettings,\n filterSettings,\n handleSearchChange,\n handleSortChange,\n handleFilterChange,\n }\n}\n"],"mappings":"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"}
|