Init multiple types of cadPackages

This commit is contained in:
Kurt Hutten
2021-04-26 07:48:52 +10:00
parent 4ebf5921e2
commit 76a570b0c3
11 changed files with 159 additions and 84 deletions

View File

@@ -1,6 +1,7 @@
const express = require('express') const express = require('express')
var cors = require('cors') var cors = require('cors')
const axios = require('axios') const axios = require('axios')
const { restart } = require('nodemon')
const app = express() const app = express()
const port = 8080 const port = 8080
app.use(express.json()) app.use(express.json())
@@ -10,19 +11,29 @@ const invocationURL = (port) =>
`http://localhost:${port}/2015-03-31/functions/function/invocations` `http://localhost:${port}/2015-03-31/functions/function/invocations`
app.post('/openscad/preview', async (req, res) => { app.post('/openscad/preview', async (req, res) => {
const { data } = await axios.post(invocationURL(5052), { try {
body: Buffer.from(JSON.stringify(req.body)).toString('base64'), const { data } = await axios.post(invocationURL(5052), {
}) body: Buffer.from(JSON.stringify(req.body)).toString('base64'),
res.status(data.statusCode) })
res.send(data.body) res.status(data.statusCode)
res.send(data.body)
} catch (e) {
res.status(500)
res.send()
}
}) })
app.post('/cadquery/stl', async (req, res) => { app.post('/cadquery/stl', async (req, res) => {
console.log('making post request to 5060') console.log('making post request to 5060')
const { data } = await axios.post(invocationURL(5060), { try {
body: Buffer.from(JSON.stringify(req.body)).toString('base64'), const { data } = await axios.post(invocationURL(5060), {
}) body: Buffer.from(JSON.stringify(req.body)).toString('base64'),
res.status(data.statusCode) })
res.send(data.body) res.status(data.statusCode)
res.send(data.body)
} catch (e) {
res.status(500)
res.send()
}
}) })
app.listen(port, () => { app.listen(port, () => {

View File

@@ -13,6 +13,7 @@
] ]
}, },
"dependencies": { "dependencies": {
"@headlessui/react": "^1.0.0",
"@material-ui/core": "^4.11.0", "@material-ui/core": "^4.11.0",
"@monaco-editor/react": "^4.0.11", "@monaco-editor/react": "^4.0.11",
"@redwoodjs/auth": "^0.30.1", "@redwoodjs/auth": "^0.30.1",

View File

@@ -35,7 +35,7 @@ const Routes = () => {
) )
return ( return (
<Router> <Router>
<Route path="/dev-ide" page={DevIdePage} name="devIde" /> <Route path="/dev-ide/{cadPackage}" page={DevIdePage} name="devIde" />
<Route path="/policies/privacy-policy" page={PrivacyPolicyPage} name="privacyPolicy" /> <Route path="/policies/privacy-policy" page={PrivacyPolicyPage} name="privacyPolicy" />
<Route path="/policies/code-of-conduct" page={CodeOfConductPage} name="codeOfConduct" /> <Route path="/policies/code-of-conduct" page={CodeOfConductPage} name="codeOfConduct" />
<Route path="/account-recovery/update-password" page={UpdatePasswordPage} name="updatePassword" /> <Route path="/account-recovery/update-password" page={UpdatePasswordPage} name="updatePassword" />

View File

@@ -12,25 +12,6 @@ const IdeEditor = () => {
openScad: 'cpp', openScad: 'cpp',
} }
const scriptKey = 'encoded_script'
useEffect(() => {
// load code from hash if it's there
let hash
if (isBrowser) {
hash = window.location.hash
}
const [key, scriptBase64] = hash.slice(1).split('=')
if (key === scriptKey) {
const script = atob(scriptBase64)
thunkDispatch({ type: 'updateCode', payload: script })
}
}, [])
useEffect(() => {
if (isBrowser) {
window.location.hash = ''
}
}, [state.code])
function handleCodeChange(value, _event) { function handleCodeChange(value, _event) {
thunkDispatch({ type: 'updateCode', payload: value }) thunkDispatch({ type: 'updateCode', payload: value })
} }
@@ -61,6 +42,7 @@ const IdeEditor = () => {
<Suspense fallback={<div>. . . loading</div>}> <Suspense fallback={<div>. . . loading</div>}>
<Editor <Editor
defaultValue={state.code} defaultValue={state.code}
value={state.code}
// TODO #247 cpp seems better than js for the time being // TODO #247 cpp seems better than js for the time being
defaultLanguage={ideTypeToLanguageMap[state.ideType] || 'cpp'} defaultLanguage={ideTypeToLanguageMap[state.ideType] || 'cpp'}
language={ideTypeToLanguageMap[state.ideType] || 'cpp'} language={ideTypeToLanguageMap[state.ideType] || 'cpp'}

View File

@@ -1,4 +1,4 @@
import { createContext } from 'react' import { createContext, useEffect } from 'react'
import IdeContainer from 'src/components/IdeContainer' import IdeContainer from 'src/components/IdeContainer'
import { isBrowser } from '@redwoodjs/prerender/browserUtils' import { isBrowser } from '@redwoodjs/prerender/browserUtils'
import { useIdeState, codeStorageKey } from 'src/helpers/hooks/useIdeState' import { useIdeState, codeStorageKey } from 'src/helpers/hooks/useIdeState'
@@ -6,11 +6,27 @@ import { copyTextToClipboard } from 'src/helpers/clipboard'
import { requestRender } from 'src/helpers/hooks/useIdeState' import { requestRender } from 'src/helpers/hooks/useIdeState'
export const IdeContext = createContext() export const IdeContext = createContext()
const IdeToolbarNew = () => { const IdeToolbarNew = ({ cadPackage }) => {
const [state, thunkDispatch] = useIdeState() const [state, thunkDispatch] = useIdeState()
function setIdeType(ide) { const scriptKey = 'encoded_script'
thunkDispatch({ type: 'setIdeType', payload: { message: ide } }) useEffect(() => {
} thunkDispatch({
type: 'initIde',
payload: { cadPackage },
})
// load code from hash if it's there
let hash
if (isBrowser) {
hash = window.location.hash
}
const [key, scriptBase64] = hash.slice(1).split('=')
if (key === scriptKey) {
const script = atob(scriptBase64)
thunkDispatch({ type: 'updateCode', payload: script })
}
window.location.hash = ''
setTimeout(() => handleRender()) // definitely a little hacky, timeout with no delay is just to push it into the next event loop.
}, [cadPackage])
function handleRender() { function handleRender() {
thunkDispatch((dispatch, getState) => { thunkDispatch((dispatch, getState) => {
const state = getState() const state = getState()
@@ -37,14 +53,6 @@ const IdeToolbarNew = () => {
<IdeContext.Provider value={{ state, thunkDispatch: thunkDispatch }}> <IdeContext.Provider value={{ state, thunkDispatch: thunkDispatch }}>
<div className="h-full flex flex-col"> <div className="h-full flex flex-col">
<nav className="flex"> <nav className="flex">
<button
onClick={() =>
setIdeType(state.ideType === 'openScad' ? 'cadQuery' : 'openScad')
}
className="p-2 br-2 border-2 m-2 bg-blue-200"
>
Switch to {state.ideType === 'openScad' ? 'CadQuery' : 'OpenSCAD'}
</button>
<button onClick={handleRender} className="p-2 br-2 border-2 m-2"> <button onClick={handleRender} className="p-2 br-2 border-2 m-2">
Render Render
</button> </button>

View File

@@ -0,0 +1,48 @@
import { Link, routes } from '@redwoodjs/router'
import Svg from 'src/components/Svg/Svg'
import { Popover } from '@headlessui/react'
const NavPlusButton: React.FC = () => {
return (
<Popover className="relative outline-none w-full h-full">
<Popover.Button className="h-full w-full outline-none">
<Svg name="plus" className="text-indigo-300" />
</Popover.Button>
<Popover.Panel className="absolute z-10">
<ul className="bg-gray-200 mt-4 rounded shadow-md overflow-hidden">
{[
{
name: 'OpenSCAD',
sub: 'beta',
ideType: 'openScad',
},
{ name: 'CadQuery', sub: 'beta', ideType: 'cadQuery' },
{
name: 'CascadeStudio',
sub: 'soon to be deprecated',
},
].map(({ name, sub, ideType }) => (
<li
key={name}
className="px-4 py-2 hover:bg-gray-400 text-gray-800"
>
<Link
to={
name === 'CascadeStudio'
? routes.draftPart()
: routes.devIde({ cadPackage: ideType })
}
>
<div>{name}</div>
<div className="text-xs text-gray-600 font-light">{sub}</div>
</Link>
</li>
))}
</ul>
</Popover.Panel>
</Popover>
)
}
export default NavPlusButton

View File

@@ -13,6 +13,9 @@ export const render = async ({ code, settings }) => {
}, },
file: code, file: code,
}) })
if (!settings.camera.position) {
return
}
try { try {
const response = await fetch(lambdaBaseURL + '/openscad/preview', { const response = await fetch(lambdaBaseURL + '/openscad/preview', {
method: 'POST', method: 'POST',

View File

@@ -8,7 +8,8 @@ function withThunk(dispatch, getState) {
: dispatch(actionOrThunk) : dispatch(actionOrThunk)
} }
const donutInitCode = ` const initCodeMap = {
openScad: `
color(c="DarkGoldenrod")rotate_extrude()translate([20,0])circle(d=30); color(c="DarkGoldenrod")rotate_extrude()translate([20,0])circle(d=30);
donut(); donut();
module donut() { module donut() {
@@ -21,16 +22,31 @@ module stick(basewid, angl){
sphere(7); sphere(7);
translate([0,0,10])sphere(9); translate([0,0,10])sphere(9);
} }
}` }`,
cadQuery: `import cadquery as cq
from cadquery import exporters
diam = 5.0
result = (cq.Workplane().circle(diam).extrude(20.0)
.faces(">Z").workplane(invert=True).circle(1.05).cutBlind(8.0)
.faces("<Z").workplane(invert=True).circle(0.8).cutBlind(12.0)
.edges("%CIRCLE").chamfer(0.15))
# exporters.export(coupler, "/home/jwright/Downloads/coupler.stl", exporters.ExportTypes.STL)
show_object(result)
`,
}
export const codeStorageKey = 'Last-openscad-code' export const codeStorageKey = 'Last-openscad-code'
let mutableState = null let mutableState = null
export const useIdeState = () => { export const useIdeState = () => {
const code = localStorage.getItem(codeStorageKey) || donutInitCode const code = localStorage.getItem(codeStorageKey) || initCodeMap.openscad
const initialState = { const initialState = {
ideType: 'cadQuery', ideType: 'INIT',
consoleMessages: [{ type: 'message', message: 'Initialising OpenSCAD' }], consoleMessages: [{ type: 'message', message: 'Initialising' }],
code, code,
objectData: { objectData: {
type: 'stl', type: 'stl',
@@ -52,6 +68,12 @@ export const useIdeState = () => {
} }
const reducer = (state, { type, payload }) => { const reducer = (state, { type, payload }) => {
switch (type) { switch (type) {
case 'initIde':
return {
...state,
code: initCodeMap[payload.cadPackage] || initCodeMap.openscad,
ideType: payload.cadPackage,
}
case 'updateCode': case 'updateCode':
return { ...state, code: payload } return { ...state, code: payload }
case 'healthyRender': case 'healthyRender':
@@ -74,11 +96,6 @@ export const useIdeState = () => {
: payload.message, : payload.message,
isLoading: false, isLoading: false,
} }
case 'setIdeType':
return {
...state,
ideType: payload.message,
}
case 'setLayout': case 'setLayout':
return { return {
...state, ...state,
@@ -122,26 +139,28 @@ export const requestRender = ({
camera, camera,
viewerSize, viewerSize,
}) => { }) => {
cadPackages[state.ideType] state.ideType !== 'INIT' &&
.render({ !state.isLoading &&
code, cadPackages[state.ideType]
settings: { .render({
camera, code,
viewerSize, settings: {
}, camera,
}) viewerSize,
.then(({ objectData, message, status }) => { },
if (status === 'error') { })
dispatch({ .then(({ objectData, message, status }) => {
type: 'errorRender', if (status === 'error') {
payload: { message }, dispatch({
}) type: 'errorRender',
} else { payload: { message },
dispatch({ })
type: 'healthyRender', } else {
payload: { objectData, message }, dispatch({
}) type: 'healthyRender',
} payload: { objectData, message, lastRunCode: code },
}) })
.catch(() => dispatch({ type: 'resetLoading' })) // TODO should probably display something to the user here }
})
.catch(() => dispatch({ type: 'resetLoading' })) // TODO should probably display something to the user here
} }

View File

@@ -8,6 +8,7 @@ import { getActiveClasses } from 'get-active-classes'
import Footer from 'src/components/Footer' import Footer from 'src/components/Footer'
import { useLocation } from '@redwoodjs/router' import { useLocation } from '@redwoodjs/router'
import LoginModal from 'src/components/LoginModal' import LoginModal from 'src/components/LoginModal'
import NavPlusButton from 'src/components/NavPlusButton'
import ReactGA from 'react-ga' import ReactGA from 'react-ga'
import { isBrowser } from '@redwoodjs/prerender/browserUtils' import { isBrowser } from '@redwoodjs/prerender/browserUtils'
@@ -132,9 +133,7 @@ const MainLayout = ({ children, shouldRemoveFooterInIde }) => {
'mr-8 h-10 w-10 rounded-full border-2 border-indigo-300 flex items-center justify-center' 'mr-8 h-10 w-10 rounded-full border-2 border-indigo-300 flex items-center justify-center'
)} )}
> >
<Link className="h-full w-full" to={routes.draftPart()}> <NavPlusButton />
<Svg name="plus" className="text-indigo-300 w-full h-full" />
</Link>
</li> </li>
{isAuthenticated ? ( {isAuthenticated ? (
<li <li

View File

@@ -3,7 +3,7 @@ import Seo from 'src/components/Seo/Seo'
import IdeToolbar from 'src/components/IdeToolbarNew' import IdeToolbar from 'src/components/IdeToolbarNew'
import OutBound from 'src/components/OutBound' import OutBound from 'src/components/OutBound'
const DevIdePage = () => { const DevIdePage = ({ cadPackage }) => {
return ( return (
<div className="h-screen flex flex-col"> <div className="h-screen flex flex-col">
<MainLayout shouldRemoveFooterInIde> <MainLayout shouldRemoveFooterInIde>
@@ -12,10 +12,9 @@ const DevIdePage = () => {
description="new ide in development" description="new ide in development"
lang="en-US" lang="en-US"
/> />
<div className="py-4 bg-pink-200"> <div className="py-2 bg-pink-200">
<div className="mx-auto max-w-6xl"> <div className="mx-auto max-w-3xl">
Woah, woah. You shouldn't be here! We're still working on this. We're still working on this. Since you're here, have a look what{' '}
Since you've seen it now, have a look what{' '}
<OutBound <OutBound
className="text-pink-700" className="text-pink-700"
to="https://github.com/Irev-Dev/cadhub/discussions/212" to="https://github.com/Irev-Dev/cadhub/discussions/212"
@@ -27,7 +26,7 @@ const DevIdePage = () => {
</div> </div>
</MainLayout> </MainLayout>
<div className="flex-auto"> <div className="flex-auto">
<IdeToolbar /> <IdeToolbar cadPackage={cadPackage} />
</div> </div>
</div> </div>
) )

View File

@@ -1404,6 +1404,11 @@
resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.0.0.tgz#5bb2193eb685c0007540ca61d166d4e1edaf918d" resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-2.0.0.tgz#5bb2193eb685c0007540ca61d166d4e1edaf918d"
integrity sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg== integrity sha512-WEezM1FWztfbzqIUbsDzFRVMxSoLy3HugVcux6KDDtTqzPsLE8NDRHfXvev66aH1i2oOKKar3/XDjbvh/OUBdg==
"@headlessui/react@^1.0.0":
version "1.0.0"
resolved "https://registry.yarnpkg.com/@headlessui/react/-/react-1.0.0.tgz#661b50ebfd25041abb45d8eedd85e7559056bcaf"
integrity sha512-mjqRJrgkbcHQBfAHnqH0yRxO/y/22jYrdltpE7WkurafREKZ+pj5bPBwYHMt935Sdz/n16yRcVmsSCqDFHee9A==
"@icons/material@^0.2.4": "@icons/material@^0.2.4":
version "0.2.4" version "0.2.4"
resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8" resolved "https://registry.yarnpkg.com/@icons/material/-/material-0.2.4.tgz#e90c9f71768b3736e76d7dd6783fc6c2afa88bc8"