Skip to content

Commit

Permalink
feat: Upload Widget Docs & Simplification (#55)
Browse files Browse the repository at this point in the history
# Description

<!-- Include a summary of the change made and also list the dependencies
that are required if any -->

## Issue Ticket Number

<!-- Specifiy which issue this fixes by referencing the issue number
(`#11`) or issue URL. -->
<!-- Example: Fixes
#1 -->

Fixes #54 

## Type of change

<!-- Please select all options that are applicable. -->

- [ ] Bug fix (non-breaking change which fixes an issue)
- [ ] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] Fix or improve the documentation
- [ ] This change requires a documentation update


# Checklist

<!-- These must all be followed and checked. -->

- [ ] I have followed the contributing guidelines of this project as
mentioned in [CONTRIBUTING.md](/CONTRIBUTING.md)
- [ ] I have created an
[issue](https://github.com/colbyfayock/next-cloudinary/issues) ticket
for this PR
- [ ] I have checked to ensure there aren't other open [Pull
Requests](https://github.com/colbyfayock/next-cloudinary/pulls) for the
same update/change?
- [ ] I have performed a self-review of my own code
- [ ] I have run tests locally to ensure they all pass
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes needed to the documentation
  • Loading branch information
colbyfayock authored Oct 31, 2022
1 parent d1c637b commit 5b1492f
Show file tree
Hide file tree
Showing 15 changed files with 345 additions and 142 deletions.
1 change: 0 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ To work on the project, you need to have an active Cloudinary account. With the
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="<Your Cloudinary Cloud Name>"
NEXT_PUBLIC_CLOUDINARY_API_KEY="<Your Cloudinary API Key>"
CLOUDINARY_API_SECRET="<Your Cloudinary API Secret>"
NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET="<Your Cloudinary Upload Preset>"
```

> Note: The Cloudinary account can be free, but some features may not work beyond free tier like Background Removal
Expand Down
1 change: 0 additions & 1 deletion docs/.env.example
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME="<Your Cloud Name (Required)>"
NEXT_PUBLIC_CLOUDINARY_API_KEY="<Your API Key (For Uploads)>"
CLOUDINARY_API_SECRET="<Your API Secret (For Uploads)>"
NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET="<Your Upload Preset (For Uploads)>"
NEXT_PUBLIC_CLOUDINARY_EXAMPLES_DIRECTORY="<Your Directory (Optional)>"
21 changes: 7 additions & 14 deletions docs/pages/components/clduploadbutton/basic-usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,16 @@ import OgImage from '../../../components/OgImage';

# Getting Started with CldUploadButton

The CldUploadButton creates a button that uses an instance of the [Cloudinary Upload Widget](https://cloudinary.com/documentation/upload_widget) to give you an easy way to add upload capabilities to your Next.js app.

At the core of it, CldUploadButton is a CldUploadWidget instance with a defined UI (a button). The same concepts apply, including having the option of using Signed or Unsigned uploads.

[Read more about CldUploadWidget.](/components/clduploadwidget/basic-usage)

## Basic Usage

```jsx
<UploadButton
signed={false}
options={{
cloudName: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME,
uploadPreset:
process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET,
}}
onUpload={(error, result) => {
/* Do Something With the Error or Result */
}}
className={styles.uploadButton}
>
<span>Upload Image</span>
</UploadButton>
<UploadButton uploadPreset="next-cloudinary-unsigned" />
```

## Learn More about CldUploadButton
Expand Down
14 changes: 14 additions & 0 deletions docs/pages/components/clduploadbutton/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,17 @@ import OgImage from '../../../components/OgImage';
/>

# CldUploadButton Configuration

## Props

| Prop Name | Type | Example |
|--------------------|--------------------|----------------------------------------|
| onClick | function | `function (event) { }` |
| onUpload | function | `function (error, result, widget) { }` |
| options | object | `{ encryption: {...} }` |
| signatureEndpoint | string | `"/api/sign-cloudinary-params.js"` |
| uploadPreset | string | `"my-upload-preset"` |

`children` are rendered "as is" inside of the `<button>` element if provided, otherwise, the button will include a label of "Upload".

The remaining props are spread onto the `<button>` element for full control of the UI.
68 changes: 53 additions & 15 deletions docs/pages/components/clduploadbutton/examples.mdx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useState } from 'react';
import Head from 'next/head';
import Callout from 'nextra-theme-docs/callout';

Expand All @@ -23,23 +24,60 @@ import styles from '../../../styles/Docs.module.scss';

## Effects

export const UnsignedUpload = () => {
const [resource, setResource] = useState();
return (
<>
<CldUploadButton
className={styles.button}
onUpload={(error, result, widget) => {
setResource(result?.info);
widget.close();
}}
uploadPreset="next-cloudinary-unsigned"
/>

<h3>Unsigned</h3>

<p>URL: { resource?.secure_url }</p>
</>
)
}

export const SignedUpload = () => {
const [resource, setResource] = useState();
return (
<>
<CldUploadButton
className={styles.button}
onUpload={(error, result, widget) => {
setResource(result?.info);
widget.close();
}}
signatureEndpoint="/api/sign-cloudinary-params"
uploadPreset="next-cloudinary-signed"
/>

<h3>Signed</h3>

<p>URL: { resource?.secure_url }</p>
</>
)
}

<ImageGrid>
<li>
<CldUploadButton
signed={false}
options={{
cloudName: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME,
uploadPreset:
process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET,
}}
onUpload={(error, result) => {
/* Do Something With the Error or Result */
}}
className={styles.uploadButton}
>
<span>Upload Image</span>
</CldUploadButton>
<UnsignedUpload />

### Unsigned
</li>
</ImageGrid>
<li>
<SignedUpload />

### Signed
</li>
</ImageGrid>

<Callout emoji={false}>
Button styles are not included as part of CldUploadButton and are only applied for this demo.
</Callout>
73 changes: 47 additions & 26 deletions docs/pages/components/clduploadwidget/basic-usage.mdx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Head from 'next/head';
import Callout from 'nextra-theme-docs/callout';

import OgImage from '../../../components/OgImage';

Expand All @@ -15,62 +16,82 @@ import OgImage from '../../../components/OgImage';

# Getting Started with CldUploadWidget

The CldUploadWidget creates a new instance of the [Cloudinary Upload Widget](https://cloudinary.com/documentation/upload_widget) giving you an easy way to add upload capabilities to your Next.js app.

It works by using the Next.js [Script](https://nextjs.org/docs/api-reference/next/script) component to load the external dependency and initialize the widget.

## Basic Usage

The CldUploadWidget will not render any UI by default. It will instead only render what's returned from the child function (see more below).

There are two options when using the CldUploadWidget: signed and unsigned. These options allow you to control the amount of security and restrictions you place on uploads.

<Callout emoji={false}>
To learn more about signed and unsigned upload, check out the [Cloudinary docs](https://cloudinary.com/documentation/upload_images#uploading_assets_to_the_cloud).
</Callout>

### Unsigned

To give unsigned access for upload, provide an upload preset as part of the component configuration.

<Callout emoji={false}>
Note: The upload preset requires that unsigned uploads are permitted.
</Callout>

Use the following to generate an unsigned upload widget:

```jsx
<CldUploadWidget
signed={false}
options={{
cloudName: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME,
uploadPreset:
process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET,
}}
onUpload={(error, result) => {
/* Do Something With the Error or Result */
}}
>
<CldUploadWidget uploadPreset="next-cloudinary-unsigned">
{({ open }) => {
function handleOnClick(e) {
e.preventDefault();
open();
}
return (
<button onClick={handleOnClick}>Upload an Image</button>
<button onClick={handleOnClick}>
Upload an Image
</button>
);
}}
</CldUploadWidget>
```

### Signed

Signing upload requests requires passing in an endpoint to the component.

You can do this by creating a serverless function that reads the parameters as the body and returns an object with the signature.

Use the following to generate an signed upload widget:

```jsx
<CldUploadWidget
signed={true}
signingEndpoint="/api/sign-cloudinary-params"
options={{
cloudName: process.env.NEXT_PUBLIC_CLOUDINARY_CLOUD_NAME, // Ex: mycloudname
uploadPreset:
process.env.NEXT_PUBLIC_CLOUDINARY_UPLOAD_PRESET, // Ex: myuploadpreset
apiKey: process.env.NEXT_PUBLIC_CLOUDINARY_API_KEY, // Ex: 1234567890
}}
onUpload={(error, result) => {
/* Do Something With the Error or Result */
}}
>
<CldUploadWidget signatureEndpoint="/api/sign-cloudinary-params">
{({ open }) => {
function handleOnClick(e) {
e.preventDefault();
open();
}
return (
<button onClick={handleOnClick}>Upload an Image</button>
<button onClick={handleOnClick}>
Upload an Image
</button>
);
}}
</CldUploadWidget>
```

Here's an example of how you could process the signature in an API endpoint that signs a request:

```js
const signature = cloudinary.utils.api_sign_request(body.paramsToSign, process.env.CLOUDINARY_API_SECRET);

res.status(200).json({
signature,
});
```

See a full example used with the Next Cloudinary docs: https://github.com/colbyfayock/next-cloudinary/blob/main/docs/pages/api/sign-cloudinary-params.js

## Learn More about CldUploadWidget
* [Configuration](/components/clduploadwidget/configuration)
* [Effects](/components/clduploadwidget/effects)
27 changes: 26 additions & 1 deletion docs/pages/components/clduploadwidget/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,29 @@ import OgImage from '../../../components/OgImage';
twitterTitle="CldUploadWidget Configuration"
/>

# CldUploadWidget Configuration
# CldUploadWidget Configuration

## Props

| Prop Name | Type | Example |
|--------------------|--------------------|----------------------------------------|
| onUpload | function | `function (error, result, widget) { }` |
| options | object | `{ encryption: {...} }` |
| signatureEndpoint | string | `"/api/sign-cloudinary-params.js"` |
| uploadPreset | string | `"my-upload-preset"` |

## Composing Widget UI

CldUploadWidget uses Render Props to pass options to the widget UI.

To make this work, use a function as the direct child of a CldWidget Instance:

```jsx
<CldUploadWidget>
{({ cloudinary, widget, open }) => {
// UI
}}
</CldUploadWidget>
```

The first and only argument is an object that contains instances of cloudinary, the widget, and an open function that controls displaying the Upload Widget UI.
Loading

1 comment on commit 5b1492f

@vercel
Copy link

@vercel vercel bot commented on 5b1492f Oct 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.