@stoker-platform/web-app 0.5.133 → 0.5.134
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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/Collection.tsx +590 -550
- package/src/main.tsx +5 -2
package/src/Collection.tsx
CHANGED
|
@@ -1834,595 +1834,635 @@ function Collection({
|
|
|
1834
1834
|
relationList ? "xl:flex-row" : "lg:flex-row",
|
|
1835
1835
|
)}
|
|
1836
1836
|
>
|
|
1837
|
-
{
|
|
1838
|
-
|
|
1839
|
-
{formList
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
{showList && (
|
|
1847
|
-
<TabsTrigger value="list">
|
|
1848
|
-
{listConfig?.title || "List"}
|
|
1849
|
-
</TabsTrigger>
|
|
1850
|
-
)}
|
|
1851
|
-
{showCards && cardsStatusField.current && (
|
|
1852
|
-
<TabsTrigger value="cards">
|
|
1853
|
-
{cardsConfig?.title || "Board"}
|
|
1854
|
-
</TabsTrigger>
|
|
1855
|
-
)}
|
|
1856
|
-
{showImages && (
|
|
1857
|
-
<TabsTrigger value="images">
|
|
1858
|
-
{imagesConfig?.title || "Pics"}
|
|
1859
|
-
</TabsTrigger>
|
|
1860
|
-
)}
|
|
1861
|
-
{showMap && (
|
|
1862
|
-
<TabsTrigger value="map">
|
|
1863
|
-
{mapConfig?.title || "Map"}
|
|
1864
|
-
</TabsTrigger>
|
|
1865
|
-
)}
|
|
1866
|
-
{showCalendar && (
|
|
1867
|
-
<TabsTrigger value="calendar">
|
|
1868
|
-
{calendarConfig?.title || "Calendar"}
|
|
1869
|
-
</TabsTrigger>
|
|
1870
|
-
)}
|
|
1871
|
-
</TabsList>
|
|
1837
|
+
{isInitialized && (
|
|
1838
|
+
<>
|
|
1839
|
+
{formList && (
|
|
1840
|
+
<Badge
|
|
1841
|
+
variant="outline"
|
|
1842
|
+
className="py-2 px-4 text-md whitespace-nowrap"
|
|
1843
|
+
>
|
|
1844
|
+
{formList.label || collectionTitle || formList.collection}
|
|
1845
|
+
</Badge>
|
|
1872
1846
|
)}
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1847
|
+
<div className="lg:h-9">
|
|
1848
|
+
{!formList &&
|
|
1849
|
+
(showList ||
|
|
1850
|
+
showCards ||
|
|
1851
|
+
showImages ||
|
|
1852
|
+
showMap ||
|
|
1853
|
+
showCalendar) && (
|
|
1854
|
+
<TabsList>
|
|
1855
|
+
{showList && (
|
|
1856
|
+
<TabsTrigger value="list">
|
|
1857
|
+
{listConfig?.title || "List"}
|
|
1858
|
+
</TabsTrigger>
|
|
1859
|
+
)}
|
|
1860
|
+
{showCards && cardsStatusField.current && (
|
|
1861
|
+
<TabsTrigger value="cards">
|
|
1862
|
+
{cardsConfig?.title || "Board"}
|
|
1863
|
+
</TabsTrigger>
|
|
1864
|
+
)}
|
|
1865
|
+
{showImages && (
|
|
1866
|
+
<TabsTrigger value="images">
|
|
1867
|
+
{imagesConfig?.title || "Pics"}
|
|
1868
|
+
</TabsTrigger>
|
|
1869
|
+
)}
|
|
1870
|
+
{showMap && (
|
|
1871
|
+
<TabsTrigger value="map">
|
|
1872
|
+
{mapConfig?.title || "Map"}
|
|
1873
|
+
</TabsTrigger>
|
|
1874
|
+
)}
|
|
1875
|
+
{showCalendar && (
|
|
1876
|
+
<TabsTrigger value="calendar">
|
|
1877
|
+
{calendarConfig?.title || "Calendar"}
|
|
1878
|
+
</TabsTrigger>
|
|
1879
|
+
)}
|
|
1880
|
+
</TabsList>
|
|
1881
|
+
)}
|
|
1882
|
+
</div>
|
|
1883
|
+
{!formList &&
|
|
1884
|
+
!relationList?.loadAll &&
|
|
1885
|
+
tab !== "calendar" &&
|
|
1886
|
+
(hasRangeFilter || currentField) && (
|
|
1887
|
+
<div
|
|
1888
|
+
className={cn(
|
|
1889
|
+
relationList
|
|
1890
|
+
? "xl:hidden 2xl:flex xl:absolute xl:left-[calc(50%+128px)] xl:transform xl:-translate-x-[calc(50%+98px)] xl:mt-0 mt-2"
|
|
1891
|
+
: "lg:hidden 2xl:flex lg:absolute lg:left-1/2 lg:transform lg:-translate-x-1/2 lg:mt-0 mt-2",
|
|
1892
|
+
)}
|
|
1893
|
+
>
|
|
1894
|
+
<DateRangeSelector
|
|
1895
|
+
collection={collection}
|
|
1896
|
+
rangeSelector={rangeSelector}
|
|
1897
|
+
setRangeSelector={setRangeSelector}
|
|
1898
|
+
relationList={!!relationList}
|
|
1899
|
+
/>
|
|
1900
|
+
</div>
|
|
1901
|
+
)}
|
|
1878
1902
|
<div
|
|
1879
1903
|
className={cn(
|
|
1904
|
+
"ml-auto flex items-center gap-2 justify-center w-full",
|
|
1880
1905
|
relationList
|
|
1881
|
-
? "xl:
|
|
1882
|
-
: "lg:
|
|
1906
|
+
? "xl:justify-end xl:mt-0 mt-2"
|
|
1907
|
+
: "lg:justify-end lg:mt-0 mt-2",
|
|
1883
1908
|
)}
|
|
1884
1909
|
>
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1920
|
-
</ToggleGroupItem>
|
|
1921
|
-
)}
|
|
1922
|
-
{statusField?.archived &&
|
|
1923
|
-
(tab !== "cards" || !autoUpdateStatusFilter) && (
|
|
1910
|
+
{(statusField || softDeleteField) && (
|
|
1911
|
+
<ToggleGroup
|
|
1912
|
+
onValueChange={onStatusFilterChange}
|
|
1913
|
+
value={statusFilter}
|
|
1914
|
+
defaultValue="active"
|
|
1915
|
+
size="sm"
|
|
1916
|
+
type="single"
|
|
1917
|
+
variant="outline"
|
|
1918
|
+
className="text-muted-foreground font-medium mr-2 gap-2"
|
|
1919
|
+
>
|
|
1920
|
+
{statusField?.active &&
|
|
1921
|
+
(tab !== "cards" || !autoUpdateStatusFilter) && (
|
|
1922
|
+
<ToggleGroupItem
|
|
1923
|
+
className="h-7 bg-muted data-[state=on]:bg-background"
|
|
1924
|
+
value="active"
|
|
1925
|
+
aria-label="Toggle active"
|
|
1926
|
+
disabled={isRouteLoading.has(location.pathname)}
|
|
1927
|
+
>
|
|
1928
|
+
Active
|
|
1929
|
+
</ToggleGroupItem>
|
|
1930
|
+
)}
|
|
1931
|
+
{statusField?.archived &&
|
|
1932
|
+
(tab !== "cards" || !autoUpdateStatusFilter) && (
|
|
1933
|
+
<ToggleGroupItem
|
|
1934
|
+
className="hidden sm:flex h-7 bg-muted data-[state=on]:bg-background relative"
|
|
1935
|
+
value="archived"
|
|
1936
|
+
aria-label="Toggle archived"
|
|
1937
|
+
disabled={isRouteLoading.has(location.pathname)}
|
|
1938
|
+
>
|
|
1939
|
+
Archived
|
|
1940
|
+
{statusFilter === "archived" && (
|
|
1941
|
+
<span className="absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 block h-3 w-3 rounded-full bg-destructive"></span>
|
|
1942
|
+
)}
|
|
1943
|
+
</ToggleGroupItem>
|
|
1944
|
+
)}
|
|
1924
1945
|
<ToggleGroupItem
|
|
1925
|
-
className="
|
|
1926
|
-
value="
|
|
1927
|
-
aria-label="Toggle
|
|
1946
|
+
className="h-7 bg-muted data-[state=on]:bg-background relative"
|
|
1947
|
+
value="all"
|
|
1948
|
+
aria-label="Toggle all"
|
|
1928
1949
|
disabled={isRouteLoading.has(location.pathname)}
|
|
1929
1950
|
>
|
|
1930
|
-
|
|
1931
|
-
{
|
|
1932
|
-
|
|
1933
|
-
|
|
1951
|
+
All
|
|
1952
|
+
{statusField &&
|
|
1953
|
+
statusFilter === "all" &&
|
|
1954
|
+
tab !== "cards" &&
|
|
1955
|
+
!revertingStatusFilter && (
|
|
1956
|
+
<span className="absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 block h-3 w-3 rounded-full bg-destructive"></span>
|
|
1957
|
+
)}
|
|
1934
1958
|
</ToggleGroupItem>
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
<span className="absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 block h-3 w-3 rounded-full bg-destructive"></span>
|
|
1959
|
+
{softDeleteField && (
|
|
1960
|
+
<ToggleGroupItem
|
|
1961
|
+
className="h-7 bg-muted data-[state=on]:bg-background relative"
|
|
1962
|
+
value="trash"
|
|
1963
|
+
aria-label="Toggle trash"
|
|
1964
|
+
disabled={isRouteLoading.has(location.pathname)}
|
|
1965
|
+
>
|
|
1966
|
+
Trash
|
|
1967
|
+
{statusFilter === "trash" && (
|
|
1968
|
+
<span className="absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 block h-3 w-3 rounded-full bg-destructive"></span>
|
|
1969
|
+
)}
|
|
1970
|
+
</ToggleGroupItem>
|
|
1948
1971
|
)}
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1972
|
+
</ToggleGroup>
|
|
1973
|
+
)}
|
|
1974
|
+
{!formList && tab === "list" && (
|
|
1975
|
+
<>
|
|
1976
|
+
{customListActions &&
|
|
1977
|
+
customListActions.some(
|
|
1978
|
+
(action) => !action.condition || action.condition(),
|
|
1979
|
+
) ? (
|
|
1980
|
+
<DropdownMenu>
|
|
1981
|
+
<DropdownMenuTrigger asChild>
|
|
1982
|
+
<Button
|
|
1983
|
+
type="button"
|
|
1984
|
+
size="sm"
|
|
1985
|
+
variant="outline"
|
|
1986
|
+
className="hidden sm:flex h-7 gap-1"
|
|
1987
|
+
>
|
|
1988
|
+
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
1989
|
+
Actions
|
|
1990
|
+
</span>
|
|
1991
|
+
<ChevronsUpDown className="h-3.5 w-3.5" />
|
|
1992
|
+
</Button>
|
|
1993
|
+
</DropdownMenuTrigger>
|
|
1994
|
+
<DropdownMenuContent>
|
|
1995
|
+
{(!restrictExport ||
|
|
1996
|
+
restrictExport.includes(permissions.Role)) && (
|
|
1997
|
+
<DropdownMenuItem
|
|
1998
|
+
key="export"
|
|
1999
|
+
onClick={handleExport}
|
|
2000
|
+
disabled={
|
|
2001
|
+
!list.default?.length ||
|
|
2002
|
+
isRouteLoading.has(location.pathname)
|
|
2003
|
+
}
|
|
2004
|
+
>
|
|
2005
|
+
<File className="h-3.5 w-3.5 shrink-0 mr-1" />
|
|
2006
|
+
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2007
|
+
Export
|
|
2008
|
+
</span>
|
|
2009
|
+
</DropdownMenuItem>
|
|
2010
|
+
)}
|
|
2011
|
+
{customListActions
|
|
2012
|
+
.filter(
|
|
2013
|
+
(action) =>
|
|
2014
|
+
!action.condition || action.condition(),
|
|
2015
|
+
)
|
|
2016
|
+
.map((action) => (
|
|
2017
|
+
<DropdownMenuItem
|
|
2018
|
+
key={action.title}
|
|
2019
|
+
onClick={action.action}
|
|
2020
|
+
>
|
|
2021
|
+
{action.icon &&
|
|
2022
|
+
createElement(action.icon, {
|
|
2023
|
+
className:
|
|
2024
|
+
"h-3.5 w-3.5 shrink-0 mr-1",
|
|
2025
|
+
})}
|
|
2026
|
+
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2027
|
+
{action.title}
|
|
2028
|
+
</span>
|
|
2029
|
+
</DropdownMenuItem>
|
|
2030
|
+
))}
|
|
2031
|
+
</DropdownMenuContent>
|
|
2032
|
+
</DropdownMenu>
|
|
2033
|
+
) : (
|
|
2034
|
+
(!restrictExport ||
|
|
2035
|
+
restrictExport.includes(permissions.Role)) && (
|
|
2036
|
+
<Button
|
|
2037
|
+
type="button"
|
|
2038
|
+
size="sm"
|
|
2039
|
+
variant="outline"
|
|
2040
|
+
disabled={
|
|
2041
|
+
!list.default?.length ||
|
|
2042
|
+
isRouteLoading.has(location.pathname)
|
|
2043
|
+
}
|
|
2044
|
+
className="hidden sm:flex h-7 gap-1"
|
|
2045
|
+
onClick={handleExport}
|
|
2046
|
+
>
|
|
2047
|
+
<File className="h-3.5 w-3.5" />
|
|
2048
|
+
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2049
|
+
Export
|
|
2050
|
+
</span>
|
|
2051
|
+
</Button>
|
|
2052
|
+
)
|
|
1960
2053
|
)}
|
|
1961
|
-
|
|
2054
|
+
{(!restrictExport ||
|
|
2055
|
+
restrictExport.includes(permissions.Role)) && (
|
|
2056
|
+
<CSVLink
|
|
2057
|
+
ref={csvLinkRef}
|
|
2058
|
+
className="hidden"
|
|
2059
|
+
data={csvData?.data || []}
|
|
2060
|
+
headers={csvData?.headers || []}
|
|
2061
|
+
filename={`${collectionTitle}.csv`}
|
|
2062
|
+
target="_blank"
|
|
2063
|
+
/>
|
|
2064
|
+
)}
|
|
2065
|
+
</>
|
|
1962
2066
|
)}
|
|
1963
|
-
|
|
1964
|
-
)}
|
|
1965
|
-
{!formList && tab === "list" && (
|
|
1966
|
-
<>
|
|
1967
|
-
{customListActions &&
|
|
1968
|
-
customListActions.some(
|
|
1969
|
-
(action) => !action.condition || action.condition(),
|
|
1970
|
-
) ? (
|
|
2067
|
+
{(tab === "cards" || tab === "images") && (
|
|
1971
2068
|
<DropdownMenu>
|
|
1972
2069
|
<DropdownMenuTrigger asChild>
|
|
1973
2070
|
<Button
|
|
1974
2071
|
type="button"
|
|
1975
2072
|
size="sm"
|
|
1976
2073
|
variant="outline"
|
|
1977
|
-
className="
|
|
2074
|
+
className="h-7 gap-1"
|
|
2075
|
+
disabled={isRouteLoading.has(location.pathname)}
|
|
1978
2076
|
>
|
|
2077
|
+
<ChevronsUpDown className="h-3.5 w-3.5" />
|
|
1979
2078
|
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
1980
|
-
|
|
2079
|
+
Sort
|
|
1981
2080
|
</span>
|
|
1982
|
-
<ChevronsUpDown className="h-3.5 w-3.5" />
|
|
1983
2081
|
</Button>
|
|
1984
2082
|
</DropdownMenuTrigger>
|
|
1985
2083
|
<DropdownMenuContent>
|
|
1986
|
-
{
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2084
|
+
<ScrollArea className={sortingHeight}>
|
|
2085
|
+
<div>
|
|
2086
|
+
{sortingFields.map((field: CollectionField) => {
|
|
2087
|
+
const fieldCustomization =
|
|
2088
|
+
getFieldCustomization(field, customization)
|
|
2089
|
+
const label =
|
|
2090
|
+
tryFunction(
|
|
2091
|
+
fieldCustomization.admin?.label,
|
|
2092
|
+
) || field.name
|
|
2093
|
+
const condition =
|
|
2094
|
+
fieldCustomization.admin?.condition?.list
|
|
2095
|
+
if (
|
|
2096
|
+
condition !== undefined &&
|
|
2097
|
+
!tryFunction(condition)
|
|
2098
|
+
)
|
|
2099
|
+
return null
|
|
2100
|
+
return (
|
|
2101
|
+
<DropdownMenuItem
|
|
2102
|
+
key={field.name}
|
|
2103
|
+
onClick={() => {
|
|
2104
|
+
if (preventChange) return
|
|
2105
|
+
if (
|
|
2106
|
+
typeof field.sorting ===
|
|
2107
|
+
"object" &&
|
|
2108
|
+
field.sorting.direction ===
|
|
2109
|
+
"desc"
|
|
2110
|
+
) {
|
|
2111
|
+
setOrder({
|
|
2112
|
+
field: field.name,
|
|
2113
|
+
direction: "desc",
|
|
2114
|
+
})
|
|
2115
|
+
} else {
|
|
2116
|
+
setOrder({
|
|
2117
|
+
field: field.name,
|
|
2118
|
+
direction: "asc",
|
|
2119
|
+
})
|
|
2120
|
+
}
|
|
2121
|
+
setState(
|
|
2122
|
+
`collection-sort-${labels.collection.toLowerCase()}`,
|
|
2123
|
+
"sort",
|
|
2124
|
+
JSON.stringify([
|
|
2125
|
+
{
|
|
2126
|
+
id: field.name,
|
|
2127
|
+
desc:
|
|
2128
|
+
typeof field.sorting ===
|
|
2129
|
+
"object" &&
|
|
2130
|
+
field.sorting
|
|
2131
|
+
.direction ===
|
|
2132
|
+
"desc",
|
|
2133
|
+
},
|
|
2134
|
+
]),
|
|
2135
|
+
)
|
|
2136
|
+
}}
|
|
2137
|
+
>
|
|
2138
|
+
{order?.field === field.name && (
|
|
2139
|
+
<Check className="absolute h-3.5 w-3.5 mr-1" />
|
|
2140
|
+
)}
|
|
2141
|
+
<span className="ml-5">{label}</span>
|
|
2142
|
+
</DropdownMenuItem>
|
|
2143
|
+
)
|
|
2144
|
+
})}
|
|
2145
|
+
</div>
|
|
2146
|
+
</ScrollArea>
|
|
2020
2147
|
</DropdownMenuContent>
|
|
2021
2148
|
</DropdownMenu>
|
|
2022
|
-
) : (
|
|
2023
|
-
(!restrictExport || restrictExport.includes(permissions.Role)) && (
|
|
2024
|
-
<Button
|
|
2025
|
-
type="button"
|
|
2026
|
-
size="sm"
|
|
2027
|
-
variant="outline"
|
|
2028
|
-
disabled={
|
|
2029
|
-
!list.default?.length ||
|
|
2030
|
-
isRouteLoading.has(location.pathname)
|
|
2031
|
-
}
|
|
2032
|
-
className="hidden sm:flex h-7 gap-1"
|
|
2033
|
-
onClick={handleExport}
|
|
2034
|
-
>
|
|
2035
|
-
<File className="h-3.5 w-3.5" />
|
|
2036
|
-
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2037
|
-
Export
|
|
2038
|
-
</span>
|
|
2039
|
-
</Button>
|
|
2040
|
-
)
|
|
2041
2149
|
)}
|
|
2042
|
-
{
|
|
2043
|
-
<
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2150
|
+
{hasFiltersToShow && (
|
|
2151
|
+
<Sheet>
|
|
2152
|
+
<SheetTrigger asChild>
|
|
2153
|
+
<Button
|
|
2154
|
+
type="button"
|
|
2155
|
+
variant="outline"
|
|
2156
|
+
size="sm"
|
|
2157
|
+
className="h-7 gap-1 relative"
|
|
2158
|
+
>
|
|
2159
|
+
<ListFilter className="h-3.5 w-3.5" />
|
|
2160
|
+
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2161
|
+
Filter
|
|
2162
|
+
</span>
|
|
2163
|
+
{filtersActive && (
|
|
2164
|
+
<span className="absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 block h-3 w-3 rounded-full bg-destructive"></span>
|
|
2165
|
+
)}
|
|
2166
|
+
</Button>
|
|
2167
|
+
</SheetTrigger>
|
|
2168
|
+
<SheetContent className="overflow-y-auto">
|
|
2169
|
+
<SheetHeader>
|
|
2170
|
+
<SheetTitle className="mb-4">Filters</SheetTitle>
|
|
2171
|
+
<SheetDescription className="hidden">
|
|
2172
|
+
Filter records in the list view.
|
|
2173
|
+
</SheetDescription>
|
|
2174
|
+
</SheetHeader>
|
|
2175
|
+
<Filters
|
|
2176
|
+
collection={collection}
|
|
2177
|
+
excluded={excludedFilters}
|
|
2178
|
+
relationList={relationList}
|
|
2179
|
+
/>
|
|
2180
|
+
</SheetContent>
|
|
2181
|
+
</Sheet>
|
|
2051
2182
|
)}
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
disabled={isRouteLoading.has(location.pathname)}
|
|
2063
|
-
>
|
|
2064
|
-
<ChevronsUpDown className="h-3.5 w-3.5" />
|
|
2065
|
-
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2066
|
-
Sort
|
|
2067
|
-
</span>
|
|
2068
|
-
</Button>
|
|
2069
|
-
</DropdownMenuTrigger>
|
|
2070
|
-
<DropdownMenuContent>
|
|
2071
|
-
<ScrollArea className={sortingHeight}>
|
|
2072
|
-
<div>
|
|
2073
|
-
{sortingFields.map((field: CollectionField) => {
|
|
2074
|
-
const fieldCustomization = getFieldCustomization(
|
|
2075
|
-
field,
|
|
2076
|
-
customization,
|
|
2077
|
-
)
|
|
2078
|
-
const label =
|
|
2079
|
-
tryFunction(fieldCustomization.admin?.label) ||
|
|
2080
|
-
field.name
|
|
2081
|
-
const condition =
|
|
2082
|
-
fieldCustomization.admin?.condition?.list
|
|
2083
|
-
if (condition !== undefined && !tryFunction(condition))
|
|
2084
|
-
return null
|
|
2183
|
+
{canAddRecords && (
|
|
2184
|
+
<>
|
|
2185
|
+
{(() => {
|
|
2186
|
+
const relationFieldSchema = relationList
|
|
2187
|
+
? getField(fields, relationList.field)
|
|
2188
|
+
: undefined
|
|
2189
|
+
const isManyToMany =
|
|
2190
|
+
relationFieldSchema &&
|
|
2191
|
+
relationFieldSchema.type === "ManyToMany"
|
|
2192
|
+
if (relationList && isManyToMany) {
|
|
2085
2193
|
return (
|
|
2086
|
-
<
|
|
2087
|
-
|
|
2088
|
-
onClick={() => {
|
|
2089
|
-
if (preventChange) return
|
|
2090
|
-
if (
|
|
2091
|
-
typeof field.sorting === "object" &&
|
|
2092
|
-
field.sorting.direction === "desc"
|
|
2093
|
-
) {
|
|
2094
|
-
setOrder({
|
|
2095
|
-
field: field.name,
|
|
2096
|
-
direction: "desc",
|
|
2097
|
-
})
|
|
2098
|
-
} else {
|
|
2099
|
-
setOrder({
|
|
2100
|
-
field: field.name,
|
|
2101
|
-
direction: "asc",
|
|
2102
|
-
})
|
|
2103
|
-
}
|
|
2104
|
-
setState(
|
|
2105
|
-
`collection-sort-${labels.collection.toLowerCase()}`,
|
|
2106
|
-
"sort",
|
|
2107
|
-
JSON.stringify([
|
|
2108
|
-
{
|
|
2109
|
-
id: field.name,
|
|
2110
|
-
desc:
|
|
2111
|
-
typeof field.sorting ===
|
|
2112
|
-
"object" &&
|
|
2113
|
-
field.sorting.direction ===
|
|
2114
|
-
"desc",
|
|
2115
|
-
},
|
|
2116
|
-
]),
|
|
2117
|
-
)
|
|
2118
|
-
}}
|
|
2119
|
-
>
|
|
2120
|
-
{order?.field === field.name && (
|
|
2121
|
-
<Check className="absolute h-3.5 w-3.5 mr-1" />
|
|
2122
|
-
)}
|
|
2123
|
-
<span className="ml-5">{label}</span>
|
|
2124
|
-
</DropdownMenuItem>
|
|
2125
|
-
)
|
|
2126
|
-
})}
|
|
2127
|
-
</div>
|
|
2128
|
-
</ScrollArea>
|
|
2129
|
-
</DropdownMenuContent>
|
|
2130
|
-
</DropdownMenu>
|
|
2131
|
-
)}
|
|
2132
|
-
{hasFiltersToShow && (
|
|
2133
|
-
<Sheet>
|
|
2134
|
-
<SheetTrigger asChild>
|
|
2135
|
-
<Button
|
|
2136
|
-
type="button"
|
|
2137
|
-
variant="outline"
|
|
2138
|
-
size="sm"
|
|
2139
|
-
className="h-7 gap-1 relative"
|
|
2140
|
-
>
|
|
2141
|
-
<ListFilter className="h-3.5 w-3.5" />
|
|
2142
|
-
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2143
|
-
Filter
|
|
2144
|
-
</span>
|
|
2145
|
-
{filtersActive && (
|
|
2146
|
-
<span className="absolute top-0 right-0 transform translate-x-1/2 -translate-y-1/2 block h-3 w-3 rounded-full bg-destructive"></span>
|
|
2147
|
-
)}
|
|
2148
|
-
</Button>
|
|
2149
|
-
</SheetTrigger>
|
|
2150
|
-
<SheetContent className="overflow-y-auto">
|
|
2151
|
-
<SheetHeader>
|
|
2152
|
-
<SheetTitle className="mb-4">Filters</SheetTitle>
|
|
2153
|
-
<SheetDescription className="hidden">
|
|
2154
|
-
Filter records in the list view.
|
|
2155
|
-
</SheetDescription>
|
|
2156
|
-
</SheetHeader>
|
|
2157
|
-
<Filters
|
|
2158
|
-
collection={collection}
|
|
2159
|
-
excluded={excludedFilters}
|
|
2160
|
-
relationList={relationList}
|
|
2161
|
-
/>
|
|
2162
|
-
</SheetContent>
|
|
2163
|
-
</Sheet>
|
|
2164
|
-
)}
|
|
2165
|
-
{canAddRecords && (
|
|
2166
|
-
<>
|
|
2167
|
-
{(() => {
|
|
2168
|
-
const relationFieldSchema = relationList
|
|
2169
|
-
? getField(fields, relationList.field)
|
|
2170
|
-
: undefined
|
|
2171
|
-
const isManyToMany =
|
|
2172
|
-
relationFieldSchema && relationFieldSchema.type === "ManyToMany"
|
|
2173
|
-
if (relationList && isManyToMany) {
|
|
2174
|
-
return (
|
|
2175
|
-
<DropdownMenu>
|
|
2176
|
-
<DropdownMenuTrigger asChild>
|
|
2177
|
-
<Button
|
|
2178
|
-
type="button"
|
|
2179
|
-
ref={addButtonRef}
|
|
2180
|
-
size="sm"
|
|
2181
|
-
className="h-7 gap-1"
|
|
2182
|
-
disabled={isCreateDisabled}
|
|
2183
|
-
>
|
|
2184
|
-
<PlusCircle className="h-3.5 w-3.5" />
|
|
2185
|
-
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2186
|
-
Add {recordTitle}
|
|
2187
|
-
</span>
|
|
2188
|
-
</Button>
|
|
2189
|
-
</DropdownMenuTrigger>
|
|
2190
|
-
<DropdownMenuContent align="end">
|
|
2191
|
-
<DropdownMenuItem
|
|
2192
|
-
onClick={() => {
|
|
2193
|
-
;(async () => {
|
|
2194
|
-
const customization =
|
|
2195
|
-
getCollectionConfigModule(
|
|
2196
|
-
labels.collection,
|
|
2197
|
-
)
|
|
2198
|
-
const override =
|
|
2199
|
-
customization.admin
|
|
2200
|
-
?.addRecordButtonOverride
|
|
2201
|
-
if (
|
|
2202
|
-
override &&
|
|
2203
|
-
typeof override === "function"
|
|
2204
|
-
) {
|
|
2205
|
-
await tryPromise(() =>
|
|
2206
|
-
override(
|
|
2207
|
-
createPrePopulatedRecord(),
|
|
2208
|
-
),
|
|
2209
|
-
)
|
|
2210
|
-
return
|
|
2211
|
-
}
|
|
2212
|
-
setSelectedDateRange(null)
|
|
2213
|
-
setIsCreateDialogOpen(true)
|
|
2214
|
-
})()
|
|
2215
|
-
}}
|
|
2216
|
-
>
|
|
2217
|
-
Add new
|
|
2218
|
-
</DropdownMenuItem>
|
|
2219
|
-
<DropdownMenuItem
|
|
2220
|
-
onClick={() => {
|
|
2221
|
-
setShowSelectExisting(true)
|
|
2222
|
-
fetchSelectableRecords()
|
|
2223
|
-
}}
|
|
2224
|
-
>
|
|
2225
|
-
Select existing
|
|
2226
|
-
</DropdownMenuItem>
|
|
2227
|
-
</DropdownMenuContent>
|
|
2228
|
-
</DropdownMenu>
|
|
2229
|
-
)
|
|
2230
|
-
}
|
|
2231
|
-
return (
|
|
2232
|
-
<Button
|
|
2233
|
-
type="button"
|
|
2234
|
-
ref={addButtonRef}
|
|
2235
|
-
size="sm"
|
|
2236
|
-
className="h-7 gap-1"
|
|
2237
|
-
disabled={isCreateDisabled}
|
|
2238
|
-
onClick={() => {
|
|
2239
|
-
;(async () => {
|
|
2240
|
-
const customization = getCollectionConfigModule(
|
|
2241
|
-
labels.collection,
|
|
2242
|
-
)
|
|
2243
|
-
const override =
|
|
2244
|
-
customization.admin?.addRecordButtonOverride
|
|
2245
|
-
if (override && typeof override === "function") {
|
|
2246
|
-
await tryPromise(() =>
|
|
2247
|
-
override(createPrePopulatedRecord()),
|
|
2248
|
-
)
|
|
2249
|
-
return
|
|
2250
|
-
}
|
|
2251
|
-
setSelectedDateRange(null)
|
|
2252
|
-
setIsCreateDialogOpen(true)
|
|
2253
|
-
})()
|
|
2254
|
-
}}
|
|
2255
|
-
>
|
|
2256
|
-
<PlusCircle className="h-3.5 w-3.5" />
|
|
2257
|
-
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2258
|
-
Add {recordTitle}
|
|
2259
|
-
</span>
|
|
2260
|
-
</Button>
|
|
2261
|
-
)
|
|
2262
|
-
})()}
|
|
2263
|
-
{isCreateDialogOpen &&
|
|
2264
|
-
createPortal(
|
|
2265
|
-
<div
|
|
2266
|
-
id="create-record-modal"
|
|
2267
|
-
className="fixed inset-0 z-50 flex items-center justify-center animate-in fade-in slide-in-from-top-4 duration-300"
|
|
2268
|
-
aria-modal="true"
|
|
2269
|
-
aria-live="polite"
|
|
2270
|
-
role="dialog"
|
|
2271
|
-
>
|
|
2272
|
-
<div className="fixed inset-0 bg-black/50" />
|
|
2273
|
-
<div
|
|
2274
|
-
className="relative bg-background sm:rounded-lg w-full max-w-2xl h-full sm:h-[90vh] overflow-hidden border border-border"
|
|
2275
|
-
aria-labelledby="dialog-title"
|
|
2276
|
-
>
|
|
2277
|
-
<div className="h-full overflow-y-auto overscroll-contain p-6">
|
|
2278
|
-
<div className="space-y-2">
|
|
2279
|
-
<div className="flex justify-between items-center mb-4">
|
|
2280
|
-
<h4
|
|
2281
|
-
id="dialog-title"
|
|
2282
|
-
className="font-medium leading-none"
|
|
2283
|
-
>
|
|
2284
|
-
Add {recordTitle}
|
|
2285
|
-
</h4>
|
|
2194
|
+
<DropdownMenu>
|
|
2195
|
+
<DropdownMenuTrigger asChild>
|
|
2286
2196
|
<Button
|
|
2287
2197
|
type="button"
|
|
2288
|
-
|
|
2289
|
-
size="
|
|
2290
|
-
className="
|
|
2198
|
+
ref={addButtonRef}
|
|
2199
|
+
size="sm"
|
|
2200
|
+
className="h-7 gap-1"
|
|
2201
|
+
disabled={isCreateDisabled}
|
|
2202
|
+
>
|
|
2203
|
+
<PlusCircle className="h-3.5 w-3.5" />
|
|
2204
|
+
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2205
|
+
Add {recordTitle}
|
|
2206
|
+
</span>
|
|
2207
|
+
</Button>
|
|
2208
|
+
</DropdownMenuTrigger>
|
|
2209
|
+
<DropdownMenuContent align="end">
|
|
2210
|
+
<DropdownMenuItem
|
|
2291
2211
|
onClick={() => {
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2212
|
+
;(async () => {
|
|
2213
|
+
const customization =
|
|
2214
|
+
getCollectionConfigModule(
|
|
2215
|
+
labels.collection,
|
|
2216
|
+
)
|
|
2217
|
+
const override =
|
|
2218
|
+
customization.admin
|
|
2219
|
+
?.addRecordButtonOverride
|
|
2220
|
+
if (
|
|
2221
|
+
override &&
|
|
2222
|
+
typeof override ===
|
|
2223
|
+
"function"
|
|
2224
|
+
) {
|
|
2225
|
+
await tryPromise(() =>
|
|
2226
|
+
override(
|
|
2227
|
+
createPrePopulatedRecord(),
|
|
2228
|
+
),
|
|
2229
|
+
)
|
|
2230
|
+
return
|
|
2231
|
+
}
|
|
2232
|
+
setSelectedDateRange(null)
|
|
2233
|
+
setIsCreateDialogOpen(true)
|
|
2234
|
+
})()
|
|
2301
2235
|
}}
|
|
2302
2236
|
>
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2237
|
+
Add new
|
|
2238
|
+
</DropdownMenuItem>
|
|
2239
|
+
<DropdownMenuItem
|
|
2240
|
+
onClick={() => {
|
|
2241
|
+
setShowSelectExisting(true)
|
|
2242
|
+
fetchSelectableRecords()
|
|
2243
|
+
}}
|
|
2244
|
+
>
|
|
2245
|
+
Select existing
|
|
2246
|
+
</DropdownMenuItem>
|
|
2247
|
+
</DropdownMenuContent>
|
|
2248
|
+
</DropdownMenu>
|
|
2249
|
+
)
|
|
2250
|
+
}
|
|
2251
|
+
return (
|
|
2252
|
+
<Button
|
|
2253
|
+
type="button"
|
|
2254
|
+
ref={addButtonRef}
|
|
2255
|
+
size="sm"
|
|
2256
|
+
className="h-7 gap-1"
|
|
2257
|
+
disabled={isCreateDisabled}
|
|
2258
|
+
onClick={() => {
|
|
2259
|
+
;(async () => {
|
|
2260
|
+
const customization =
|
|
2261
|
+
getCollectionConfigModule(
|
|
2262
|
+
labels.collection,
|
|
2263
|
+
)
|
|
2264
|
+
const override =
|
|
2265
|
+
customization.admin
|
|
2266
|
+
?.addRecordButtonOverride
|
|
2267
|
+
if (
|
|
2268
|
+
override &&
|
|
2269
|
+
typeof override === "function"
|
|
2270
|
+
) {
|
|
2271
|
+
await tryPromise(() =>
|
|
2272
|
+
override(
|
|
2273
|
+
createPrePopulatedRecord(),
|
|
2274
|
+
),
|
|
2275
|
+
)
|
|
2276
|
+
return
|
|
2315
2277
|
}
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2278
|
+
setSelectedDateRange(null)
|
|
2279
|
+
setIsCreateDialogOpen(true)
|
|
2280
|
+
})()
|
|
2281
|
+
}}
|
|
2282
|
+
>
|
|
2283
|
+
<PlusCircle className="h-3.5 w-3.5" />
|
|
2284
|
+
<span className="sr-only sm:not-sr-only sm:whitespace-nowrap">
|
|
2285
|
+
Add {recordTitle}
|
|
2286
|
+
</span>
|
|
2287
|
+
</Button>
|
|
2288
|
+
)
|
|
2289
|
+
})()}
|
|
2290
|
+
{isCreateDialogOpen &&
|
|
2291
|
+
createPortal(
|
|
2292
|
+
<div
|
|
2293
|
+
id="create-record-modal"
|
|
2294
|
+
className="fixed inset-0 z-50 flex items-center justify-center animate-in fade-in slide-in-from-top-4 duration-300"
|
|
2295
|
+
aria-modal="true"
|
|
2296
|
+
aria-live="polite"
|
|
2297
|
+
role="dialog"
|
|
2298
|
+
>
|
|
2299
|
+
<div className="fixed inset-0 bg-black/50" />
|
|
2300
|
+
<div
|
|
2301
|
+
className="relative bg-background sm:rounded-lg w-full max-w-2xl h-full sm:h-[90vh] overflow-hidden border border-border"
|
|
2302
|
+
aria-labelledby="dialog-title"
|
|
2303
|
+
>
|
|
2304
|
+
<div className="h-full overflow-y-auto overscroll-contain p-6">
|
|
2305
|
+
<div className="space-y-2">
|
|
2306
|
+
<div className="flex justify-between items-center mb-4">
|
|
2307
|
+
<h4
|
|
2308
|
+
id="dialog-title"
|
|
2309
|
+
className="font-medium leading-none"
|
|
2310
|
+
>
|
|
2311
|
+
Add {recordTitle}
|
|
2312
|
+
</h4>
|
|
2313
|
+
<Button
|
|
2314
|
+
type="button"
|
|
2315
|
+
variant="ghost"
|
|
2316
|
+
size="icon"
|
|
2317
|
+
className="right-4 top-4"
|
|
2318
|
+
onClick={() => {
|
|
2319
|
+
setIsCreateDialogOpen(false)
|
|
2320
|
+
setSelectedDateRange(null)
|
|
2321
|
+
setTimeout(() => {
|
|
2322
|
+
addButtonRef.current?.focus()
|
|
2323
|
+
}, 0)
|
|
2324
|
+
|
|
2325
|
+
localStorage.removeItem(
|
|
2326
|
+
`stoker-draft-${labels.collection}`,
|
|
2327
|
+
)
|
|
2328
|
+
}}
|
|
2329
|
+
>
|
|
2330
|
+
<X className="h-4 w-4" />
|
|
2331
|
+
<span className="sr-only">
|
|
2332
|
+
Close
|
|
2333
|
+
</span>
|
|
2334
|
+
</Button>
|
|
2335
|
+
</div>
|
|
2336
|
+
<RecordForm
|
|
2337
|
+
collection={collection}
|
|
2338
|
+
operation="create"
|
|
2339
|
+
path={[labels.collection]}
|
|
2340
|
+
record={createPrePopulatedRecord()}
|
|
2341
|
+
draft={true}
|
|
2342
|
+
parentCollection={
|
|
2343
|
+
relationCollection?.labels
|
|
2344
|
+
.collection
|
|
2345
|
+
}
|
|
2346
|
+
parentRecord={relationParent}
|
|
2347
|
+
onSuccess={() => {
|
|
2348
|
+
setIsCreateDialogOpen(false)
|
|
2349
|
+
setSelectedDateRange(null)
|
|
2350
|
+
setTimeout(() => {
|
|
2351
|
+
addButtonRef.current?.focus()
|
|
2352
|
+
}, 0)
|
|
2353
|
+
if (isServerReadOnly) {
|
|
2354
|
+
setBackToStartKey(
|
|
2355
|
+
(prev) => prev + 1,
|
|
2356
|
+
)
|
|
2357
|
+
}
|
|
2358
|
+
}}
|
|
2359
|
+
/>
|
|
2360
|
+
</div>
|
|
2361
|
+
</div>
|
|
2367
2362
|
</div>
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2363
|
+
</div>,
|
|
2364
|
+
document.body,
|
|
2365
|
+
)}
|
|
2366
|
+
{showSelectExisting &&
|
|
2367
|
+
relationList &&
|
|
2368
|
+
relationParent &&
|
|
2369
|
+
createPortal(
|
|
2370
|
+
<div
|
|
2371
|
+
id="select-existing-modal"
|
|
2372
|
+
className="fixed inset-0 z-50 flex items-center justify-center animate-in fade-in slide-in-from-top-4 duration-300"
|
|
2373
|
+
aria-modal="true"
|
|
2374
|
+
aria-live="polite"
|
|
2375
|
+
role="dialog"
|
|
2376
|
+
>
|
|
2377
|
+
<div className="fixed inset-0 bg-black/50" />
|
|
2378
|
+
<div className="relative bg-background sm:rounded-lg w-full max-w-2xl h-full sm:h-[50vh] overflow-hidden border border-border">
|
|
2379
|
+
<div className="h-full overflow-y-auto overscroll-contain p-6">
|
|
2380
|
+
<div className="flex items-center justify-between mb-4">
|
|
2381
|
+
<h4 className="font-medium leading-none">
|
|
2382
|
+
Select {recordTitle}
|
|
2383
|
+
</h4>
|
|
2384
|
+
<Button
|
|
2385
|
+
type="button"
|
|
2386
|
+
variant="ghost"
|
|
2387
|
+
size="icon"
|
|
2388
|
+
onClick={() => {
|
|
2389
|
+
setShowSelectExisting(false)
|
|
2390
|
+
setSelectableSearch("")
|
|
2391
|
+
setSelectableData([])
|
|
2392
|
+
}}
|
|
2393
|
+
>
|
|
2394
|
+
<X className="h-4 w-4" />
|
|
2395
|
+
<span className="sr-only">
|
|
2396
|
+
Close
|
|
2397
|
+
</span>
|
|
2398
|
+
</Button>
|
|
2399
|
+
</div>
|
|
2400
|
+
<div>
|
|
2401
|
+
<Command filter={() => 1}>
|
|
2402
|
+
<CommandInput
|
|
2403
|
+
placeholder={`Search ${collectionTitle}...`}
|
|
2404
|
+
className="h-9"
|
|
2405
|
+
value={selectableSearch}
|
|
2406
|
+
onValueChange={(value) => {
|
|
2407
|
+
setSelectableSearch(value)
|
|
2408
|
+
fetchSelectableRecords(
|
|
2409
|
+
value,
|
|
2410
|
+
)
|
|
2411
|
+
}}
|
|
2412
|
+
/>
|
|
2413
|
+
<CommandList className="max-h-full sm:max-h-[calc(50vh-138px)]">
|
|
2414
|
+
<CommandEmpty>
|
|
2415
|
+
{selectLoading ? (
|
|
2416
|
+
<LoadingSpinner
|
|
2417
|
+
size={7}
|
|
2418
|
+
className="m-auto"
|
|
2419
|
+
/>
|
|
2420
|
+
) : !selectLoadingImmediate ? (
|
|
2421
|
+
`No ${collectionTitle} found.`
|
|
2422
|
+
) : null}
|
|
2423
|
+
</CommandEmpty>
|
|
2424
|
+
{(!selectLoading ||
|
|
2425
|
+
isPreloadCacheEnabled) && (
|
|
2426
|
+
<CommandGroup>
|
|
2427
|
+
{selectableData.map(
|
|
2428
|
+
(record) => (
|
|
2429
|
+
<CommandItem
|
|
2430
|
+
key={
|
|
2431
|
+
record.id
|
|
2432
|
+
}
|
|
2433
|
+
value={
|
|
2434
|
+
record.id
|
|
2435
|
+
}
|
|
2436
|
+
onSelect={() => {
|
|
2437
|
+
linkExistingRecord(
|
|
2438
|
+
record,
|
|
2439
|
+
)
|
|
2440
|
+
}}
|
|
2441
|
+
>
|
|
2442
|
+
{
|
|
2443
|
+
record[
|
|
2444
|
+
recordTitleField ||
|
|
2445
|
+
"id"
|
|
2446
|
+
]
|
|
2447
|
+
}
|
|
2448
|
+
</CommandItem>
|
|
2449
|
+
),
|
|
2450
|
+
)}
|
|
2451
|
+
</CommandGroup>
|
|
2412
2452
|
)}
|
|
2413
|
-
</
|
|
2414
|
-
|
|
2415
|
-
</
|
|
2416
|
-
</
|
|
2453
|
+
</CommandList>
|
|
2454
|
+
</Command>
|
|
2455
|
+
</div>
|
|
2456
|
+
</div>
|
|
2417
2457
|
</div>
|
|
2418
|
-
</div
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2458
|
+
</div>,
|
|
2459
|
+
document.body,
|
|
2460
|
+
)}
|
|
2461
|
+
</>
|
|
2462
|
+
)}
|
|
2463
|
+
</div>
|
|
2464
|
+
</>
|
|
2465
|
+
)}
|
|
2426
2466
|
</div>
|
|
2427
2467
|
{tab && isInitialized ? (
|
|
2428
2468
|
<>
|