-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
c1be11d
commit c550453
Showing
34 changed files
with
176 additions
and
60 deletions.
There are no files selected for viewing
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
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
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 |
---|---|---|
@@ -1,3 +1,77 @@ | ||
# Multi-part form data | ||
|
||
TODO: write this | ||
🧝♂️ I've made some adjustments you may want to know about. We now have a new | ||
resource route that's responsible for serving | ||
images: <InlineFile file="app/routes/resources+/images.$imageId.tsx" />. | ||
|
||
So now any image can be displayed by its ID via: `/resources/images/:imageId`. | ||
So I updated <InlineFile file="app/routes/users+/$username_+/notes.$noteId.tsx" /> | ||
to use this new route to display the images for notes. So that's all ready for | ||
us to start storing images for notes. | ||
|
||
Another thing I did to help prepare for your work is I put together a fancy | ||
`ImageChooser` component you can use for the user to have a nicer UX for | ||
selecting an image than the default file input. It's a bit more involved than | ||
you have time for, but feel free to explore how that's implemented if you've got | ||
time. You will be making some changes to it during the workshop. | ||
|
||
You'll find it at the bottom | ||
of <InlineFile file="app/routes/users+/$username_+/notes.$noteId_.edit.tsx" line="182" />. | ||
I also updated the loader to load the note's images if it already has images: | ||
|
||
<CodeFile | ||
file="app/routes/users+/$username_+/notes.$noteId_.edit.tsx" | ||
range="17-35" | ||
highlight="32" | ||
/> | ||
|
||
So you can use that to preload the images for the note if it already has images | ||
when the user goes to edit the note. | ||
|
||
As a reminder, you can check the Diff tab and select the previous solution step | ||
vs this problem step to see all the changes I made. | ||
|
||
Alright, with that background, I think you're ready to make your adjustments! | ||
Good luck! | ||
|
||
👨💼 Thanks Kellie! Alright, we need you to make adjustments so we can start | ||
uploading images to the notes page. We'll be making the minimal changes for this | ||
and we'll progressively improve it in the next steps. That means we'll be | ||
ignoring some of the TypeScript stuff (sorry Lily! 🦺😢). | ||
|
||
At a high-level, here's what you'll be adjusting: | ||
|
||
- Update the `encType` of the form so we can accept file uploads | ||
- Update the `type` on our file upload input so it's a file input | ||
- Properly parse the request in our action so it can handle the file upload | ||
using Remix's memory upload handler | ||
- Render a hidden input for the existing image ID if it does exist so it's | ||
preserved if the user's just wanting to update the alt text. | ||
|
||
Here's that example again of how to process the file in your action: | ||
|
||
```tsx | ||
import { | ||
unstable_createMemoryUploadHandler as createMemoryUploadHandler, | ||
unstable_parseMultipartFormData as parseMultipartFormData, | ||
} from '@remix-run/node' | ||
export const action = async ({ request }: ActionArgs) => { | ||
const uploadHandler = createMemoryUploadHandler({ | ||
maxPartSize: 1024 * 1024 * 5, // 5 MB | ||
}) | ||
const formData = await parseMultipartFormData(request, uploadHandler) | ||
|
||
const file = formData.get('avatar') | ||
|
||
// file is a "File" (https://mdn.io/File) polyfilled for node | ||
// ... etc | ||
} | ||
``` | ||
|
||
The emoji team (🐨💰🦺💣) will be in there to help guide you through this one. | ||
Enjoy! | ||
|
||
- [📜 `input[type=file]`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file) | ||
- [📜 `File`](https://developer.mozilla.org/en-US/docs/Web/API/File) | ||
- [📜 **`unstable_parseMultipartFormData`**](https://remix.run/docs/en/main/utils/parse-multipart-form-data) | ||
- [📜 **`unstable_createMemoryUploadHandler`**](https://remix.run/docs/en/main/utils/unstable-create-memory-upload-handler) |
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 |
---|---|---|
@@ -1,3 +1,12 @@ | ||
# Multi-part form data | ||
|
||
TODO: write this | ||
👨💼 Great work! To be honest, we're being a little hand-wavy on the bit around | ||
persisting the data. That's just out of scope for this workshop. It does highly | ||
depend on your application and where you choose to host your images. If you'd | ||
like to see how we're managing it in the app currently (not recommended for | ||
production), check <InlineFile file="app/utils/db.server.ts">`updateNote`</InlineFile>. | ||
|
||
We'll get to improving this in the future. | ||
|
||
We're missing some nice validation and our types aren't great, let's fix that | ||
next. |
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
50 changes: 49 additions & 1 deletion
50
exercises/04.file-upload/02.problem.file-validation/README.mdx
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 |
---|---|---|
@@ -1,3 +1,51 @@ | ||
# File Validation | ||
|
||
TODO: write this | ||
🦺 I'm not too pleased with the fact that we're just ignoring TypeScript. | ||
Remember: | ||
|
||
<callout-success> | ||
TypeScript isn't making your life **worse**. It's just showing you how **bad | ||
your life already is.** | ||
<br />– [me](https://twitter.com/kentcdodds/status/1540025247134429185) | ||
</callout-success> | ||
|
||
Currently, users could upload whatever they want to our server and we don't | ||
validate anything at all, so it could lead to pretty broken experiences. | ||
|
||
We've already got Zod setup in this form, we just need to add support for the | ||
`imageId`, `file`, and `altText` fields. | ||
|
||
To help you with the Zod schema, you may checkout | ||
[the Conform docs on File Uploads](https://conform.guide/file-upload). Here's | ||
a snippet from that example: | ||
|
||
```tsx | ||
const schema = z.object({ | ||
profile: z | ||
.instanceof(File) | ||
// When browser constructs a form data from an empty file input, a default file | ||
// entry would be created. we can validate this by checking the filename and size. | ||
.refine(file => file.name !== '' && file.size !== 0, 'Profile is required'), | ||
}) | ||
``` | ||
|
||
In our case, the file is optional since the user may just be updating an | ||
existing file. But we _do_ want to warn the user if they're going to try and | ||
upload a file that's too large, so for our `refine` call, we can just check that | ||
the `file.size` isn't too big. | ||
|
||
We'll get to actually _displaying_ errors later on. | ||
|
||
<callout-danger> | ||
If you're trying to submit the form and nothing is happening, it could be an | ||
error that's preventing the form from submitting. But you'll not see the | ||
errors until we add those. Until then, you can comment out the `onValidate` | ||
function to prevent client-side validation and check out errors in the network | ||
tab. | ||
</callout-danger> | ||
|
||
With that, you should be good to go on this one! | ||
|
||
- [📜 Conform File Uploads](https://conform.guide/file-upload) | ||
- [📜 Zod `instanceof`](https://zod.dev/?id=instanceof) | ||
- [📜 Zod `refine`](https://zod.dev/?id=refine) |
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
11 changes: 10 additions & 1 deletion
11
exercises/04.file-upload/02.solution.file-validation/README.mdx
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 |
---|---|---|
@@ -1,3 +1,12 @@ | ||
# File Validation | ||
|
||
TODO: write this | ||
🦺 I'm just so relieved to have everything typed and validated. | ||
|
||
👨💼 Great work! | ||
|
||
As mentioned, we're not yet displaying errors because we've not wired up Conform | ||
form utilities to our form. We'll be changing the structure a bit in the next | ||
exercise so that's why we're not doing that as part of the exercise. | ||
|
||
💯 If you've got some extra time, you can go ahead and wire the form fields up | ||
to `conform` so you can display the errors. |
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
Oops, something went wrong.