Skip to content

Commit

Permalink
Make example page options persistent (#208)
Browse files Browse the repository at this point in the history
  • Loading branch information
Murderlon authored Mar 14, 2024
1 parent 05d46da commit bc05066
Show file tree
Hide file tree
Showing 5 changed files with 112 additions and 54 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@docusaurus/plugin-client-redirects": "^3.0.0",
"@docusaurus/preset-classic": "^3.0.0",
"@mdx-js/react": "^3.0.0",
"@uidotdev/usehooks": "^2.4.1",
"@uppy/audio": "latest",
"@uppy/box": "latest",
"@uppy/core": "latest",
Expand Down
7 changes: 6 additions & 1 deletion src/pages/examples.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,15 @@
color: gray;
}

.main input[type='checkbox']:not(:checked):hover + label {
.main input[type='checkbox']:not(:checked, :disabled):hover + label {
color: black;
}

.main input[type='checkbox']:disabled:hover,
.main input[type='checkbox']:disabled:hover + label {
cursor: not-allowed;
}

.main select {
grid-column: 1 / 3;
background: white;
Expand Down
144 changes: 92 additions & 52 deletions src/pages/examples.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useCallback, useEffect, useReducer, useState } from 'react';
import { useLocalStorage } from '@uidotdev/usehooks';

import Layout from '@theme/Layout';
import Admonition from '@theme/Admonition';
Expand All @@ -10,6 +11,7 @@ import GoogleDrive from '@uppy/google-drive';
import Instagram from '@uppy/instagram';
import Dropbox from '@uppy/dropbox';
import OneDrive from '@uppy/onedrive';
import Facebook from '@uppy/facebook';
import Unsplash from '@uppy/unsplash';
import Url from '@uppy/url';
import Box from '@uppy/box';
Expand Down Expand Up @@ -42,42 +44,35 @@ const restrictions = {

type Action = { type: string; checked?: boolean; value: string };
type State = {
width?: number | string;
height: number | string;
small: boolean;
restrictions?: typeof restrictions;
disabled: boolean;
theme: 'light' | 'dark' | 'auto';
theme: string;
// theme: 'light' | 'dark' | 'auto';
plugins: string[];
enableGoldenRetriever: boolean;
};

const initialState: State = {
height: 570,
width: '100%',
small: false,
restrictions: null,
disabled: false,
theme: 'light',
plugins: [
'Webcam',
'GoogleDrive',
'Dropbox',
'Instagram',
'Url',
'OneDrive',
'Unsplash',
'Box',
'ImageEditor',
],
enableGoldenRetriever: false,
};

function reducer(state: State, action: Action) {
switch (action.type) {
case 'small':
if (action.checked) {
return { ...state, width: 400, height: 400 };
}
return { ...state, width: '100%', height: 570 };
return { ...state, small: action.checked };
case 'theme':
return { ...state, theme: action.checked ? 'dark' : 'light' };
case 'disabled':
Expand All @@ -95,9 +90,6 @@ function reducer(state: State, action: Action) {
...state,
plugins: state.plugins.filter((p) => p !== action.value),
};
case 'enableGoldenRetriever': {
return { ...state, enableGoldenRetriever: action.checked };
}
default:
return state;
}
Expand All @@ -111,34 +103,40 @@ const options = [
label: 'Google Drive',
value: 'GoogleDrive',
type: 'plugins',
defaultChecked: true,
},
{
label: 'Dropbox',
value: 'Dropbox',
type: 'plugins',
defaultChecked: true,
},
{
label: 'Instagram',
value: 'Instagram',
type: 'plugins',
defaultChecked: true,
title:
'Temporarily disabled until our credentials are approved again. You can still use the plugin yourself.',
disabled: true,
},
{
label: 'Facebook',
value: 'Facebook',
type: 'plugins',
title:
'Temporarily disabled until our credentials are approved again. You can still use the plugin yourself.',
disabled: true,
},
{ label: 'Url', value: 'Url', type: 'plugins', defaultChecked: true },
{ label: 'Url', value: 'Url', type: 'plugins' },
{
label: 'OneDrive',
value: 'OneDrive',
type: 'plugins',
defaultChecked: true,
},
{
label: 'Unsplash',
value: 'Unsplash',
type: 'plugins',
defaultChecked: true,
},
{ label: 'Box', value: 'Box', type: 'plugins', defaultChecked: true },
{ label: 'Box', value: 'Box', type: 'plugins' },
],
},
{
Expand All @@ -148,19 +146,16 @@ const options = [
label: 'Webcam',
value: 'Webcam',
type: 'plugins',
defaultChecked: true,
},
{
label: 'Audio',
value: 'Audio',
type: 'plugins',
defaultChecked: false,
},
{
label: 'Screencast',
value: 'ScreenCapture',
type: 'plugins',
defaultChecked: false,
},
],
},
Expand All @@ -176,58 +171,80 @@ const options = [
heading: 'Uppy',
options: [
{ label: 'Restrictions', type: 'restrictions' },
{ label: 'Golden Retriever', type: 'enableGoldenRetriever' },
{ label: 'Golden Retriever', value: 'GoldenRetriever', type: 'plugins' },
],
},
];

