Projekt

Obecné

Profil

« Předchozí | Další » 

Revize 8ff3394e

Přidáno uživatelem Fantič před více než 1 rok

re #10819 ItemView next, previous item list switching

Zobrazit rozdíly:

src/components/item/ItemTabBar.tsx
1
import { HStack, CircleIcon, View, ScrollView, Button, Center, Heading, Pressable, Text, Box, Container, VStack, Icon, ArrowBackIcon, ChevronLeftIcon, ChevronRightIcon } from "native-base";
1
import { HStack, CircleIcon, View, ScrollView, Button, Center, Heading, Pressable, Text, Box, Container, VStack, Icon, ArrowBackIcon, ChevronLeftIcon, ChevronRightIcon, useToast } from "native-base";
2 2
import { CertaintyWithColors } from "../../stores/reducers/itemSlice";
3 3
import { Certainty, Concordance } from "../../types/item";
4 4
import LoadingBox from "../loading/LoadingBox";
5
import { DrawerNavigationProp } from "@react-navigation/drawer";
6
import { RootDrawerParamList } from "../../pages/Navigation";
7
import { InfoToast } from "../toast/InfoToast";
5 8

  
6 9
// custom render Tab
7
const ItemTabBar = (props: { navigationState: { routes: any[] }, concordances: Concordance[], index: number, onIndexChange: any, onBackPressed: any }) => {
10
const ItemTabBar = (props: { navigationState: { routes: any[] }, concordances: Concordance[], index: number, onIndexChange: any, onBackPressed: any, navigation: DrawerNavigationProp<RootDrawerParamList, "Item", undefined>, nextItem?: string | boolean, prevItem?:string | boolean }) => {
8 11

  
9
    const { concordances, onIndexChange, index, onBackPressed } = props
12
    const { concordances, onIndexChange, index, onBackPressed, nextItem, prevItem } = props
13

  
14
    const toast = useToast();
10 15

  
11 16
    if (concordances && concordances.length > 0) {
12 17
        return (
......
25 30
                        </HStack>
26 31
                        <HStack marginRight={0}>
27 32
                            <Button variant="ghost" size="lg"
28
                                onPress={() => onIndexChange(index - 1)}
33
                                onPress={() => {
34
                                    if(prevItem){
35
                                        console.log(prevItem)
36
                                        props.navigation.navigate("Item", { itemId: prevItem.toString() })
37
                                    }
38
                                    else{
39
                                        toast.show({
40
                                            render: ({
41
                                                id
42
                                            }) => {
43
                                                return <InfoToast text={"No previous item..."} onClose={() => toast.close(id)} />;
44
                                            },
45
                                            duration: 3000
46
                                        });
47
                                    }
48
                                }}
29 49
                                leftIcon={<ChevronLeftIcon size="lg" />}>
30 50
                            </Button>
31 51
                            <Button variant="ghost" size="lg"
32
                                onPress={() => onIndexChange(index + 1)}
52
                                onPress={() => {
53
                                    
54
                                    if(nextItem){
55
                                        props.navigation.navigate("Item", { itemId: nextItem.toString() })
56
                                    }
57
                                    else{
58
                                        toast.show({
59
                                            render: ({
60
                                                id
61
                                            }) => {
62
                                                return <InfoToast text={"No next item..."} onClose={() => toast.close(id)} />;
63
                                            },
64
                                            duration: 3000
65
                                        });
66
                                    }
67
                                }}
33 68
                                leftIcon={<ChevronRightIcon size="lg" />}>
34 69
                            </Button>
35 70
                        </HStack>
......
46 81
                                                <CircleIcon
47 82
                                                    marginLeft="5"
48 83
                                                    size="2"
49
                                                    color={CertaintyWithColors[concordances[i].cert ?? Certainty.Unknown].color}
84
                                                    color={CertaintyWithColors[concordances[i]?.cert ?? Certainty.Unknown].color}
50 85
                                                />
51 86
                                                <Text marginLeft="5%">
52
                                                    {i == index ? <Text bold>{concordances[i].id}</Text> : concordances[i].id}
87
                                                    {i == index ? <Text bold>{concordances[i]?.id}</Text> : concordances[i]?.id}
53 88

  
54 89
                                                </Text>
55 90
                                            </HStack>
......
64 99
                                                <CircleIcon
65 100
                                                    marginLeft="42%"
66 101
                                                    size="2"
67
                                                    color={CertaintyWithColors[concordances[0].cert ?? Certainty.Unknown].color}
102
                                                    color={CertaintyWithColors[concordances[0]?.cert ?? Certainty.Unknown].color}
68 103
                                                />
69 104
                                                <Text marginLeft="2%">
70
                                                    <Text bold>{concordances[0].id}</Text>
105
                                                    <Text bold>{concordances[0]?.id}</Text>
71 106
                                                </Text>
72 107
                                            </HStack>
73 108
                                        </Pressable>
src/components/item/ItemView.tsx
12 12
import { getItemNotes } from "../../stores/actions/itemThunks"
13 13

  
14 14
import { Dimensions } from "react-native";
15
import { DrawerNavigationProp } from "@react-navigation/drawer"
16
import { RootDrawerParamList } from "../../pages/Navigation"
15 17

  
16 18
interface ItemDetailProps {
17 19
    item: Item,
18 20
    itemLoading: boolean,
19 21
    notes: Note[],
20 22
    notesLoading: boolean,
21
    navigation: any
23
    navigation: DrawerNavigationProp<RootDrawerParamList, "Item", undefined>
22 24
}
23 25

  
24 26
const ItemDetail = (props: { item: Item, itemLoading: boolean }) => {
......
26 28

  
27 29
    const [selectedImage, setSelectedImage] = useState<number>(0);
28 30

  
29
    console.log("rerender")
30

  
31 31
    return (<>
32 32
        {
33 33
            item && props.itemLoading ?
......
137 137

  
138 138

  
139 139

  
140
const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, navigation: any }) => {
140
const ItemNotes = (props: { item: Item, notes: Note[], notesLoading: boolean, navigation: DrawerNavigationProp<RootDrawerParamList, "Item", undefined> }) => {
141 141

  
142 142
    const [showRelatedComments, setShowRelatedComments] = useState(true);
143 143

  
......
152 152
            dispatch(getItemNotes({ item: props.item, relatedComments: showRelatedComments }));
153 153
        }
154 154
    }, [triggerRefresh])
155

  
156
    const toggleRelatedComments = () => {
155
    
156
    const toggleRelatedComments = useCallback(() => {
157 157
        if (!props.notesLoading) {
158 158

  
159 159
            let value = !showRelatedComments;
......
161 161
            setShowRelatedComments(value);
162 162
            dispatch(getItemNotes({ item: props.item, relatedComments: value }));
163 163
        }
164
    }
164
      }, [showRelatedComments]);
165

  
165 166

  
166 167
    const handleCreateItemComment = useCallback(
167 168
        (newComment: string, replyingTo: { messageId: string; userName: string } | null) => {
src/pages/ItemViewPage.tsx
1
import React, { useEffect } from "react"
1
import React, { useCallback, useEffect } from "react"
2 2
import { useDispatch, useSelector } from "react-redux"
3 3
import { AppDispatch, RootState } from "../stores/store"
4 4
import { getItem, getItemNotes, setConcordances } from "../stores/actions/itemThunks"
......
15 15
import { ErrorToast } from "../components/toast/ErrorToast"
16 16

  
17 17

  
18
const ItemViewPage = ({route, navigation}: DrawerScreenProps<RootDrawerParamList, 'Item'>) => {
18
const ItemViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamList, 'Item'>) => {
19 19

  
20 20
  const layout = useWindowDimensions();
21 21

  
22
  const [routes, setRoutes] = React.useState<{key: string, title: string}[]>([
22
  const [routes, setRoutes] = React.useState<{ key: string, title: string }[]>([
23 23
    // initial tab
24 24
    { key: 'loading', title: 'Loading item...' },
25 25
  ]);
......
36 36
  const lastError = useSelector((state: RootState) => state.itemViewState.lastError)
37 37
  const toast = useToast();
38 38

  
39

  
39 40
  useEffect(() => {
40
      if (lastError) {
41
          toast.closeAll()
42
          toast.show({
43
              render: ({
44
                  id
45
              }) => {
46
                  return <ErrorToast headerText={"Error"} text={lastError} onClose={() => toast.close(id)} />;
47
              },
48
              duration: 3000
49
          });
50
      }
41
    if (lastError) {
42
      toast.closeAll()
43
      toast.show({
44
        render: ({
45
          id
46
        }) => {
47
          return <ErrorToast headerText={"Error"} text={lastError} onClose={() => toast.close(id)} />;
48
        },
49
        duration: 3000
50
      });
51
    }
51 52
  }, [lastError])
52 53

  
53 54
  // initial: load main item
......
89 90
      }
90 91
      // set item notes if item is loaded
91 92
      if (item && item.id) {
92
        dispatch(getItemNotes({item: item, relatedComments: true}));
93
        dispatch(getItemNotes({ item: item, relatedComments: true }));
93 94
      }
94 95
    }
95 96
  }, [item]);
96 97

  
97
  const handleIndexChanged = (newIndex: number) => {
98
    if(newIndex >= 0 && newIndex < concordances.length && index != newIndex){
98

  
99
  const handleIndexChanged = useCallback((newIndex: number) => {
100
    if (newIndex >= 0 && newIndex < concordances.length && index != newIndex) {
99 101
      console.log("index changed");
100 102
      setIndex(newIndex);
101 103
      if (concordances && concordances.length > 0) {
102 104
        dispatch(getItem(concordances[newIndex].id ?? ""));
103 105
      }
104 106
    }
105
  }
107
  }, [concordances, index]);
106 108

  
107 109
  const onBackPressed = () => {
108 110
    log.debug("back pressed")
......
111 113

  
112 114
  return (
113 115
    !concordances || concordances.length < 1 ?
114
      <LoadingBox text={`Loading item ${route.params.itemId}...`}/>
116
      <LoadingBox text={`Loading item ${route.params.itemId}...`} />
115 117
      :
116 118
      <TabView
117 119
        renderTabBar={() => ItemTabBar({
......
122 124
          index: index,
123 125
          onIndexChange: handleIndexChanged,
124 126
          onBackPressed: onBackPressed,
127
          navigation: navigation,
128
          prevItem: item.prevItem,
129
          nextItem: item.nextItem,
125 130
        })}
126 131

  
127 132
        navigationState={{ index, routes }}
128
        renderScene={() => <ItemView item={item} notes={notes} itemLoading={itemLoading} notesLoading={notesLoading} navigation={navigation}/>}
133
        renderScene={() => <ItemView item={item} notes={notes} itemLoading={itemLoading} notesLoading={notesLoading} navigation={navigation} />}
129 134

  
130 135
        initialLayout={{ width: layout.width }}
131 136
        onIndexChange={handleIndexChanged}
src/stores/actions/itemThunks.ts
42 42
                    workName: response.data.object[0]?.caption ?? undefined,
43 43
                    inventoryItem: response.data.text ?? undefined,
44 44
                    searchSubjects: response.data.search_subject ?? undefined,
45
                    prevItem: response.data.prevItem ?? undefined,
46
                    nextItem: response.data.nextItem ?? undefined,
45 47
                    authorName,
46 48
                    images,
47 49
                    institution,
......
61 63
                        [{ id: itemId, cert: response.data?.object[1]?.cert ?? Certainty.Unknown }],
62 64
                    authorDisplayName: response.data.object[0]?.name?.[0]?.getty_data?.display_name ?? undefined,
63 65
                    workName: response.data.object[0]?.caption ?? undefined,
66
                    prevItem: response.data.prevItem ?? undefined,
67
                    nextItem: response.data.nextItem ?? undefined,
64 68
                    inventoryItem: response.data.text ?? undefined,
65 69
                    searchSubjects: response.data.search_subject ?? undefined,
66 70
                }
src/stores/reducers/itemSlice.ts
39 39
                concordances : action.payload.concordances,
40 40
                searchSubjects : action.payload.searchSubjects,
41 41
                inventoryItem : action.payload.inventoryItem,
42
                prevItem: action.payload.prevItem,
43
                nextItem: action.payload.nextItem,
42 44
                fullView : action.payload.fullView,
43 45
            }
44 46

  
src/types/item.ts
25 25
    repository?: string
26 26
    provenance?: string
27 27
    description?: string
28

  
29
    prevItem?: string | boolean
30
    nextItem?: string | boolean
28 31
}
29 32

  
30 33
export type ItemViewState = {

Také k dispozici: Unified diff