Revize ab632fe5
Přidáno uživatelem Michal Schwob před více než 1 rok
src/components/listView/ListView.tsx | ||
---|---|---|
7 | 7 |
import { log } from "../../logging/logger" |
8 | 8 |
import ListViewInventoryGroup from "./ListViewInventoryGroup" |
9 | 9 |
import { ErrorToast } from "../toast/ErrorToast" |
10 |
import LoadingBox from "../loading/LoadingBox" |
|
10 | 11 |
|
11 | 12 |
type ListViewProps = { |
12 | 13 |
navigation: any |
... | ... | |
16 | 17 |
|
17 | 18 |
const inventories = useSelector((state: RootState) => state.listView.inventories) |
18 | 19 |
const numberOfResults = useSelector((state: RootState) => state.listView.numOfResults) |
19 |
|
|
20 |
const loading = useSelector((state: RootState) => state.listView.loading) |
|
20 | 21 |
|
21 | 22 |
const lastError = useSelector((state: RootState) => state.listView.lastError) |
22 | 23 |
const toast = useToast(); |
... | ... | |
38 | 39 |
return ( |
39 | 40 |
<> |
40 | 41 |
<Text fontSize={16} fontWeight={"bold"} color={"primary.500"}>Search results{numberOfResults ? ` (${numberOfResults})` : ""}:</Text> |
41 |
{inventories && inventories.length > 0 ? |
|
42 |
{loading ? ( |
|
43 |
<LoadingBox text={"Loading..."} /> |
|
44 |
) : |
|
45 |
inventories && inventories.length > 0 ? |
|
42 | 46 |
(inventories.length > 1 ? |
43 | 47 |
inventories.map((inventory) => ( |
44 | 48 |
<ListViewInventoryGroup |
... | ... | |
57 | 61 |
)) : ( |
58 | 62 |
<Text alignSelf={"center"}>No results found</Text> |
59 | 63 |
) |
64 |
|
|
60 | 65 |
} |
61 | 66 |
</> |
62 | 67 |
) |
src/components/listView/ListViewInventoryGroup.tsx | ||
---|---|---|
1 |
import { Badge, Button, Pressable, VStack, Text, Fab, Divider } from "native-base"
|
|
2 |
import { ItemPreviewType } from "../../types/listViewTypes"
|
|
1 |
import {Badge, Button, Pressable, VStack, Text, Fab, Divider} from "native-base"
|
|
2 |
import {ItemPreviewType} from "../../types/listViewTypes"
|
|
3 | 3 |
import ItemPreview from "./ItemPreview" |
4 |
import { useDispatch, useSelector } from "react-redux" |
|
5 |
import { AppDispatch, RootState } from "../../stores/store" |
|
6 |
import { useEffect, useState } from "react" |
|
7 |
import { loadItemsByInventory } from "../../stores/actions/listViewThunks" |
|
4 |
import {useDispatch, useSelector} from "react-redux" |
|
5 |
import {AppDispatch, RootState} from "../../stores/store" |
|
6 |
import {useEffect, useState} from "react" |
|
7 |
import {loadItemsByInventory} from "../../stores/actions/listViewThunks" |
|
8 |
import LoadingBox from "../loading/LoadingBox" |
|
8 | 9 |
|
9 | 10 |
interface ListViewInventoryGroupProps { |
10 | 11 |
inventoryName: string |
... | ... | |
16 | 17 |
const ListViewInventoryGroup = (props: ListViewInventoryGroupProps) => { |
17 | 18 |
const items = useSelector((state: RootState) => state.listView.data[props.inventoryName]) |
18 | 19 |
const loading = useSelector((state: RootState) => state.listView.loading) |
20 |
const inventoriesDataLoading = useSelector((state: RootState) => state.listView.inventoriesDataLoading) |
|
21 |
const [isInventoryDataLoading, setIsInventoryDataLoading] = useState(false) |
|
19 | 22 |
const [isExpanded, setIsExpanded] = useState(props.defaultOpen ? props.defaultOpen : false) |
20 | 23 |
const pagination = useSelector((state: RootState) => state.listView.loadedPages[props.inventoryName]) |
21 | 24 |
|
... | ... | |
77 | 80 |
} |
78 | 81 |
}, [loading]) |
79 | 82 |
|
83 |
useEffect(() => { |
|
84 |
setIsInventoryDataLoading(inventoriesDataLoading[props.inventoryName] ? inventoriesDataLoading[props.inventoryName] : false) |
|
85 |
}, [inventoriesDataLoading]); |
|
86 |
|
|
80 | 87 |
useEffect(() => { |
81 | 88 |
if (props.defaultOpen) { |
82 | 89 |
if (!items || items.length == 0) { |
... | ... | |
86 | 93 |
}, []) |
87 | 94 |
|
88 | 95 |
return ( |
89 |
<VStack mb={2} key={props.inventoryName}>
|
|
96 |
<VStack mb={ 2 } key={ props.inventoryName }>
|
|
90 | 97 |
<Button |
91 |
onPress={() => setIsExpanded(!isExpanded)}
|
|
92 |
alignSelf={"flex-start"}
|
|
98 |
onPress={ () => setIsExpanded(!isExpanded) }
|
|
99 |
alignSelf={ "flex-start" }
|
|
93 | 100 |
variant="solid" |
94 |
bg={"primary.500"}
|
|
95 |
mb={2}
|
|
96 |
p={1}
|
|
97 |
key={props.inventoryName}
|
|
98 |
size={"md"}
|
|
101 |
bg={ "primary.500" }
|
|
102 |
mb={ 2 }
|
|
103 |
p={ 1 }
|
|
104 |
key={ props.inventoryName }
|
|
105 |
size={ "md" }
|
|
99 | 106 |
> |
100 |
{props.inventoryLabel}
|
|
107 |
{ props.inventoryLabel }
|
|
101 | 108 |
</Button> |
102 |
{isExpanded && items && items.map((item) => ( |
|
109 |
{ isExpanded && items && items.map((item) => (
|
|
103 | 110 |
<ItemPreview |
104 | 111 |
// @ts-ignore |
105 |
caption={item.object[0].caption}
|
|
106 |
title={item.text}
|
|
107 |
name={parseArtists(item)}
|
|
108 |
image={parseImage(item)}
|
|
109 |
itemId={item.xml_id}
|
|
110 |
inventoryLabel={props.inventoryLabel}
|
|
111 |
navigation={props.navigation}
|
|
112 |
caption={ item.object[0].caption }
|
|
113 |
title={ item.text }
|
|
114 |
name={ parseArtists(item) }
|
|
115 |
image={ parseImage(item) }
|
|
116 |
itemId={ item.xml_id }
|
|
117 |
inventoryLabel={ props.inventoryLabel }
|
|
118 |
navigation={ props.navigation }
|
|
112 | 119 |
/> |
113 |
))} |
|
114 |
{isExpanded && items && pagination && pagination.cursor < pagination.records && (
|
|
120 |
)) }
|
|
121 |
{ isExpanded && items && pagination && pagination.cursor < pagination.records && !isInventoryDataLoading && (
|
|
115 | 122 |
<Button |
116 |
onPress={() => dispatch(loadItemsByInventory(props.inventoryName))}
|
|
117 |
variant={"Link"}
|
|
118 |
mt={0}
|
|
119 |
size={"sm"}
|
|
120 |
color={"primary.500"}
|
|
121 |
textDecoration={"underline"}
|
|
123 |
onPress={ () => dispatch(loadItemsByInventory(props.inventoryName)) }
|
|
124 |
variant={ "Link" }
|
|
125 |
mt={ 0 }
|
|
126 |
size={ "sm" }
|
|
127 |
color={ "primary.500" }
|
|
128 |
textDecoration={ "underline" }
|
|
122 | 129 |
> |
123 |
<Text fontSize={"sm"} color={"primary.500"} underline>Load more</Text>
|
|
130 |
<Text fontSize={ "sm" } color={ "primary.500" } underline>Load more</Text>
|
|
124 | 131 |
</Button> |
125 |
)} |
|
126 |
<Divider my={2} colorScheme={"primary"}/> |
|
132 |
) } |
|
133 |
{ isExpanded && isInventoryDataLoading && ( |
|
134 |
<LoadingBox text={ "Loading..." }/> |
|
135 |
) } |
|
136 |
<Divider my={ 2 } colorScheme={ "primary" }/> |
|
127 | 137 |
|
128 | 138 |
</VStack> |
129 | 139 |
) |
src/components/search/SearchForm.tsx | ||
---|---|---|
17 | 17 |
import MultiSelect from "./MultiSelect" |
18 | 18 |
import SwitchWithLabel from "./SwitchWithLabel" |
19 | 19 |
import { log } from "../../logging/logger" |
20 |
import { setFilterState } from "../../stores/reducers/listViewSlice"
|
|
20 |
import {resetInventories, setFilterState} from "../../stores/reducers/listViewSlice"
|
|
21 | 21 |
import { SearchParams } from "../../api/searchService" |
22 | 22 |
|
23 | 23 |
interface SearchFormProps { |
... | ... | |
27 | 27 |
|
28 | 28 |
const SearchForm = (props: SearchFormProps) => { |
29 | 29 |
const [isFilterOpen, setIsFilterOpen] = useState<boolean>(true) |
30 |
const loading = useSelector((state: RootState) => state.listView.loading) |
|
30 | 31 |
|
31 | 32 |
const inventories: Inventory[] = useSelector((state: RootState) => state.searchForm.inventories) |
32 | 33 |
const nationalities = useSelector((state: RootState) => state.searchForm.nationalities) |
... | ... | |
75 | 76 |
isLowQuality, |
76 | 77 |
searchQuery: searchQuery, |
77 | 78 |
} |
79 |
dispatch(resetInventories()) |
|
78 | 80 |
dispatch(setFilterState(filterState)) |
79 | 81 |
dispatch(search(filterState)) |
80 | 82 |
setIsFilterOpen(false) |
... | ... | |
161 | 163 |
</Button> |
162 | 164 |
{ !isFilterOpen && ( |
163 | 165 |
<Button |
166 |
isLoading={ loading } |
|
164 | 167 |
borderRadius={ 10 } |
165 | 168 |
onPress={ () => searchSubmit() } |
166 | 169 |
colorScheme="primary" |
... | ... | |
279 | 282 |
Reset |
280 | 283 |
</Button> |
281 | 284 |
<Button |
285 |
isLoading={ loading } |
|
282 | 286 |
borderRadius={ 10 } |
283 | 287 |
onPress={ () => searchSubmit() } |
284 | 288 |
colorScheme="primary" |
src/stores/reducers/listViewSlice.ts | ||
---|---|---|
32 | 32 |
resetListView: () => initialState, |
33 | 33 |
setFilterState: (state, action) => { |
34 | 34 |
state.filterState = action.payload |
35 |
}, |
|
36 |
resetInventories: (state) => { |
|
37 |
state.inventories = [] |
|
35 | 38 |
} |
36 | 39 |
}, |
37 | 40 |
extraReducers: (builder) => { |
... | ... | |
57 | 60 |
state.data[inventories[0].name] = state.data[inventories[0].name] ? [...prevData, ...data] : [...data] |
58 | 61 |
state.loading = false |
59 | 62 |
state.loadedPages[inventories[0].name] = {cursor, items, records} |
63 |
state.inventoriesDataLoading[action.meta.arg] = false |
|
60 | 64 |
}) |
61 | 65 |
builder.addCase(loadItemsByInventory.pending, (state, action) => { |
62 | 66 |
state.inventoriesDataLoading[action.meta.arg] = true |
... | ... | |
64 | 68 |
} |
65 | 69 |
}) |
66 | 70 |
|
67 |
export const { resetListView, setFilterState } = listViewSlice.actions |
|
71 |
export const { resetListView, setFilterState, resetInventories } = listViewSlice.actions
|
|
68 | 72 |
export default listViewSlice.reducer |
Také k dispozici: Unified diff
NEW: added loading indicator for individual inventories
re #10850