From 2f006d3e3ba6777b988c6b7ff564c958c9451b22 Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sat, 18 Sep 2021 19:54:54 -0400 Subject: [PATCH 01/11] Added test tabs, got closing and switching working --- .../src/components/IdeEditor/IdeEditor.tsx | 49 +++++++++++++---- .../helpers/cadPackages/cadQuery/userGuide.md | 12 +++++ .../helpers/cadPackages/jsCad/userGuide.md | 7 +++ .../helpers/cadPackages/openScad/userGuide.md | 7 +++ app/web/src/helpers/hooks/useIdeState.ts | 54 +++++++++++++++++++ 5 files changed, 119 insertions(+), 10 deletions(-) create mode 100644 app/web/src/helpers/cadPackages/cadQuery/userGuide.md create mode 100644 app/web/src/helpers/cadPackages/jsCad/userGuide.md create mode 100644 app/web/src/helpers/cadPackages/openScad/userGuide.md diff --git a/app/web/src/components/IdeEditor/IdeEditor.tsx b/app/web/src/components/IdeEditor/IdeEditor.tsx index 97b9060..06fcd1f 100644 --- a/app/web/src/components/IdeEditor/IdeEditor.tsx +++ b/app/web/src/components/IdeEditor/IdeEditor.tsx @@ -73,16 +73,45 @@ const IdeEditor = ({ Loading }) => { className="h-full" onKeyDown={handleSaveHotkey} > - + { (state.models.length > 1) && ( +
+ { state.models.map((model, i) => ( + + )) } +
+ )} + { (state.models[state.currentModel].type === 'code') + ? + :
{ state.models[state.currentModel].content }
+ } ) } diff --git a/app/web/src/helpers/cadPackages/cadQuery/userGuide.md b/app/web/src/helpers/cadPackages/cadQuery/userGuide.md new file mode 100644 index 0000000..83d28ae --- /dev/null +++ b/app/web/src/helpers/cadPackages/cadQuery/userGuide.md @@ -0,0 +1,12 @@ +--- +"Written with": Python +"Kernal type": BREP +--- +# CadQuery + +CadQuery is an intuitive, easy-to-use Python library for building parametric 3D CAD models. It has several goals: + +- Build models with scripts that are as close as possible to how you’d describe the object to a human, using a standard, already established programming language +- Create parametric models that can be very easily customized by end users +- Output high quality CAD formats like STEP and AMF in addition to traditional STL +- Provide a non-proprietary, plain text model format that can be edited and executed with only a web browser \ No newline at end of file diff --git a/app/web/src/helpers/cadPackages/jsCad/userGuide.md b/app/web/src/helpers/cadPackages/jsCad/userGuide.md new file mode 100644 index 0000000..b199867 --- /dev/null +++ b/app/web/src/helpers/cadPackages/jsCad/userGuide.md @@ -0,0 +1,7 @@ +--- +"Written with": JavaScript +"Kernal type": BREP +--- +# JSCAD + +JSCAD is an open source set of modular, browser and command line tools for creating parametric 2D and 3D designs with Javascript code. It provides a quick, precise and reproducible method for generating 3D models, and is especially useful for 3D printing applications. \ No newline at end of file diff --git a/app/web/src/helpers/cadPackages/openScad/userGuide.md b/app/web/src/helpers/cadPackages/openScad/userGuide.md new file mode 100644 index 0000000..a04c417 --- /dev/null +++ b/app/web/src/helpers/cadPackages/openScad/userGuide.md @@ -0,0 +1,7 @@ +--- +"Written with": C+-like +"Kernal type": BREP +--- +# OpenSCAD + +OpenSCAD is a solid 3D modeler that enables the creation of parametric models using its scripting language. Models are created by utilizing a technique called constructive solid geometry. According to this technique, simple objects can be transformed and combined in order to create almost any complex model. \ No newline at end of file diff --git a/app/web/src/helpers/hooks/useIdeState.ts b/app/web/src/helpers/hooks/useIdeState.ts index 0e64da2..5dc6121 100644 --- a/app/web/src/helpers/hooks/useIdeState.ts +++ b/app/web/src/helpers/hooks/useIdeState.ts @@ -95,10 +95,18 @@ interface XYZ { z: number } +interface EditorModel { + type: 'code' | 'guide' + label: string + content?: string +} + export interface State { ideType: 'INIT' | CadPackageType consoleMessages: { type: 'message' | 'error'; message: string; time: Date }[] code: string + models: EditorModel[] + currentModel: number objectData: { type: 'INIT' | ArtifactTypes data: any @@ -136,6 +144,11 @@ export const initialState: State = { { type: 'message', message: 'Initialising', time: new Date() }, ], code, + models: [ + { type: 'code', label: 'Code', }, + { type: 'guide', label: 'Test', content: '# Testing!' }, + ], + currentModel: 0, objectData: { type: 'INIT', data: null, @@ -269,6 +282,47 @@ const reducer = (state: State, { type, payload }): State => { ...state, sideTray: payload, } + case 'switchEditorModel': + return { + ...state, + currentModel: payload, + } + case 'addEditorModel': + return { + ...state, + models: [ + ...state.models, + payload, + ] + } + case 'removeEditorModel': + return { + ...state, + models: [ + ...state.models.slice(0, payload), + ...state.models.slice(payload + 1), + ], + currentModel: (payload === 0) ? 0 : payload - 1, + } + case 'updateEditorModel': { + let newModels = [...state.models] + newModels[state.currentModel].content = payload + return { + ...state, + models: newModels, + } + } + case 'reorderEditorModels': { + let newModels = [ + ...state.models.slice(0, state.currentModel), + ...state.models.slice(state.currentModel + 1) + ].splice(payload, 0, state.models[state.currentModel]) + return { + ...state, + models: newModels, + currentModel: payload, + } + } default: return state } From b27bcd2d352d0704cfb05c0aba1f5f19cfe4a15d Mon Sep 17 00:00:00 2001 From: Frank Johnson Date: Sat, 18 Sep 2021 23:16:43 -0400 Subject: [PATCH 02/11] Completed initial CAD package guides, tweaked initial code import --- app/web/config/webpack.config.js | 4 + app/web/package.json | 1 + .../src/components/CadPackage/CadPackage.tsx | 60 ++++++---- .../components/EditorGuide/EditorGuide.tsx | 53 +++++++++ .../src/components/EditorMenu/EditorMenu.tsx | 19 +++- .../components/EncodedUrl/ExternalScript.tsx | 4 +- .../src/components/IdeEditor/IdeEditor.tsx | 71 +++++++----- .../cadPackages/cadQuery/initialCode.py | 17 +++ .../helpers/cadPackages/cadQuery/userGuide.md | 9 +- .../cadPackages/jsCad/initialCode.jscad | 33 ++++++ .../helpers/cadPackages/jsCad/userGuide.md | 9 +- .../cadPackages/openScad/initialCode.SCAD | 12 ++ .../helpers/cadPackages/openScad/userGuide.md | 9 +- app/web/src/helpers/hooks/useIdeState.ts | 104 +++++------------- app/web/src/helpers/markdown.ts | 24 ++++ app/web/src/index.css | 5 + app/yarn.lock | 2 +- 17 files changed, 297 insertions(+), 139 deletions(-) create mode 100644 app/web/src/components/EditorGuide/EditorGuide.tsx create mode 100644 app/web/src/helpers/cadPackages/cadQuery/initialCode.py create mode 100644 app/web/src/helpers/cadPackages/jsCad/initialCode.jscad create mode 100644 app/web/src/helpers/cadPackages/openScad/initialCode.SCAD create mode 100644 app/web/src/helpers/markdown.ts diff --git a/app/web/config/webpack.config.js b/app/web/config/webpack.config.js index 5f8af79..08dcbd9 100644 --- a/app/web/config/webpack.config.js +++ b/app/web/config/webpack.config.js @@ -5,5 +5,9 @@ module.exports = (config, { env }) => { plugin.userOptions.favicon = './src/favicon.svg' } }) + config.module.rules.push({ + test: /\.md$|\.jscad$|\.py$|\.SCAD$/i, + use: 'raw-loader', + }); return config } diff --git a/app/web/package.json b/app/web/package.json index d3f435e..1dd0060 100644 --- a/app/web/package.json +++ b/app/web/package.json @@ -58,6 +58,7 @@ "postcss": "^8.3.6", "postcss-import": "^14.0.2", "postcss-loader": "^6.1.1", + "raw-loader": "^4.0.2", "tailwindcss": "^2.2.7" } } diff --git a/app/web/src/components/CadPackage/CadPackage.tsx b/app/web/src/components/CadPackage/CadPackage.tsx index fa3aa82..e339995 100644 --- a/app/web/src/components/CadPackage/CadPackage.tsx +++ b/app/web/src/components/CadPackage/CadPackage.tsx @@ -1,43 +1,63 @@ -export type CadPackageType = 'openscad' | 'cadquery' | 'jscad' +export type CadPackageType = 'openscad' | 'cadquery' | 'jscad' | 'INIT' -export const ideTypeNameMap: { [key in CadPackageType]: string } = { - openscad: 'OpenSCAD', - cadquery: 'CadQuery', - jscad: 'JSCAD', +interface CadPackageConfig { + label: string + buttonClasses: string + dotClasses: string } +export const cadPackageConfigs: { [key in CadPackageType]: CadPackageConfig } = + { + openscad: { + label: 'OpenSCAD', + buttonClasses: 'bg-yellow-800', + dotClasses: 'bg-yellow-200', + }, + cadquery: { + label: 'CadQuery', + buttonClasses: 'bg-ch-blue-700', + dotClasses: 'bg-blue-800', + }, + jscad: { + label: 'JSCAD', + buttonClasses: 'bg-ch-purple-500', + dotClasses: 'bg-yellow-300', + }, + INIT: { + label: '', + buttonClasses: '', + dotClasses: '', + }, + } + interface CadPackageProps { cadPackage: CadPackageType className?: string dotClass?: string + onClick?: any } const CadPackage = ({ cadPackage, className = '', dotClass = 'w-5 h-5', + onClick, }: CadPackageProps) => { - const cadName = ideTypeNameMap[cadPackage] || '' - const isOpenScad = cadPackage === 'openscad' - const isCadQuery = cadPackage === 'cadquery' - const isJsCad = cadPackage === 'jscad' + const cadPackageConfig = cadPackageConfigs[cadPackage] + return ( -
-
{cadName}
-
+ {cadPackageConfig.label} + ) } diff --git a/app/web/src/components/EditorGuide/EditorGuide.tsx b/app/web/src/components/EditorGuide/EditorGuide.tsx new file mode 100644 index 0000000..a5f53a6 --- /dev/null +++ b/app/web/src/components/EditorGuide/EditorGuide.tsx @@ -0,0 +1,53 @@ +import { extractMetaData } from 'src/helpers/markdown' +import Editor from 'rich-markdown-editor' +import { useRef } from 'react' +import KeyValue from 'src/components/KeyValue/KeyValue' + +export default function EditorGuide({ content }) { + const [rawMetadata, metadata] = extractMetaData(content) + + const processedContent = rawMetadata + ? content.replace(rawMetadata[0], '') + : content + const ref = useRef(null) + + return ( +
+ {metadata && ( + <> +

{metadata.title}

+
+ {Object.entries(metadata) + .filter(([key]) => key !== 'title') + .map(([key, value], i) => ( + + {value} + + ))} +
+ + )} + {}} + /> +
+ ) +} + +function LinkOrParagraph({ children }) { + const markdownUrlExpression = + /\[(.*)\]\((https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|www\.[a-zA-Z0-9][a-zA-Z0-9-]+[a-zA-Z0-9]\.[^\s]{2,}|https?:\/\/(?:www\.|(?!www))[a-zA-Z0-9]+\.[^\s]{2,}|www\.[a-zA-Z0-9]+\.[^\s]{2,})\)/i + const matches = children.match(markdownUrlExpression) + + return matches === null ? ( +

{children}

+ ) : ( + + {matches[1]} + + ) +} diff --git a/app/web/src/components/EditorMenu/EditorMenu.tsx b/app/web/src/components/EditorMenu/EditorMenu.tsx index 9ef9456..33c0517 100644 --- a/app/web/src/components/EditorMenu/EditorMenu.tsx +++ b/app/web/src/components/EditorMenu/EditorMenu.tsx @@ -48,7 +48,24 @@ const EditorMenu = () => {
- + { + thunkDispatch({ + type: 'addEditorModel', + payload: { + type: 'guide', + label: 'Guide', + content: state.ideGuide, + }, + }) + thunkDispatch({ + type: 'switchEditorModel', + payload: state.models.length, + }) + }} + /> diff --git a/app/web/src/components/EncodedUrl/ExternalScript.tsx b/app/web/src/components/EncodedUrl/ExternalScript.tsx index 99687dd..db152a4 100644 --- a/app/web/src/components/EncodedUrl/ExternalScript.tsx +++ b/app/web/src/components/EncodedUrl/ExternalScript.tsx @@ -1,6 +1,6 @@ import { useState } from 'react' import { useIdeContext } from 'src/helpers/hooks/useIdeContext' -import { ideTypeNameMap } from 'src/components/CadPackage/CadPackage' +import { cadPackageConfigs } from 'src/components/CadPackage/CadPackage' import OutBound from 'src/components/OutBound/OutBound' import { prepareEncodedUrl, makeExternalUrl } from './helpers' import { copyTextToClipboard } from 'src/helpers/clipboard' @@ -16,7 +16,7 @@ const ExternalScript = () => { 'INIT' | 'SUCCESS' | 'ERROR' | 'LOADING' >('INIT') - const cadName = ideTypeNameMap[state.ideType] + const cadName = cadPackageConfigs[state.ideType].label const onPaste: React.ClipboardEventHandler = async ({ clipboardData, diff --git a/app/web/src/components/IdeEditor/IdeEditor.tsx b/app/web/src/components/IdeEditor/IdeEditor.tsx index 06fcd1f..7840d4c 100644 --- a/app/web/src/components/IdeEditor/IdeEditor.tsx +++ b/app/web/src/components/IdeEditor/IdeEditor.tsx @@ -1,10 +1,11 @@ -import { useEffect, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import { useIdeContext } from 'src/helpers/hooks/useIdeContext' import { makeCodeStoreKey, requestRender } from 'src/helpers/hooks/useIdeState' import Editor, { useMonaco } from '@monaco-editor/react' import { theme } from 'src/../config/tailwind.config' import { useSaveCode } from 'src/components/IdeWrapper/useSaveCode' import type { CadPackageType } from 'src/components/CadPackage/CadPackage' +import EditorGuide from 'src/components/EditorGuide/EditorGuide' const colors = theme.extend.colors @@ -17,6 +18,7 @@ const IdeEditor = ({ Loading }) => { cadquery: 'python', openscad: 'cpp', jscad: 'javascript', + INIT: '', } const monaco = useMonaco() useEffect(() => { @@ -73,34 +75,50 @@ const IdeEditor = ({ Loading }) => { className="h-full" onKeyDown={handleSaveHotkey} > - { (state.models.length > 1) && ( -
- { state.models.map((model, i) => ( -