Revize b225ffee
Přidáno uživatelem Fantič před téměř 2 roky(ů)
src/api/constants.ts | ||
---|---|---|
1 |
export const BASE_URL = 'http://147.228.173.159/api' |
|
1 |
export const BASE_URL = 'http://147.228.173.159/api' |
|
2 |
|
|
3 |
export const AVATAR_URL = 'http://147.228.173.159/static/avatars' |
|
4 |
|
|
5 |
export const IMAGE_URL = 'http:147.228.173.159/static/images' |
src/api/notesservice.ts | ||
---|---|---|
6 | 6 |
`/api/notes/?item_id[]=${itemId}` |
7 | 7 |
) |
8 | 8 |
} |
9 |
|
src/components/general/Dialogs.tsx | ||
---|---|---|
1 |
import { AlertDialog, Button } from "native-base"; |
|
2 |
|
|
3 |
export const ConfirmDialog = (props: { isShown: boolean, headerText?: string, bodyText?: string, confirmText?: string, confirmColor?: string, cancelRef?: any, onClose?: any, onSubmit?: any }): JSX.Element => ( |
|
4 |
<> |
|
5 |
{props.isShown && |
|
6 |
<AlertDialog leastDestructiveRef={props.cancelRef} isOpen={true} onClose={props.onClose}> |
|
7 |
<AlertDialog.Content> |
|
8 |
<AlertDialog.CloseButton /> |
|
9 |
<AlertDialog.Header>{props.headerText}</AlertDialog.Header> |
|
10 |
{props.bodyText && |
|
11 |
<AlertDialog.Body> |
|
12 |
{props.bodyText} |
|
13 |
</AlertDialog.Body> |
|
14 |
} |
|
15 |
<AlertDialog.Footer> |
|
16 |
<Button.Group space={2}> |
|
17 |
<Button variant="unstyled" colorScheme="coolGray" onPress={props.onClose} ref={props.cancelRef}> |
|
18 |
Cancel |
|
19 |
</Button> |
|
20 |
<Button colorScheme={props.confirmColor} onPress={props.onSubmit}> |
|
21 |
{props.confirmText} |
|
22 |
</Button> |
|
23 |
</Button.Group> |
|
24 |
</AlertDialog.Footer> |
|
25 |
</AlertDialog.Content> |
|
26 |
</AlertDialog>} |
|
27 |
</> |
|
28 |
|
|
29 |
) |
src/components/general/Icons.tsx | ||
---|---|---|
1 |
import { Icon } from "native-base" |
|
2 |
import { G, Path } from "react-native-svg" |
|
3 |
|
|
4 |
export const MessageIcon = (props: { color: string }): JSX.Element => ( |
|
5 |
<Icon> |
|
6 |
<G fill={props.color} stroke={props.color} strokeWidth={1}> |
|
7 |
<Path d="M15.854.146a.5.5 0 0 1 .11.54l-5.819 14.547a.75.75 0 0 1-1.329.124l-3.178-4.995L.643 7.184a.75.75 0 0 1 .124-1.33L15.314.037a.5.5 0 0 1 .54.11ZM6.636 10.07l2.761 4.338L14.13 2.576 6.636 10.07Zm6.787-8.201L1.591 6.602l4.339 2.76 7.494-7.493Z" /> |
|
8 |
</G> |
|
9 |
</Icon> |
|
10 |
) |
|
11 |
|
|
12 |
export const EditIcon = (props: { color: string }): JSX.Element => ( |
|
13 |
<Icon> |
|
14 |
<G fill={props.color} stroke={props.color} strokeWidth={1}> |
|
15 |
<Path d="M15.502 1.94a.5.5 0 0 1 0 .706L14.459 3.69l-2-2L13.502.646a.5.5 0 0 1 .707 0l1.293 1.293zm-1.75 2.456-2-2L4.939 9.21a.5.5 0 0 0-.121.196l-.805 2.414a.25.25 0 0 0 .316.316l2.414-.805a.5.5 0 0 0 .196-.12l6.813-6.814z" /> |
|
16 |
<Path fill-rule="evenodd" d="M1 13.5A1.5 1.5 0 0 0 2.5 15h11a1.5 1.5 0 0 0 1.5-1.5v-6a.5.5 0 0 0-1 0v6a.5.5 0 0 1-.5.5h-11a.5.5 0 0 1-.5-.5v-11a.5.5 0 0 1 .5-.5H9a.5.5 0 0 0 0-1H2.5A1.5 1.5 0 0 0 1 2.5v11z" /> |
|
17 |
</G> |
|
18 |
</Icon> |
|
19 |
) |
|
20 |
|
|
21 |
|
src/components/item/ItemView.tsx | ||
---|---|---|
4 | 4 |
import { Note } from "../../types/note" |
5 | 5 |
import LoadingBox from "../loading/LoadingBox" |
6 | 6 |
import NotesListView from "../notes/NotesListView" |
7 |
import { IMAGE_URL } from "../../api/constants" |
|
7 | 8 |
|
8 | 9 |
interface ItemDetailProps { |
9 | 10 |
item: Item, |
... | ... | |
54 | 55 |
{item.fullView && item.imageUrl && ( |
55 | 56 |
<Center background="primary.100" marginTop="5%"> |
56 | 57 |
<Text>Resembling object</Text> |
57 |
<Image size={250} alt="image" source={{ uri: `http:147.228.173.159/static/images/${item.imageUrl}` }} />
|
|
58 |
<Image size={250} alt="image" source={{ uri: IMAGE_URL + "/" + item.imageUrl }} />
|
|
58 | 59 |
</Center>)} |
59 | 60 |
{item.fullView && ( |
60 | 61 |
<Card shadow="1" marginTop="5%" marginBottom="5%"> |
... | ... | |
137 | 138 |
notesLoading ? |
138 | 139 |
<LoadingBox text="Notes loading" /> |
139 | 140 |
: |
140 |
<NotesListView notes={props.notes} /> |
|
141 |
<NotesListView notes={props.notes} handleDelete={() => console.log("TODO handle delete")} handleEdit={() => console.log("TODO handle edit")} handleReply={() => console.log("TODO handle reply")}/>
|
|
141 | 142 |
)} |
142 | 143 |
|
143 | 144 |
{/* item notes switch tab */} |
src/components/notes/NoteView.tsx | ||
---|---|---|
1 |
import { HStack, Box, Text } from "native-base"; |
|
1 |
import { HStack, Box, Text, Image, VStack, Flex, Pressable, DeleteIcon, Button, Center, Avatar, TextArea, AlertDialog } from "native-base";
|
|
2 | 2 |
import { Note } from "../../types/note"; |
3 |
import { EditIcon } from "../general/Icons"; |
|
4 |
import { AVATAR_URL } from "../../api/constants"; |
|
5 |
import { useState } from "react"; |
|
6 |
import React from "react"; |
|
7 |
import { ConfirmDialog } from "../general/Dialogs"; |
|
3 | 8 |
|
4 |
const NoteView = (props: { note: Note }) => { |
|
9 |
const NoteView = (props: { note: Note, handleReply: any, handleDelete: any, handleEdit: any, setConfirmDialog: any }) => {
|
|
5 | 10 |
const note = props.note; |
11 |
|
|
12 |
const [isEdited, setIsEdited] = useState(false); |
|
13 |
|
|
14 |
const [text, setText] = useState(note.note); |
|
15 |
|
|
16 |
const getDateString = (date: Date): string => { |
|
17 |
return date.toLocaleDateString("en-US", |
|
18 |
{ year: "numeric", month: "short", day: "2-digit", hour: "2-digit", minute: "2-digit", hour12: false } |
|
19 |
).replace(/,/g, "").replace(/ /g, "-").replace(/-(?!.*-)/, " "); |
|
20 |
} |
|
21 |
|
|
22 |
const getUsernameInitials = (username: string): string => { |
|
23 |
const words = username.split(" "); |
|
24 |
const initials = words.map(word => word.charAt(0).toUpperCase()); |
|
25 |
return initials.join(""); |
|
26 |
} |
|
27 |
|
|
28 |
const toggleEdited = () => { |
|
29 |
console.log("Toggle edit"); |
|
30 |
if (isEdited) { |
|
31 |
if (text == note.note) { |
|
32 |
setIsEdited(false); |
|
33 |
} |
|
34 |
else{ |
|
35 |
// confirm dialog |
|
36 |
props.setConfirmDialog({ |
|
37 |
headerText: "Cancel Edit", |
|
38 |
bodyText: "Are you sure you want to revert changes on this note?", |
|
39 |
confirmText: "Revert Changes", |
|
40 |
confirmColor: "danger", |
|
41 |
onClose: () => { props.setConfirmDialog(null) }, |
|
42 |
onSubmit: () => { setText(note.note); setIsEdited(false); props.setConfirmDialog(null) } |
|
43 |
}); |
|
44 |
} |
|
45 |
} |
|
46 |
else { |
|
47 |
setIsEdited(true); |
|
48 |
} |
|
49 |
} |
|
50 |
|
|
51 |
const deleteClicked = () => { |
|
52 |
props.setConfirmDialog({ |
|
53 |
headerText: "Delete Note", |
|
54 |
bodyText: "Are you sure you want to delete selected note?", |
|
55 |
confirmText: "Delete", |
|
56 |
confirmColor: "danger", |
|
57 |
onClose: () => { props.setConfirmDialog(null) }, |
|
58 |
onSubmit: () => { props.handleDelete(note.uuid);props.setConfirmDialog(null) } |
|
59 |
}); |
|
60 |
} |
|
61 |
|
|
62 |
const saveEdit = () => { |
|
63 |
if (note.note == text) { |
|
64 |
setIsEdited(false); |
|
65 |
} |
|
66 |
else { |
|
67 |
props.handleEdit(note.uuid, text); |
|
68 |
// todo |
|
69 |
setIsEdited(false); |
|
70 |
} |
|
71 |
} |
|
72 |
|
|
6 | 73 |
return ( |
7 |
<HStack> |
|
8 |
<Box width="5%" /> |
|
9 |
<Box width="30%"> |
|
10 |
<Text bold>{note.username}</Text> |
|
74 |
<HStack marginTop="5%"> |
|
75 |
<Box width="10" height="10" marginTop="2.5%"> |
|
76 |
<Avatar bg={note.noteColor} size="sm" source={{ |
|
77 |
uri: AVATAR_URL + "/" + note.avatarUrl |
|
78 |
}}> |
|
79 |
{getUsernameInitials(note.username)} |
|
80 |
</Avatar> |
|
11 | 81 |
</Box> |
82 |
<VStack width="97.5%"> |
|
83 |
<HStack> |
|
84 |
<Text bold width="60%"> |
|
85 |
{note.username} |
|
86 |
</Text> |
|
87 |
<Flex direction="row" alignItems="center" justify="flex-end" > |
|
88 |
<Text italic color="light.500"> |
|
89 |
{getDateString(note.createdTime)} |
|
90 |
</Text> |
|
91 |
</Flex> |
|
92 |
</HStack> |
|
93 |
<HStack> |
|
94 |
{isEdited ? |
|
95 |
<TextArea fontSize="14" width="72.5%" autoCompleteType={undefined} value={text} onChangeText={setText} /> |
|
96 |
: |
|
97 |
<Text width="72.5%"> |
|
98 |
{text} |
|
99 |
</Text> |
|
100 |
} |
|
101 |
|
|
102 |
{note.items && note.items.length > 0 && |
|
103 |
<Flex marginLeft="1.5%" direction="column" alignItems="flex-start" justify="flex-start" > |
|
104 |
<Button width={"16"} variant="outline" size="sm"> |
|
105 |
{note.items[0]} |
|
106 |
</Button> |
|
107 |
</Flex> |
|
12 | 108 |
|
13 |
<Text>{note.note}</Text> |
|
109 |
} |
|
110 |
</HStack> |
|
111 |
<HStack> |
|
112 |
{/* () => props.handleEdit(note.uuid, text) */} |
|
113 |
{props.handleReply != null && |
|
114 |
<Pressable onPress={() => props.handleReply(note.uuid, note.username)}> |
|
115 |
<Text color="light.500">Reply</Text> |
|
116 |
</Pressable>} |
|
117 |
<Flex width="82.5%" direction="row" alignItems="center" justify="flex-end" marginTop="0.5%"> |
|
118 |
{props.handleEdit != null && |
|
119 |
isEdited ? |
|
120 |
<> |
|
121 |
<Pressable onPress={saveEdit} marginRight="5%"> |
|
122 |
<Text color="light.500">Save</Text> |
|
123 |
</Pressable> |
|
124 |
<Pressable onPress={toggleEdited} marginRight="18.5%"> |
|
125 |
<Text color="light.500">Cancel</Text> |
|
126 |
</Pressable> |
|
127 |
</> |
|
128 |
: |
|
129 |
<Pressable onPress={toggleEdited} marginRight={"5%"}> |
|
130 |
<EditIcon color="light.500" /> |
|
131 |
</Pressable>} |
|
132 |
{props.handleDelete != null && |
|
133 |
<Pressable onPress={deleteClicked}> |
|
134 |
<DeleteIcon /> |
|
135 |
</Pressable>} |
|
136 |
</Flex> |
|
137 |
</HStack> |
|
138 |
</VStack> |
|
14 | 139 |
</HStack> |
15 | 140 |
); |
16 | 141 |
} |
src/components/notes/NotesListView.tsx | ||
---|---|---|
1 |
import { Center, VStack, Box, Text, HStack } from "native-base"; |
|
1 |
import { Center, VStack, Box, Text, HStack, ScrollView } from "native-base";
|
|
2 | 2 |
import { Note } from "../../types/note"; |
3 | 3 |
import NoteView from "./NoteView"; |
4 | 4 |
|
5 |
const NotesListView = (props: { notes: Note[] }) => {
|
|
5 |
const NotesListView = (props: { notes: Note[], handleReply : any, handleDelete : any, handleEdit : any, setConfirmDialog: any}) => {
|
|
6 | 6 |
const notes = props.notes; |
7 | 7 |
return ( |
8 |
<VStack>
|
|
8 |
<ScrollView>
|
|
9 | 9 |
{ |
10 | 10 |
notes && notes.length > 0 ? ( |
11 | 11 |
<VStack> |
12 | 12 |
{notes.map((note, index) => ( |
13 |
<NoteView key={index} note={note}/> |
|
13 |
<NoteView key={index} note={note} handleReply={props.handleReply} handleDelete={props.handleDelete} handleEdit={props.handleEdit} setConfirmDialog={props.setConfirmDialog}/>
|
|
14 | 14 |
))} |
15 | 15 |
</VStack> |
16 | 16 |
) : ( |
17 | 17 |
<Text>There are no notes.</Text> |
18 | 18 |
) |
19 | 19 |
} |
20 |
</VStack>
|
|
20 |
</ScrollView>
|
|
21 | 21 |
); |
22 | 22 |
} |
23 | 23 |
|
src/pages/NotesViewPage.tsx | ||
---|---|---|
2 | 2 |
import { log } from "../logging/logger" |
3 | 3 |
import { DrawerScreenProps } from "@react-navigation/drawer" |
4 | 4 |
import { RootDrawerParamList } from "../components/Navigation" |
5 |
import { Box, Button, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, FormControl, HStack, Heading, Input, MinusIcon, Popover, ScrollView, Switch, Text, VStack } from "native-base"
|
|
5 |
import { Box, Button, ChevronDownIcon, ChevronUpIcon, CloseIcon, Flex, HStack, Icon, IconButton, MinusIcon, Popover, Pressable, ScrollView, Switch, Text, TextArea, VStack } from "native-base"
|
|
6 | 6 |
import { SortOptions } from "../types/general" |
7 |
import { current } from "@reduxjs/toolkit" |
|
8 |
|
|
7 |
import { Note } from "../types/note" |
|
8 |
import NotesListView from "../components/notes/NotesListView" |
|
9 |
import { G, Path } from "react-native-svg" |
|
10 |
import { MessageIcon } from "../components/general/Icons" |
|
11 |
import { ConfirmDialog } from "../components/general/Dialogs" |
|
9 | 12 |
const NotesViewPage = ({ route, navigation }: DrawerScreenProps<RootDrawerParamList, 'Notes'>) => { |
10 | 13 |
|
11 | 14 |
const [isSortOpen, setIsSortOpen] = useState(false); |
... | ... | |
13 | 16 |
const [myCommentsCheck, setMyCommentsCheck] = useState(false); |
14 | 17 |
const [generalCommentsCheck, setGeneralCommentsCheck] = useState(true); |
15 | 18 |
|
19 |
const [replyingTo, setReplyingTo] = useState<{ messageId: string; userName: string } | null>(null); |
|
20 |
|
|
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 |
}]; |
|
156 |
|
|
157 |
const [confirmDialog, setConfirmDialog] = React.useState<{ |
|
158 |
headerText?: string; |
|
159 |
bodyText?: string; |
|
160 |
confirmText?: string; |
|
161 |
confirmColor?: string; |
|
162 |
cancelRef?: any; |
|
163 |
onClose?: () => void; |
|
164 |
onSubmit?: () => void; |
|
165 |
} | null>(null); |
|
16 | 166 |
|
17 | 167 |
const [sortSettings, setSortSettings] = useState({ |
18 | 168 |
items: SortOptions.None, |
... | ... | |
56 | 206 |
console.log("Get NOTES"); |
57 | 207 |
} |
58 | 208 |
|
59 |
return ( |
|
60 |
<ScrollView flex="1"> |
|
61 |
<Box width="90%" marginLeft="5%"> |
|
62 |
<VStack> |
|
63 |
<HStack marginTop="5%"> |
|
209 |
const handleReply = (messageId: string, userName: string) => { |
|
210 |
console.log("Handling reply: " + messageId); |
|
211 |
setReplyingTo({ messageId, userName }) |
|
212 |
} |
|
64 | 213 |
|
65 |
<Box width="30%"> |
|
66 |
<Popover // @ts-ignore |
|
67 |
trigger={triggerProps => { |
|
68 |
return <Button colorScheme="primary" {...triggerProps} onPress={() => setIsSortOpen(true)}> |
|
69 |
Sort Options |
|
70 |
</Button>; |
|
71 |
}} isOpen={isSortOpen} onClose={() => setIsSortOpen(!isSortOpen)}> |
|
72 |
<Popover.Content w="48"> |
|
73 |
<Popover.Arrow /> |
|
74 |
<Popover.CloseButton onPress={() => setIsSortOpen(false)} /> |
|
75 |
<Popover.Header>Sort Options</Popover.Header> |
|
76 |
<Popover.Body> |
|
77 |
<VStack> |
|
78 |
<Button size="md" variant="outline" onPress={() => handleSortChanged("items")} |
|
79 |
rightIcon={getSortIcon(sortSettings.items, "sm")} |
|
80 |
> |
|
81 |
Items</Button> |
|
82 |
<Button size="md" variant="outline" marginTop={"5%"} onPress={() => handleSortChanged("date")} |
|
83 |
rightIcon={getSortIcon(sortSettings.date, "sm")}> |
|
84 |
Date</Button> |
|
85 |
</VStack> |
|
86 |
</Popover.Body> |
|
87 |
<Popover.Footer justifyContent="flex-end"> |
|
88 |
<Button.Group space={2}> |
|
89 |
<Button colorScheme="coolGray" variant="ghost" onPress={() => setIsSortOpen(false)}> |
|
90 |
Cancel |
|
91 |
</Button> |
|
92 |
<Button colorScheme="success" onPress={() => { setIsSortOpen(false); getNotes() }}> |
|
93 |
Save |
|
94 |
</Button> |
|
95 |
</Button.Group> |
|
96 |
</Popover.Footer> |
|
97 |
</Popover.Content> |
|
98 |
</Popover> |
|
99 |
</Box> |
|
100 |
<VStack width="20%"> |
|
101 |
<HStack > |
|
102 |
<Text>My comments</Text> |
|
103 |
<Switch isChecked={myCommentsCheck} onValueChange={setMyCommentsCheck} size="md" /> |
|
104 |
</HStack> |
|
105 |
<HStack > |
|
106 |
<Text>General comments</Text> |
|
107 |
<Switch isChecked={generalCommentsCheck} onValueChange={setGeneralCommentsCheck} size="md" /> |
|
108 |
</HStack> |
|
109 |
</VStack> |
|
110 |
</HStack> |
|
214 |
const handleEdit = (messageId: string, newMessage: string) => { |
|
215 |
console.log("Handling edit:" + messageId + ", " + newMessage); |
|
216 |
} |
|
111 | 217 |
|
112 |
</VStack>
|
|
113 |
</Box>
|
|
114 |
</ScrollView>
|
|
218 |
const handleDelete = (messageId: string) => {
|
|
219 |
console.log("Handling delete:" + messageId);
|
|
220 |
}
|
|
115 | 221 |
|
222 |
return ( |
|
223 |
<Box width="90%" marginLeft="5%"> |
|
224 |
<VStack> |
|
225 |
<HStack marginTop="5%"> |
|
226 |
<Box width="30%" justifyContent={"center"}> |
|
227 |
<Popover // @ts-ignore |
|
228 |
trigger={triggerProps => { |
|
229 |
return <Button colorScheme="primary" {...triggerProps} onPress={() => setIsSortOpen(true)}> |
|
230 |
Sort Options |
|
231 |
</Button>; |
|
232 |
}} isOpen={isSortOpen} onClose={() => setIsSortOpen(!isSortOpen)}> |
|
233 |
<Popover.Content w="48"> |
|
234 |
<Popover.Arrow /> |
|
235 |
<Popover.CloseButton onPress={() => setIsSortOpen(false)} /> |
|
236 |
<Popover.Header>Sort Options</Popover.Header> |
|
237 |
<Popover.Body> |
|
238 |
<VStack> |
|
239 |
<Button size="md" variant="outline" onPress={() => handleSortChanged("items")} |
|
240 |
rightIcon={getSortIcon(sortSettings.items, "sm")} |
|
241 |
> |
|
242 |
Items</Button> |
|
243 |
<Button size="md" variant="outline" marginTop={"5%"} onPress={() => handleSortChanged("date")} |
|
244 |
rightIcon={getSortIcon(sortSettings.date, "sm")}> |
|
245 |
Date</Button> |
|
246 |
</VStack> |
|
247 |
</Popover.Body> |
|
248 |
<Popover.Footer justifyContent="flex-end"> |
|
249 |
<Button.Group space={2}> |
|
250 |
<Button colorScheme="coolGray" variant="ghost" onPress={() => setIsSortOpen(false)}> |
|
251 |
Cancel |
|
252 |
</Button> |
|
253 |
<Button colorScheme="success" onPress={() => { setIsSortOpen(false); getNotes() }}> |
|
254 |
Save |
|
255 |
</Button> |
|
256 |
</Button.Group> |
|
257 |
</Popover.Footer> |
|
258 |
</Popover.Content> |
|
259 |
</Popover> |
|
260 |
</Box> |
|
261 |
<VStack width="70%" space="0"> |
|
262 |
<Flex direction="row" alignItems="center" justify="flex-end"> |
|
263 |
<Text>My comments</Text> |
|
264 |
<Switch isChecked={myCommentsCheck} onValueChange={() => setMyCommentsCheck(!myCommentsCheck)} size="md" /> |
|
265 |
</Flex> |
|
266 |
<Flex direction="row" alignItems="center" justify="flex-end" marginTop="-7.5%"> |
|
267 |
<Text>General comments</Text> |
|
268 |
<Switch isChecked={generalCommentsCheck} onValueChange={() => setGeneralCommentsCheck(!generalCommentsCheck)} size="md" /> |
|
269 |
</Flex> |
|
270 |
</VStack> |
|
271 |
</HStack> |
|
272 |
<Box h={replyingTo != null ? "62.5%" : "67.5%"}> |
|
273 |
<NotesListView notes={notes} handleReply={handleReply} handleDelete={handleDelete} handleEdit={handleEdit} setConfirmDialog={setConfirmDialog} /> |
|
274 |
</Box> |
|
275 |
{replyingTo != null && |
|
276 |
<Flex direction="row" alignItems="center" justify="flex-end" h="5%" marginRight="10%"> |
|
277 |
<Text>Replying to {replyingTo.userName}</Text> |
|
278 |
<IconButton onPress={() => setReplyingTo(null)} size="sm" icon={<CloseIcon />} marginLeft="-1%"> |
|
279 |
</IconButton> |
|
280 |
</Flex> |
|
281 |
} |
|
282 |
<HStack h={replyingTo != null ? "20%" : "15%"} marginTop={replyingTo != null ? "0%" : "5%"}> |
|
283 |
<TextArea placeholder="Add comment" width="90%" autoCompleteType={undefined} ></TextArea> |
|
284 |
<VStack> |
|
285 |
<Box h={replyingTo != null ? "30%" : "45%"}></Box> |
|
286 |
<Box marginLeft="2"> |
|
287 |
<Button startIcon={<MessageIcon color="#FFF" />}></Button> |
|
288 |
</Box> |
|
289 |
</VStack> |
|
290 |
</HStack> |
|
291 |
</VStack> |
|
292 |
<ConfirmDialog {...confirmDialog} isShown={confirmDialog != null} cancelRef={cancelRef} /> |
|
293 |
</Box> |
|
116 | 294 |
); |
117 | 295 |
} |
118 | 296 |
|
src/types/note.ts | ||
---|---|---|
1 | 1 |
export interface Note { |
2 |
uuid: string |
|
2 | 3 |
username: string |
3 | 4 |
userId: string |
4 | 5 |
note: string // text |
... | ... | |
7 | 8 |
createdTime: Date |
8 | 9 |
updatedTime: Date |
9 | 10 |
noteColor: string |
10 |
} |
|
11 |
} |
|
12 |
|
Také k dispozici: Unified diff
re #10569: NotesView: interface implementation