using chats instead of notes for the chat

This commit is contained in:
Carter 2024-12-05 20:53:57 -06:00
parent 9ec1956687
commit cf45fcb98a
9 changed files with 201 additions and 284 deletions

2
package-lock.json generated
View file

@ -4220,7 +4220,7 @@
}, },
"node_modules/protobuf-ts": { "node_modules/protobuf-ts": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#81a4e3f24369057b3d022ae0a8ef3e5fab58ea09", "resolved": "git+https://gitlab+deploy-token-50627:hv8mB4WkyvtjBpJKU1rN@gitlab.com/brandx/protobuf-ts.git#8c31044c11d0b97c40a253cc917a333f33c3cdf4",
"dependencies": { "dependencies": {
"protobufjs": "^6.8.8" "protobufjs": "^6.8.8"
} }

View file

@ -64,6 +64,7 @@ export default function UserWrapper(props: Props) {
let user_id = or(useAuth.user?.sub, "") let user_id = or(useAuth.user?.sub, "")
const loadUser = useCallback(() => { const loadUser = useCallback(() => {
if (!userAPI.getUserWithTeam) return;
if (hasFetched.current) return; if (hasFetched.current) return;
setLoading(true) setLoading(true)
userAPI.getUserWithTeam(user_id).then(resp => { userAPI.getUserWithTeam(user_id).then(resp => {

View file

@ -3,6 +3,16 @@ import { createRoot } from 'react-dom/client'
import './index.css' import './index.css'
import App from './App.tsx' import App from './App.tsx'
// I don't consider providing a disabled button to a Tooltip an error.
// console.error = (message) => {
// if (message.includes('You are providing a disabled `button` child to the Tooltip component.')) {
// return; // Suppress specific warning
// }
// console.error(message); // Other warnings still show
// console.info(message, "error"); // Other warnings still show
// };
createRoot(document.getElementById('root')!).render( createRoot(document.getElementById('root')!).render(
<StrictMode> <StrictMode>
<App /> <App />

View file

@ -1,4 +1,4 @@
import { Box, CircularProgress, Theme } from "@mui/material"; import { Box, CircularProgress } from "@mui/material";
import { useGlobalState, useNoteAPI, useTeamAPI } from "providers"; import { useGlobalState, useNoteAPI, useTeamAPI } from "providers";
import React from "react"; import React from "react";
import { useCallback } from "react"; import { useCallback } from "react";
@ -9,7 +9,6 @@ import ChatOutput from "./ChatOutput";
import { Note } from "models"; import { Note } from "models";
import { pond } from "protobuf-ts/pond"; import { pond } from "protobuf-ts/pond";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { makeStyles } from "@mui/styles";
interface Props { interface Props {
objectKey: string; objectKey: string;
@ -17,95 +16,73 @@ interface Props {
} }
export default function Chat(props: Props) { export default function Chat(props: Props) {
const [notes, setNotes] = useState<Note[]>([]); const [chats, setChats] = useState<pond.Chat[]>([]);
const { objectKey, type } = props; const { objectKey, type } = props;
const noteAPI = useNoteAPI(); const noteAPI = useNoteAPI();
const [notesLoaded, setNotesLoaded] = useState<boolean>(false); const [loaded, setLoaded] = useState<boolean>(false);
const [loading, setLoading] = useState<boolean>(false);
const [totalMessages, setTotalMessages] = useState(0); const [totalMessages, setTotalMessages] = useState(0);
const [scrollPos, setScrollPos] = useState(0); const [scrollPos, setScrollPos] = useState(0);
const [{ team }] = useGlobalState(); const [{ user }] = useGlobalState();
const [attachmentMap, setAttachmentMap] = useState<Map<string, pond.FileReference[]>>(new Map()); const [attachmentMap, setAttachmentMap] = useState<Map<string, pond.FileReference[]>>(new Map());
const teamAPI = useTeamAPI();
// const classes = useStyles();
const loadNotes = useCallback(() => { useEffect(() => {
let currentNotes: Note[] = notes; console.log(totalMessages)
noteAPI }, [totalMessages])
.listNotes(15, currentNotes.length, "desc", "timestamp", objectKey)
.then(resp => {
setNotesLoaded(true);
if (resp.data.notes.length < 1) {
return;
}
setTotalMessages(resp.data.total);
let tempNotes: Note[] = [];
let tempAttachmentMap: Map<string, pond.FileReference[]> = attachmentMap;
resp.data.notes.forEach(note => {
let n = Note.any(note);
tempNotes.push(n);
let refList = resp.data.attachments[n.key()];
if (refList) {
tempAttachmentMap.set(n.key(), refList.refs);
}
});
setScrollPos(tempNotes.length);
currentNotes = currentNotes.concat(tempNotes);
currentNotes.reverse();
setNotes(currentNotes);
setAttachmentMap(tempAttachmentMap);
if (type) { const loadChats = () => {
// Setting the note type for future use setLoading(true)
currentNotes.forEach(note => { noteAPI.listChats(10, chats.length, "desc", "timestamp", objectKey).then(resp => {
if (note.settings.objectType === pond.NoteType.NOTE_TYPE_UNKNOWN && type) { setChats(resp.data.chats ? resp.data.chats.reverse().concat(chats) : [])
note.settings.objectType = type; setTotalMessages(resp.data.total)
noteAPI.updateNote(note.settings); }).finally(() => {
} setLoading(false)
}); setLoaded(true)
// Update new chat viewed timestamp
if (type === pond.NoteType.NOTE_TYPE_TEAM) {
team.preferences.chatViewedTimestamp = moment().toISOString();
teamAPI.updatePreferences(team.key(), team.preferences);
}
}
}) })
.catch(_err => {}); }
}, [noteAPI, objectKey, notes, type, team, teamAPI, attachmentMap]);
const removeNote = (index: number) => { const removeNote = (index: number) => {
let n = notes; let c = chats
setTotalMessages(totalMessages - 1); setTotalMessages(totalMessages - 1);
n.splice(index, 1); c.splice(index, 1);
setNotes([...n]); setChats([...c])
}; };
const showNewNotes = (newNote: Note) => { const showNewNotes = (newNote: Note) => {
let n = notes; let note = pond.Note.create({
n.push(newNote); settings: newNote.settings,
setScrollPos(n.length); status: newNote.status,
setNotes([...n]); })
let profile = pond.UserProfile.create({
name: user.name(),
avatar: user.settings.avatar,
})
let permissions = [
pond.Permission.PERMISSION_READ,
pond.Permission.PERMISSION_WRITE,
]
let c = chats;
c.push({
note: note,
profile: profile,
permissions: permissions
} as any)
setChats([...c])
}; };
useEffect(() => { useEffect(() => {
if (!notesLoaded) { loadChats()
loadNotes(); }, []);
}
// setNotesLoaded(true);
}, [notesLoaded, loadNotes]);
const loadMore = () => { const loadMore = () => {
let n = notes; loadChats();
n.reverse();
setNotes(n);
loadNotes();
}; };
return ( return (
<React.Fragment> <React.Fragment>
{!notesLoaded ? ( { loading && !loaded ? (
<Box marginTop={"51%"} marginLeft={"44%"}> <Box width="100%" height="100%" alignContent={"center"} textAlign={"center"} >
<CircularProgress /> <CircularProgress />
</Box> </Box>
) : ( ) : (
@ -114,7 +91,7 @@ export default function Chat(props: Props) {
<ChatOutput <ChatOutput
totalMessages={totalMessages} totalMessages={totalMessages}
attachmentMap={attachmentMap} attachmentMap={attachmentMap}
messages={notes} messages={chats}
scrollPos={scrollPos} scrollPos={scrollPos}
removeNoteMethod={removeNote} removeNoteMethod={removeNote}
loadMore={loadMore} loadMore={loadMore}

View file

@ -1,12 +1,6 @@
import { import {
Box, Box,
Button,
//DialogActions,
//DialogContent,
//DialogTitle,
Grid2 as Grid, Grid2 as Grid,
//IconButton,
TextareaAutosize,
Theme, Theme,
Typography, Typography,
useTheme useTheme
@ -15,10 +9,8 @@ import {
import { useGlobalState, useNoteAPI, useSnackbar } from "providers"; import { useGlobalState, useNoteAPI, useSnackbar } from "providers";
import React, { useState } from "react"; import React, { useState } from "react";
// import { getThemeType } from "theme"; // import { getThemeType } from "theme";
import ChatIcon from "@mui/icons-material/Chat";
import { Note } from "models"; import { Note } from "models";
import { pond } from "protobuf-ts/pond"; import { pond } from "protobuf-ts/pond";
import { getThemeType } from "theme/themeType";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
//import { AttachFile } from "@material-ui/icons"; //import { AttachFile } from "@material-ui/icons";
//import ResponsiveDialog from "common/ResponsiveDialog"; //import ResponsiveDialog from "common/ResponsiveDialog";
@ -134,47 +126,6 @@ export default function ChatInput(props: Props) {
clearEntry(); clearEntry();
}; };
/**
* Dialog to select attachments
* postponing note attachments until notes can be overhauled to be more in line with the rest of the objects
* @returns
*/
// const attachmentDialog = () => {
// return (
// <ResponsiveDialog
// open={attachmentDialogOpen}
// onClose={() => {
// setAttachmentDialogOpen(false);
// }}>
// <DialogTitle>Add Attachments</DialogTitle>
// <DialogContent>
// <FileUploader
// uploadStart={() => {
// setUploadingFile(true);
// }}
// uploadEnd={(fileID, fileName) => {
// setUploadingFile(false);
// if (fileID && fileName) {
// let f = cloneDeep(uploadedFiles);
// f.set(fileID, fileName);
// setUploadedFiles(f);
// }
// }}
// />
// </DialogContent>
// <DialogActions>
// <Button
// disabled={uploadingFile}
// onClick={() => {
// setAttachmentDialogOpen(false);
// }}>
// Close
// </Button>
// </DialogActions>
// </ResponsiveDialog>
// );
// };
return ( return (
<React.Fragment> <React.Fragment>
<Grid <Grid
@ -185,11 +136,6 @@ export default function ChatInput(props: Props) {
justifyContent="space-between" justifyContent="space-between"
spacing={1} spacing={1}
style={{ marginTop: theme.spacing(1) }}> style={{ marginTop: theme.spacing(1) }}>
{/* <Grid>
<Button onClick={validateMessage} variant="contained" color="primary">
<ChatIcon />
</Button>
</Grid> */}
<Grid size={{ xs: 12 }} > <Grid size={{ xs: 12 }} >
<Box className={classes.textAreaBox}> <Box className={classes.textAreaBox}>
<textarea <textarea
@ -201,15 +147,6 @@ export default function ChatInput(props: Props) {
/> />
</Box> </Box>
</Grid> </Grid>
{/* <Grid item xs={2}>
<IconButton
onClick={() => {
setAttachmentDialogOpen(true);
}}
color="primary">
<AttachFile />
</IconButton>
</Grid> */}
</Grid> </Grid>
<Typography>{Array.from(uploadedFiles.values()).toString()}</Typography> <Typography>{Array.from(uploadedFiles.values()).toString()}</Typography>
</React.Fragment> </React.Fragment>

View file

@ -17,24 +17,15 @@ import {
} from "@mui/material"; } from "@mui/material";
import { MoreVert, Person, Delete as DeleteIcon, } from "@mui/icons-material"; import { MoreVert, Person, Delete as DeleteIcon, } from "@mui/icons-material";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { useGlobalState, useNoteAPI, useSnackbar, useUserAPI } from "providers"; import { useGlobalState, useNoteAPI, useSnackbar } from "providers";
import React, { useState } from "react"; import React, { useState } from "react";
// import { getThemeType } from "theme";
// import { red } from "@material-ui/core/colors";
import { useEffect } from "react";
import { noteScope } from "models/Scope";
import { pond } from "protobuf-ts/pond"; import { pond } from "protobuf-ts/pond";
import { useCallback } from "react";
import { Note } from "models";
import { red } from "@mui/material/colors"; import { red } from "@mui/material/colors";
import { getThemeType } from "theme/themeType";
import { makeStyles } from "@mui/styles"; import { makeStyles } from "@mui/styles";
//import ImageViewer from "common/ImageViewer";
//import ResponsiveDialog from "common/ResponsiveDialog";
interface Props { interface Props {
index: number; index: number;
note: Note; chat: pond.Chat;
attachments?: pond.FileReference[]; attachments?: pond.FileReference[];
removeNoteMethod: (index: number) => void; removeNoteMethod: (index: number) => void;
} }
@ -44,11 +35,13 @@ const useStyles = makeStyles((theme: Theme) => ({
}, },
oddGrid: { oddGrid: {
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
padding: 4 // padding: 4,
padding: theme.spacing(1)
}, },
evenGrid: { evenGrid: {
backgroundColor: theme.palette.background.default, // backgroundColor: theme.palette.background.default,
padding: 4 // padding: 4
padding: theme.spacing(1)
}, },
textContainer: { textContainer: {
padding: theme.spacing(1), padding: theme.spacing(1),
@ -61,6 +54,8 @@ const useStyles = makeStyles((theme: Theme) => ({
} }
})) }))
/** /**
* Takes in a note and renders it * Takes in a note and renders it
* handles deleting of the note * handles deleting of the note
@ -71,40 +66,33 @@ export default function ChatMessage(props: Props) {
const [{ user }] = useGlobalState(); const [{ user }] = useGlobalState();
const noteAPI = useNoteAPI(); const noteAPI = useNoteAPI();
const { openSnack } = useSnackbar(); const { openSnack } = useSnackbar();
const [permissions, setPermissions] = useState<pond.Permission[]>([]);
const userAPI = useUserAPI();
const [dialog, setDialog] = useState(false); const [dialog, setDialog] = useState(false);
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null); const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
//const [fileListOpen, setFileListOpen] = useState(false);
const [name, setName] = useState(""); const avatar = props.chat.profile?.avatar
const [avatar, setAvatar] = useState(""); const name = props.chat.profile?.name
const timestamp = props.chat.note?.settings?.timestamp ? props.chat.note?.settings?.timestamp : undefined
const loadPermissions = useCallback(() => { const generatePermissions = () => {
let scope = noteScope(props.note.key()); let perms: pond.Permission[] = []
userAPI if (Array.isArray(props.chat.permissions)) {
.getUser(user.id(), scope) perms = props.chat.permissions.map((perm: unknown) => {
.then(resp => { const mappedPerm = pond.Permission[perm as keyof typeof pond.Permission];
setPermissions(resp.permissions); return mappedPerm; // Return null for invalid keys
}) }).filter(Boolean); // Optionally filter out any null values
.catch(_err => {}); } else {
userAPI console.error("data.permissions is not an array or does not exist");
.getProfile(props.note.settings.userId) perms = [];
.then(resp => { }
setName(resp.name); return perms
setAvatar(resp.avatar); }
}) const permissions = generatePermissions()
.catch(_err => {});
}, [props.note, userAPI, user]);
useEffect(() => {
loadPermissions();
}, [loadPermissions]);
const deleteMessage = () => { const deleteMessage = () => {
if (!props.chat?.note?.settings) return
setAnchorEl(null); setAnchorEl(null);
noteAPI noteAPI
.removeNote(props.note.key()) .removeNote(props.chat.note.settings.key)
.then(_resp => { .then(_resp => {
openSnack("Message Deleted"); openSnack("Message Deleted");
props.removeNoteMethod(props.index); props.removeNoteMethod(props.index);
@ -123,54 +111,6 @@ export default function ChatMessage(props: Props) {
setDialog(false); setDialog(false);
}; };
// const uploadedImages = () => {
// return (
// <Grid container direction="row">
// {props.attachments?.map(attachment => {
// if (attachment.metadata && attachment.metadata.contentType.split("/")[0] === "image") {
// return (
// <Grid item xs={4} key={attachment.uuid}>
// <ImageViewer image={attachment} width={"100%"} />
// </Grid>
// );
// } else {
// return undefined;
// }
// })}
// </Grid>
// );
// };
// const fileListDialog = () => {
// return (
// <ResponsiveDialog
// open={fileListOpen}
// onClose={() => {
// setFileListOpen(false);
// }}>
// <DialogTitle>Message Attachments</DialogTitle>
// <DialogContent>
// {props.attachments &&
// props.attachments.map(file => {
// if (file.metadata && file.metadata.contentType.includes("image/")) {
// //if the file is an image
// return (
// <Box margin={2} key={file.uuid}>
// <ImageViewer image={file} width={"100%"} />
// </Box>
// );
// } else {
// return undefined;
// }
// })}
// </DialogContent>
// <DialogActions>
// <Button onClick={() => setFileListOpen(false)}>Close</Button>
// </DialogActions>
// </ResponsiveDialog>
// );
// };
const messageMenu = () => { const messageMenu = () => {
return ( return (
<Menu <Menu
@ -236,28 +176,36 @@ export default function ChatMessage(props: Props) {
</Grid> </Grid>
<Grid justifyContent={"center"}> <Grid justifyContent={"center"}>
<Typography variant="caption" color="textSecondary"> <Typography variant="caption" color="textSecondary">
{moment(props.note.date()) {moment.unix(timestamp ? timestamp/1000: 0)
.tz(user.settings.timezone) .tz(user.settings.timezone ? user.settings.timezone : "Canada/Central")
.format("MMMM Do YYYY, h:mm:ss a")} .format("MMMM Do YYYY, h:mm:ss a")}
</Typography> </Typography>
</Grid> </Grid>
</Grid> </Grid>
<Grid size={{ xs: 12 }}> <Grid size={{ xs: 12 }}>
<Typography variant="body2" whiteSpace={"pre-line"}> <Typography variant="body2" whiteSpace={"pre-line"}>
{props.note.content()} {props.chat.note?.settings?.content}
</Typography> </Typography>
{/*load files and display attached images below the message */} {/*load files and display attached images below the message */}
</Grid> </Grid>
</Grid> </Grid>
<Grid padding={1}> <Grid padding={1}>
{/* delete button */} {/* delete button */}
{permissions.includes(pond.Permission.PERMISSION_WRITE) && ( {permissions.includes(pond.Permission.PERMISSION_WRITE) ? (
<IconButton <IconButton
onClick={(event: React.MouseEvent<HTMLButtonElement>) => onClick={(event: React.MouseEvent<HTMLButtonElement>) =>
setAnchorEl(event.currentTarget) setAnchorEl(event.currentTarget)
}> }>
<MoreVert /> <MoreVert />
</IconButton> </IconButton>
) : (
// <span>
// <Tooltip title="No permissions to edit or delete" disableInteractive>
<IconButton disabled>
<MoreVert />
</IconButton>
// </Tooltip>
// </span>
)} )}
</Grid> </Grid>
</Grid> </Grid>

View file

@ -1,12 +1,12 @@
import { useEffect, useRef } from "react"; import { useEffect, useRef } from "react";
import ChatMessage from "./ChatMessage"; import ChatMessage from "./ChatMessage";
import { Box, Button } from "@mui/material"; import { Box, Button, ListItemButton } from "@mui/material";
import { Note } from "models"; // import { Note } from "models";
import { pond } from "protobuf-ts/pond"; import { pond } from "protobuf-ts/pond";
interface Props { interface Props {
messages: Note[]; messages: pond.Chat[];
attachmentMap?: Map<string, pond.FileReference[]>; attachmentMap?: Map<string, pond.FileReference[]>;
totalMessages: number; totalMessages: number;
scrollPos: number; scrollPos: number;
@ -54,33 +54,31 @@ export default function ChatOutput(props: Props) {
let display = props.messages.map((curMessage, index) => ( let display = props.messages.map((curMessage, index) => (
<div key={index}> <div key={index}>
<ChatMessage <ChatMessage
note={curMessage} chat={curMessage}
index={index} index={index}
attachments={props.attachmentMap?.get(curMessage.key())} // attachments={props.attachmentMap?.get(curMessage.note?.settings?.key)}
removeNoteMethod={props.removeNoteMethod} removeNoteMethod={props.removeNoteMethod}
/> />
{props.scrollPos !== 0 && index === props.scrollPos && <ScrollTo />} {/* {props.scrollPos !== 0 && index === props.scrollPos && <ScrollTo />} */}
<ScrollTo />
</div> </div>
)); ));
return display; return display;
}; };
return ( return (
<Box <Box style={{
//height="85%"
// height="auto"
style={{
overflowY: "scroll", overflowY: "scroll",
overflowX: "hidden", overflowX: "hidden",
// borderRadius: "4px"
}}> }}>
{props.messages.length < props.totalMessages && ( {props.messages.length < props.totalMessages && (
<div style={{ textAlign: "center" }}> <ListItemButton onClick={seeMore} sx={{ justifyContent: "center"}}>
<Button onClick={seeMore}>See More</Button> <Button >See More</Button>
</div> </ListItemButton>
)} )}
{displayMessages()} {displayMessages()}
{props.scrollPos === 0 && <ScrollTo />} {props.scrollPos === 0 && <ScrollTo />}
{/* <ScrollTo/> */}
</Box> </Box>
); );
} }

View file

@ -17,8 +17,15 @@ import ObjectUsers from "user/ObjectUsers";
import UserAvatar from "user/UserAvatar"; import UserAvatar from "user/UserAvatar";
import { or } from "utils/types"; import { or } from "utils/types";
const useStyles = makeStyles((theme: Theme) => ({ interface StylesProps {
isMobile: boolean;
}
const useStyles = makeStyles<Theme, StylesProps>((theme: Theme) => {
// const isMobile = useMobile()
return ({
avatar: { avatar: {
// margin: theme.spacing(2),
width: theme.spacing(4), width: theme.spacing(4),
height: theme.spacing(4) height: theme.spacing(4)
}, },
@ -30,7 +37,10 @@ const useStyles = makeStyles((theme: Theme) => ({
color: getSignatureAccentColour(), color: getSignatureAccentColour(),
}, },
card: { card: {
height: theme.spacing(72) height: theme.spacing(72),
},
cardMobile: {
height: theme.spacing(48)
}, },
container: { container: {
display: 'flex', display: 'flex',
@ -53,13 +63,15 @@ const useStyles = makeStyles((theme: Theme) => ({
overflow: 'hidden', overflow: 'hidden',
textOverflow: 'ellipsis', textOverflow: 'ellipsis',
}, },
})); });
});
export default function TeamPage() { export default function TeamPage() {
const teamAPI = useTeamAPI(); const teamAPI = useTeamAPI();
const userAPI = useUserAPI(); const userAPI = useUserAPI();
const snackbar = useSnackbar() const snackbar = useSnackbar()
const classes = useStyles(); const isMobile = useMobile();
const classes = useStyles({isMobile});
const { state } = useLocation(); const { state } = useLocation();
// const { teamID } = useParams<{ teamID: string }>() as { teamID: string }; // const { teamID } = useParams<{ teamID: string }>() as { teamID: string };
const { teamID } = useParams<{ teamID: string }>(); const { teamID } = useParams<{ teamID: string }>();
@ -71,7 +83,6 @@ export default function TeamPage() {
const [userDialog, setUserDialog] = useState(false) const [userDialog, setUserDialog] = useState(false)
const teamKey = teamID ? teamID : ""; const teamKey = teamID ? teamID : "";
const isMobile = useMobile();
const getTeam = () => { const getTeam = () => {
if (teamKey.length < 1) return if (teamKey.length < 1) return
@ -119,7 +130,7 @@ export default function TeamPage() {
}; };
useEffect(() => { useEffect(() => {
if (state.team) return if (state && state.team) return
getTeam(); getTeam();
}, []); }, []);
@ -213,12 +224,12 @@ export default function TeamPage() {
/> />
<Grid2 container spacing={1}> <Grid2 container spacing={1}>
<Grid2 size={{ xs: 12, sm: 6 }}> <Grid2 size={{ xs: 12, sm: 6 }}>
<Card className={classes.card}> <Card className={ isMobile ? classes.cardMobile : classes.card }>
<Chat objectKey={team.key()} /> <Chat objectKey={team.key()} />
</Card> </Card>
</Grid2> </Grid2>
<Grid2 size={{ xs: 12, sm: 6 }}> <Grid2 size={{ xs: 12, sm: 6 }}>
<Card className={classes.card}> <Card className={ isMobile ? classes.cardMobile : classes.card }>
</Card> </Card>
</Grid2> </Grid2>

View file

@ -17,6 +17,15 @@ export interface INoteAPIContext {
asRoot?: boolean, asRoot?: boolean,
as?: string as?: string
) => Promise<AxiosResponse<pond.ListNotesResponse>>; ) => Promise<AxiosResponse<pond.ListNotesResponse>>;
listChats: (
limit: number,
offset: number,
order?: "asc" | "desc",
orderBy?: string,
search?: string,
asRoot?: boolean,
as?: string
) => Promise<AxiosResponse<pond.ListChatsResponse>>;
removeNote: (noteID: string) => Promise<AxiosResponse<pond.RemoveBinResponse>>; removeNote: (noteID: string) => Promise<AxiosResponse<pond.RemoveBinResponse>>;
} }
@ -72,12 +81,38 @@ export default function NoteProvider(props: PropsWithChildren<Props>) {
); );
}; };
const listChats = (
limit: number,
offset: number,
order?: "asc" | "desc",
orderBy?: string,
search?: string,
asRoot?: boolean,
as?: string
) => {
return get<pond.ListChatsResponse>(
pondURL(
"/chats" +
"?limit=" +
limit +
"&offset=" +
offset +
("&order=" + (order ? order : "asc")) +
("&by=" + (orderBy ? orderBy : "key")) +
(search ? "&search=" + search : "") +
(asRoot ? "&asRoot=" + asRoot.toString() : "") +
(as ? "&as=" + as : "")
)
);
};
return ( return (
<NoteAPIContext.Provider <NoteAPIContext.Provider
value={{ value={{
addNote, addNote,
getNote, getNote,
updateNote, updateNote,
listChats,
listNotes, listNotes,
removeNote removeNote
}}> }}>