From 96ee9c4aa417f74dd32ee4419d27e267a1dccc67 Mon Sep 17 00:00:00 2001 From: Jeremy Wright Date: Thu, 14 Oct 2021 11:39:03 -0400 Subject: [PATCH 1/3] Add CadQuery customizer (#547) * Rough changes to make the CadQuery integration work with the customizer * Tweak runCQ * Switched to Anaconda * Cleaned up code * Update CadHub after anaconda Related to #547 * Add final tweaks to CQ customizer * Separated out customizer.json from params.json * Changes after discussing CadHub integration * linting runCQ Co-authored-by: Kurt Hutten --- app/api/src/docker/cadquery/Dockerfile | 27 +++++--- app/api/src/docker/cadquery/runCQ.ts | 22 +++++-- app/api/src/docker/openscad/Dockerfile | 2 +- .../{ => cadQuery}/cadQueryController.ts | 14 +++-- .../cadPackages/cadQuery/cadQueryParams.ts | 63 +++++++++++++++++++ app/web/src/helpers/cadPackages/index.ts | 2 +- 6 files changed, 110 insertions(+), 20 deletions(-) rename app/web/src/helpers/cadPackages/{ => cadQuery}/cadQueryController.ts (78%) create mode 100644 app/web/src/helpers/cadPackages/cadQuery/cadQueryParams.ts diff --git a/app/api/src/docker/cadquery/Dockerfile b/app/api/src/docker/cadquery/Dockerfile index 0589092..e529ccf 100644 --- a/app/api/src/docker/cadquery/Dockerfile +++ b/app/api/src/docker/cadquery/Dockerfile @@ -1,8 +1,9 @@ FROM public.ecr.aws/lts/ubuntu:20.04_stable - +ENV PATH="/root/miniconda3/bin:${PATH}" +ARG PATH="/root/miniconda3/bin:${PATH}" ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update -qq +RUN apt-get update --fix-missing -qq RUN apt-get -y -qq install software-properties-common dirmngr apt-transport-https lsb-release ca-certificates xvfb RUN apt-get update -qq RUN apt-get install -y wget @@ -21,7 +22,9 @@ RUN apt-get update && \ cmake \ unzip \ automake autoconf libtool \ - libcurl4-openssl-dev + libcurl4-openssl-dev \ + curl \ + git # Add the lambda emulator for local dev, (see entrypoint.sh for where it's used), # I have the file locally (gitignored) to speed up build times (as it downloads everytime), @@ -35,15 +38,23 @@ COPY package*.json /var/task/ RUN npm install RUN npm install aws-lambda-ric@1.0.0 +# Install Miniconda +RUN wget \ + https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \ + && bash Miniconda3-latest-Linux-x86_64.sh -b \ + && rm -f Miniconda3-latest-Linux-x86_64.sh +RUN conda --version + +# Install CadQuery +RUN conda install -c cadquery -c conda-forge cadquery=master ocp=7.5.2 python=3.8 +RUN conda info + +# Get a copy of cq-cli from GitHub +RUN git clone https://github.com/CadQuery/cq-cli.git # Get the distribution copy of cq-cli RUN apt-get install -y libglew2.1 -RUN wget https://github.com/CadQuery/cq-cli/releases/download/v2.2-beta.2/cq-cli-Linux-x86_64.zip -# Comment the entry above out and uncomment the one below to revert to the stable release -# RUN wget https://github.com/CadQuery/cq-cli/releases/download/v2.1.0/cq-cli-Linux-x86_64.zip -RUN unzip cq-cli-Linux-x86_64.zip -RUN chmod +x cq-cli/cq-cli RUN echo "cadhub-concat-split" > /var/task/cadhub-concat-split # using built javascript from dist diff --git a/app/api/src/docker/cadquery/runCQ.ts b/app/api/src/docker/cadquery/runCQ.ts index afcb916..64576cd 100644 --- a/app/api/src/docker/cadquery/runCQ.ts +++ b/app/api/src/docker/cadquery/runCQ.ts @@ -1,31 +1,45 @@ import { writeFiles, runCommand } from '../common/utils' import { nanoid } from 'nanoid' +import { readFile } from 'fs/promises' export const runCQ = async ({ file, - settings: { deflection = 0.3 } = {}, + settings: { deflection = 0.3, parameters } = {}, } = {}) => { const tempFile = await writeFiles( - [{ file, fileName: 'main.py' }], + [ + { file, fileName: 'main.py' }, + { + file: JSON.stringify(parameters), + fileName: 'params.json', + }, + ], 'a' + nanoid() // 'a' ensure nothing funny happens if it start with a bad character like "-", maybe I should pick a safer id generator :shrug: ) const fullPath = `/tmp/${tempFile}/output.gz` const stlPath = `/tmp/${tempFile}/output.stl` + const customizerPath = `/tmp/${tempFile}/customizer.json` const command = [ - `cq-cli/cq-cli`, + `./cq-cli/cq-cli.py`, `--codec stl`, `--infile /tmp/${tempFile}/main.py`, `--outfile ${stlPath}`, `--outputopts "deflection:${deflection};angularDeflection:${deflection};"`, + `--params /tmp/${tempFile}/params.json`, + `--getparams ${customizerPath}`, ].join(' ') console.log('command', command) let consoleMessage = '' try { consoleMessage = await runCommand(command, 30000) + const params = JSON.parse( + await readFile(customizerPath, { encoding: 'ascii' }) + ) await writeFiles( [ { file: JSON.stringify({ + customizerParams: params, consoleMessage, type: 'stl', }), @@ -41,6 +55,6 @@ export const runCQ = async ({ ) return { consoleMessage, fullPath } } catch (error) { - return { error: consoleMessage, fullPath } + return { error: consoleMessage || error, fullPath } } } diff --git a/app/api/src/docker/openscad/Dockerfile b/app/api/src/docker/openscad/Dockerfile index 001730d..d17153a 100644 --- a/app/api/src/docker/openscad/Dockerfile +++ b/app/api/src/docker/openscad/Dockerfile @@ -3,7 +3,7 @@ FROM public.ecr.aws/lts/ubuntu:20.04_stable ARG DEBIAN_FRONTEND=noninteractive ## install things needed to run openscad (xvfb is an important one) -RUN apt-get update -qq +RUN apt-get update --fix-missing -qq # double check this below, I'm not sure we need inkscape etc RUN apt-get -y -qq install software-properties-common dirmngr apt-transport-https lsb-release ca-certificates xvfb imagemagick unzip inkscape RUN apt-get install -y curl wget diff --git a/app/web/src/helpers/cadPackages/cadQueryController.ts b/app/web/src/helpers/cadPackages/cadQuery/cadQueryController.ts similarity index 78% rename from app/web/src/helpers/cadPackages/cadQueryController.ts rename to app/web/src/helpers/cadPackages/cadQuery/cadQueryController.ts index 5f77b93..21d9659 100644 --- a/app/web/src/helpers/cadPackages/cadQueryController.ts +++ b/app/web/src/helpers/cadPackages/cadQuery/cadQueryController.ts @@ -7,15 +7,17 @@ import { RenderArgs, DefaultKernelExport, splitGziped, -} from './common' +} from '../common' +import { CadQueryToCadhubParams } from './cadQueryParams' export const render: DefaultKernelExport['render'] = async ({ code, - settings: { quality = 'low' }, + settings: { quality = 'low', parameters }, }: RenderArgs) => { const body = JSON.stringify({ settings: { deflection: quality === 'low' ? 0.35 : 0.11, + parameters, }, file: code, }) @@ -43,21 +45,21 @@ export const render: DefaultKernelExport['render'] = async ({ } const blob = await response.blob() const text = await new Response(blob).text() - const { consoleMessage } = splitGziped(text) + const { consoleMessage, customizerParams, type } = splitGziped(text) return createHealthyResponse({ type: 'geometry', data: await stlToGeometry(window.URL.createObjectURL(blob)), consoleMessage, date: new Date(), + customizerParams: CadQueryToCadhubParams(customizerParams), }) } catch (e) { return createUnhealthyResponse(new Date()) } } -const openscad: DefaultKernelExport = { +const cadQuery: DefaultKernelExport = { render, - // more functions to come } -export default openscad +export default cadQuery diff --git a/app/web/src/helpers/cadPackages/cadQuery/cadQueryParams.ts b/app/web/src/helpers/cadPackages/cadQuery/cadQueryParams.ts new file mode 100644 index 0000000..4df9492 --- /dev/null +++ b/app/web/src/helpers/cadPackages/cadQuery/cadQueryParams.ts @@ -0,0 +1,63 @@ +import { CadhubParams } from 'src/components/Customizer/customizerConverter' + +interface CadQueryParamsBase { + name: string + initial: number | string | boolean + type?: 'number' | 'string' | 'boolean' +} + +interface CadQueryNumberParam extends CadQueryParamsBase { + type: 'number' + initial: number +} + +interface CadQueryStringParam extends CadQueryParamsBase { + type: 'string' + initial: string +} + +interface CadQueryBooleanParam extends CadQueryParamsBase { + type: 'boolean' + initial: boolean +} + +export type CadQueryStringParams = + | CadQueryNumberParam + | CadQueryStringParam + | CadQueryBooleanParam + +export function CadQueryToCadhubParams( + input: CadQueryStringParams[] +): CadhubParams[] { + return input + .map((param): CadhubParams => { + const common: { caption: string; name: string } = { + caption: '', + name: param.name, + } + switch (param.type) { + case 'number': + return { + type: 'number', + input: 'default-number', + ...common, + initial: param.initial, + } + case 'string': + return { + type: 'string', + input: 'default-string', + ...common, + initial: param.initial, + } + case 'boolean': + return { + type: 'boolean', + input: 'default-boolean', + ...common, + initial: param.initial, + } + } + }) + .filter((a) => a) +} diff --git a/app/web/src/helpers/cadPackages/index.ts b/app/web/src/helpers/cadPackages/index.ts index f1d3053..ea420c6 100644 --- a/app/web/src/helpers/cadPackages/index.ts +++ b/app/web/src/helpers/cadPackages/index.ts @@ -5,7 +5,7 @@ import openscad from './openScad/openScadController' import openScadGuide from 'src/helpers/cadPackages/openScad/userGuide.md' import openScadInitialCode from 'src/helpers/cadPackages/openScad/initialCode.scad' -import cadquery from './cadQueryController' +import cadquery from './cadQuery/cadQueryController' import cadQueryGuide from 'src/helpers/cadPackages/cadQuery/userGuide.md' import cadQueryInitialCode from 'src/helpers/cadPackages/cadQuery/initialCode.py' -- 2.39.5 From 7c6cc0f5c8e1fa3ed4baebe91c1b67ec4099b8ec Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Fri, 15 Oct 2021 17:33:20 +1100 Subject: [PATCH 2/3] Refactor recent projects into it's own cell --- .../ProfileSlashLogin/ProfileSlashLogin.tsx | 28 ++--------- app/web/src/components/Projects/Projects.tsx | 34 +++----------- .../components/ProjectsCell/ProjectsCell.tsx | 15 +----- .../ProjectsOfUserCell/ProjectsOfUserCell.tsx | 12 ++--- .../RecentProjectsCell/RecentProjectsCell.tsx | 46 +++++++++++++++++++ app/web/src/layouts/MainLayout/MainLayout.js | 8 +--- 6 files changed, 66 insertions(+), 77 deletions(-) create mode 100644 app/web/src/components/RecentProjectsCell/RecentProjectsCell.tsx diff --git a/app/web/src/components/ProfileSlashLogin/ProfileSlashLogin.tsx b/app/web/src/components/ProfileSlashLogin/ProfileSlashLogin.tsx index f4102a4..c0ba080 100644 --- a/app/web/src/components/ProfileSlashLogin/ProfileSlashLogin.tsx +++ b/app/web/src/components/ProfileSlashLogin/ProfileSlashLogin.tsx @@ -7,33 +7,13 @@ import { ImageFallback } from 'src/components/ImageUploader' import useUser from 'src/helpers/hooks/useUser' import LoginModal from 'src/components/LoginModal' -import Gravatar from 'src/components/Gravatar/Gravatar' -import ProjectsOfUserCell from 'src/components/ProjectsOfUserCell' +import RecentProjectsCell from 'src/components/RecentProjectsCell' const ProfileSlashLogin = () => { - const { logOut, isAuthenticated, currentUser, client } = useAuth() + const { logOut, isAuthenticated, currentUser } = useAuth() const { user, loading } = useUser() const [isLoginModalOpen, setIsLoginModalOpen] = useState(false) - const [isOpen, setIsOpen] = useState(false) - const [anchorEl, setAnchorEl] = useState(null) - const [popoverId, setPopoverId] = useState(undefined) - const openPopover = (target) => { - setAnchorEl(target) - setPopoverId('simple-popover') - setIsOpen(true) - } - const closePopover = () => { - setAnchorEl(null) - setPopoverId(undefined) - setIsOpen(false) - } - const togglePopover = ({ currentTarget }) => { - if (isOpen) { - return closePopover() - } - openPopover(currentTarget) - } const recordedLogin = () => { ReactGA.event({ category: 'login', @@ -87,9 +67,7 @@ const ProfileSlashLogin = () => {

Recent Projects

- diff --git a/app/web/src/components/Projects/Projects.tsx b/app/web/src/components/Projects/Projects.tsx index 14d541e..8753d40 100644 --- a/app/web/src/components/Projects/Projects.tsx +++ b/app/web/src/components/Projects/Projects.tsx @@ -1,17 +1,15 @@ import { useMemo } from 'react' -import { Link, routes } from '@redwoodjs/router' -import Svg from 'src/components/Svg/Svg' -import CadPackage from 'src/components/CadPackage/CadPackage' - -import { countEmotes } from 'src/helpers/emote' -import ImageUploader from 'src/components/ImageUploader' +import type { Projects_Of_User } from 'types/graphql' import ProjectCard from 'src/components/ProjectCard/ProjectCard' const ProjectsList = ({ projects, shouldFilterProjectsWithoutImage = false, projectLimit = 80, - isMinimal = false, +}: { + projects: Projects_Of_User['projects'] + shouldFilterProjectsWithoutImage: boolean + projectLimit: number }) => { // temporary filtering projects that don't have images until some kind of search is added and there are more things on the website // it helps avoid the look of the website just being filled with dumby data. @@ -34,7 +32,7 @@ const ProjectsList = ({ [projects, shouldFilterProjectsWithoutImage] ) - return !isMinimal ? ( + return (
    ( ) )}
