1
.eslintignore
Normal file
1
.eslintignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/web/src/cascade/*
|
||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -17,7 +17,9 @@
|
|||||||
"./web/src/Routes.js",
|
"./web/src/Routes.js",
|
||||||
],
|
],
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"Initialised",
|
||||||
"Uploader",
|
"Uploader",
|
||||||
|
"initialise",
|
||||||
"redwoodjs"
|
"redwoodjs"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ const Routes = () => {
|
|||||||
return (
|
return (
|
||||||
<Router>
|
<Router>
|
||||||
<Route path="/" page={PartsPage} name="home" />
|
<Route path="/" page={PartsPage} name="home" />
|
||||||
{/* <Route path="/blah/*" page={PartsPage} name="home" /> */}
|
|
||||||
<Route notfound page={NotFoundPage} />
|
<Route notfound page={NotFoundPage} />
|
||||||
|
|
||||||
{/* Ownership enforced routes */}
|
{/* Ownership enforced routes */}
|
||||||
@@ -24,7 +23,7 @@ const Routes = () => {
|
|||||||
|
|
||||||
<Route path="/u/{userName}" page={User2Page} name="user2" />
|
<Route path="/u/{userName}" page={User2Page} name="user2" />
|
||||||
<Route path="/u/{userName}/{partTitle}" page={Part2Page} name="part2" />
|
<Route path="/u/{userName}/{partTitle}" page={Part2Page} name="part2" />
|
||||||
{/* <Route path="/u/{userName}/{partTitle}/ide" page={Part2Page} name="part2" /> */}
|
<Route path="/u/{userName}/{partTitle}/ide" page={IdePartPage} name="ide" />
|
||||||
|
|
||||||
{/* GENERATED ROUTES BELOW, probably going to clean these up and delete most of them, but the CRUD functionality is useful for now */}
|
{/* GENERATED ROUTES BELOW, probably going to clean these up and delete most of them, but the CRUD functionality is useful for now */}
|
||||||
{/* All private by default for safety and because the routes that are left after clean up will probably be admin pages */}
|
{/* All private by default for safety and because the routes that are left after clean up will probably be admin pages */}
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 50 KiB |
Submodule web/src/cascade updated: e634591e27...37cea9eeb2
@@ -1,41 +1,57 @@
|
|||||||
import MainLayout from 'src/layouts/MainLayout'
|
import { useMutation, useFlash } from '@redwoodjs/web'
|
||||||
// import BlogPostsCell from 'src/components/BlogPostsCell'
|
import { Link, routes, navigate } from '@redwoodjs/router'
|
||||||
import { initialize } from 'src/cascade/js/MainPage/CascadeMain'
|
import { initialize } from 'src/cascade/js/MainPage/CascadeMain'
|
||||||
|
import CascadeController from 'src/helpers/cascadeController'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
const starterCode = `// Welcome to Cascade Studio! Here are some useful functions:
|
const DELETE_PART_MUTATION = gql`
|
||||||
// Translate(), Rotate(), Scale(), Union(), Difference(), Intersection()
|
mutation DeletePartMutation($id: Int!) {
|
||||||
// Box(), Sphere(), Cylinder(), Cone(), Text3D(), Polygon()
|
deletePart(id: $id) {
|
||||||
// Offset(), Extrude(), RotatedExtrude(), Revolve(), Pipe(), Loft(),
|
id
|
||||||
// FilletEdges(), ChamferEdges(),
|
}
|
||||||
// Slider(), Button(), Checkbox()
|
}
|
||||||
|
|
||||||
// Uncomment and hover over them to see their apis
|
|
||||||
|
|
||||||
let holeRadius = Slider("Radius", 30 , 20 , 40);
|
|
||||||
|
|
||||||
let sphere = Sphere(50);
|
|
||||||
let cylinderZ = Cylinder(holeRadius, 200, true);
|
|
||||||
let cylinderY = Rotate([0,1,0], 90, Cylinder(holeRadius, 200, true));
|
|
||||||
let cylinderX = Rotate([1,0,0], 90, Cylinder(holeRadius, 200, true));
|
|
||||||
|
|
||||||
Translate([0, 0, 50], Difference(sphere, [cylinderX, cylinderY, cylinderZ]));
|
|
||||||
|
|
||||||
Translate([-100, 0, 100], Text3D("cadhub.xyz"));
|
|
||||||
|
|
||||||
// Don't forget to push imported or oc-defined shapes into sceneShapes to add them to the workspace!
|
|
||||||
`
|
`
|
||||||
|
const domNode = document.createElement('div').setAttribute('id', 'sickId')
|
||||||
|
|
||||||
const HomePage1 = () => {
|
const IdeCascadeStudio = ({ part, saveCode, loading, error }) => {
|
||||||
const [code, setCode] = useState(starterCode)
|
const [code, setCode] = useState(part.code)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const sickCallback = (code) => setCode(code)
|
const onCodeChange = (code) => setCode(code)
|
||||||
new initialize(sickCallback, starterCode)
|
CascadeController.initialise(onCodeChange, part.code, domNode)
|
||||||
|
const element = document.getElementById('cascade-container')
|
||||||
|
element.setAttribute('style', 'height: auto; display: block; opacity: 100%') // eslint-disable-line
|
||||||
|
return () => {
|
||||||
|
element.setAttribute('style', 'height: auto; display: none;') // eslint-disable-line
|
||||||
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
const hasChanges = code !== part.code
|
||||||
|
const { addMessage } = useFlash()
|
||||||
|
const [deletePart] = useMutation(DELETE_PART_MUTATION, {
|
||||||
|
onCompleted: () => {
|
||||||
|
// navigate(routes.parts())
|
||||||
|
addMessage('Part deleted.', { classes: 'rw-flash-success' })
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const onDeleteClick = (id) => {
|
||||||
|
if (confirm('Are you sure you want to delete part ' + id + '?')) {
|
||||||
|
deletePart({ variables: { id } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MainLayout>
|
<>
|
||||||
<div>current code {code}</div>
|
<nav className="rw-button-group">
|
||||||
<BlogPostsCell />
|
{loading && 'Loading...'}
|
||||||
|
{hasChanges && !loading && (
|
||||||
|
<button
|
||||||
|
onClick={() => saveCode({ code }, part.id)}
|
||||||
|
className="rw-button rw-button-blue"
|
||||||
|
>
|
||||||
|
Save Changes
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</nav>
|
||||||
<div>
|
<div>
|
||||||
<div id="topnav" className="topnav">
|
<div id="topnav" className="topnav">
|
||||||
<a href="https://github.com/zalo/CascadeStudio">
|
<a href="https://github.com/zalo/CascadeStudio">
|
||||||
@@ -109,15 +125,14 @@ const HomePage1 = () => {
|
|||||||
Reset Project
|
Reset Project
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div id="cascade-container" style={{ height: 'auto' }}></div>
|
{/* <div
|
||||||
<footer>footer</footer>
|
id="cascade-container"
|
||||||
|
style={{ height: 'auto' }}
|
||||||
|
// dangerouslySetInnerHTML={domNode}
|
||||||
|
></div> */}
|
||||||
</div>
|
</div>
|
||||||
</MainLayout>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const HomePage = () => {
|
export default IdeCascadeStudio
|
||||||
return <MainLayout>hi</MainLayout>
|
|
||||||
}
|
|
||||||
|
|
||||||
export default HomePage
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
import IdeCascadeStudio from './IdeCascadeStudio'
|
||||||
|
|
||||||
|
export const generated = () => {
|
||||||
|
return <IdeCascadeStudio />
|
||||||
|
}
|
||||||
|
|
||||||
|
export default { title: 'Components/IdeCascadeStudio' }
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
import { render } from '@redwoodjs/testing'
|
import { render } from '@redwoodjs/testing'
|
||||||
|
|
||||||
import HomePage from './HomePage'
|
import IdeCascadeStudio from './IdeCascadeStudio'
|
||||||
|
|
||||||
describe('HomePage', () => {
|
describe('IdeCascadeStudio', () => {
|
||||||
it('renders successfully', () => {
|
it('renders successfully', () => {
|
||||||
expect(() => {
|
expect(() => {
|
||||||
render(<HomePage />)
|
render(<IdeCascadeStudio />)
|
||||||
}).not.toThrow()
|
}).not.toThrow()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import { useMutation, useFlash } from '@redwoodjs/web'
|
import { useMutation, useFlash } from '@redwoodjs/web'
|
||||||
import { navigate, routes } from '@redwoodjs/router'
|
import { navigate, routes } from '@redwoodjs/router'
|
||||||
// import Part from 'src/components/Part'
|
import IdeCascadeStudio from 'src/components/IdeCascadeStudio'
|
||||||
|
// import Part from 'src/components/Part'a
|
||||||
|
|
||||||
export const QUERY = gql`
|
export const QUERY = gql`
|
||||||
query FIND_PART_BY_ID($id: Int!) {
|
query FIND_PART_BY_USENAME_TITLE($partTitle: String!, $userName: String!) {
|
||||||
part: part(id: $id) {
|
part: partByUserAndTitle(partTitle: $partTitle, userName: $userName) {
|
||||||
id
|
id
|
||||||
title
|
title
|
||||||
description
|
description
|
||||||
@@ -16,7 +17,7 @@ export const QUERY = gql`
|
|||||||
`
|
`
|
||||||
|
|
||||||
const UPDATE_PART_MUTATION = gql`
|
const UPDATE_PART_MUTATION = gql`
|
||||||
mutation UpdatePartMutation($id: Int!, $input: UpdatePartInput!) {
|
mutation UpdatePartMutation($id: String!, $input: UpdatePartInput!) {
|
||||||
updatePart(id: $id, input: $input) {
|
updatePart(id: $id, input: $input) {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
@@ -27,7 +28,7 @@ export const Loading = () => <div>Loading...</div>
|
|||||||
|
|
||||||
export const Empty = () => <div>Part not found</div>
|
export const Empty = () => <div>Part not found</div>
|
||||||
|
|
||||||
export const Success = ({ part }) => {
|
export const Success = ({ part, refetch }) => {
|
||||||
const { addMessage } = useFlash()
|
const { addMessage } = useFlash()
|
||||||
const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION, {
|
const [updatePart, { loading, error }] = useMutation(UPDATE_PART_MUTATION, {
|
||||||
onCompleted: () => {
|
onCompleted: () => {
|
||||||
@@ -40,7 +41,14 @@ export const Success = ({ part }) => {
|
|||||||
const saveCode = (input, id) => {
|
const saveCode = (input, id) => {
|
||||||
console.log(id, input, 'wowow')
|
console.log(id, input, 'wowow')
|
||||||
updatePart({ variables: { id, input } })
|
updatePart({ variables: { id, input } })
|
||||||
|
refetch()
|
||||||
}
|
}
|
||||||
return <div>TODO part</div>
|
return (
|
||||||
// return <Part part={{...part, code: part.code}} saveCode={saveCode} loading={loading} error={error} />
|
<IdeCascadeStudio
|
||||||
|
part={part}
|
||||||
|
saveCode={saveCode}
|
||||||
|
loading={loading}
|
||||||
|
error={error}
|
||||||
|
/>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,14 +92,21 @@ const PartProfile = ({
|
|||||||
>
|
>
|
||||||
Comments 11
|
Comments 11
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Link
|
||||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200"
|
to={routes.ide({
|
||||||
shouldAnimateHover
|
userName: userPart.userName,
|
||||||
iconName="terminal"
|
partTitle: part.title,
|
||||||
onClick={() => {}}
|
})}
|
||||||
>
|
>
|
||||||
Open IDE
|
<Button
|
||||||
</Button>
|
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200"
|
||||||
|
shouldAnimateHover
|
||||||
|
iconName="terminal"
|
||||||
|
onClick={() => {}}
|
||||||
|
>
|
||||||
|
Open IDE
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
{canEdit && (
|
{canEdit && (
|
||||||
<Button
|
<Button
|
||||||
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 relative z-20"
|
className="mt-4 ml-auto shadow-md hover:shadow-lg bg-indigo-200 relative z-20"
|
||||||
|
|||||||
25
web/src/helpers/cascadeController.js
Normal file
25
web/src/helpers/cascadeController.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { initialize, getEditor } from 'src/cascade/js/MainPage/CascadeMain'
|
||||||
|
|
||||||
|
class CascadeController {
|
||||||
|
_hasInitialised = false
|
||||||
|
incomingOnCodeChang = () => {}
|
||||||
|
controllerOnCodeChange = (code) => {
|
||||||
|
this.incomingOnCodeChang(code)
|
||||||
|
}
|
||||||
|
|
||||||
|
initialise(onCodeChange, code) {
|
||||||
|
// only inits on first call, after that it just updates the editor and revaluates code, maybe should rename?
|
||||||
|
this.incomingOnCodeChang = onCodeChange
|
||||||
|
if (!this._hasInitialised) {
|
||||||
|
initialize(this.controllerOnCodeChange, code)
|
||||||
|
this._hasInitialised = true
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const editor = getEditor()
|
||||||
|
editor.setValue(code)
|
||||||
|
editor.evaluateCode(false)
|
||||||
|
return this.domNode
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new CascadeController()
|
||||||
@@ -14,16 +14,16 @@
|
|||||||
var cascadeStudioWorker
|
var cascadeStudioWorker
|
||||||
var workerWorking = false
|
var workerWorking = false
|
||||||
var galleryProject = undefined
|
var galleryProject = undefined
|
||||||
function coolGuy() {
|
function initCascadeStudio() {
|
||||||
if ('serviceWorker' in navigator) {
|
// if ('serviceWorker' in navigator) {
|
||||||
navigator.serviceWorker.register('service-worker.js').then(function(registration) {
|
// navigator.serviceWorker.register('service-worker.js').then(function(registration) {
|
||||||
registration.update(); // Always update the registration for the latest assets
|
// registration.update(); // Always update the registration for the latest assets
|
||||||
}, function() {
|
// }, function() {
|
||||||
console.log('Could not register Cascade Studio for offline use!');
|
// console.log('Could not register Cascade Studio for offline use!');
|
||||||
});
|
// });
|
||||||
} else {
|
// } else {
|
||||||
console.log('Browser does not support offline access!');
|
// console.log('Browser does not support offline access!');
|
||||||
}
|
// }
|
||||||
|
|
||||||
// Begins loading the CAD Kernel Web Worker
|
// Begins loading the CAD Kernel Web Worker
|
||||||
if (window.Worker) {
|
if (window.Worker) {
|
||||||
@@ -38,10 +38,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// coolGuy()
|
initCascadeStudio()
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="redwood-app"></div>
|
<div id="redwood-app"></div>
|
||||||
|
<div
|
||||||
|
id="cascade-container"
|
||||||
|
style="height: auto; opacity: 0;"
|
||||||
|
></div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
import HomePage from './HomePage'
|
|
||||||
|
|
||||||
export const generated = () => {
|
|
||||||
return <HomePage />
|
|
||||||
}
|
|
||||||
|
|
||||||
export default { title: 'Pages/HomePage' }
|
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
import { Link, routes } from '@redwoodjs/router'
|
|
||||||
import MainLayout from 'src/layouts/MainLayout'
|
import MainLayout from 'src/layouts/MainLayout'
|
||||||
import IdePartCell from 'src/components/IdePartCell'
|
import IdePartCell from 'src/components/IdePartCell'
|
||||||
|
|
||||||
const IdePartPage = ({ id }) => {
|
const IdePartPage = ({ userName, partTitle }) => {
|
||||||
return (
|
return (
|
||||||
<MainLayout>
|
<MainLayout>
|
||||||
<IdePartCell id={id} />
|
<IdePartCell userName={userName} partTitle={partTitle} />
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user