Skip to content

Commit

Permalink
feat: Action Props for CldUploadWidget (#487)
Browse files Browse the repository at this point in the history
Adds `*Action` callbacks (ex: onSucccessAction, onQueuesStartAction) to the CldUploadWidget for each Event that's made available through the Upload Widget.

The feature makes a few changes to the `CloudUploadWidget` and `CloudUploadButton` components by adding a new Action props where a server action can be passed as a function to be called during those events.

The Action will pass a single argument consisting of the results of the event.

Fixes #486
  • Loading branch information
JoshuaRotimi authored Jul 30, 2024
1 parent a8e6f63 commit ea29cf3
Show file tree
Hide file tree
Showing 6 changed files with 165 additions and 5 deletions.
2 changes: 1 addition & 1 deletion docs/pages/clduploadbutton/basic-usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export const UnsignedUpload = () => {
setResource(result?.info);
widget.close();
}}
uploadPreset="next-cloudinary-unsigned"
uploadPreset="<Upload Preset>"
/>
<p>URL: { resource?.secure_url }</p>
</>
Expand Down
2 changes: 1 addition & 1 deletion docs/pages/clduploadwidget/basic-usage.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ export const UnsignedUpload = ({ options }) => {
return (
<div className={`grid gap-6 ${resource ? 'grid-cols-2' : 'grid-cols-1'}`}>
<CldUploadWidget
uploadPreset="next-cloudinary-unsigned"
uploadPreset="<Your Upload Preset>"
onSuccess={(result, { widget }) => {
setResource(result?.info);
widget.close();
Expand Down
112 changes: 112 additions & 0 deletions docs/pages/clduploadwidget/configuration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,15 @@ uploadPreset="my-upload-preset"

## Events

Upload Widget events allow you to tap into different points of the upload lifecycle including
when an upload has completed, but also when it starts the queue and more. To allow interaction with
these events, CldUplodWidget provides both "Callback Functions" and "Actions".

The difference between the Callback Functions and the Actions is the second argument of options
that the Callback Functions receive. While Callback Functions pass in both the results along with the
widget instance and instance methods, Actions only pass along the results in order to support the
Server Actions workflow.

### Callback Functions

<Table
Expand Down Expand Up @@ -275,6 +284,109 @@ uploadPreset="my-upload-preset"
]}
/>


### Actions

<Table
columns={[
{
id: 'prop',
title: 'Prop'
},
{
id: 'type',
title: 'Type'
},
{
id: 'example',
title: 'Example'
},
{
id: 'more',
},
]}
data={[
{
prop: 'onAbortAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#abort">More Info</a>)
},
{
prop: 'onBatchCancelledAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#batch_cancelled">More Info</a>)
},
{
prop: 'onCloseAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#close_event">More Info</a>)
},
{
prop: 'onDisplayChangedAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#display_changed">More Info</a>)
},
{
prop: 'onPublicIdAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#publicid">More Info</a>)
},
{
prop: 'onQueuesEndAction',
type: 'function',
example: () => (<code>{`(results, options) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#queues_end">More Info</a>)
},
{
prop: 'onQueuesStartAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#queues_start">More Info</a>)
},
{
prop: 'onRetryAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#retry">More Info</a>)
},
{
prop: 'onShowCompletedAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#show_completed">More Info</a>)
},
{
prop: 'onSourceChangedAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#source_changed">More Info</a>)
},
{
prop: 'onSuccessAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#success">More Info</a>)
},
{
prop: 'onTagsAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#tags">More Info</a>)
},
{
prop: 'onUploadAddedAction',
type: 'function',
example: () => (<code>{`(results) => { }`}</code>),
more: () => (<a className="whitespace-nowrap" href="https://cloudinary.com/documentation/upload_widget_reference#upload_added">More Info</a>)
},
]}
/>

To learn more about the event callbacks and when they trigger, see: https://cloudinary.com/documentation/upload_widget_reference#events

**Example**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const CldUploadButton = ({
onError,
onOpen,
onUpload,
onAbort,
onAbort,
onBatchCancelled,
onClose,
onDisplayChanged,
Expand All @@ -30,6 +30,19 @@ const CldUploadButton = ({
options,
signatureEndpoint,
uploadPreset,
onAbortAction,
onBatchCancelledAction,
onCloseAction,
onDisplayChangedAction,
onPublicIdAction,
onQueuesEndAction,
onQueuesStartAction,
onRetryAction,
onShowCompletedAction,
onSourceChangedAction,
onSuccessAction,
onTagsAction,
onUploadAddedAction,
...props
}: CldUploadButtonProps) => {

Expand All @@ -55,6 +68,19 @@ const CldUploadButton = ({
options={options}
signatureEndpoint={signatureEndpoint}
uploadPreset={uploadPreset}
onAbortAction={onAbortAction}
onBatchCancelledAction={onBatchCancelledAction}
onCloseAction={onCloseAction}
onDisplayChangedAction={onDisplayChangedAction}
onPublicIdAction={onPublicIdAction}
onQueuesEndAction={onQueuesEndAction}
onQueuesStartAction={onQueuesStartAction}
onRetryAction={onRetryAction}
onShowCompletedAction={onShowCompletedAction}
onSourceChangedAction={onSourceChangedAction}
onSuccessAction={onSuccessAction}
onTagsAction={onTagsAction}
onUploadAddedAction={onUploadAddedAction}
>
{({ open, isLoading }) => {
function handleOnClick(e: React.MouseEvent<HTMLButtonElement, MouseEvent>) {
Expand Down
12 changes: 10 additions & 2 deletions next-cloudinary/src/components/CldUploadWidget/CldUploadWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
import { triggerOnIdle } from '../../lib/util';

import {
CldUploadEventAction,
CldUploadEventCallback,
CldUploadWidgetCloudinaryInstance,
CldUploadWidgetProps,
Expand All @@ -25,7 +26,7 @@ const WIDGET_WATCHED_EVENTS = [
'success',
];

const WIDGET_EVENTS: { [key: string]: string } = {
export const WIDGET_EVENTS: { [key: string]: string } = {
'abort': 'onAbort',
'batch-cancelled': 'onBatchCancelled',
'close': 'onClose',
Expand Down Expand Up @@ -251,7 +252,7 @@ const CldUploadWidget = ({
}

if ( typeof uploadResult?.event === 'string' ) {
if ( WIDGET_WATCHED_EVENTS.includes(uploadResult?.event) ) {
if ( WIDGET_WATCHED_EVENTS.includes(uploadResult?.event as string) ) {
setResults(uploadResult);
}

Expand All @@ -264,6 +265,13 @@ const CldUploadWidget = ({
...instanceMethods
});
}

const widgetEventAction = `${widgetEvent}Action` as keyof typeof props;

if ( widgetEventAction && typeof props[widgetEventAction] === 'function' ) {
const action = props[widgetEventAction] as CldUploadEventAction;
action(uploadResult);
}
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,19 @@ export interface CldUploadWidgetProps {
options?: CloudinaryUploadWidgetOptions;
signatureEndpoint?: URL | RequestInfo;
uploadPreset?: string;
onAbortAction?: CldUploadEventAction;
onBatchCancelledAction?: CldUploadEventAction;
onCloseAction?: CldUploadEventAction;
onDisplayChangedAction?: CldUploadEventAction;
onPublicIdAction?: CldUploadEventAction;
onQueuesEndAction?: CldUploadEventAction;
onQueuesStartAction?: CldUploadEventAction;
onRetryAction?: CldUploadEventAction;
onShowCompletedAction?: CldUploadEventAction;
onSourceChangedAction?: CldUploadEventAction;
onSuccessAction?: CldUploadEventAction;
onTagsAction?: CldUploadEventAction;
onUploadAddedAction?: CldUploadEventAction;
}

export type CldUploadWidgetPropsChildren = {
Expand All @@ -45,6 +58,7 @@ export type CldUploadWidgetPropsChildren = {
} & CloudinaryUploadWidgetInstanceMethods;

export type CldUploadEventCallback = (results: CloudinaryUploadWidgetResults, widget: CldUploadEventCallbackWidget) => void;
export type CldUploadEventAction = (results: CloudinaryUploadWidgetResults) => void;
export type CldUploadEventCallbackNoOptions = (results: CloudinaryUploadWidgetResults, widget: CldUploadWidgetWidgetInstance) => void;
export type CldUploadEventCallbackWidgetOnly = (widget: CldUploadWidgetWidgetInstance) => void;
export type CldUploadEventCallbackError = (error: CloudinaryUploadWidgetError, widget: CldUploadEventCallbackWidget) => void;
Expand Down

0 comments on commit ea29cf3

Please sign in to comment.