- ) : ( -
-
    - {filteredProjects.map(({ title, user }, index) => ( - -

    {title.replace(/[-_]/g, ' ')}

    - - ))} -
-
) } diff --git a/app/web/src/components/ProjectsCell/ProjectsCell.tsx b/app/web/src/components/ProjectsCell/ProjectsCell.tsx index cccc6fe..55c9101 100644 --- a/app/web/src/components/ProjectsCell/ProjectsCell.tsx +++ b/app/web/src/components/ProjectsCell/ProjectsCell.tsx @@ -27,30 +27,19 @@ export const QUERY = gql` export const Loading = () =>
Loading...
-export const Empty = ({ isMinimal = false }) => { - return !isMinimal ? ( -
- {'No projects yet. '} - - {'Create one?'} - -
- ) : ( -

None yet!

- ) +export const Empty = () => { + return
{'No projects yet.'}
} export const Success = ({ projects, variables: { shouldFilterProjectsWithoutImage, projectLimit }, - isMinimal = false, }) => { return ( ) } diff --git a/app/web/src/components/ProjectsOfUserCell/ProjectsOfUserCell.tsx b/app/web/src/components/ProjectsOfUserCell/ProjectsOfUserCell.tsx index bddd1c2..b199806 100644 --- a/app/web/src/components/ProjectsOfUserCell/ProjectsOfUserCell.tsx +++ b/app/web/src/components/ProjectsOfUserCell/ProjectsOfUserCell.tsx @@ -1,7 +1,5 @@ -import { Link, routes } from '@redwoodjs/router' - +import type { Projects_Of_User } from 'types/graphql' import Projects from 'src/components/Projects/Projects' - export const QUERY = gql` query PROJECTS_OF_USER($userName: String!) { projects(userName: $userName) { @@ -20,6 +18,7 @@ export const QUERY = gql` userName } Reaction { + id emote } } @@ -38,17 +37,18 @@ export const Empty = ({ isMinimal = false }) => { export const Success = ({ projects, - variables: { userName }, shouldFilterProjectsWithoutImage = false, projectLimit = 80, - isMinimal = false, +}: { + projects: Projects_Of_User['projects'] + shouldFilterProjectsWithoutImage: boolean + projectLimit: number }) => { return ( ) } diff --git a/app/web/src/components/RecentProjectsCell/RecentProjectsCell.tsx b/app/web/src/components/RecentProjectsCell/RecentProjectsCell.tsx new file mode 100644 index 0000000..f64c443 --- /dev/null +++ b/app/web/src/components/RecentProjectsCell/RecentProjectsCell.tsx @@ -0,0 +1,46 @@ +import type { CellSuccessProps, CellFailureProps } from '@redwoodjs/web' + +import type { Projects_Of_User } from 'types/graphql' +import { Link, routes } from '@redwoodjs/router' +import { QUERY as _QUERY } from 'src/components/ProjectsOfUserCell/ProjectsOfUserCell' + +export const QUERY = _QUERY + +export const Loading = () =>
Loading...
+ +export const Empty = () =>

None yet!

+ +export const Failure = ({ error }: CellFailureProps) => ( +
Error: {error.message}
+) + +export const Success = ({ projects }: CellSuccessProps) => { + const filteredProjects = React.useMemo( + () => + projects + .slice(0, 3) + .sort( + (a, b) => + new Date(b.updatedAt).getTime() - new Date(a.updatedAt).getTime() + ), + [projects] + ) + return ( +
+
    + {filteredProjects.map(({ title, user }, index) => ( + +

    {title.replace(/[-_]/g, ' ')}

    + + ))} +
+
+ ) +} diff --git a/app/web/src/layouts/MainLayout/MainLayout.js b/app/web/src/layouts/MainLayout/MainLayout.js index d4c65e1..fd17a0f 100644 --- a/app/web/src/layouts/MainLayout/MainLayout.js +++ b/app/web/src/layouts/MainLayout/MainLayout.js @@ -16,7 +16,7 @@ import Svg from 'src/components/Svg' import { ImageFallback } from 'src/components/ImageUploader' import useUser from 'src/helpers/hooks/useUser' import './MainLayout.css' -import ProjectsOfUserCell from 'src/components/ProjectsOfUserCell' +import RecentProjectsCell from 'src/components/RecentProjectsCell' let previousSubmission = '' @@ -152,11 +152,7 @@ const MainLayout = ({ children, shouldRemoveFooterInIde }) => {

Recent Projects

- + )} -- 2.39.5 From 434eb0ef86bc513251308ab12fb8e474140a69c0 Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Fri, 15 Oct 2021 18:06:31 +1100 Subject: [PATCH 3/3] Release CQ customizer (#559) * Switched to Miniconda image * Update cad endpoint url and some minor tweaks Co-authored-by: Jeremy Wright Co-authored-by: Jeremy Wright --- app/api/src/docker/cadquery/Dockerfile | 7 +------ app/api/src/docker/cadquery/runCQ.ts | 2 +- app/web/src/helpers/cadPackages/common.ts | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/app/api/src/docker/cadquery/Dockerfile b/app/api/src/docker/cadquery/Dockerfile index e529ccf..86bfb7d 100644 --- a/app/api/src/docker/cadquery/Dockerfile +++ b/app/api/src/docker/cadquery/Dockerfile @@ -1,4 +1,4 @@ -FROM public.ecr.aws/lts/ubuntu:20.04_stable +FROM continuumio/miniconda3 ENV PATH="/root/miniconda3/bin:${PATH}" ARG PATH="/root/miniconda3/bin:${PATH}" ARG DEBIAN_FRONTEND=noninteractive @@ -38,11 +38,6 @@ COPY package*.json /var/task/ RUN npm install RUN npm install aws-lambda-ric@1.0.0 -# Install Miniconda -RUN wget \ - https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh \ - && bash Miniconda3-latest-Linux-x86_64.sh -b \ - && rm -f Miniconda3-latest-Linux-x86_64.sh RUN conda --version # Install CadQuery diff --git a/app/api/src/docker/cadquery/runCQ.ts b/app/api/src/docker/cadquery/runCQ.ts index 64576cd..2f73e68 100644 --- a/app/api/src/docker/cadquery/runCQ.ts +++ b/app/api/src/docker/cadquery/runCQ.ts @@ -20,7 +20,7 @@ export const runCQ = async ({ const stlPath = `/tmp/${tempFile}/output.stl` const customizerPath = `/tmp/${tempFile}/customizer.json` const command = [ - `./cq-cli/cq-cli.py`, + `/var/task/cq-cli/cq-cli.py`, `--codec stl`, `--infile /tmp/${tempFile}/main.py`, `--outfile ${stlPath}`, diff --git a/app/web/src/helpers/cadPackages/common.ts b/app/web/src/helpers/cadPackages/common.ts index 4fac6ff..4edbd8b 100644 --- a/app/web/src/helpers/cadPackages/common.ts +++ b/app/web/src/helpers/cadPackages/common.ts @@ -4,7 +4,7 @@ import { CadhubParams } from 'src/components/Customizer/customizerConverter' export const lambdaBaseURL = process.env.CAD_LAMBDA_BASE_URL || - 'https://oxt2p7ddgj.execute-api.us-east-1.amazonaws.com/prod' + 'https://2inlbple1b.execute-api.us-east-1.amazonaws.com/prod2' export const stlToGeometry = (url) => new Promise((resolve, reject) => { -- 2.39.5