const Uppy = ({ state, locale }) => {
const createUppy = useCallback(() => {
const ret = new UppyCore({
const uppy = new UppyCore({
restrictions: state.restrictions,
locale,
debug: true,
})
.use(Webcam)
.use(ScreenCapture)
.use(Audio)
.use(ImageEditor, {})
.use(Tus, { endpoint })
.use(GoogleDrive, {
.use(Tus, { endpoint });

if (state.plugins.includes('Box')) {
uppy.use(Box, { companionUrl });
}
if (state.plugins.includes('Instagram')) {
uppy.use(Instagram, { companionUrl });
}
if (state.plugins.includes('Url')) {
uppy.use(Url, { companionUrl });
}
if (state.plugins.includes('Facebook')) {
uppy.use(Facebook, { companionUrl });
}
if (state.plugins.includes('OneDrive')) {
uppy.use(OneDrive, { companionUrl });
}
if (state.plugins.includes('Unsplash')) {
uppy.use(Unsplash, { companionUrl });
}
if (state.plugins.includes('Webcam')) {
uppy.use(Webcam);
}
if (state.plugins.includes('ScreenCapture')) {
uppy.use(ScreenCapture);
}
if (state.plugins.includes('Audio')) {
uppy.use(Audio);
}
if (state.plugins.includes('GoogleDrive')) {
uppy.use(GoogleDrive, {
companionUrl,
companionKeysParams: {
key: 'unused-key',
credentialsName: 'unused-credentials',
},
})
.use(Dropbox, { companionUrl })
.use(Instagram, { companionUrl })
.use(Url, { companionUrl })
.use(OneDrive, { companionUrl })
.use(Unsplash, { companionUrl })
.use(Box, { companionUrl });

if (state.enableGoldenRetriever) {
ret.use(GoldenRetriever);
});
}
if (state.plugins.includes('Dropbox')) {
uppy.use(Dropbox, { companionUrl });
}
if (state.plugins.includes('GoldenRetriever')) {
uppy.use(GoldenRetriever);
}

// Expose for easier debugging
globalThis.uppy = ret;
globalThis.uppy = uppy;

return ret;
return uppy;
}, [state, locale]);

const [uppy, setUppy] = useState(createUppy);
const [uppy, setUppy] = useState(() => createUppy());

useEffect(() => setUppy(createUppy()), [createUppy]);

return (
<div className={styles['uppy-wrapper']}>
<Dashboard
uppy={uppy}
width={state.width}
height={state.height}
plugins={state.plugins}
width={state.small ? 400 : '100%'}
height={state.small ? 400 : 570}
theme={state.theme}
disabled={state.disabled}
note={
Expand All @@ -245,8 +262,20 @@ const companionUrl = 'https://companion.uppy.io';
const endpoint = 'https://tusd.tusdemo.net/files/';

export default function Examples() {
const [state, dispatch] = useReducer(reducer, initialState);
// Silly trick to please Docusaurus with client-side hooks such as useLocalStorage
return <BrowserOnly>{() => <Page />}</BrowserOnly>;
}

function Page() {
const [state, setPersistentState] = useLocalStorage(
'uppy-examples-state',
initialState,
);
const [locale, setLocale] = useState(null);
const dispatch = useCallback(
(action: Action) => setPersistentState(reducer(state, action)),
[state],
);

return (
<Layout>
Expand Down Expand Up @@ -282,15 +311,24 @@ export default function Examples() {
className={styles['options-wrapper']}
>
{section.options.map(
({ label, value, type, defaultChecked }) => (
({ label, value, type, disabled, title }) => (
<div key={label}>
<input
type="checkbox"
id={label}
className={styles['framework-input']}
name="framework"
value={type}
defaultChecked={defaultChecked}
title={title}
checked={
// Forgive me for this logic
Array.isArray(state[type])
? state[type].includes(value)
: type === 'theme'
? state.theme === 'dark'
: state[type]
}
disabled={disabled}
onChange={(event) =>
dispatch({
type: type,
Expand All @@ -299,7 +337,9 @@ export default function Examples() {
})
}
/>
<label htmlFor={label}>{label}</label>
<label title={title} htmlFor={label}>
{label}
</label>
</div>
),
)}
Expand Down
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"extends": "@docusaurus/tsconfig",
"compilerOptions": {
"baseUrl": ".",
"resolveJsonModule": true
"resolveJsonModule": true,
"jsx": "react"
}
}
11 changes: 11 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4758,6 +4758,16 @@ __metadata:
languageName: node
linkType: hard

"@uidotdev/usehooks@npm:^2.4.1":
version: 2.4.1
resolution: "@uidotdev/usehooks@npm:2.4.1"
peerDependencies:
react: ">=18.0.0"
react-dom: ">=18.0.0"
checksum: 7f2e1dcfcaf654841150fde36556a257afb2240bca0145586b4e1e9385b85fea108a7dd17c2cbc4c2bd46d136126ffdf84267118933120fe54ad2e028c2dfa68
languageName: node
linkType: hard

"@ungap/structured-clone@npm:^1.0.0":
version: 1.2.0
resolution: "@ungap/structured-clone@npm:1.2.0"
Expand Down Expand Up @@ -17685,6 +17695,7 @@ __metadata:
"@tsconfig/docusaurus": "npm:^2.0.2"
"@typescript-eslint/eslint-plugin": "npm:^5.48.1"
"@typescript-eslint/parser": "npm:^5.48.1"
"@uidotdev/usehooks": "npm:^2.4.1"
"@uppy/audio": "npm:latest"
"@uppy/box": "npm:latest"
"@uppy/core": "npm:latest"
Expand Down

0 comments on commit bc05066

Please sign in to comment.