Files
cadhub/app/web/src/components/EncodedUrl/ExternalScript.tsx

129 lines
4.3 KiB
TypeScript

import { useState } from 'react'
import { useIdeContext } from 'src/helpers/hooks/useIdeContext'
import { cadPackageConfigs } from 'src/components/CadPackage/CadPackage'
import OutBound from 'src/components/OutBound/OutBound'
import { prepareEncodedUrl, makeExternalUrl } from './helpers'
import { copyTextToClipboard } from 'src/helpers/clipboard'
import { useRender } from 'src/components/IdeWrapper/useRender'
import { toast } from '@redwoodjs/web/toast'
const ExternalScript = () => {
const { state, thunkDispatch } = useIdeContext()
const handleRender = useRender()
const [rawUrl, setRawUrl] = useState('')
const [script, setScript] = useState('')
const [asyncState, setAsyncState] = useState<
'INIT' | 'SUCCESS' | 'ERROR' | 'LOADING'
>('INIT')
const cadName = cadPackageConfigs[state.ideType].label
const onPaste: React.ClipboardEventHandler<HTMLInputElement> = async ({
clipboardData,
}) => {
const url = clipboardData.getData('Text')
processUserUrl(url)
}
const onChange: React.ChangeEventHandler<HTMLInputElement> = async ({
target,
}) => setRawUrl(target.value)
const onKeyDown = async ({ key, target }) =>
key === 'Enter' && processUserUrl(target.value)
async function processUserUrl(url: string) {
setRawUrl(url)
try {
setAsyncState('LOADING')
const response = await fetch(prepareEncodedUrl(url))
if (response.status === 404) throw new Error("couldn't find script")
const script2 = await response.text()
if (script2.startsWith('<!DOCTYPE html>'))
throw new Error('got html document, not a script')
setScript(script2)
setAsyncState('SUCCESS')
} catch (e) {
setAsyncState('ERROR')
toast.error(
"We had trouble with you're URL, are you sure it was correct?"
)
}
}
const onCopyRender: React.MouseEventHandler<HTMLButtonElement> = () => {
copyTextToClipboard(makeExternalUrl(rawUrl))
thunkDispatch({ type: 'updateCode', payload: script })
setTimeout(handleRender)
}
return (
<div className="p-4">
<p className="text-sm pb-4 border-b border-gray-700">
Paste an external url containing a {cadName} script to generate a new
CadHub url for this resource.{' '}
<OutBound
className="underline text-gray-500"
to="https://learn.cadhub.xyz/docs/general-cadhub/external-resource-url"
>
Learn more
</OutBound>{' '}
about this feature.
</p>
{['INIT', 'ERROR'].includes(asyncState) && (
<>
<p className="mt-4">Paste url</p>
<input
className="p-1 text-xs border border-ch-purple-450 w-full"
value={rawUrl}
onChange={onChange}
onPaste={onPaste}
onKeyDown={onKeyDown}
/>
</>
)}
{asyncState === 'ERROR' && (
<p className="text-sm text-red-800">That didn't work, try again.</p>
)}
{asyncState === 'LOADING' && (
<div className="h-10 relative">
<div className="inset-0 absolute flex items-center justify-center">
<div className="h-6 w-6 bg-pink-600 rounded-full animate-ping"></div>
</div>
</div>
)}
{asyncState === 'SUCCESS' && (
<>
<input
value={makeExternalUrl(rawUrl).replace(/^.+:\/\//g, '')}
readOnly
className="py-1 px-2 mt-4 text-xs border border-ch-purple-450 w-full"
/>
<button
className="w-full bg-ch-purple-450 hover:bg-ch-purple-400 py-1 text-gray-300"
onClick={() => copyTextToClipboard(makeExternalUrl(rawUrl))}
>
Copy URL
</button>
<div className="flex flex-col gap-2 pt-2">
<button
className="bg-gray-500 hover:bg-gray-600 p-1 px-2 text-gray-200"
onClick={onCopyRender}
>
Copy &amp; Render
</button>
<button
className="bg-gray-500 hover:bg-gray-600 p-1 px-2 text-gray-200"
onClick={() => {
setAsyncState('INIT')
setRawUrl('')
setScript('')
}}
>
Create another URL
</button>
</div>
</>
)}
</div>
)
}
export default ExternalScript