howto resources :)

This commit is contained in:
lovebird 2025-03-22 01:00:07 +01:00
parent 0297411b46
commit 00d2f636e8
24 changed files with 447 additions and 45 deletions

View File

@ -23,7 +23,7 @@
"format": "unix-time"
}
],
"default": "2025-03-20T23:45:29.153Z"
"default": "2025-03-21T23:09:43.108Z"
},
"description": {
"type": "string",

View File

@ -4,10 +4,7 @@
"path": "."
},
{
"path": "../astro-components"
},
{
"path": "../polymech-mono/packages/commons"
"path": "../polymech-mono/packages"
}
],
"settings": {

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 392 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 99 KiB

View File

@ -0,0 +1,141 @@
---
import fs from 'fs';
import path from 'path';
import { IHowto,asset_local_rel } from "@/model/howto";
import { Img } from 'imagetools/components';
import { i18n as Translate } from "@polymech/astro-base";
import { files,forward_slash } from "@polymech/commons"
import BaseLayout from "@/layouts/BaseLayout.astro";
import Wrapper from "@/components/containers/Wrapper.astro";
import GalleryK from "@/components/polymech/GalleryK.astro";
import { HOWTO_FILES_WEB, HOWTO_FILES_ABS } from "config/config.js"
import Sidebar from "@/components/howtos/sidebar2.astro";
interface Props {
howto: IHowto;
}
const { howto } = Astro.props;
const coverLocaleRel = await asset_local_rel(howto, howto.cover_image);
const howto_abs = HOWTO_FILES_ABS(howto.slug)
let model_files: any = [ ...files(howto_abs, '**/**/*.(step|stp)')]
model_files = model_files.map((f) => forward_slash(`${howto.slug}/${path.relative(path.resolve(howto_abs), f)}`))
---
<BaseLayout class="markdown-content">
<Wrapper>
<div class="howto-container max-w-4xl mx-auto p-4 ml-4 pl-8">
<header class="mb-8">
<h1 class="text-3xl font-bold mb-2">
<Translate>{howto.title}</Translate>
</h1>
<div class="bg-gray-50 p-4 rounded-lg m-4">
{
howto.tags.map((tag) => (
<span class="inline-block text-gray-700 px-2 py-1 rounded-full text-sm mr-2">
<Translate>{tag}</Translate>
</span>
))
}
</div>
<!-- Cover image -->
<div class="mb-4">
<Img
src={coverLocaleRel}
alt={"none"}
attributes={{
img: { class: "w-full h-64 object-cover rounded-lg" }
}}
/>
</div>
<!-- Metadata -->
<div class="flex flex-wrap gap-4 mb-4 text-sm text-gray-600">
<div>
<span class="font-semibold">Difficulty:</span>
<Translate>{howto.difficulty_level}</Translate>
</div>
<div>
<span class="font-semibold">Time:</span>
<Translate>{howto.time}</Translate>
</div>
<div>
<span class="font-semibold">Views:</span> {howto.total_views}
</div>
<div>
<span class="font-semibold">Created by:</span> {howto._createdBy}
</div>
<div>
<span class="font-semibold">Country:</span> {howto.creatorCountry}
</div>
</div>
<!-- Description -->
<div class="bg-gray-50 p-4 rounded-lg">
<p class="whitespace-pre-line white-space: pre-line;">
<Translate><div set:html={howto.description.replace(/\n/g, '<br>')}></div></Translate>
</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<h3 class="font-semibold mb-4"> <Translate>Resources</Translate></h3>
<div class="">
{
howto.files.map((file) => (
<a href={`${file.downloadUrl}`} target="_blank" rel="noopener noreferrer">{file.name}</a>
))
}
</div>
<a href={`${HOWTO_FILES_WEB(howto.slug)}`} target="_blank" rel="noopener noreferrer"><Translate>Browse Files</Translate></a>
</div>
</header>
<!-- Steps -->
<div class="steps-container space-y-12">
{howto.steps.map((step, index) => (
<div class="step-item" id={`step-${index + 1}`}>
<h2 class="text-2xl font-semibold mb-4">
<span class="bg-orange-500/75 text-white w-8 h-8 rounded-full text-center leading-8 mr-2 inline-block float-left">
{index + 1}
</span>
<Translate>{step.title}</Translate>
</h2>
<div class="step-content mb-6">
<p class="whitespace-pre-line mb-4">
<Translate><div set:html={step.text.replace(/\n/g, '<br>')}></div></Translate>
</p>
</div>
{step.images && step.images.length > 0 && (
<div class="step-images">
<GalleryK images={step.images} />
</div>
)}
</div>
))}
</div>
<!-- Footer information -->
<footer class="mt-12 pt-6 border-t border-gray-200">
<div class="flex justify-between items-center">
<div>
<span class="text-sm text-gray-500">
<Translate>Created</Translate>: {new Date(howto._created).toLocaleDateString()}
</span>
</div>
<div class="text-sm text-gray-500">
<span>
<Translate>Found useful by</Translate>: {howto.votedUsefulBy.length} <Translate>people</Translate>
</span>
</div>
</div>
</footer>
</div>
</Wrapper>
</BaseLayout>

View File

@ -1,7 +1,7 @@
---
import BaseLayout from "@/layouts/BaseLayout.astro";
import { getCollection } from "astro:content";
import Item from "@/components/howtos/Item.astro";
import Item from "@/components/howtos/ListItem.astro";
import Wrapper from "@/components/containers/Wrapper.astro";
const all = await getCollection("howtos");

View File

@ -0,0 +1,188 @@
{
"_createdBy": "gus-merckel",
"mentions": [],
"_deleted": false,
"fileLink": "",
"slug": "cut-out-shapes-out-of-plastic-sheets-with-a-cnc-",
"_modified": "2023-10-27T18:09:36.519Z",
"previousSlugs": [
"cut-out-shapes-out-of-plastic-sheets-with-a-cnc-"
],
"_created": "2023-08-23T18:20:09.098Z",
"description": "In this how to, I will show you our process to cut HDPE Sheets using a X-Carve CNC.\n\nHere is the full video in spanish with subtitles https://www.youtube.com/watch?v=4LrrFz802To ",
"votedUsefulBy": [
"sigolene",
"mattia",
"uillinoispreciousplastics"
],
"creatorCountry": "mx",
"total_downloads": 0,
"title": "Cut out shapes out of plastic sheets with a CNC ",
"time": "< 5 hours",
"files": [],
"difficulty_level": "Medium",
"_id": "038gjWgLjiyYknbEjDeI",
"tags": {
"RTCBJAFa05YBVVBy0KeO": true
},
"category":"machines",
"total_views": 232,
"_contentModifiedTimestamp": "2023-08-23T18:20:09.098Z",
"cover_image": {
"name": "IMG_20200605_142311.jpg",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2F038gjWgLjiyYknbEjDeI%2FIMG_20200605_142311.jpg?alt=media&token=c272c174-1adc-45af-967b-771adce7295d",
"type": "image/jpeg",
"fullPath": "uploads/howtos/038gjWgLjiyYknbEjDeI/IMG_20200605_142311.jpg",
"updated": "2021-04-05T15:09:00.605Z",
"size": 124661,
"timeCreated": "2021-04-05T15:09:00.605Z",
"contentType": "image/jpeg"
},
"comments": [],
"moderatorFeedback": "",
"steps": [
{
"title": "Measure the plastic sheet",
"text": "For this step we need to measure our plastic sheet: Height, Width and Thickness. Our X-Carve machine works with the CAM Software EASEL, for me, the easiest software for CNC milling out there. \n\nThe cool thing about Easel (https://easel.inventables.com/) is that you can \"simulate\" your actual material and THEY EVEN HAVE HDPE 2-Colors in their cutting material lists!!\n\n\n",
"images": [
{
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/1.jpg",
"name": "1.jpg",
"size": 74095,
"type": "image/jpeg",
"timeCreated": "2021-03-26T19:42:05.766Z",
"contentType": "image/jpeg",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F1.jpg?alt=media&token=293d733d-05a5-494a-9340-47f4564f1939",
"updated": "2021-03-26T19:42:05.766Z"
},
{
"contentType": "image/jpeg",
"timeCreated": "2021-03-26T19:42:05.669Z",
"updated": "2021-03-26T19:42:05.669Z",
"size": 69665,
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F2.jpg?alt=media&token=004f50f1-97ac-4df4-9ba9-f463aa4cbca3",
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/2.jpg",
"name": "2.jpg",
"type": "image/jpeg"
}
],
"_animationKey": "unique1"
},
{
"text": "Using the CNC clamps from the X-Carve, secure the sheet to the table, ",
"_animationKey": "unique2",
"images": [
{
"updated": "2021-03-26T19:42:06.249Z",
"size": 55544,
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/3.jpg",
"timeCreated": "2021-03-26T19:42:06.249Z",
"name": "3.jpg",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F3.jpg?alt=media&token=0b9c1914-1c75-429e-b34a-1e2b3706edef",
"contentType": "image/jpeg",
"type": "image/jpeg"
}
],
"title": "Secure sheet "
},
{
"title": "Choosing a file to cut ",
"text": "Now we go to our illustrator, such as Inkscape to design a vector file or download and open source one frome https://thenounproject.com/.\n\nWe download the SVG file, which is an open source vector format and import it to Easel. \n",
"images": [
{
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F4.jpg?alt=media&token=1cd2d49d-9335-4bb1-ac2a-e625322ca604",
"contentType": "image/jpeg",
"timeCreated": "2021-03-26T19:42:06.727Z",
"updated": "2021-03-26T19:42:06.727Z",
"name": "4.jpg",
"size": 42952,
"type": "image/jpeg",
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/4.jpg"
},
{
"size": 69255,
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/5.jpg",
"updated": "2021-03-26T19:42:06.833Z",
"timeCreated": "2021-03-26T19:42:06.833Z",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F5.jpg?alt=media&token=7cca786a-7d47-43bb-900b-b8d101c276b4",
"name": "5.jpg",
"contentType": "image/jpeg",
"type": "image/jpeg"
}
],
"_animationKey": "unique3"
},
{
"text": "Now with the file we can choose the width we want to carve/cut and then we go to cut and start the wizzard:\n- We check that the sheet is fixed.\n- We also specify the cutting bit, we are using a 1/8 flat flute bit. \n- We tell the machine where the coordinate 0-0 is, which we always choose as the down left corner.\n- We raise the bit, turn on the Router!!!\n\nAND PUM THE MAGIC BEGINS!!",
"title": "Follow the cutting Wizzard",
"images": [
{
"timeCreated": "2021-03-26T19:42:07.493Z",
"size": 72226,
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/6.jpg",
"updated": "2021-03-26T19:42:07.493Z",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F6.jpg?alt=media&token=ba7195dd-7771-435f-a188-057457697332",
"contentType": "image/jpeg",
"type": "image/jpeg",
"name": "6.jpg"
},
{
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/7.jpg",
"size": 52424,
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F7.jpg?alt=media&token=a3d5820c-cfe2-484e-8f76-f861ab8b756d",
"contentType": "image/jpeg",
"type": "image/jpeg",
"timeCreated": "2021-03-26T19:42:07.308Z",
"updated": "2021-03-26T19:42:07.308Z",
"name": "7.jpg"
},
{
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/8.jpg",
"name": "8.jpg",
"type": "image/jpeg",
"timeCreated": "2021-03-26T19:42:07.346Z",
"size": 55264,
"contentType": "image/jpeg",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F8.jpg?alt=media&token=1c9816d7-3a99-4f41-8d3c-acc2670240f6",
"updated": "2021-03-26T19:42:07.346Z"
}
],
"_animationKey": "uniquenisc2v"
},
{
"text": "You take now your glasses or object and postprocess them and of course show it to your friends, family and so on.\n\n\n",
"images": [
{
"fullPath": "uploads/howtos/pbo0Pe44aTngvlD04kGf/9.jpg",
"contentType": "image/jpeg",
"timeCreated": "2021-03-26T19:42:08.147Z",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2Fpbo0Pe44aTngvlD04kGf%2F9.jpg?alt=media&token=4dcfe37d-e1ad-41e5-a590-40b4c37c5e1a",
"name": "9.jpg",
"updated": "2021-03-26T19:42:08.147Z",
"type": "image/jpeg",
"size": 82214
}
],
"_animationKey": "uniquesgl34",
"title": "Post-production and show case"
},
{
"_animationKey": "uniquem4y0yi",
"title": "Hack it and try it yourself",
"text": "You can try this project with other types of CNC machines, even manual Routers or manual saw, as I did on this video: https://youtu.be/gxkcffQD3eQ, but the important thing is that you share what you do and help this community to grow!!!\n\nShare your ideas and comments!",
"images": [
{
"contentType": "image/jpeg",
"timeCreated": "2021-04-05T15:09:01.445Z",
"fullPath": "uploads/howtos/038gjWgLjiyYknbEjDeI/IMG_20200605_142311.jpg",
"type": "image/jpeg",
"downloadUrl": "https://firebasestorage.googleapis.com/v0/b/onearmyworld.appspot.com/o/uploads%2Fhowtos%2F038gjWgLjiyYknbEjDeI%2FIMG_20200605_142311.jpg?alt=media&token=f94152ff-f923-4054-a3ad-d8ec588856fa",
"size": 124661,
"updated": "2021-04-05T15:09:01.445Z",
"name": "IMG_20200605_142311.jpg"
}
]
}
],
"moderation": "accepted"
}

View File

@ -0,0 +1,47 @@
## Todos
- for Astro, tailwind
- no react or additional dependencies
- IHowto: import { IHowto } from "@/model/howto.js"
- For text, use {text} (import { i18n as Translate } from "@polymech/astro-base")
- data is provided via `import { getCollection } from 'astro:content'
const items = await getCollection('howtos')`
### Example Tailwind Sidebar
<button data-drawer-target="default-sidebar" data-drawer-toggle="default-sidebar" aria-controls="default-sidebar" type="button" class="inline-flex items-center p-2 mt-2 ms-3 text-sm text-gray-500 rounded-lg sm:hidden hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-200 dark:text-gray-400 dark:hover:bg-gray-700 dark:focus:ring-gray-600">
<span class="sr-only">Open sidebar</span>
<svg class="w-6 h-6" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path clip-rule="evenodd" fill-rule="evenodd" d="M2 4.75A.75.75 0 012.75 4h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 4.75zm0 10.5a.75.75 0 01.75-.75h7.5a.75.75 0 010 1.5h-7.5a.75.75 0 01-.75-.75zM2 10a.75.75 0 01.75-.75h14.5a.75.75 0 010 1.5H2.75A.75.75 0 012 10z"></path>
</svg>
</button>
<aside id="default-sidebar" class="fixed top-0 left-0 z-40 w-64 h-screen transition-transform -translate-x-full sm:translate-x-0" aria-label="Sidebar">
<div class="h-full px-3 py-4 overflow-y-auto bg-gray-50 dark:bg-gray-800">
<ul class="space-y-2 font-medium">
<li>
<a href="#" class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
<svg class="w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 21">
<path d="M16.975 11H10V4.025a1 1 0 0 0-1.066-.998 8.5 8.5 0 1 0 9.039 9.039.999.999 0 0 0-1-1.066h.002Z"/>
<path d="M12.5 0c-.157 0-.311.01-.565.027A1 1 0 0 0 11 1.02V10h8.975a1 1 0 0 0 1-.935c.013-.188.028-.374.028-.565A8.51 8.51 0 0 0 12.5 0Z"/>
</svg>
<span class="ms-3">Dashboard</span>
</a>
</li>
<li>
<a href="#" class="flex items-center p-2 text-gray-900 rounded-lg dark:text-white hover:bg-gray-100 dark:hover:bg-gray-700 group">
<svg class="shrink-0 w-5 h-5 text-gray-500 transition duration-75 dark:text-gray-400 group-hover:text-gray-900 dark:group-hover:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 18 18">
<path d="M6.1"/>
</svg>
<span class="flex-1 ms-3 whitespace-nowrap">Kanban</span>
<span class="inline-flex items-center justify-center px-2 ms-3 text-sm font-medium text-gray-800 bg-gray-100 rounded-full dark:bg-gray-700 dark:text-gray-300">Pro</span>
</a>
</li>
</ul>
</div>
</aside>
## Todos
- [ ] create minimal Astro component, a sidebar using flowbit (see example) for the given interface ("IHowto") and sample data ../components/libary/howto.astro, use the 'category' field, save as ../components/howtos/sidebar2.astro

View File

@ -0,0 +1,7 @@
kbotd --preferences ./todos-howto.md \
--include=./howto.ts \
--include=./howto.json \
--disable=terminal,git,npm,user,interact,search,email,web \
--disableTools=read_file,read_files,list_files,file_exists,web \
--model=anthropic/claude-3.7-sonnet

View File

@ -20,9 +20,12 @@ export const I18N_ASSET_PATH = "${SRC_DIR}/${SRC_NAME}-${DST_LANG}${SRC_EXT}"
// Library - Howtos
// Products
export const HOWTO_ROOT = () => path.resolve(resolve("./public/resources/howtos"))
export const HOWTO_GLOB = '**/config.json'
export const FILES_WEB = 'https://files.polymech.io/files/machines/howtos/'
export const HOWTO_ROOT = () => path.resolve(resolve("./public/resources/howtos"))
export const HOWTO_FILES_ABS = (id) => `${HOWTO_ROOT()}/${id}`
export const HOWTO_FILES_WEB = (id: string) => `${FILES_WEB}/${id}`
// Products

View File

@ -1,35 +1,45 @@
---
import fs from 'fs';
import path from 'path';
import { IHowto,asset_local_rel } from "@/model/howto";
import { Gallery } from "@polymech/astro-base";
import { Img } from 'imagetools/components';
import { i18n as Translate } from "@polymech/astro-base";
import Item from "@/components/howtos/Item.astro";
import { files,forward_slash } from "@polymech/commons"
import BaseLayout from "@/layouts/BaseLayout.astro";
import Wrapper from "@/components/containers/Wrapper.astro";
import GalleryK from "@/components/polymech/GalleryK.astro";
import { HOWTO_FILES_WEB, HOWTO_FILES_ABS } from "config/config.js"
import Sidebar from "@/components/howtos/sidebar2.astro";
interface Props {
howto: IHowto;
}
const { howto } = Astro.props;
import BaseLayout from "@/layouts/BaseLayout.astro";
import Wrapper from "@/components/containers/Wrapper.astro";
const _url = Astro.url
const canonicalUrl = _url.origin
function getProxyUrl(imageUrl: string): string {
const ret = `${canonicalUrl}/api/image-proxy?url=${encodeURIComponent(imageUrl)}`;
return ret
}
const { howto } = Astro.props;
const coverLocaleRel = await asset_local_rel(howto, howto.cover_image);
import Sidebar from "@/components/howtos/sidebar2.astro";
import GalleryK from "@/components/polymech/GalleryK.astro";
const howto_abs = HOWTO_FILES_ABS(howto.slug)
let model_files: any = [ ...files(howto_abs, '**/**/*.(step|stp)')]
model_files = model_files.map((f) => forward_slash(`${howto.slug}/${path.relative(path.resolve(howto_abs), f)}`))
---
<BaseLayout class="markdown-content">
<Wrapper>
<Sidebar />
<div class="howto-container max-w-4xl mx-auto p-4 ml-4 pl-8">
<header class="mb-8">
<h1 class="text-3xl font-bold mb-2">
<Translate>{howto.title}</Translate>
</h1>
<div class="bg-gray-50 p-4 rounded-lg m-4">
{
howto.tags.map((tag) => (
<span class="inline-block text-gray-700 px-2 py-1 rounded-full text-sm mr-2">
<Translate>{tag}</Translate>
</span>
))
}
</div>
<!-- Cover image -->
<div class="mb-4">
<Img
@ -39,8 +49,7 @@ import GalleryK from "@/components/polymech/GalleryK.astro";
img: { class: "w-full h-64 object-cover rounded-lg" }
}}
/>
</div>
</div>
<!-- Metadata -->
<div class="flex flex-wrap gap-4 mb-4 text-sm text-gray-600">
<div>
@ -61,13 +70,30 @@ import GalleryK from "@/components/polymech/GalleryK.astro";
<span class="font-semibold">Country:</span> {howto.creatorCountry}
</div>
</div>
<!-- Description -->
<div class="bg-gray-50 p-4 rounded-lg">
<p class="whitespace-pre-line">
<Translate>{howto.description}</Translate>
<p class="whitespace-pre-line white-space: pre-line;">
<Translate><div set:html={howto.description.replace(/\n/g, '<br>')}></div></Translate>
</p>
</div>
<div class="bg-gray-50 p-4 rounded-lg">
<h3 class="font-semibold mb-4"> <Translate>Resources</Translate></h3>
<div class="">
{
howto.files.map((file) => (
<a href={`${file.downloadUrl}`} target="_blank" rel="noopener noreferrer">{file.name}</a>
))
}
</div>
<a href={`${HOWTO_FILES_WEB(howto.slug)}`} target="_blank" rel="noopener noreferrer"><Translate>Browse Files</Translate></a>
</div>
</header>
<!-- Steps -->
@ -75,16 +101,15 @@ import GalleryK from "@/components/polymech/GalleryK.astro";
{howto.steps.map((step, index) => (
<div class="step-item" id={`step-${index + 1}`}>
<h2 class="text-2xl font-semibold mb-4">
<span class="inline-block bg-blue-500 text-white w-8 h-8 rounded-full text-center leading-8 mr-2">
<span class="bg-orange-500/75 text-white w-8 h-8 rounded-full text-center leading-8 mr-2 inline-block float-left">
{index + 1}
</span>
<Translate>{step.title}</Translate>
</h2>
<!-- Step content -->
<div class="step-content mb-6">
<p class="whitespace-pre-line mb-4">
<Translate>{step.text}</Translate>
<Translate><div set:html={step.text.replace(/\n/g, '<br>')}></div></Translate>
</p>
</div>

View File

@ -63,7 +63,6 @@ export const items = (branch: string) =>{
PRODUCT_ROOT(), PFilterValid.marketplace_component), branch)
}
const onComponent = async (item: IStoreItem, ctx: LoaderContext) => {
/*
const onNode = async (data: INodeCallback, configuration: string) => {

View File

@ -6,9 +6,7 @@ import { filesEx, resolveConfig, resolve } from '@polymech/commons'
import { ICADNodeSchema, IComponentConfig } from '@polymech/commons/component'
import { RenderedContent, DataEntry } from "astro:content"
import type { Loader, LoaderContext } from 'astro/loaders'
import { get } from '@polymech/commons/component'
import { forward_slash } from "@polymech/commons"
import { sanitizeFilename, validateFilename } from "@polymech/fs/utils"
import { sanitizeFilename } from "@polymech/fs/utils"
import {
CAD_MAIN_MATCH, PRODUCT_BRANCHES,
@ -32,18 +30,19 @@ import { IAssemblyData } from '@polymech/cad'
import { logger as log } from '@/base/index.js'
import { translate } from "@/base/i18n.js"
import { I18N_SOURCE_LANGUAGE } from "config/config.js"
import { slugify } from "@/base/strings.js"
import { got } from 'got'
import pMap from 'p-map'
import { HOWTO_MIGRATION } from '@/app/config.js'
import { createWriteStream } from 'fs';
export const ITEM_TYPE = 'howto'
//export const load = () => get(`${HOWTO_ROOT()}/${HOWTO_GLOB}`, HOWTO_ROOT(), ITEM_TYPE)
export const item_path = (item: any) => {
return `${HOWTO_ROOT()}/${item.data.slug}`
}
export const item_path = (item: any) => `${HOWTO_ROOT()}/${item.data.slug}`
const download = async (url, outputPath) => {
const stream = createWriteStream(outputPath);
got.stream(url).pipe(stream);
@ -60,8 +59,6 @@ export const asset_local_abs = async (item: IHowto, asset: Image) => {
}
return false
}
export const asset_local_rel = async (item: IHowto, asset: Image) => {
const sanitizedFilename = sanitizeFilename(asset.name)
const asset_path = path.join(HOWTO_ROOT(), item.slug, sanitizedFilename)
@ -79,7 +76,6 @@ export const howtos = async () => {
let howtos = data.v3_howtos as any[]
howtos = howtos.filter((h) => h.moderation == 'accepted');
const tags = data.v3_tags;
let output = {
tags: {},
howtows: {}
@ -128,7 +124,6 @@ export const defaults = async (data: any, cwd: string, root: string) => {
return data;
};
const onItem = async (store: any, ctx: LoaderContext) => {
const item = store.data.item as IHowto
item.steps = item.steps || []
@ -136,7 +131,7 @@ const onItem = async (store: any, ctx: LoaderContext) => {
step.images = await pMap(step.images, async (image) => {
return {
...image,
src: await asset_local_rel(item, image),
src: await asset_local_rel(item, image) || default_image().src,
alt: image.name || ''
};
}, {

View File

@ -1,5 +1,5 @@
---
import Layout from '@/layouts/Howto.astro'
import Layout from '@/components/howtos/Detail.astro'
import { getCollection } from 'astro:content'
import { LANGUAGES_PROD as LANGUAGES } from "config/config.js"

View File

@ -1,7 +1,7 @@
---
import BaseLayout from "@/layouts/BaseLayout.astro"
import { getCollection } from "astro:content"
import List from "@/components/howtos/Item.astro"
import List from "@/components/howtos/ListItem.astro"
const all = await getCollection("howtos")
const locale = Astro.currentLocale || "en"