129 lines
4.3 KiB
TypeScript
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 & 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
|