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/CONTRIBUTING.md b/CONTRIBUTING.md index fd4f9ff..014721a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -32,9 +32,9 @@ Install dependencies yarn install ``` -Setting up the db, you'll need to have a postgres installed locally, you can [follow this guide](https://redwoodjs.com/docs/local-postgres-setup). +Setting up the db, you'll need to have a postgres installed locally, you can [follow this guide](https://redwoodjs.com/docs/local-postgres-setup). -Run the following +Run the following (Note: these commands require the `DATABASE_URL` env variable to be set. if you see no result when you run `echo $DATABASE_URL`, you can set it with a command like `export DATABASE_URL=postgres://postgres:somepassword@localhost`) ``` terminal yarn rw prisma migrate dev yarn rw prisma db seed diff --git a/app/api/db/schema.prisma b/app/api/db/schema.prisma index e62813d..9b02179 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/EditorMenu/menuConfig.tsx b/app/web/src/components/EditorMenu/menuConfig.tsx index 4408ad9..1e6d41b 100644 --- a/app/web/src/components/EditorMenu/menuConfig.tsx +++ b/app/web/src/components/EditorMenu/menuConfig.tsx @@ -1,6 +1,6 @@ import React from 'react' import { useRender } from 'src/components/IdeWrapper/useRender' -import { makeStlDownloadHandler, PullTitleFromFirstLine } from './helpers' +import { makeStlDownloadHandler, PullTitleFromFirstLine } from 'src/helpers/download_stl' import { useSaveCode } from 'src/components/IdeWrapper/useSaveCode' import { DropdownItem } from './Dropdowns' import { useShortcutsModalContext } from './AllShortcutsModal' diff --git a/app/web/src/components/EmbedProject/EmbedProject.tsx b/app/web/src/components/EmbedProject/EmbedProject.tsx new file mode 100644 index 0000000..a8ef33c --- /dev/null +++ b/app/web/src/components/EmbedProject/EmbedProject.tsx @@ -0,0 +1,31 @@ +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(() => { + 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..d55e518 --- /dev/null +++ b/app/web/src/components/EmbedProjectCell/EmbedProjectCell.tsx @@ -0,0 +1,47 @@ +import { useIdeState } from 'src/helpers/hooks/useIdeState' +import { IdeContext } from 'src/helpers/hooks/useIdeContext' +import EmbedViewer from '../EmbedViewer/EmbedViewer' +import { QUERY as IdeQuery } from 'src/components/IdeProjectCell' + +export const QUERY = IdeQuery +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..77d3ed8 --- /dev/null +++ b/app/web/src/components/EmbedViewer/EmbedViewer.tsx @@ -0,0 +1,34 @@ +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() + useIdeInit(project?.cadPackage, project?.code || state?.code, "viewer") + const { viewerDomRef } = use3dViewerResize() + + return ( +
+ +
+

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

+

by @{ project?.user?.userName }

+

built with

+
+
+ View on +
+
+ ) +} + +export default EmbedViewer diff --git a/app/web/src/components/IdeViewer/IdeViewer.tsx b/app/web/src/components/IdeViewer/IdeViewer.tsx index d1045c3..a5d2ce0 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 @@ -41,7 +43,7 @@ const IdeViewer = ({ } }) } - + return ( ) } 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/components/ProjectCell/ProjectCell.tsx b/app/web/src/components/ProjectCell/ProjectCell.tsx index 8c41c20..5fafc4e 100644 --- a/app/web/src/components/ProjectCell/ProjectCell.tsx +++ b/app/web/src/components/ProjectCell/ProjectCell.tsx @@ -2,6 +2,7 @@ import { useMutation } from '@redwoodjs/web' import { toast } from '@redwoodjs/web/toast' import { navigate, routes } from '@redwoodjs/router' import { useAuth } from '@redwoodjs/auth' +import { makeStlDownloadHandler } from 'src/helpers/download_stl' import { useIdeState } from 'src/helpers/hooks/useIdeState' import { IdeContext } from 'src/helpers/hooks/useIdeContext' import { CREATE_PROJECT_MUTATION } from 'src/components/NavPlusButton/NavPlusButton' @@ -192,6 +193,15 @@ export const Success = ({ userProject, refetch }) => { }, }) + const onStlDownload = makeStlDownloadHandler({ + type: state.objectData?.type, + ideType: state.ideType, + geometry: state.objectData?.data, + quality: state.objectData?.quality, + fileName: `${userProject.title }.stl`, + thunkDispatch, + }) + return ( { onDelete={onDelete} onReaction={onReaction} onComment={onComment} + onStlDownload={onStlDownload} /> ) diff --git a/app/web/src/components/ProjectProfile/ProjectProfile.tsx b/app/web/src/components/ProjectProfile/ProjectProfile.tsx index bb8cd1b..65019c0 100644 --- a/app/web/src/components/ProjectProfile/ProjectProfile.tsx +++ b/app/web/src/components/ProjectProfile/ProjectProfile.tsx @@ -25,6 +25,7 @@ const ProjectProfile = ({ onDelete, onReaction, onComment, + onStlDownload, }) => { const [comment, setComment] = useState('') const [isEditing, setIsEditing] = useState(false) @@ -52,6 +53,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()) @@ -91,12 +93,25 @@ const ProjectProfile = ({

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

-
- Built with - +
+
+ Built with + +
+
{(project?.description || hasPermissionToEdit) && ( ), + 'document-download': ( + + + + ), 'dots-vertical': ( new MeshPhongMaterial(params), }, line: { 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', diff --git a/app/web/src/components/EditorMenu/helpers.ts b/app/web/src/helpers/download_stl.ts similarity index 100% rename from app/web/src/components/EditorMenu/helpers.ts rename to app/web/src/helpers/download_stl.ts 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 (