From bd9224fec98345419104cc3bf78b2683cfb1e3fb Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Mon, 15 Nov 2021 01:26:47 -0500 Subject: [PATCH 1/8] initial commit, issue with OpenSCAD embed viewing --- app/api/db/schema.prisma | 2 +- app/web/src/Routes.js | 1 + .../EmbedProjectCell/EmbedProjectCell.mock.ts | 6 ++ .../EmbedProjectCell.stories.tsx | 16 +++++ .../EmbedProjectCell.test.tsx | 21 ++++++ .../EmbedProjectCell/EmbedProjectCell.tsx | 71 +++++++++++++++++++ .../components/EmbedViewer/EmbedViewer.tsx | 19 +++++ .../src/components/IdeViewer/IdeViewer.tsx | 7 +- .../ProjectProfile/ProjectProfile.tsx | 1 + .../EmbedProjectPage/EmbedProjectPage.tsx | 11 +++ 10 files changed, 152 insertions(+), 3 deletions(-) create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx create mode 100644 app/web/src/components/EmbedViewer/EmbedViewer.tsx create mode 100644 app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx diff --git a/app/api/db/schema.prisma b/app/api/db/schema.prisma index d91dda8..3bc72bf 100644 --- a/app/api/db/schema.prisma +++ b/app/api/db/schema.prisma @@ -5,7 +5,7 @@ datasource db { generator client { provider = "prisma-client-js" - binaryTargets = "native" + binaryTargets = ["native", "darwin-arm64", "darwin"] } // sqlLight does not suport enums so we can't use enums until we set up postgresql in dev mode diff --git a/app/web/src/Routes.js b/app/web/src/Routes.js index a2f053b..58578bc 100644 --- a/app/web/src/Routes.js +++ b/app/web/src/Routes.js @@ -56,6 +56,7 @@ const Routes = () => { + diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts new file mode 100644 index 0000000..2e297e0 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts @@ -0,0 +1,6 @@ +// Define your own mock data here: +export const standard = (/* vars, { ctx, req } */) => ({ + ideProject: { + id: 42, + }, +}) diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx new file mode 100644 index 0000000..8a20e23 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx @@ -0,0 +1,16 @@ +import { Loading, Empty, Success } from './EmbedProjectCell' +import { standard } from './EmbedProjectCell.mock' + +export const loading = () => { + return Loading ? : null +} + +export const empty = () => { + return Empty ? : null +} + +export const success = () => { + return Success ? : null +} + +export default { title: 'Cells/EmbedProjectCell' } diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx new file mode 100644 index 0000000..58efd22 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx @@ -0,0 +1,21 @@ +import { render, screen } from '@redwoodjs/testing' +import { Loading, Empty, Success } from './EmbedProjectCell' +import { standard } from './EmbedProjectCell.mock' + +describe('EmbedProjectCell', () => { + test('Loading renders successfully', () => { + render() + // Use screen.debug() to see output + expect(screen.getByText('Loading...')).toBeInTheDocument() + }) + + test('Empty renders successfully', async () => { + render() + expect(screen.getByText('Empty')).toBeInTheDocument() + }) + + test('Success renders successfully', async () => { + render() + expect(screen.getByText(/42/i)).toBeInTheDocument() + }) +}) diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx new file mode 100644 index 0000000..fdda356 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx @@ -0,0 +1,71 @@ +import useUser from 'src/helpers/hooks/useUser' +import EmbedViewer from 'src/components/EmbedViewer/EmbedViewer' +import { useIdeState } from 'src/helpers/hooks/useIdeState' +import { IdeContext } from 'src/helpers/hooks/useIdeContext' + +export const QUERY = gql` + query FIND_PROJECT_BY_USENAME_TITLE( + $projectTitle: String! + $userName: String! + ) { + project: projectByUserAndTitle( + projectTitle: $projectTitle + userName: $userName + ) { + id + title + description + code + mainImage + createdAt + cadPackage + user { + id + userName + image + } + } + } +` + +export interface Project { + id: string + title: string + code: string + description: string + mainImage: string + createdAt: string + cadPackage: 'openscad' | 'cadquery' + user: { + id: string + userName: string + image: string + } +} + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
Project not found
+ +interface SaveCodeArgs { + input: any + id: string + isFork: boolean +} + +export const Success = ({ + project, + refetch, +}: { + project: Project + refetch: any +}) => { + const [state, thunkDispatch] = useIdeState() + + + return ( + + + + ) +} diff --git a/app/web/src/components/EmbedViewer/EmbedViewer.tsx b/app/web/src/components/EmbedViewer/EmbedViewer.tsx new file mode 100644 index 0000000..6d28e98 --- /dev/null +++ b/app/web/src/components/EmbedViewer/EmbedViewer.tsx @@ -0,0 +1,19 @@ +import { useIdeInit } from 'src/components/EncodedUrl/helpers' +import { useIdeContext } from 'src/helpers/hooks/useIdeContext' +import IdeViewer from 'src/components/IdeViewer/IdeViewer' +import { use3dViewerResize } from 'src/helpers/hooks/use3dViewerResize' + +function EmbedViewer() { + const { state, project } = useIdeContext() + console.log('from EmbedViewer', { cadPackage: project.cadPackage, code: project.code }) + useIdeInit(project?.cadPackage, project?.code || state?.code, "viewer") + const { viewerDomRef } = use3dViewerResize() + + return ( +
+ +
+ ) +} + +export default EmbedViewer \ No newline at end of file diff --git a/app/web/src/components/IdeViewer/IdeViewer.tsx b/app/web/src/components/IdeViewer/IdeViewer.tsx index 51ea4a4..d1af0d7 100644 --- a/app/web/src/components/IdeViewer/IdeViewer.tsx +++ b/app/web/src/components/IdeViewer/IdeViewer.tsx @@ -4,8 +4,10 @@ import { PureIdeViewer } from './PureIdeViewer' const IdeViewer = ({ handleOwnCamera = false, + isMinimal = false, }: { - handleOwnCamera?: boolean + handleOwnCamera?: boolean, + isMinimal?: boolean, }) => { const { state, thunkDispatch } = useIdeContext() const dataType = state.objectData?.type @@ -35,7 +37,7 @@ const IdeViewer = ({ } }) } - + return ( ) } diff --git a/app/web/src/components/ProjectProfile/ProjectProfile.tsx b/app/web/src/components/ProjectProfile/ProjectProfile.tsx index cb0fb36..02d4700 100644 --- a/app/web/src/components/ProjectProfile/ProjectProfile.tsx +++ b/app/web/src/components/ProjectProfile/ProjectProfile.tsx @@ -52,6 +52,7 @@ const ProjectProfile = ({ }) ) }, [currentUser, project?.title, userProject.userName]) + console.log('from ProjectProfile', { cadPackage: project.cadPackage, code: project.code }) useIdeInit(project?.cadPackage, project?.code, 'viewer') const [newDescription, setNewDescription] = useState(project?.description) const onDescriptionChange = (description) => setNewDescription(description()) diff --git a/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx b/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx new file mode 100644 index 0000000..bca9257 --- /dev/null +++ b/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx @@ -0,0 +1,11 @@ +import EmbedProjectCell from 'src/components/EmbedProjectCell' + +const EmbedProjectPage = ({ userName, projectTitle }) => { + return ( + <> + + + ) +} + +export default EmbedProjectPage -- 2.39.5 From cd3060b3c729d791f8965c93f939304067dd91b8 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Fri, 17 Dec 2021 05:57:31 +1100 Subject: [PATCH 2/8] Update CONTRIBUTING.md CC @Isaac-Tait --- CONTRIBUTING.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 96d0889..fd4f9ff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,9 +22,9 @@ Because Each CadPackage is it's own beast we opted to use Docker in order to giv ## Getting your dev environment setup -Clone the repo and `cd` in the app directory (the docs directory is for [learn.cadhub](https://learn.cadhub.xyz/)) +Clone the repo, then `cd` in the repo and app directory (the docs directory is for [learn.cadhub](https://learn.cadhub.xyz/)) ``` -cd app +cd cadhub/app ``` Install dependencies -- 2.39.5 From 3fef6474d34097c25b7da134bf981384cb552c90 Mon Sep 17 00:00:00 2001 From: Davor Hrg Date: Sat, 8 Jan 2022 20:32:32 +0100 Subject: [PATCH 3/8] default values and float type (#582) --- .gitignore | 1 + app/web/src/helpers/cadPackages/jsCad/jscadParams.ts | 4 +++- app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts | 9 +++++++-- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 1110f69..c89327a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea +.history .DS_Store .env .netlify diff --git a/app/web/src/helpers/cadPackages/jsCad/jscadParams.ts b/app/web/src/helpers/cadPackages/jsCad/jscadParams.ts index 855579a..33f0fc3 100644 --- a/app/web/src/helpers/cadPackages/jsCad/jscadParams.ts +++ b/app/web/src/helpers/cadPackages/jsCad/jscadParams.ts @@ -8,6 +8,7 @@ type JscadTypeNames = | 'group' | 'text' | 'int' + | 'float' | 'number' | 'slider' | 'email' @@ -37,7 +38,7 @@ interface JscadTextParam extends JscadParamBase { maxLength: number } interface JscadIntNumberSliderParam extends JscadParamBase { - type: 'int' | 'number' | 'slider' + type: 'int' | 'number' | 'float' | 'slider' initial: number min?: number max?: number @@ -93,6 +94,7 @@ export function jsCadToCadhubParams(input: JsCadParams[]): CadhubParams[] { switch (param.type) { case 'slider': case 'number': + case 'float': case 'int': return { type: 'number', diff --git a/app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts b/app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts index 50f2ad6..4a5751a 100644 --- a/app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts +++ b/app/web/src/helpers/cadPackages/jsCad/jscadWorker.ts @@ -315,9 +315,12 @@ function parseDef(code, line) { } const makeScriptWorker = ({ callback, convertToSolids }) => { - let onInit, main, scriptStats, entities + let onInit, main, scriptStats, entities, lastParamsDef function runMain(params = {}) { + if(lastParamsDef) lastParamsDef.forEach(def=>{ + if(!(def.name in params) && 'initial' in def) params[def.name] = def.initial + }) let time = Date.now() let solids const transfer = [] @@ -397,10 +400,12 @@ const makeScriptWorker = ({ callback, convertToSolids }) => { if (idx === -1) { paramsDef.push(p) } else { - paramsDef.splice(idx, 1, p) + paramsDef[idx] = p } }) } + console.log('paramsDef', paramsDef) + lastParamsDef = paramsDef callback({ action: 'parameterDefinitions', worker: 'main', -- 2.39.5 From 35fcd5522981dd1689efd2d80918f611123347d4 Mon Sep 17 00:00:00 2001 From: Davor Hrg Date: Sat, 8 Jan 2022 20:33:13 +0100 Subject: [PATCH 4/8] Update jsCadController.tsx (#583) --- app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx b/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx index bfdcf97..e48b210 100644 --- a/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx +++ b/app/web/src/helpers/cadPackages/jsCad/jsCadController.tsx @@ -20,7 +20,7 @@ import TheWorker from 'worker-loader!./jscadWorker' const materials = { mesh: { - def: new MeshPhongMaterial({ color: 0x0084d1, flatShading: true }), + def: new MeshPhongMaterial({ color: 0x13579d, flatShading: true }), material: (params) => new MeshPhongMaterial(params), }, line: { -- 2.39.5 From 4def7e1ac56e2847a6d20d9f0149d9c3ae9ec513 Mon Sep 17 00:00:00 2001 From: Frank Noirot Date: Sat, 8 Jan 2022 14:55:10 -0500 Subject: [PATCH 5/8] initial implementation --- app/web/src/Routes.js | 1 + .../components/EmbedProject/EmbedProject.tsx | 32 +++++++++ .../EmbedProjectCell/EmbedProjectCell.mock.ts | 6 ++ .../EmbedProjectCell.stories.tsx | 16 +++++ .../EmbedProjectCell.test.tsx | 21 ++++++ .../EmbedProjectCell/EmbedProjectCell.tsx | 71 +++++++++++++++++++ .../EmbedProjectPage.test.tsx | 11 +++ .../EmbedProjectPage/EmbedProjectPage.tsx | 11 +++ docs/blog/2021-08-14-ux-studies-timeline.mdx | 43 +++++++++++ 9 files changed, 212 insertions(+) create mode 100644 app/web/src/components/EmbedProject/EmbedProject.tsx create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx create mode 100644 app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx create mode 100644 app/web/src/pages/EmbedProjectPage/EmbedProjectPage.test.tsx create mode 100644 app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx create mode 100644 docs/blog/2021-08-14-ux-studies-timeline.mdx diff --git a/app/web/src/Routes.js b/app/web/src/Routes.js index a2f053b..58578bc 100644 --- a/app/web/src/Routes.js +++ b/app/web/src/Routes.js @@ -56,6 +56,7 @@ const Routes = () => { + diff --git a/app/web/src/components/EmbedProject/EmbedProject.tsx b/app/web/src/components/EmbedProject/EmbedProject.tsx new file mode 100644 index 0000000..8a75697 --- /dev/null +++ b/app/web/src/components/EmbedProject/EmbedProject.tsx @@ -0,0 +1,32 @@ +import Seo from 'src/components/Seo/Seo' +import IdeViewer from 'src/components/IdeViewer/IdeViewer' +import { useIdeState } from 'src/helpers/hooks/useIdeState' +import type { Project } from 'src/components/EmbedProjectCell/EmbedProjectCell' +import { IdeContext } from 'src/helpers/hooks/useIdeContext' +import { use3dViewerResize } from 'src/helpers/hooks/use3dViewerResize' +import { useEffect } from 'react' + + +interface Props { + project?: Project +} + +const EmbedProject = ({ project }: Props) => { + const [state, thunkDispatch] = useIdeState() + const { viewerDomRef, handleViewerSizeUpdate } = use3dViewerResize() + + useEffect(() => { + console.log({ rect: viewerDomRef.current.getBoundingClientRect(), status: 'uh what?'}) + handleViewerSizeUpdate() + }, []) + + return ( +
+ + + +
+ ) +} + +export default EmbedProject diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts new file mode 100644 index 0000000..2e297e0 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.mock.ts @@ -0,0 +1,6 @@ +// Define your own mock data here: +export const standard = (/* vars, { ctx, req } */) => ({ + ideProject: { + id: 42, + }, +}) diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx new file mode 100644 index 0000000..77b02cf --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.stories.tsx @@ -0,0 +1,16 @@ +import { Loading, Empty, Success } from './EmbedProjectCell' +import { standard } from './EmbedProjectCell.mock' + +export const loading = () => { + return Loading ? : null +} + +export const empty = () => { + return Empty ? : null +} + +export const success = () => { + return Success ? : null +} + +export default { title: 'Cells/IdeProjectCell' } diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx new file mode 100644 index 0000000..9e770d4 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.test.tsx @@ -0,0 +1,21 @@ +import { render, screen } from '@redwoodjs/testing' +import { Loading, Empty, Success } from './EmbedProjectCell' +import { standard } from './EmbedProjectCell.mock' + +describe('IdeProjectCell', () => { + test('Loading renders successfully', () => { + render() + // Use screen.debug() to see output + expect(screen.getByText('Loading...')).toBeInTheDocument() + }) + + test('Empty renders successfully', async () => { + render() + expect(screen.getByText('Empty')).toBeInTheDocument() + }) + + test('Success renders successfully', async () => { + render() + expect(screen.getByText(/42/i)).toBeInTheDocument() + }) +}) diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx new file mode 100644 index 0000000..33398e8 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx @@ -0,0 +1,71 @@ +import useUser from 'src/helpers/hooks/useUser' +import EmbedProject from 'src/components/EmbedProject/EmbedProject' +import { useIdeState } from 'src/helpers/hooks/useIdeState' +import { IdeContext } from 'src/helpers/hooks/useIdeContext' + +export const QUERY = gql` + query FIND_PROJECT_BY_USENAME_TITLE( + $projectTitle: String! + $userName: String! + ) { + project: projectByUserAndTitle( + projectTitle: $projectTitle + userName: $userName + ) { + id + title + description + code + mainImage + createdAt + cadPackage + user { + id + userName + image + } + } + } +` + +export interface Project { + id: string + title: string + code: string + description: string + mainImage: string + createdAt: string + cadPackage: 'openscad' | 'cadquery' + user: { + id: string + userName: string + image: string + } +} + +export const Loading = () =>
Loading...
+ +export const Empty = () =>
Project not found
+ +interface SaveCodeArgs { + input: any + id: string + isFork: boolean +} + +export const Success = ({ + project, + refetch, +}: { + project: Project + refetch: any +}) => { + const [state, thunkDispatch] = useIdeState() + + + return ( + + + + ) +} \ No newline at end of file diff --git a/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.test.tsx b/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.test.tsx new file mode 100644 index 0000000..77b70df --- /dev/null +++ b/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.test.tsx @@ -0,0 +1,11 @@ +import { render } from '@redwoodjs/testing' + +import EmbedProjectPage from './EmbedProjectPage' + +describe('EmbedProjectPage', () => { + it('renders successfully', () => { + expect(() => { + render() + }).not.toThrow() + }) +}) diff --git a/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx b/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx new file mode 100644 index 0000000..bca9257 --- /dev/null +++ b/app/web/src/pages/EmbedProjectPage/EmbedProjectPage.tsx @@ -0,0 +1,11 @@ +import EmbedProjectCell from 'src/components/EmbedProjectCell' + +const EmbedProjectPage = ({ userName, projectTitle }) => { + return ( + <> + + + ) +} + +export default EmbedProjectPage diff --git a/docs/blog/2021-08-14-ux-studies-timeline.mdx b/docs/blog/2021-08-14-ux-studies-timeline.mdx new file mode 100644 index 0000000..9021d75 --- /dev/null +++ b/docs/blog/2021-08-14-ux-studies-timeline.mdx @@ -0,0 +1,43 @@ +--- +slug: ux-studies-intro +title: "GUI-CAD UX studies: introduction" +author: Frank Noirot +author_title: CadHub Core Team +author_url: https://github.com/franknoirot +author_image_url: https://avatars.githubusercontent.com/u/23481541?v=4 +tags: [] +--- + +import Image from '@theme/IdealImage'; + +import ivanSutherland from '../static/img/blog/ux-case-studies-intro/ivan-sutherland-sketchpad.jpg'; + +I'm helping CadHub out by designing the interfaces for the [new editor](https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/CadHub?node-id=1114%3A1608), [project viewer](https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/?node-id=1046%3A0), and [more](https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/?node-id=1150%3A1618). Right now we're focused on getting the Code-CAD user experience perfected so that users can try out all the great Code-CAD packages out there in a simple and sharable way. But we think that the future of Code-CAD will pull UX lessons from traditional, GUI-based CAD systems. So I'll be taking a look at the history and UX of some of today's CAD tools to see how we might bring them along with the Code-CAD evolution. + + + +## Why GUIs aren't enough anymore + +As others like [Jessie Frazelle](https://medium.com/embedded-ventures/mechanical-cad-yesterday-today-and-tomorrow-981cef7e06b1) have pointed out, the history of CAD software has been focused primarily on using software to emulate the frictionless user experiences of sketching and modelling by hand. That paradigm lead most of the major tools to build GUI-based systems, as they correctly assumed at the the time that the GUI offered an interface that could be understood by people in the industry. Decades have passed and the same assumption still forms the foundation of the paradigm, but could these assumptions have fundamentally changed? + +Ivan Sutherland's Sketchpad program from the 1960's, a man using a pen-like tool on a screen to manipulate a 2D model, considered the first CAD program. + +It's hard to understate how much of a sea change web development has brought to technical culture. In the past decade the web technologies of HTML, CSS, and especially JavaScript have trained a large part of technical workers to think not in terms of software packages, but in terms of the technologies and languages that are used to construct them, because as a culture we have become accustomed to the idea that there is always an API powering whatever tool we're using. Technical users of course still want seamless GUI user experiences on platforms, but increasingly they also want the ability to get under the hood and use the APIs that power whatever tool or platform they're on. This trend is evident in the rise of API-first services like [Stripe](https://stripe.com) and monolith-fracturing trends like [JAMstack web development](https://jamstack.org). + +With Code-CAD, we are putting a spotlight on this sea change in user expectations, and putting out a call to action for people to start creating experiences for this web-native, language-comfortable audience of CAD users. With CadHub, we're building a showcase for the great Code-CAD packages like [CadQuery](https://cadquery.readthedocs.io/en/latest/) and [OpenSCAD](https://openscad.org/) that have been under development by early adopters for years. + +## A Gooey Hegelian Dialectic + +Okay, so we in the Code-CAD community are a bunch of developers who want more interfaces from our CAD programs. We're comfortable with programming languages and APIs and we want access to them in addition to the GUIs that CAD has traditionally provided. That's all great, but then why isn't Code-CAD mainstream right now? + +For one, the process of building a robust, text-first approach to so visual an activity is, as [Kurt has written about](/blog/right-level-of-abstraction) on this blog, incredibly difficult. But the Code-CAD community has been doing the monumental work of developing clean, expressive APIs for modelling. That important work is what we want to showcase and make more accessible with CadHub. But we think it's only half of the equation for creating the next step in CAD. + +There are myriads of thorny user experience problems that have been solved by the dominant CAD packages of today. They are amazing pieces of software that users know and love. And all those clever UX solutions were created in the design space of GUIs. If Code-CAD as a paradigm is going to become the new normal for computer-aided design, we need to understand and address all the innovation that GUI-CAD has brought to design, and translate them into Code-CAD. We need to find a gooey-code synthesis. As previously stated, this new generation of users *still want seamless GUI experiences*. Code-CAD needs to provide a way of switching seamlessly between "Application Programming" and "Graphical User" interfaces. + +## Already under construction + +I'll try to explore that design space with a few brief case studies on UX that I love from existing CAD and 3D modelling software. I'm looking for key experiences that help empower designers, how they operate in the GUI-CAD paradigm, and how Code-CAD might provide code-based synonyms of these GUI experiences. + +But I want to mention that work is already being done on this front. Jeremy Wright of the CadQuery team is building [Semblage](https://semblage.7bindustries.com/en/latest/), a GUI-code hybrid built with CadQuery and the Godot gaming engine. [BuildBee](https://makecode.buildbee.com/) lets users switch between Scratch-like block interface and JavaScript code for making models. Blender provides an [excellent Python API](https://docs.blender.org/api/current/index.html) for almost all of its incredible functionality, and there a dozen other projects pushing things forward while we look to the present and the past for more inspiration. + +Our first stop will be the timeline feature of AutoDesk Fusion360, which is a clever way to make the order of operations in modelling intuitive. Stay tuned for this post and more in the coming weeks, check out our work on [GitHub](https://github.com/Irev-Dev/cadhub/discussions/404) and [Figma](https://www.figma.com/file/VUh53RdncjZ7NuFYj0RGB9/?node-id=633%3A0), sign up for [Kurt's newsletter](https://kurthutten.com/), and join [our Discord](https://discord.gg/sFYJyEJ6) to get plugged into our ongoing discussions about the future of Code-CAD. \ No newline at end of file -- 2.39.5 From 9b52bb85e22c8c17482a40d955d08bec912458fd Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sun, 9 Jan 2022 07:47:45 +1100 Subject: [PATCH 6/8] Fix openscad size bug --- app/web/src/components/EmbedViewer/EmbedViewer.tsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/app/web/src/components/EmbedViewer/EmbedViewer.tsx b/app/web/src/components/EmbedViewer/EmbedViewer.tsx index 6d28e98..1d27684 100644 --- a/app/web/src/components/EmbedViewer/EmbedViewer.tsx +++ b/app/web/src/components/EmbedViewer/EmbedViewer.tsx @@ -7,13 +7,17 @@ function EmbedViewer() { const { state, project } = useIdeContext() console.log('from EmbedViewer', { cadPackage: project.cadPackage, code: project.code }) useIdeInit(project?.cadPackage, project?.code || state?.code, "viewer") - const { viewerDomRef } = use3dViewerResize() + const { viewerDomRef, handleViewerSizeUpdate } = use3dViewerResize() + + React.useEffect(() => { + handleViewerSizeUpdate() + }, []) return ( -
+
) } -export default EmbedViewer \ No newline at end of file +export default EmbedViewer -- 2.39.5 From 49e8a235cedb76150d1ecda4b6c840e47e6a6c55 Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sat, 8 Jan 2022 23:33:33 -0500 Subject: [PATCH 7/8] Add overlays to embed --- .../EmbedProjectCell/EmbedProjectCell.tsx | 4 +- .../components/EmbedViewer/EmbedViewer.tsx | 25 ++++++--- .../src/components/IdeViewer/IdeViewer.tsx | 1 + .../components/IdeViewer/PureIdeViewer.tsx | 2 +- app/web/src/components/LogoType/LogoType.js | 43 +++++++++++++++ app/web/src/layouts/MainLayout/MainLayout.js | 52 +++++-------------- 6 files changed, 77 insertions(+), 50 deletions(-) create mode 100644 app/web/src/components/LogoType/LogoType.js diff --git a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx index b9f32fc..2a7f390 100644 --- a/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx @@ -1,7 +1,7 @@ import useUser from 'src/helpers/hooks/useUser' -import EmbedProject from 'src/components/EmbedProject/EmbedProject' import { useIdeState } from 'src/helpers/hooks/useIdeState' import { IdeContext } from 'src/helpers/hooks/useIdeContext' +import EmbedViewer from '../EmbedViewer/EmbedViewer' export const QUERY = gql` query FIND_PROJECT_BY_USENAME_TITLE( @@ -65,7 +65,7 @@ export const Success = ({ return ( - + ) } diff --git a/app/web/src/components/EmbedViewer/EmbedViewer.tsx b/app/web/src/components/EmbedViewer/EmbedViewer.tsx index 1d27684..77d3ed8 100644 --- a/app/web/src/components/EmbedViewer/EmbedViewer.tsx +++ b/app/web/src/components/EmbedViewer/EmbedViewer.tsx @@ -2,20 +2,31 @@ import { useIdeInit } from 'src/components/EncodedUrl/helpers' import { useIdeContext } from 'src/helpers/hooks/useIdeContext' import IdeViewer from 'src/components/IdeViewer/IdeViewer' import { use3dViewerResize } from 'src/helpers/hooks/use3dViewerResize' +import CadPackage from '../CadPackage/CadPackage' +import LogoType from '../LogoType/LogoType' +import { Link, routes } from '@redwoodjs/router' function EmbedViewer() { const { state, project } = useIdeContext() - console.log('from EmbedViewer', { cadPackage: project.cadPackage, code: project.code }) useIdeInit(project?.cadPackage, project?.code || state?.code, "viewer") - const { viewerDomRef, handleViewerSizeUpdate } = use3dViewerResize() - - React.useEffect(() => { - handleViewerSizeUpdate() - }, []) + const { viewerDomRef } = use3dViewerResize() return ( -
+
+
+

+ {project?.title.replace(/-/g, ' ')} +

+

by @{ project?.user?.userName }

+

built with

+
+
+ View on +
) } diff --git a/app/web/src/components/IdeViewer/IdeViewer.tsx b/app/web/src/components/IdeViewer/IdeViewer.tsx index f1bf741..a5d2ce0 100644 --- a/app/web/src/components/IdeViewer/IdeViewer.tsx +++ b/app/web/src/components/IdeViewer/IdeViewer.tsx @@ -53,6 +53,7 @@ const IdeViewer = ({ isLoading={state.isLoading} camera={state?.camera} ideType={ideType} + isMinimal={isMinimal} /> ) } diff --git a/app/web/src/components/IdeViewer/PureIdeViewer.tsx b/app/web/src/components/IdeViewer/PureIdeViewer.tsx index 33f5e46..8b0f56f 100644 --- a/app/web/src/components/IdeViewer/PureIdeViewer.tsx +++ b/app/web/src/components/IdeViewer/PureIdeViewer.tsx @@ -212,7 +212,7 @@ export function PureIdeViewer({ alt="code-cad preview" id="special" src={URL.createObjectURL(image)} - className="h-full w-full" + className="w-full h-full" />
)} diff --git a/app/web/src/components/LogoType/LogoType.js b/app/web/src/components/LogoType/LogoType.js new file mode 100644 index 0000000..450ac4f --- /dev/null +++ b/app/web/src/components/LogoType/LogoType.js @@ -0,0 +1,43 @@ +import Tooltip from '@material-ui/core/Tooltip' +import { Link, routes } from '@redwoodjs/router' +import Svg from 'src/components/Svg' + +export default function LogoType({ className="", wrappedInLink=false }) { + return ( +
    +
  • + { (wrappedInLink + ? +
    + +
    + + :
    +
    + +
    +
    + )} +
  • +
  • + +
    + {/* Because of how specific these styles are to this heading/logo and it doesn't need to be replicated else where as well as it's very precise with the placement of "pre-alpha" I think it's appropriate. */} +

    + CadHub +

    +
    + pre-alpha +
    +
    +
    +
  • +
+ ) +} \ No newline at end of file diff --git a/app/web/src/layouts/MainLayout/MainLayout.js b/app/web/src/layouts/MainLayout/MainLayout.js index fd17a0f..7061590 100644 --- a/app/web/src/layouts/MainLayout/MainLayout.js +++ b/app/web/src/layouts/MainLayout/MainLayout.js @@ -2,7 +2,6 @@ import { useState, useEffect } from 'react' import { Link, routes, navigate } from '@redwoodjs/router' import { useAuth } from '@redwoodjs/auth' import { Toaster, toast } from '@redwoodjs/web/toast' -import Tooltip from '@material-ui/core/Tooltip' import { Popover } from '@headlessui/react' import { getActiveClasses } from 'get-active-classes' import Footer from 'src/components/Footer' @@ -12,11 +11,11 @@ import NavPlusButton from 'src/components/NavPlusButton' import ReactGA from 'react-ga' import { isBrowser } from '@redwoodjs/prerender/browserUtils' -import Svg from 'src/components/Svg' import { ImageFallback } from 'src/components/ImageUploader' import useUser from 'src/helpers/hooks/useUser' import './MainLayout.css' import RecentProjectsCell from 'src/components/RecentProjectsCell' +import LogoType from 'src/components/LogoType' let previousSubmission = '' @@ -72,39 +71,12 @@ const MainLayout = ({ children, shouldRemoveFooterInIde }) => { }, [hash, client]) return (