Merge pull request #380 from Irev-Dev/main
Release 25th June 2021
This commit was merged in pull request #380.
This commit is contained in:
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"cSpell.words": [
|
||||||
|
"Hutten"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -9,7 +9,7 @@ Let's help Code-CAD reach its [full potential!](https://cadhub.xyz) We're making
|
|||||||
If you want to be involved in anyway, checkout the [Road Map](https://github.com/Irev-Dev/cadhub/discussions/212) and get in touch via, [twitter](https://twitter.com/IrevDev), [discord](https://discord.gg/SD7zFRNjGH) or [discussions](https://github.com/Irev-Dev/cadhub/discussions).
|
If you want to be involved in anyway, checkout the [Road Map](https://github.com/Irev-Dev/cadhub/discussions/212) and get in touch via, [twitter](https://twitter.com/IrevDev), [discord](https://discord.gg/SD7zFRNjGH) or [discussions](https://github.com/Irev-Dev/cadhub/discussions).
|
||||||
|
|
||||||
<img src="https://raw.githubusercontent.com/Irev-Dev/repo-images/main/images/fullcadhubshot.jpg">
|
<img src="https://raw.githubusercontent.com/Irev-Dev/repo-images/main/images/fullcadhubshot.jpg">
|
||||||
|
<img src="https://raw.githubusercontent.com/Irev-Dev/cadhub/main/docs/static/img/blog/curated-code-cad/CadHubSS.jpg">
|
||||||
|
|
||||||
## Getting your dev environment setup
|
## Getting your dev environment setup
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@redwoodjs/api": "^0.34.1",
|
"@redwoodjs/api": "^0.34.1",
|
||||||
"@sentry/node": "^6.5.1",
|
"@sentry/node": "^6.5.1",
|
||||||
"cloudinary": "^1.23.0",
|
"cloudinary": "^1.23.0"
|
||||||
"graphql-tag": "^2.12.4"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ app.post('/cadquery/stl', async (req, res) => {
|
|||||||
console.log('making post request to 5060')
|
console.log('making post request to 5060')
|
||||||
try {
|
try {
|
||||||
const { data } = await axios.post(invocationURL(5060), {
|
const { data } = await axios.post(invocationURL(5060), {
|
||||||
body: req.body
|
body: JSON.stringify(req.body),
|
||||||
})
|
})
|
||||||
res.status(data.statusCode)
|
res.status(data.statusCode)
|
||||||
res.send(data.body)
|
res.send(data.body)
|
||||||
|
|||||||
@@ -36,7 +36,10 @@ RUN npm install
|
|||||||
|
|
||||||
|
|
||||||
# Get the distribution copy of cq-cli
|
# Get the distribution copy of cq-cli
|
||||||
RUN wget https://github.com/CadQuery/cq-cli/releases/download/v2.1.0/cq-cli-Linux-x86_64.zip
|
RUN apt-get install -y libglew2.1
|
||||||
|
RUN wget https://github.com/CadQuery/cq-cli/releases/download/v2.2-beta.1/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 unzip cq-cli-Linux-x86_64.zip
|
||||||
|
|
||||||
RUN chmod +x cq-cli/cq-cli
|
RUN chmod +x cq-cli/cq-cli
|
||||||
|
|||||||
@@ -144,3 +144,23 @@ functions:
|
|||||||
# NewOutput:
|
# NewOutput:
|
||||||
# Description: "Description for the output"
|
# Description: "Description for the output"
|
||||||
# Value: "Some output value"
|
# Value: "Some output value"
|
||||||
|
resources:
|
||||||
|
Resources:
|
||||||
|
GatewayResponseDefault4XX:
|
||||||
|
Type: 'AWS::ApiGateway::GatewayResponse'
|
||||||
|
Properties:
|
||||||
|
ResponseParameters:
|
||||||
|
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
|
||||||
|
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
|
||||||
|
ResponseType: DEFAULT_4XX
|
||||||
|
RestApiId:
|
||||||
|
Ref: 'ApiGatewayRestApi'
|
||||||
|
GatewayResponseDefault5XX:
|
||||||
|
Type: 'AWS::ApiGateway::GatewayResponse'
|
||||||
|
Properties:
|
||||||
|
ResponseParameters:
|
||||||
|
gatewayresponse.header.Access-Control-Allow-Origin: "'*'"
|
||||||
|
gatewayresponse.header.Access-Control-Allow-Headers: "'*'"
|
||||||
|
ResponseType: DEFAULT_5XX
|
||||||
|
RestApiId:
|
||||||
|
Ref: 'ApiGatewayRestApi'
|
||||||
|
|||||||
@@ -17,9 +17,7 @@ export const handler = createGraphQLHandler({
|
|||||||
schemas,
|
schemas,
|
||||||
services: makeServices({ services }),
|
services: makeServices({ services }),
|
||||||
}),
|
}),
|
||||||
plugins: [
|
plugins: [createSentryApolloPlugin()],
|
||||||
createSentryApolloPlugin(),
|
|
||||||
],
|
|
||||||
onException: () => {
|
onException: () => {
|
||||||
// Disconnect from your database with an unhandled exception.
|
// Disconnect from your database with an unhandled exception.
|
||||||
db.$disconnect()
|
db.$disconnect()
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ export const requireOwnership = async ({ userId, userName, partId } = {}) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (context.currentUser.roles?.includes('admin')) {
|
if (context.currentUser.roles?.includes('admin')) {
|
||||||
|
if (context.currentUser?.sub === '5cea3906-1e8e-4673-8f0d-89e6a963c096') {
|
||||||
|
throw new ForbiddenError("That's a local admin ONLY.")
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,45 +62,44 @@ export const createSentryApolloPlugin: Config['plugins'][number] = () => ({
|
|||||||
// If we couldn't parse the operation, don't
|
// If we couldn't parse the operation, don't
|
||||||
// do anything here
|
// do anything here
|
||||||
if (!ctx.operation) {
|
if (!ctx.operation) {
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const err of ctx.errors) {
|
for (const err of ctx.errors) {
|
||||||
// Only report internal server errors,
|
// Only report internal server errors,
|
||||||
// all errors extending ApolloError should be user-facing
|
// all errors extending ApolloError should be user-facing
|
||||||
if (err instanceof ApolloError) {
|
if (err instanceof ApolloError) {
|
||||||
continue;
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add scoped report details and send to Sentry
|
// Add scoped report details and send to Sentry
|
||||||
Sentry.withScope(scope => {
|
Sentry.withScope((scope) => {
|
||||||
// Annotate whether failing operation was query/mutation/subscription
|
// Annotate whether failing operation was query/mutation/subscription
|
||||||
scope.setTag("kind", ctx.operation.operation);
|
scope.setTag('kind', ctx.operation.operation)
|
||||||
|
|
||||||
// Log query and variables as extras (make sure to strip out sensitive data!)
|
// Log query and variables as extras (make sure to strip out sensitive data!)
|
||||||
scope.setExtra("query", ctx.request.query);
|
scope.setExtra('query', ctx.request.query)
|
||||||
scope.setExtra("variables", ctx.request.variables);
|
scope.setExtra('variables', ctx.request.variables)
|
||||||
|
|
||||||
if (err.path) {
|
if (err.path) {
|
||||||
// We can also add the path as breadcrumb
|
// We can also add the path as breadcrumb
|
||||||
scope.addBreadcrumb({
|
scope.addBreadcrumb({
|
||||||
category: "query-path",
|
category: 'query-path',
|
||||||
message: err.path.join(" > "),
|
message: err.path.join(' > '),
|
||||||
level: Sentry.Severity.Debug
|
level: Sentry.Severity.Debug,
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const transactionId = ctx.request.http.headers.get(
|
const transactionId =
|
||||||
"x-transaction-id"
|
ctx.request.http.headers.get('x-transaction-id')
|
||||||
);
|
|
||||||
if (transactionId) {
|
if (transactionId) {
|
||||||
scope.setTransaction(transactionId);
|
scope.setTransaction(transactionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err)
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -77,13 +77,13 @@ export const updatePart = async ({ id, input }) => {
|
|||||||
}
|
}
|
||||||
const originalPart = await db.part.findUnique({ where: { id } })
|
const originalPart = await db.part.findUnique({ where: { id } })
|
||||||
const imageToDestroy =
|
const imageToDestroy =
|
||||||
originalPart.mainImage !== input.mainImage && originalPart.mainImage
|
originalPart.mainImage !== input.mainImage && input.mainImage && originalPart.mainImage
|
||||||
const update = await db.part.update({
|
const update = await db.part.update({
|
||||||
data: foreignKeyReplacement(input),
|
data: foreignKeyReplacement(input),
|
||||||
where: { id },
|
where: { id },
|
||||||
})
|
})
|
||||||
if (imageToDestroy) {
|
if (imageToDestroy) {
|
||||||
console.log(`image destroyed, publicId: ${imageToDestroy}, partId: ${id}`)
|
console.log(`image destroyed, publicId: ${imageToDestroy}, partId: ${id}, replacing image is ${input.mainImage}`)
|
||||||
// destroy after the db has been updated
|
// destroy after the db has been updated
|
||||||
destroyImage({ publicId: imageToDestroy })
|
destroyImage({ publicId: imageToDestroy })
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const SmallLoadingPing = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const BigLoadingPing = () => (
|
const BigLoadingPing = () => (
|
||||||
<div className="inset-0 absolute flex items-center justify-center">
|
<div className="inset-0 absolute flex items-center justify-center bg-ch-gray-800">
|
||||||
<div className="h-16 w-16 bg-pink-600 rounded-full animate-ping"></div>
|
<div className="h-16 w-16 bg-pink-600 rounded-full animate-ping"></div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ const LandingSection = () => {
|
|||||||
<li>Build your own helper functions and abstractions</li>
|
<li>Build your own helper functions and abstractions</li>
|
||||||
<li>
|
<li>
|
||||||
Trigger{' '}
|
Trigger{' '}
|
||||||
<QuickLink to="https://en.wikipedia.org/wiki/Finite_element_method">
|
<QuickLink to="https://learn.cadhub.xyz/blog/testing-code-cad">
|
||||||
FEM
|
FEM
|
||||||
</QuickLink>{' '}
|
</QuickLink>{' '}
|
||||||
or regenerate tool paths with a{' '}
|
or regenerate tool paths with a{' '}
|
||||||
@@ -100,7 +100,7 @@ const LandingSection = () => {
|
|||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Auto-generate a{' '}
|
Auto-generate a{' '}
|
||||||
<QuickLink to="https://en.wikipedia.org/wiki/Bill_of_materials">
|
<QuickLink to="https://learn.cadhub.xyz/blog/codecad-artifacts">
|
||||||
BOM
|
BOM
|
||||||
</QuickLink>
|
</QuickLink>
|
||||||
</li>
|
</li>
|
||||||
@@ -111,6 +111,11 @@ const LandingSection = () => {
|
|||||||
</QuickLink>{' '}
|
</QuickLink>{' '}
|
||||||
tools
|
tools
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<QuickLink to="https://learn.cadhub.xyz/blog/3d-diffs">
|
||||||
|
3d-diffs
|
||||||
|
</QuickLink>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ const OutBound = ({ className, children, to }) => {
|
|||||||
})
|
})
|
||||||
return true
|
return true
|
||||||
}}
|
}}
|
||||||
|
rel="noreferrer"
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ const PartProfile = ({
|
|||||||
const [isInvalid, setIsInvalid] = useState(false)
|
const [isInvalid, setIsInvalid] = useState(false)
|
||||||
const { currentUser } = useAuth()
|
const { currentUser } = useAuth()
|
||||||
const editorRef = useRef(null)
|
const editorRef = useRef(null)
|
||||||
const canEdit = currentUser?.sub === userPart.id
|
const canEdit = currentUser?.sub === userPart.id || currentUser?.roles.includes('admin')
|
||||||
const isImageEditable = !isEditable && canEdit // image is editable when not in profile edit mode in order to separate them as it's too hard too to upload an image to cloudinary temporarily until the use saves (and maybe have to clean up) for the time being
|
const isImageEditable = !isEditable && canEdit // image is editable when not in profile edit mode in order to separate them as it's too hard too to upload an image to cloudinary temporarily until the use saves (and maybe have to clean up) for the time being
|
||||||
const part = userPart?.Part
|
const part = userPart?.Part
|
||||||
const emotes = countEmotes(part?.Reaction)
|
const emotes = countEmotes(part?.Reaction)
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
stlToGeometry,
|
stlToGeometry,
|
||||||
createHealthyResponse,
|
createHealthyResponse,
|
||||||
createUnhealthyResponse,
|
createUnhealthyResponse,
|
||||||
|
timeoutErrorMessage,
|
||||||
} from './common'
|
} from './common'
|
||||||
|
|
||||||
export const render = async ({ code }) => {
|
export const render = async ({ code }) => {
|
||||||
@@ -29,6 +30,9 @@ export const render = async ({ code }) => {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (response.status === 502) {
|
||||||
|
return createUnhealthyResponse(new Date(), timeoutErrorMessage)
|
||||||
|
}
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
const geometry = await stlToGeometry(data.url)
|
const geometry = await stlToGeometry(data.url)
|
||||||
return createHealthyResponse({
|
return createHealthyResponse({
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { STLLoader } from 'three/examples/jsm/loaders/STLLoader'
|
|||||||
|
|
||||||
export const lambdaBaseURL =
|
export const lambdaBaseURL =
|
||||||
process.env.CAD_LAMBDA_BASE_URL ||
|
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) =>
|
export const stlToGeometry = (url) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
@@ -38,3 +38,5 @@ export function createUnhealthyResponse(date, message = 'network issue') {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const timeoutErrorMessage = `timeout: We're currently limited a 30s execution time. You can try again, sometimes it works the second time`
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import {
|
|||||||
stlToGeometry,
|
stlToGeometry,
|
||||||
createHealthyResponse,
|
createHealthyResponse,
|
||||||
createUnhealthyResponse,
|
createUnhealthyResponse,
|
||||||
|
timeoutErrorMessage,
|
||||||
} from './common'
|
} from './common'
|
||||||
|
|
||||||
export const render = async ({ code, settings }) => {
|
export const render = async ({ code, settings }) => {
|
||||||
@@ -49,6 +50,9 @@ export const render = async ({ code, settings }) => {
|
|||||||
const cleanedErrorMessage = cleanError(error)
|
const cleanedErrorMessage = cleanError(error)
|
||||||
return createUnhealthyResponse(new Date(), cleanedErrorMessage)
|
return createUnhealthyResponse(new Date(), cleanedErrorMessage)
|
||||||
}
|
}
|
||||||
|
if (response.status === 502) {
|
||||||
|
return createUnhealthyResponse(new Date(), timeoutErrorMessage)
|
||||||
|
}
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
const type = data.type !== 'stl' ? 'png' : 'geometry'
|
const type = data.type !== 'stl' ? 'png' : 'geometry'
|
||||||
const newData = data.type !== 'stl' ? data.url : stlToGeometry(data.url)
|
const newData = data.type !== 'stl' ? data.url : stlToGeometry(data.url)
|
||||||
@@ -81,6 +85,9 @@ export const stl = async ({ code, settings }) => {
|
|||||||
const cleanedErrorMessage = cleanError(error)
|
const cleanedErrorMessage = cleanError(error)
|
||||||
return createUnhealthyResponse(new Date(), cleanedErrorMessage)
|
return createUnhealthyResponse(new Date(), cleanedErrorMessage)
|
||||||
}
|
}
|
||||||
|
if (response.status === 502) {
|
||||||
|
return createUnhealthyResponse(new Date(), timeoutErrorMessage)
|
||||||
|
}
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
const geometry = await stlToGeometry(data.url)
|
const geometry = await stlToGeometry(data.url)
|
||||||
return createHealthyResponse({
|
return createHealthyResponse({
|
||||||
|
|||||||
3164
app/yarn.lock
3164
app/yarn.lock
File diff suppressed because it is too large
Load Diff
@@ -83,18 +83,14 @@ export default function Home() {
|
|||||||
<li>Build your own helper functions and abstractions</li>
|
<li>Build your own helper functions and abstractions</li>
|
||||||
<li>
|
<li>
|
||||||
Trigger{' '}
|
Trigger{' '}
|
||||||
<a href="https://en.wikipedia.org/wiki/Finite_element_method">
|
<a href="/blog/testing-code-cad">
|
||||||
FEM
|
FEM
|
||||||
</a>{' '}
|
</a>{' '}
|
||||||
or regenerate tool paths with a{' '}
|
or regenerate tool paths with a CI/CD process
|
||||||
<a href="https://www.redhat.com/en/topics/devops/what-is-ci-cd">
|
|
||||||
CI/CD
|
|
||||||
</a>{' '}
|
|
||||||
process
|
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Auto-generate a{' '}
|
Auto-generate a{' '}
|
||||||
<a href="https://en.wikipedia.org/wiki/Bill_of_materials">
|
<a href="/blog/codecad-artifacts">
|
||||||
BOM
|
BOM
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -103,6 +99,11 @@ export default function Home() {
|
|||||||
<a href="https://www.ptc.com/en/technologies/plm">PLM</a>{' '}
|
<a href="https://www.ptc.com/en/technologies/plm">PLM</a>{' '}
|
||||||
tools
|
tools
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="/blog/3d-diffs">
|
||||||
|
3d-diffs
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user