Projekt

Obecné

Profil

« Předchozí | Další » 

Revize bb690a9a

Přidáno uživatelem Fantič před asi 2 roky(ů)

re #10569: NotesView: Get Notes

Zobrazit rozdíly:

src/api/api.ts
6 6
    baseURL: BASE_URL,
7 7
    withCredentials: true
8 8
})
9

  
src/api/notesservice.ts
1
import { SortOptions } from "../types/general"
1 2
import { axiosInstance } from "./api"
2 3

  
3 4

  
4 5
export const getItemNotesRequest = async (itemId : string) => {
5 6
    return await axiosInstance.get(
6
        `/api/notes/?item_id[]=${itemId}`
7
        `/notes/?item_id[]=${itemId}`
7 8
    )
8 9
}
9 10

  
11
export const getAllNotesRequest = async (myComments : boolean, generalComments : boolean, sortOptions: { items: SortOptions, date: SortOptions }) => {
12
    let url = `/notes/?my_notes=${myComments}&general_notes=${generalComments}`;
13

  
14
    if(sortOptions.date != SortOptions.None){
15
        url += "&order_by=date&order_dir="+sortOptions.date;
16
    }
17
    if(sortOptions.items != SortOptions.None){
18
        url += "&order_by=items&order_dir="+sortOptions.items;
19
    }
20

  
21
    return await axiosInstance.get(
22
        url
23
    )
24
}
25

  
26

  
27

  
src/components/item/ItemView.tsx
55 55
                            {item.fullView && item.imageUrl && (
56 56
                                <Center background="primary.100" marginTop="5%">
57 57
                                    <Text>Resembling object</Text>
58
                                    <Image size={250} alt="image" source={{ uri: IMAGE_URL + "/" + item.imageUrl }} />
58
                                    <Image size={250} alt="image" source={{ uri: IMAGE_URL + "/" + item.imageUrl }}/>
59 59
                                </Center>)}
60 60
                            {item.fullView && (
61 61
                                <Card shadow="1" marginTop="5%" marginBottom="5%">
......
138 138
                notesLoading ?
139 139
                    <LoadingBox text="Notes loading" />
140 140
                    :
141
                    <NotesListView notes={props.notes} handleDelete={() => console.log("TODO handle delete")} handleEdit={() => console.log("TODO handle edit")} handleReply={() => console.log("TODO handle reply")}/>
141
                    <NotesListView notes={props.notes} handleDelete={() => console.log("TODO handle delete")} handleEdit={() => console.log("TODO handle edit")} handleReply={() => console.log("TODO handle reply")} setConfirmDialog={() => {}}/>
142 142
            )}
143 143

  
144 144
            {/* item notes switch tab */}
src/components/notes/NoteView.tsx
13 13

  
14 14
    const [text, setText] = useState(note.note);
