-
Notifications
You must be signed in to change notification settings - Fork 148
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* initial commit * start * tweaks * Update feedback.ts * Update debugFlags.ts * move logic into api layer * add v0 prefix for feedback * remove email * add minrows * don't show feedback on mobile --------- Co-authored-by: David Kircos <davidkircos@gmail.com>
- Loading branch information
1 parent
afc526f
commit 0232a5c
Showing
15 changed files
with
290 additions
and
15 deletions.
There are no files selected for viewing
9 changes: 9 additions & 0 deletions
9
quadratic-api/prisma/migrations/20230525192704_feedback/migration.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
-- CreateTable | ||
CREATE TABLE "QFeedback" ( | ||
"id" SERIAL NOT NULL, | ||
"feedback" TEXT NOT NULL, | ||
"created_date" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, | ||
"qUserId" INTEGER NOT NULL, | ||
|
||
CONSTRAINT "QFeedback_pkey" PRIMARY KEY ("id") | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
import express from 'express'; | ||
import { z } from 'zod'; | ||
import { Request as JWTRequest } from 'express-jwt'; | ||
import { PrismaClient } from '@prisma/client'; | ||
import { validateAccessToken } from '../middleware/auth'; | ||
import { get_user } from '../helpers/get_user'; | ||
|
||
const files_router = express.Router(); | ||
const prisma = new PrismaClient(); | ||
|
||
const RequestBodySchema = z.object({ | ||
feedback: z.string(), | ||
}); | ||
type RequestBody = z.infer<typeof RequestBodySchema>; | ||
|
||
files_router.post('/', validateAccessToken, async (request: JWTRequest, response) => { | ||
const { feedback }: RequestBody = RequestBodySchema.parse(request.body); | ||
const user = await get_user(request); | ||
|
||
await prisma.qFeedback.create({ | ||
data: { | ||
feedback, | ||
qUserId: user.id, | ||
created_date: new Date(), | ||
}, | ||
}); | ||
|
||
response.status(200).end(); | ||
}); | ||
|
||
export default files_router; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import { useState } from 'react'; | ||
import { | ||
Button, | ||
Dialog, | ||
DialogActions, | ||
DialogContent, | ||
DialogContentText, | ||
DialogTitle, | ||
IconButton, | ||
TextField, | ||
} from '@mui/material'; | ||
import { useTheme } from '@mui/system'; | ||
import { useRecoilState } from 'recoil'; | ||
import { editorInteractionStateAtom } from '../../../atoms/editorInteractionStateAtom'; | ||
import { BUG_REPORT_URL, DISCORD, TWITTER } from '../../../constants/urls'; | ||
import useLocalStorage from '../../../hooks/useLocalStorage'; | ||
import { useGlobalSnackbar } from '../../contexts/GlobalSnackbar'; | ||
import apiClientSingleton from '../../../api-client/apiClientSingleton'; | ||
import { SocialDiscord, SocialGithub, SocialTwitter } from '../../icons'; | ||
|
||
export const FeedbackMenu = () => { | ||
const [editorInteractionState, setEditorInteractionState] = useRecoilState(editorInteractionStateAtom); | ||
const { showFeedbackMenu } = editorInteractionState; | ||
// We'll keep the user's state around unless they explicitly cancel or get a successful submit | ||
const [value, setValue] = useLocalStorage('feedback-message', ''); | ||
const [loadState, setLoadState] = useState<'INITIAL' | 'LOADING' | 'LOAD_ERROR'>('INITIAL'); | ||
const theme = useTheme(); | ||
const { addGlobalSnackbar } = useGlobalSnackbar(); | ||
|
||
const closeMenu = () => { | ||
setEditorInteractionState((state) => ({ | ||
...state, | ||
showFeedbackMenu: false, | ||
})); | ||
}; | ||
|
||
const onSubmit = async () => { | ||
setLoadState('LOADING'); | ||
const success = await apiClientSingleton.postFeedback(value); | ||
if (success) { | ||
setValue(''); | ||
closeMenu(); | ||
addGlobalSnackbar('Feedback submitted! Thank you.'); | ||
} else { | ||
setLoadState('LOAD_ERROR'); | ||
} | ||
}; | ||
|
||
const isLoading = loadState === 'LOADING'; | ||
const hasError = loadState === 'LOAD_ERROR'; | ||
|
||
return ( | ||
<Dialog open={showFeedbackMenu} onClose={closeMenu} fullWidth maxWidth={'sm'} BackdropProps={{ invisible: true }}> | ||
<DialogTitle sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}> | ||
<span>Provide feedback</span> | ||
<span style={{ display: 'flex', alignItems: 'center', gap: theme.spacing(1) }}> | ||
<IconButton href={BUG_REPORT_URL} target="_blank" color="inherit"> | ||
<SocialGithub /> | ||
</IconButton> | ||
<IconButton href={TWITTER} target="_blank" color="inherit"> | ||
<SocialTwitter /> | ||
</IconButton> | ||
<IconButton href={DISCORD} target="_blank" color="inherit"> | ||
<SocialDiscord /> | ||
</IconButton> | ||
</span> | ||
</DialogTitle> | ||
<DialogContent> | ||
<DialogContentText>How can we make Quadratic better? Reach out, or let us know below:</DialogContentText> | ||
|
||
<TextField | ||
InputLabelProps={{ shrink: true }} | ||
id="feedback" | ||
variant="outlined" | ||
disabled={isLoading} | ||
fullWidth | ||
minRows={4} | ||
multiline | ||
sx={{ mt: theme.spacing(2) }} | ||
autoFocus | ||
value={value} | ||
onFocus={(event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { | ||
// If an error exists, reset | ||
if (loadState === 'LOAD_ERROR') { | ||
setLoadState('INITIAL'); | ||
} | ||
// Ensure cursor position to the end on focus | ||
if (value.length > 0) { | ||
event.target.setSelectionRange(value.length, value.length); | ||
} | ||
}} | ||
// Allow submit via keyboard CMD + Enter | ||
onKeyDown={(event) => { | ||
if ((event.metaKey || event.ctrlKey) && event.key === 'Enter') { | ||
onSubmit(); | ||
} | ||
}} | ||
onChange={(event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => { | ||
setValue(event.target.value); | ||
}} | ||
{...(hasError ? { error: true, helperText: 'Failed to send. Try again.' } : {})} | ||
/> | ||
</DialogContent> | ||
<DialogActions> | ||
<Button | ||
variant="text" | ||
color="inherit" | ||
onClick={() => { | ||
setValue(''); | ||
closeMenu(); | ||
}} | ||
disabled={isLoading} | ||
> | ||
Cancel | ||
</Button> | ||
<Button | ||
variant="text" | ||
sx={{ mr: theme.spacing(1) }} | ||
onClick={onSubmit} | ||
disabled={value.length === 0 || isLoading} | ||
> | ||
{isLoading ? 'Submitting…' : 'Submit'} | ||
</Button> | ||
</DialogActions> | ||
</Dialog> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
import { FeedbackMenu } from './FeedbackMenu'; | ||
export default FeedbackMenu; |
Oops, something went wrong.
0232a5c
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
quadratic – ./
quadratic-git-main-quadratic.vercel.app
quadratic-quadratic.vercel.app
quadratic-nu.vercel.app