15 15

  
16
    const getDateString = (date: Date): string => {
17
        return date.toLocaleDateString("en-US",
16
    const getDateString = (timestamp: Date): string => {
17
        return new Date(timestamp).toLocaleString("en-US",
18 18
            { year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false }
19 19
        ).replace(/,/g, "").replace(/ /g, "-").replace(/-(?!.*-)/, " ");
20 20
    }
......
31 31
            if (text == note.note) {
32 32
                setIsEdited(false);
33 33
            }
34
            else{
34
            else {
35 35
                // confirm dialog
36 36
                props.setConfirmDialog({
37 37
                    headerText: "Cancel Edit",
......
55 55
            confirmText: "Delete",
56 56
            confirmColor: "danger",
57 57
            onClose: () => { props.setConfirmDialog(null) },
58
            onSubmit: () => { props.handleDelete(note.uuid);props.setConfirmDialog(null) }
58
            onSubmit: () => { props.handleDelete(note.uuid); props.setConfirmDialog(null) }
59 59
        });
60 60
    }
61 61

  
......
74 74
        <HStack marginTop="5%">
75 75
            <Box width="10" height="10" marginTop="2.5%">
76 76
                <Avatar bg={note.noteColor} size="sm" source={{
77
                    uri: AVATAR_URL + "/" + note.avatarUrl
78
                }}>
77
                    uri: AVATAR_URL + "/" + note.avatarUrl                                     
78
                    // TODO bude zde nebo v atributu ta připona?
79
                    + ".png"                }}>
79 80
                    {getUsernameInitials(note.username)}
80 81
                </Avatar>
81 82
            </Box>
src/pages/NotesViewPage.tsx
9 9
import { G, Path } from "react-native-svg"
10 10
import { MessageIcon } from "../components/general/Icons"
11 11
import { ConfirmDialog } from "../components/general/Dialogs"
12
import { useDispatch, useSelector } from "react-redux"
13
import { AppDispatch, RootState } from "../stores/store"
14
import LoadingBox from "../components/loading/LoadingBox"
15
import { getAllNotes } from "../stores/actions/notesThunks"
16
import { login } from "../stores/actions/userThunks"
12 17
const NotesViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamList, 'Notes'>) => {
13 18

  
19
  const { notes, notesLoading, requestPending } = useSelector((state: RootState) => state.noteViewState)
20
  const dispatch = useDispatch<AppDispatch>();
21

  
14 22
  const [isSortOpen, setIsSortOpen] = useState(false);
15 23

  
16 24
  const [myCommentsCheck, setMyCommentsCheck] = useState(false);
......
18 26

  
19 27
  const [replyingTo, setReplyingTo] = useState<{ messageId: string; userName: string } | null>(null);
20 28

  
21
  const cancelRef = React.useRef(null)
22

  
23
  const notes = [
24
    {
25
      uuid: "fadfsfdsaf",
26
      username: "Alice",
27
      userId: "123",
28
      note: "Buy milk and bread",
29
      avatarUrl: "martin.png",
30
      items: [],
31
      createdTime: new Date("2022-01-01T10:00:00Z"),
32
      updatedTime: new Date("2022-01-01T12:00:00Z"),
33
      noteColor: "#FFA500",
34
    },
35
    {
36
      uuid: "fadfsfdsaf",
37
      username: "Bob",
38
      userId: "456",
39
      note: "Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM ,Call Jane at 2 PM",
40
      avatarUrl: "https://example.com/avatar2.jpg",
41
      items: ["Jane"],
42
      createdTime: new Date("2022-01-02T10:00:00Z"),
43
      updatedTime: new Date("2022-01-02T14:00:00Z"),
44
      noteColor: "#6495ED",
45
    },
46
    {
47
      uuid: "fadfsfdsaf",
48
      username: "Charlie",
49
      userId: "789",
50
      note: "Pick up dry cleaning",
51
      avatarUrl: "https://example.com/avatar3.jpg",
52
      items: ["dry cleaning"],
53
      createdTime: new Date("2022-01-03T10:00:00Z"),
54
      updatedTime: new Date("2022-01-03T12:30:00Z"),
55
      noteColor: "#FFA07A",
56
    },
57
    {
58
      uuid: "fadfsfdsaf",
59
      username: "Dave",
60
      userId: "012",
61
      note: "Finish report by Friday",
62
      avatarUrl: "https://example.com/avatar4.jpg",
63
      items: ["report"],
64
      createdTime: new Date("2022-01-04T10:00:00Z"),
65
      updatedTime: new Date("2022-01-04T16:00:00Z"),
66
      noteColor: "#7B68EE",
67
    },
68
    {
69
      uuid: "fadfsfdsaf",
70
      username: "Eve",
71
      userId: "345",
72
      note: "Buy flowers for mom's birthday",
73
      avatarUrl: "https://example.com/avatar5.jpg",
74
      items: ["flowers"],
75
      createdTime: new Date("2022-01-05T10:00:00Z"),
76
      updatedTime: new Date("2022-01-05T18:00:00Z"),
77
      noteColor: "#F08080",
78
    },
79
    {
80
      uuid: "fadfsfdsaf",
81
      username: "Frank",
82
      userId: "678",
83
      note: "Schedule dentist appointment",
84
      avatarUrl: "https://example.com/avatar6.jpg",
85
      items: ["dentist appointment"],
86
      createdTime: new Date("2022-01-06T10:00:00Z"),
87
      updatedTime: new Date("2022-01-06T11:00:00Z"),
88
      noteColor: "#98FB98",
89
    },
90
    {
91
      uuid: "fadfsfdsaf",
92
      username: "Grace",
93
      userId: "901",
94
      note: "Book hotel for vacation",
95
      avatarUrl: "https://example.com/avatar7.jpg",
96
      items: ["hotel"],
97
      createdTime: new Date("2022-01-07T10:00:00Z"),
98
      updatedTime: new Date("2022-01-07T15:00:00Z"),
99
      noteColor: "#87CEFA",
100
    },
101
    {
102
      uuid: "fadfsfdsaf",
103
      username: "Alice",
104
      userId: "123",
105
      note: "Buy milk and bread",
106
      avatarUrl: "https://example.com/avatar1.jpg",
107
      items: ["milk", "bread"],
108
      createdTime: new Date("2022-01-01T10:00:00Z"),
109
      updatedTime: new Date("2022-01-01T12:00:00Z"),
110
      noteColor: "#FFA500",
111
    },
112
    {
113
      uuid: "fadfsfdsaf",
114
      username: "Bob",
115
      userId: "456",
116
      note: "Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM, Call Jane at 2 PM ,Call Jane at 2 PM",
117
      avatarUrl: "https://example.com/avatar2.jpg",
118
      items: ["Jane"],
119
      createdTime: new Date("2022-01-02T10:00:00Z"),
120
      updatedTime: new Date("2022-01-02T14:00:00Z"),
121
      noteColor: "#6495ED",
122
    },
123
    {
124
      uuid: "fadfsfdsaf",
125
      username: "Charlie",
126
      userId: "789",
127
      note: "Pick up dry cleaning",
128
      avatarUrl: "https://example.com/avatar3.jpg",
129
      items: ["dry cleaning"],
130
      createdTime: new Date("2022-01-03T10:00:00Z"),
131
      updatedTime: new Date("2022-01-03T12:30:00Z"),
132
      noteColor: "#FFA07A",
133
    },
134
    {
135
      uuid: "fadfsfdsaf",
136
      username: "Dave",
137
      userId: "012",
138
      note: "Finish report by Friday",
139
      avatarUrl: "https://example.com/avatar4.jpg",
140
      items: ["report"],
141
      createdTime: new Date("2022-01-04T10:00:00Z"),
142
      updatedTime: new Date("2022-01-04T16:00:00Z"),
143
      noteColor: "#7B68EE",
144
    },
145
    {
146
      uuid: "fadfsfdsaf",
147
      username: "Eve",
148
      userId: "345",
149
      note: "Buy flowers for mom's birthday",
150
      avatarUrl: "https://example.com/avatar5.jpg",
151
      items: ["flowers"],
152
      createdTime: new Date("2022-01-05T10:00:00Z"),
153
      updatedTime: new Date("2022-01-05T18:00:00Z"),
154
      noteColor: "#F08080",
155
    }];
29
  const cancelRef = React.useRef(null);
156 30

  
157 31
  const [confirmDialog, setConfirmDialog] = React.useState<{
158 32
    headerText?: string;
......
202 76
    }
203 77
  };
204 78

  
79
  // initial: load notes
80
  useEffect(() => {
81
    log.debug("NotesViewPage", "useEffect", "getNotes");
82
    getNotes();
83
  }, [])
84

  
85
  // general comments check changed
86
  useEffect(() => {
87
    if(!notesLoading){
88
      log.debug("NotesViewPage", "useEffect", "getNotes");
89
      getNotes();
90
    }
91
  }, [generalCommentsCheck, myCommentsCheck])
92

  
93

  
205 94
  const getNotes = () => {
206
    console.log("Get NOTES");
95
    dispatch(getAllNotes({
96
      myComments: myCommentsCheck,
97
      generalComments: generalCommentsCheck,
98
      sortOptions: sortSettings
99
    }));
207 100
  }
208 101

  
209 102
  const handleReply = (messageId: string, userName: string) => {
......
219 112
    console.log("Handling delete:" + messageId);
220 113
  }
221 114

  
115
  console.log("notes loading: " + notesLoading);
116

  
222 117
  return (
223 118
    <Box width="90%" marginLeft="5%">
224 119
      <VStack>
......
261 156
          <VStack width="70%" space="0">
262 157
            <Flex direction="row" alignItems="center" justify="flex-end">
263 158
              <Text>My comments</Text>
264
              <Switch isChecked={myCommentsCheck} onValueChange={() => setMyCommentsCheck(!myCommentsCheck)} size="md" />
159
              <Switch isChecked={myCommentsCheck} onValueChange={() => {if(!notesLoading) setMyCommentsCheck(!myCommentsCheck)}} size="md" />
265 160
            </Flex>
266 161
            <Flex direction="row" alignItems="center" justify="flex-end" marginTop="-7.5%">
267 162
              <Text>General comments</Text>
268
              <Switch isChecked={generalCommentsCheck} onValueChange={() => setGeneralCommentsCheck(!generalCommentsCheck)} size="md" />
163
              <Switch isChecked={generalCommentsCheck} onValueChange={() => {if(!notesLoading) setGeneralCommentsCheck(!generalCommentsCheck)}} size="md" />
269 164
            </Flex>
270 165
          </VStack>
271 166
        </HStack>
272 167
        <Box h={replyingTo != null ? "62.5%" : "67.5%"}>
273
          <NotesListView notes={notes} handleReply={handleReply} handleDelete={handleDelete} handleEdit={handleEdit} setConfirmDialog={setConfirmDialog} />
168
          {
169
            notesLoading ? (<LoadingBox text="Loading notes"/>)
170
              :
171
              (<NotesListView notes={notes} handleReply={handleReply} handleDelete={handleDelete} handleEdit={handleEdit} setConfirmDialog={setConfirmDialog} />)
172
          }
274 173
        </Box>
275 174
        {replyingTo != null &&
276 175
          <Flex direction="row" alignItems="center" justify="flex-end" h="5%" marginRight="10%">
src/stores/actions/itemThunks.ts
111 111
                    for(let i = 0; i < response.data.length; i++){
112 112
                        let note = response.data[i];
113 113
                        notes.push({
114
                            uuid: (note as any).uuid,
114 115
                            username: (note as any).created_by,
115 116
                            userId: (note as any).created_by_id,
116 117
                            note: (note as any).note,
src/stores/actions/notesThunks.ts
1
import { createAsyncThunk } from "@reduxjs/toolkit"
2
import { getAllNotesRequest } from "../../api/notesservice"
3
import { SortOptions } from "../../types/general";
4

  
5

  
6
export const getAllNotes = createAsyncThunk(
7
    "notes/getAllNotes",
8
    async ({ myComments, generalComments, sortOptions }: { myComments : boolean, generalComments : boolean, sortOptions: { items: SortOptions, date: SortOptions }}) => {
9
        try {
10
            console.log("GET notes/getNotes/");
11

  
12
            const response = await getAllNotesRequest(myComments, generalComments, sortOptions);
13

  
14
            console.log(response);
15

  
16
            if (response.status === 200) {
17
                if(response.data.length > 0){
18

  
19
                    let notes = [];
20
                    for(let i = 0; i < response.data.length; i++){
21
                        let note = response.data[i];
22
                        notes.push({
23
                            uuid: (note as any).uuid,
24
                            username: (note as any).created_by,
25
                            userId: (note as any).created_by_id,
26
                            note: (note as any).note,
27
                            avatarUrl: (note as any).avatar,
28
                            items: (note as any).items,
29
                            createdTime: (note as any).created, 
30
                            updatedTime: (note as any).updated,
31
                            noteColor: (note as any).note_color,
32
                        })
33
                    }
34

  
35
                    return {
36
                        notes,
37
                    }
38
                }
39
                else{
40
                    // no notes
41
                    return {
42
                        notes: [],
43
                    }
44
                }
45
            }
46
            else {
47
                console.log("Error");
48
                return Promise.reject(response.data ? response.data : "Error")
49
            }
50
        } catch (err: any) {
51
            console.log(err);
52
            return Promise.reject(err.response.data)
53
        }
54
    }
55
)
src/stores/reducers/notesSlice.ts
1
import { PayloadAction, createSlice } from "@reduxjs/toolkit"
2
import { getAllNotes } from "../actions/notesThunks"
3
import { Certainty, ItemViewState, Item } from "../../types/item";
4
import { Note, NotesViewState } from "../../types/note";
5

  
6

  
7

  
8
const initialState: NotesViewState = {
9
    notes: [],
10
    notesLoading: true, // for reading notes
11
    requestPending: false, // for updating or deleting note
12
    lastError: ""
13
}
14

  
15
export const noteSlice = createSlice({
16
    name: "note",
17
    initialState: initialState,
18
    reducers: {
19
    },
20
    extraReducers: (builder) => {
21
            // getAllNotes
22
            builder.addCase(getAllNotes.fulfilled, (state, action) => {
23
                state.notesLoading = false;
24
                state.notes = action.payload.notes;
25
            })
26
            builder.addCase(getAllNotes.pending, (state, action) => {
27
                state.notesLoading = true;
28
            })
29
            builder.addCase(getAllNotes.rejected, (state, action) => {
30
                state.notesLoading = false;
31
                state.lastError = action.error.message
32
            })
33
    }
34
})
35

  
36
export default noteSlice.reducer
src/stores/store.ts
3 3
import itemReducer from "./reducers/itemSlice"
4 4
import searchFormReducer from "./reducers/searchFormSlice"
5 5
import listViewReducer from "./reducers/listViewSlice"
6
import noteViewReducer from "./reducers/notesSlice"
6 7

  
7 8
const store = configureStore({
8 9
    reducer: {
9 10
        user: userReducer,
10 11
        itemViewState: itemReducer,
12
        noteViewState: noteViewReducer,
11 13
        searchForm: searchFormReducer,
12 14
        listView: listViewReducer,
13 15
    },
src/types/note.ts
10 10
    noteColor: string
11 11
}
12 12

  
13

  
14
export type NotesViewState = {
15
    notes: Note[] 
16
    notesLoading: boolean
17
    requestPending: boolean
18
    lastError?: string
19
}
20

  

Také k dispozici: Unified diff