Compare commits
13 Commits
25d7193fff
...
website-co
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ff2249955 | |||
| ec6cfba9ba | |||
| 22b6a06b32 | |||
| dac9e80efd | |||
| 8fd744118f | |||
| adcbce68c8 | |||
| 33fbbe96b3 | |||
| 076618784a | |||
| 91ce9aa6c6 | |||
| 52eac520e8 | |||
| 2583e4e99b | |||
| 1b1db88a2a | |||
| 028637fdd3 |
@@ -57,12 +57,16 @@ jobs:
|
|||||||
- name: Login to Docker Registry
|
- name: Login to Docker Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: gitea.perren.cloud
|
registry: 192.168.1.36:30008
|
||||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
password: ${{ secrets.ACTIONS_TOKEN }}
|
password: ${{ secrets.ACTIONS_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
buildkitd-config-inline: |
|
||||||
|
[registry."192.168.1.36:30008"]
|
||||||
|
http = true
|
||||||
|
|
||||||
- name: Build and Push
|
- name: Build and Push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
@@ -70,8 +74,8 @@ jobs:
|
|||||||
context: caperren-com
|
context: caperren-com
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
gitea.perren.cloud/caperren/${{ needs.test.outputs.repo_name }}:${{ needs.test.outputs.repo_version_hash }}
|
192.168.1.36:30008/caperren/${{ needs.test.outputs.repo_name }}:${{ needs.test.outputs.repo_version_hash }}
|
||||||
gitea.perren.cloud/caperren/caperren-com:latest
|
192.168.1.36:30008/caperren/caperren-com:latest
|
||||||
build-args: |
|
build-args: |
|
||||||
REPO_VERSION_HASH=${{ needs.test.outputs.repo_version_hash }}
|
REPO_VERSION_HASH=${{ needs.test.outputs.repo_version_hash }}
|
||||||
BUILD_ENVIRONMENT=production
|
BUILD_ENVIRONMENT=production
|
||||||
|
|||||||
@@ -57,12 +57,16 @@ jobs:
|
|||||||
- name: Login to Docker Registry
|
- name: Login to Docker Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
registry: gitea.perren.cloud
|
registry: 192.168.1.36:30008
|
||||||
username: ${{ secrets.REGISTRY_USERNAME }}
|
username: ${{ secrets.REGISTRY_USERNAME }}
|
||||||
password: ${{ secrets.ACTIONS_TOKEN }}
|
password: ${{ secrets.ACTIONS_TOKEN }}
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3
|
||||||
|
with:
|
||||||
|
buildkitd-config-inline: |
|
||||||
|
[registry."192.168.1.36:30008"]
|
||||||
|
http = true
|
||||||
|
|
||||||
- name: Build and Push
|
- name: Build and Push
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
@@ -70,7 +74,7 @@ jobs:
|
|||||||
context: caperren-com
|
context: caperren-com
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
gitea.perren.cloud/caperren/caperren-com:latest-staging
|
192.168.1.36:30008/caperren/caperren-com:latest-staging
|
||||||
build-args: |
|
build-args: |
|
||||||
REPO_VERSION_HASH=${{ needs.test.outputs.repo_version_hash }}
|
REPO_VERSION_HASH=${{ needs.test.outputs.repo_version_hash }}
|
||||||
BUILD_ENVIRONMENT=staging
|
BUILD_ENVIRONMENT=staging
|
||||||
|
|||||||
13
Makefile
@@ -15,7 +15,8 @@
|
|||||||
cleanup-check \
|
cleanup-check \
|
||||||
cleanup-code \
|
cleanup-code \
|
||||||
convert_video \
|
convert_video \
|
||||||
convert_video_times
|
convert_video_times \
|
||||||
|
generate_asset_imports
|
||||||
|
|
||||||
default: dev
|
default: dev
|
||||||
|
|
||||||
@@ -83,9 +84,17 @@ convert_video_times:
|
|||||||
-init_hw_device vaapi=va:/dev/dri/renderD128 \
|
-init_hw_device vaapi=va:/dev/dri/renderD128 \
|
||||||
-filter_hw_device va \
|
-filter_hw_device va \
|
||||||
-i $(input) \
|
-i $(input) \
|
||||||
-vf 'format=nv12,hwupload,scale_vaapi=-2:720,trim=start=$(start):end=$(end)' \
|
-ss $(start) \
|
||||||
|
-to $(end) \
|
||||||
|
-vf 'format=nv12,hwupload,scale_vaapi=-2:720' \
|
||||||
-c:v h264_vaapi \
|
-c:v h264_vaapi \
|
||||||
-rc_mode CQP \
|
-rc_mode CQP \
|
||||||
-qp 28 \
|
-qp 28 \
|
||||||
-an \
|
-an \
|
||||||
$(output)
|
$(output)
|
||||||
|
|
||||||
|
generate_asset_imports:
|
||||||
|
@for assets_path in `find "src/assets/${assets_relative_path}" -maxdepth 1 -type f -printf "%f\n"`; do \
|
||||||
|
without_extension=$${assets_path/%.*}; \
|
||||||
|
echo "import $${without_extension//-/_} from \"@assets/${assets_relative_path}/$$assets_path\";"; \
|
||||||
|
done;
|
||||||
|
|||||||
@@ -3,7 +3,10 @@ Altium
|
|||||||
ASSEM
|
ASSEM
|
||||||
astrojs
|
astrojs
|
||||||
Atmel
|
Atmel
|
||||||
|
automations
|
||||||
barebones
|
barebones
|
||||||
|
beaglebone
|
||||||
|
Bitwarden
|
||||||
Candian
|
Candian
|
||||||
caperren
|
caperren
|
||||||
CEOAS
|
CEOAS
|
||||||
@@ -12,10 +15,19 @@ Concours
|
|||||||
CONSERV
|
CONSERV
|
||||||
Corwin
|
Corwin
|
||||||
dangerousthings
|
dangerousthings
|
||||||
|
dechorionation
|
||||||
Dechorionator
|
Dechorionator
|
||||||
|
dechorionators
|
||||||
|
dockerization
|
||||||
|
dockerizing
|
||||||
|
drumheller
|
||||||
ebox
|
ebox
|
||||||
|
ELMI
|
||||||
fhhs
|
fhhs
|
||||||
flowbite
|
flowbite
|
||||||
|
flowrate
|
||||||
|
gcode
|
||||||
|
gerbers
|
||||||
Gitea
|
Gitea
|
||||||
HDFS
|
HDFS
|
||||||
headshot
|
headshot
|
||||||
@@ -25,36 +37,60 @@ iceops
|
|||||||
ITAR
|
ITAR
|
||||||
Jetson
|
Jetson
|
||||||
KFSK
|
KFSK
|
||||||
|
Labjack
|
||||||
leconte
|
leconte
|
||||||
Loctite
|
Loctite
|
||||||
luxon
|
luxon
|
||||||
MGMT
|
MGMT
|
||||||
|
microcontroller
|
||||||
|
microcontroller's
|
||||||
|
Micropumps
|
||||||
|
Millis
|
||||||
|
modbus
|
||||||
Mokai
|
Mokai
|
||||||
Multimeters
|
Multimeters
|
||||||
nixos
|
nixos
|
||||||
|
nvme
|
||||||
offroad
|
offroad
|
||||||
Onshape
|
Onshape
|
||||||
OSSM
|
OSSM
|
||||||
OSURC
|
OSURC
|
||||||
|
panelized
|
||||||
|
Passthroughs
|
||||||
|
pcbs
|
||||||
Perren
|
Perren
|
||||||
Perren's
|
Perren's
|
||||||
Pixhawk
|
Pixhawk
|
||||||
|
Protocase
|
||||||
pubpath
|
pubpath
|
||||||
RFID
|
RFID
|
||||||
|
Rito
|
||||||
RSSI
|
RSSI
|
||||||
SARL
|
SARL
|
||||||
|
SCARA
|
||||||
|
showerheads
|
||||||
Shuttlebox
|
Shuttlebox
|
||||||
|
simplemotion
|
||||||
sinnhuber
|
sinnhuber
|
||||||
sitemapindex
|
sitemapindex
|
||||||
|
Smartsheet
|
||||||
|
solderable
|
||||||
ssds
|
ssds
|
||||||
Starlink
|
Starlink
|
||||||
steller
|
steller
|
||||||
Steller
|
Steller
|
||||||
|
Tanguay
|
||||||
|
Teamcenter
|
||||||
timelapse
|
timelapse
|
||||||
|
touchoff
|
||||||
|
triaging
|
||||||
trivago
|
trivago
|
||||||
|
Truong
|
||||||
|
Ubiquiti
|
||||||
Unstow
|
Unstow
|
||||||
uuidv
|
uuidv
|
||||||
vaapi
|
vaapi
|
||||||
vitest
|
vitest
|
||||||
|
Waterjet
|
||||||
Zebrafish
|
Zebrafish
|
||||||
zscan
|
zscan
|
||||||
|
|||||||
|
After Width: | Height: | Size: 3.9 MiB |
|
Before Width: | Height: | Size: 2.7 MiB After Width: | Height: | Size: 2.7 MiB |
|
After Width: | Height: | Size: 10 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 3.3 MiB |
|
After Width: | Height: | Size: 10 MiB |
|
After Width: | Height: | Size: 1.9 MiB |
|
After Width: | Height: | Size: 10 MiB |
|
After Width: | Height: | Size: 14 MiB |
|
After Width: | Height: | Size: 12 MiB |
|
After Width: | Height: | Size: 1.2 MiB |
|
After Width: | Height: | Size: 4.7 MiB |
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 4.0 MiB |
|
After Width: | Height: | Size: 3.1 MiB |
|
After Width: | Height: | Size: 3.6 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 3.7 MiB |
|
After Width: | Height: | Size: 7.7 MiB |
|
After Width: | Height: | Size: 7.3 MiB |
|
After Width: | Height: | Size: 8.3 MiB |
|
After Width: | Height: | Size: 7.6 MiB |
|
After Width: | Height: | Size: 4.4 MiB |
|
After Width: | Height: | Size: 3.5 MiB |
|
After Width: | Height: | Size: 3.8 MiB |
|
After Width: | Height: | Size: 4.1 MiB |
|
After Width: | Height: | Size: 166 KiB |
|
After Width: | Height: | Size: 239 KiB |
|
After Width: | Height: | Size: 3.8 MiB |
|
After Width: | Height: | Size: 3.9 MiB |
|
After Width: | Height: | Size: 4.6 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 4.3 MiB |
|
After Width: | Height: | Size: 4.4 MiB |
|
After Width: | Height: | Size: 4.4 MiB |
|
After Width: | Height: | Size: 6.4 MiB |
|
After Width: | Height: | Size: 7.9 MiB |
|
After Width: | Height: | Size: 8.9 MiB |
|
After Width: | Height: | Size: 8.7 MiB |
|
After Width: | Height: | Size: 7.8 MiB |
|
After Width: | Height: | Size: 5.9 MiB |
|
After Width: | Height: | Size: 9.2 MiB |
|
After Width: | Height: | Size: 4.2 MiB |
|
After Width: | Height: | Size: 1013 KiB |
|
After Width: | Height: | Size: 6.8 MiB |
|
After Width: | Height: | Size: 9.2 MiB |
|
After Width: | Height: | Size: 8.8 MiB |
|
After Width: | Height: | Size: 8.5 MiB |
|
After Width: | Height: | Size: 6.3 MiB |
|
After Width: | Height: | Size: 1017 KiB |
|
After Width: | Height: | Size: 878 KiB |
|
After Width: | Height: | Size: 7.1 MiB |
|
After Width: | Height: | Size: 605 KiB |
|
After Width: | Height: | Size: 826 KiB |
|
After Width: | Height: | Size: 7.1 MiB |
|
After Width: | Height: | Size: 6.1 MiB |
|
After Width: | Height: | Size: 6.9 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 8.3 MiB |
|
After Width: | Height: | Size: 7.5 MiB |
|
After Width: | Height: | Size: 7.2 MiB |
|
After Width: | Height: | Size: 1.3 MiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
After Width: | Height: | Size: 4.6 MiB |
|
After Width: | Height: | Size: 4.6 MiB |
|
After Width: | Height: | Size: 4.4 MiB |
|
After Width: | Height: | Size: 1.0 MiB |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 167 KiB |
|
After Width: | Height: | Size: 438 KiB |
|
After Width: | Height: | Size: 224 KiB |
|
After Width: | Height: | Size: 437 KiB |
|
After Width: | Height: | Size: 2.0 MiB |
|
After Width: | Height: | Size: 600 KiB |
|
After Width: | Height: | Size: 701 KiB |
BIN
src/assets/hobby/homelab/offsite-backup-rack/installed.jpg
Normal file
|
After Width: | Height: | Size: 2.4 MiB |
|
Before Width: | Height: | Size: 2.4 MiB After Width: | Height: | Size: 2.4 MiB |
5
src/components/H4.astro
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<h4 class="md:text-md text-xs sm:text-sm"><slot /></h4>
|
||||||
@@ -1,15 +1,21 @@
|
|||||||
---
|
---
|
||||||
import { Image } from "astro:assets";
|
import { Image } from "astro:assets";
|
||||||
|
|
||||||
|
import type { ComponentPropsBase } from "@interfaces/components.ts";
|
||||||
import type { carouselGroup } from "@interfaces/image-carousel.ts";
|
import type { carouselGroup } from "@interfaces/image-carousel.ts";
|
||||||
|
|
||||||
const groupToShow: carouselGroup = Astro.props.carouselGroup;
|
interface Props extends ComponentPropsBase {
|
||||||
|
carouselGroup: carouselGroup;
|
||||||
|
showBorder?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { class: className, carouselGroup, showBorder = true } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<custom-carousel
|
<custom-carousel
|
||||||
class="relative flex w-full flex-col"
|
class="relative flex w-full flex-col"
|
||||||
data-custom-carousel={groupToShow.animation}
|
data-custom-carousel={carouselGroup.animation ?? "slide"}
|
||||||
data-custom-carousel-interval={groupToShow.interval}
|
data-custom-carousel-interval={carouselGroup.interval}
|
||||||
>
|
>
|
||||||
<!-- Modal for fullscreen viewing -->
|
<!-- Modal for fullscreen viewing -->
|
||||||
<div
|
<div
|
||||||
@@ -57,11 +63,18 @@ const groupToShow: carouselGroup = Astro.props.carouselGroup;
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Carousel wrapper -->
|
<!-- Carousel wrapper -->
|
||||||
<div class="relative h-56 w-full overflow-hidden md:h-120">
|
|
||||||
{
|
|
||||||
groupToShow.images.map((image, index) => (
|
|
||||||
<div
|
<div
|
||||||
class="hidden duration-1500 ease-in-out"
|
class:list={[
|
||||||
|
"relative h-56 w-full overflow-hidden rounded-lg md:h-120",
|
||||||
|
showBorder ? "border" : false,
|
||||||
|
className ? className : "border-caperren-green-dark",
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
{
|
||||||
|
carouselGroup.images &&
|
||||||
|
carouselGroup.images.map((image, index) => (
|
||||||
|
<div
|
||||||
|
class="hidden bg-black duration-1500 ease-in-out"
|
||||||
data-custom-carousel-item={index}
|
data-custom-carousel-item={index}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
@@ -78,13 +91,14 @@ const groupToShow: carouselGroup = Astro.props.carouselGroup;
|
|||||||
|
|
||||||
<!-- Slider indicators -->
|
<!-- Slider indicators -->
|
||||||
{
|
{
|
||||||
groupToShow.images.length > 1 && (
|
carouselGroup.images && carouselGroup.images.length > 1 && (
|
||||||
<div>
|
<div>
|
||||||
<div class="absolute bottom-2 left-1/2 z-30 flex -translate-x-1/2 space-x-3 rounded-full">
|
<div class="absolute bottom-2 left-1/2 z-30 flex -translate-x-1/2 space-x-3 rounded-full">
|
||||||
{groupToShow.images.map((_, index) => (
|
{carouselGroup.images &&
|
||||||
|
carouselGroup.images.map((_, index) => (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="hover:bg-caperren-green-light h-3 w-3 rounded-full bg-black"
|
class="hover:bg-caperren-green-light h-3 w-3 rounded-full"
|
||||||
aria-current={index ? "false" : "true"}
|
aria-current={index ? "false" : "true"}
|
||||||
aria-label={index.toString()}
|
aria-label={index.toString()}
|
||||||
data-custom-carousel-slide-to={index}
|
data-custom-carousel-slide-to={index}
|
||||||
@@ -96,15 +110,16 @@ const groupToShow: carouselGroup = Astro.props.carouselGroup;
|
|||||||
class="group absolute start-0 top-0 z-30 flex h-full cursor-pointer items-center justify-center px-4 focus:outline-none"
|
class="group absolute start-0 top-0 z-30 flex h-full cursor-pointer items-center justify-center px-4 focus:outline-none"
|
||||||
data-custom-carousel-prev
|
data-custom-carousel-prev
|
||||||
>
|
>
|
||||||
<span class="ring-caperren-green/25 inline-flex h-10 w-10 items-center justify-center rounded-full bg-black/25 ring-2 group-hover:bg-black/75">
|
<span class="ring-caperren-green/35 group-hover:ring-caperren-green inline-flex h-10 w-10 items-center justify-center rounded-full bg-black/35 ring-2 group-hover:bg-black/75">
|
||||||
<svg
|
<svg
|
||||||
class="text-caperren-green group-hover:text-caperren-green-light h-4 w-4"
|
class="text-caperren-green stroke-caperren-green group-hover:text-caperren-green-light h-4 w-4"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 6 10"
|
viewBox="0 0 8 10"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
|
fill-opacity="0%"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
@@ -119,15 +134,16 @@ const groupToShow: carouselGroup = Astro.props.carouselGroup;
|
|||||||
class="group absolute end-0 top-0 z-30 flex h-full cursor-pointer items-center justify-center px-4 focus:outline-none"
|
class="group absolute end-0 top-0 z-30 flex h-full cursor-pointer items-center justify-center px-4 focus:outline-none"
|
||||||
data-custom-carousel-next
|
data-custom-carousel-next
|
||||||
>
|
>
|
||||||
<span class="ring-caperren-green/25 inline-flex h-10 w-10 items-center justify-center rounded-full bg-black/25 ring-2 group-hover:bg-black/75">
|
<span class="ring-caperren-green/25 group-hover:ring-caperren-green inline-flex h-10 w-10 items-center justify-center rounded-full bg-black/25 ring-2 group-hover:bg-black/75">
|
||||||
<svg
|
<svg
|
||||||
class="text-caperren-green group-hover:text-caperren-green-light h-4 w-4"
|
class="text-caperren-green stroke-caperren-green group-hover:text-caperren-green-light h-4 w-4"
|
||||||
aria-hidden="true"
|
aria-hidden="true"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 6 10"
|
viewBox="0 0 4 10"
|
||||||
>
|
>
|
||||||
<path
|
<path
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
|
fill-opacity="0%"
|
||||||
stroke-linecap="round"
|
stroke-linecap="round"
|
||||||
stroke-linejoin="round"
|
stroke-linejoin="round"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ const {
|
|||||||
|
|
||||||
<div class="mx-auto my-auto">
|
<div class="mx-auto my-auto">
|
||||||
<video
|
<video
|
||||||
class="h-auto w-full"
|
class="border-caperren-green-dark h-auto w-full rounded-lg border"
|
||||||
controls={controls}
|
controls={controls}
|
||||||
autoplay={autoPlay}
|
autoplay={autoPlay}
|
||||||
loop={loop}
|
loop={loop}
|
||||||
|
|||||||
@@ -1,13 +1,26 @@
|
|||||||
---
|
---
|
||||||
import type { videoConfig } from "@interfaces/video.ts";
|
import type { videoConfig } from "@interfaces/video.ts";
|
||||||
|
|
||||||
const config: videoConfig = Astro.props.videoConfig;
|
interface Props extends videoConfig {}
|
||||||
|
|
||||||
|
const {
|
||||||
|
videoPath,
|
||||||
|
videoTitle,
|
||||||
|
width = "1920",
|
||||||
|
height = "1080",
|
||||||
|
autoPlay = false,
|
||||||
|
} = Astro.props;
|
||||||
|
|
||||||
|
const aspect = `${width} / ${height}`;
|
||||||
---
|
---
|
||||||
|
|
||||||
<iframe
|
<div class="mx-auto my-auto w-full" style={`aspect-ratio: ${aspect};`}>
|
||||||
class="h-128 w-full max-w-1/2"
|
<iframe
|
||||||
src={config.videoPath}
|
src={videoPath}
|
||||||
title={config.videoTitle ?? ""}
|
title={videoTitle}
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
class="border-caperren-green-dark h-full w-full rounded-lg border"
|
||||||
|
allow={"accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; " +
|
||||||
|
(autoPlay ? "autoplay;" : "")}
|
||||||
referrerpolicy="strict-origin-when-cross-origin"
|
referrerpolicy="strict-origin-when-cross-origin"
|
||||||
allowfullscreen></iframe>
|
allowfullscreen></iframe>
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -36,7 +36,8 @@ const { pathname } = Astro.url;
|
|||||||
data-dropdown-offset-skidding="12"
|
data-dropdown-offset-skidding="12"
|
||||||
class:list={[
|
class:list={[
|
||||||
"hover:text-caperren-green-light lg:hover:text-caperren-green-light flex w-full items-center justify-between lg:p-0 lg:hover:bg-transparent",
|
"hover:text-caperren-green-light lg:hover:text-caperren-green-light flex w-full items-center justify-between lg:p-0 lg:hover:bg-transparent",
|
||||||
pathname.startsWith(getHrefPath(paths, entry))
|
pathname.startsWith(getHrefPath(paths, entry)) &&
|
||||||
|
!(entry.placeholderEntry ?? false)
|
||||||
? "border-caperren-green border-b-2"
|
? "border-caperren-green border-b-2"
|
||||||
: false,
|
: false,
|
||||||
]}
|
]}
|
||||||
@@ -71,20 +72,32 @@ const { pathname } = Astro.url;
|
|||||||
) : (
|
) : (
|
||||||
<div>
|
<div>
|
||||||
<a
|
<a
|
||||||
href={getHrefPath(paths, entry)}
|
href={
|
||||||
|
!(entry.placeholderEntry ?? false)
|
||||||
|
? getHrefPath(paths, entry)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
target={
|
target={
|
||||||
getHrefPath(paths, entry).startsWith("/") ? "" : "_blank"
|
getHrefPath(paths, entry).startsWith("/") ? "" : "_blank"
|
||||||
}
|
}
|
||||||
class:list={[
|
class:list={[
|
||||||
"hover:text-caperren-green-light ring-caperren-green-dark block bg-transparent lg:p-0",
|
"ring-caperren-green-dark block bg-transparent lg:p-0",
|
||||||
pathname === getHrefPath(paths, entry)
|
pathname === getHrefPath(paths, entry)
|
||||||
? "border-caperren-green border-b-2"
|
? "border-caperren-green border-b-2"
|
||||||
: false,
|
: false,
|
||||||
|
entry.isSubItem ? "ms-3" : false,
|
||||||
|
entry.placeholderEntry
|
||||||
|
? false
|
||||||
|
: "hover:text-caperren-green-light",
|
||||||
]}
|
]}
|
||||||
aria-current={
|
aria-current={
|
||||||
pathname === getHrefPath(paths, entry) ? "page" : undefined
|
pathname === getHrefPath(paths, entry) &&
|
||||||
|
!(entry.placeholderEntry ?? false)
|
||||||
|
? "page"
|
||||||
|
: undefined
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
{entry.isSubItem && "∟ "}
|
||||||
{entry.navText}
|
{entry.navText}
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ const hasHeader = Astro.slots.has("header");
|
|||||||
const hasDefault = Astro.slots.has("default");
|
const hasDefault = Astro.slots.has("default");
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="grid grid-cols-1 gap-3">
|
<div class="grid grid-cols-1 gap-0.5">
|
||||||
{
|
{
|
||||||
Astro.slots.has("header") && (
|
Astro.slots.has("header") && (
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const keys: { [key: string]: string } = {
|
|||||||
GUI: "Graphical user interface",
|
GUI: "Graphical user interface",
|
||||||
NUC: "A small and low-power computer made by Intel",
|
NUC: "A small and low-power computer made by Intel",
|
||||||
PCBs: "Printed circuit boards",
|
PCBs: "Printed circuit boards",
|
||||||
|
SCARA: "Selective Compliance Assembly Robot Arm",
|
||||||
TDD: "Test driven development",
|
TDD: "Test driven development",
|
||||||
UPS: "Uninterruptible power supply",
|
UPS: "Uninterruptible power supply",
|
||||||
VISA: "Virtual instrument software architecture",
|
VISA: "Virtual instrument software architecture",
|
||||||
|
|||||||
58
src/components/PrintedCircuitBoard.astro
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
import Carousel from "@components/Media/CustomCarousel/CustomCarousel.astro";
|
||||||
|
import Ul from "@components/Ul.astro";
|
||||||
|
|
||||||
|
import H3 from "@components/H3.astro";
|
||||||
|
import H4 from "@components/H4.astro";
|
||||||
|
import PageGroup from "@components/PageGroup.astro";
|
||||||
|
import type {
|
||||||
|
printedCircuitBoard,
|
||||||
|
printedCircuitBoardRevision,
|
||||||
|
} from "@interfaces/printed-circuit-board.ts";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
pcb: printedCircuitBoard;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { pcb } = Astro.props;
|
||||||
|
const semanticPcbRevisionSort = (
|
||||||
|
a: printedCircuitBoardRevision,
|
||||||
|
b: printedCircuitBoardRevision,
|
||||||
|
): number =>
|
||||||
|
-((a.major - b.major) * 100 + (a.minor - b.minor) * 10 + (a.patch - b.patch));
|
||||||
|
---
|
||||||
|
|
||||||
|
<PageGroup>
|
||||||
|
<Fragment slot="header"
|
||||||
|
><H3>{pcb.name}</H3><H4>{pcb.description}</H4></Fragment
|
||||||
|
>
|
||||||
|
<div class="mt-1 grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||||
|
{
|
||||||
|
pcb.revisions?.sort(semanticPcbRevisionSort).map((revision) => (
|
||||||
|
<div class="border-caperren-green block space-y-2 rounded-lg border bg-black py-2">
|
||||||
|
<div class="border-caperren-green flex flex-wrap items-center justify-between rounded-none border-b px-4 pb-2">
|
||||||
|
<div>
|
||||||
|
<span class="font-black">Revision:</span>
|
||||||
|
<span>
|
||||||
|
{revision.major}.{revision.minor}.{revision.patch}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div class="text-sm italic">{revision.date.toISODate()}</div>
|
||||||
|
</div>
|
||||||
|
<div class="px-4">
|
||||||
|
<Carousel
|
||||||
|
class=""
|
||||||
|
carouselGroup={{ images: revision.images }}
|
||||||
|
showBorder={false}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{revision.notes && revision.notes.length > 0 && (
|
||||||
|
<div class="border-caperren-green border-t px-4 pt-4 pb-2 text-sm">
|
||||||
|
<Ul lineItems={revision.notes} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</PageGroup>
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
---
|
---
|
||||||
import type { timelineEntry } from "@interfaces/timeline.ts";
|
import type { timelineEntry } from "@interfaces/timeline.ts";
|
||||||
|
|
||||||
const timeline: timelineEntry[] = Astro.props.timeline || [];
|
interface Props {
|
||||||
|
timeline: timelineEntry[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { timeline = [] } = Astro.props;
|
||||||
---
|
---
|
||||||
|
|
||||||
<custom-timeline>
|
<custom-timeline>
|
||||||
@@ -11,7 +15,11 @@ const timeline: timelineEntry[] = Astro.props.timeline || [];
|
|||||||
data-timeline
|
data-timeline
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
timeline.map((entry, index) => (
|
timeline
|
||||||
|
.sort((a: timelineEntry, b: timelineEntry) =>
|
||||||
|
a.date.diff(b.date).toMillis(),
|
||||||
|
)
|
||||||
|
.map((entry, index) => (
|
||||||
<div
|
<div
|
||||||
class="border-caperren-green min-w-s max-w-s rounded-lg border bg-black px-2 pt-1 pb-2"
|
class="border-caperren-green min-w-s max-w-s rounded-lg border bg-black px-2 pt-1 pb-2"
|
||||||
data-timeline-node-index={index}
|
data-timeline-node-index={index}
|
||||||
@@ -19,7 +27,7 @@ const timeline: timelineEntry[] = Astro.props.timeline || [];
|
|||||||
<h3 class="text-lg font-bold">{entry.event}</h3>
|
<h3 class="text-lg font-bold">{entry.event}</h3>
|
||||||
<h4 class="leading-none font-semibold">{entry.eventDetail}</h4>
|
<h4 class="leading-none font-semibold">{entry.eventDetail}</h4>
|
||||||
<time class="mt-1 mb-2 text-sm leading-none italic">
|
<time class="mt-1 mb-2 text-sm leading-none italic">
|
||||||
{entry.date}
|
{entry.date.toFormat("LLLL kkkk")}
|
||||||
</time>
|
</time>
|
||||||
{entry.description && (
|
{entry.description && (
|
||||||
<p class="text-sm font-normal">{entry.description}</p>
|
<p class="text-sm font-normal">{entry.description}</p>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import type { navLink } from "@interfaces/site-layout.ts";
|
import type { navLink } from "@interfaces/site-layout.ts";
|
||||||
|
|
||||||
export const siteLayout: navLink[] = [
|
export const siteLayout: navLink[] = [
|
||||||
// Standard navbar entries
|
|
||||||
{ navText: "About", path: "" },
|
{ navText: "About", path: "" },
|
||||||
{ navText: "Education", path: "education" },
|
{ navText: "Education", path: "education" },
|
||||||
{
|
{
|
||||||
@@ -13,7 +12,6 @@ export const siteLayout: navLink[] = [
|
|||||||
path: "spacex",
|
path: "spacex",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "Hardware Test Engineer I/II",
|
navText: "Hardware Test Engineer I/II",
|
||||||
path: "hardware-test-engineer-i-ii",
|
path: "hardware-test-engineer-i-ii",
|
||||||
},
|
},
|
||||||
@@ -27,60 +25,65 @@ export const siteLayout: navLink[] = [
|
|||||||
navText: "OSU CEOAS Ocean Mixing Group",
|
navText: "OSU CEOAS Ocean Mixing Group",
|
||||||
path: "osu-ceoas-ocean-mixing-group",
|
path: "osu-ceoas-ocean-mixing-group",
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
navText: "Student Software/Electrical Engineer",
|
||||||
|
placeholderEntry: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
navText: "Robotic Oceanographic Surface Sampler",
|
navText: "Robotic Oceanographic Surface Sampler",
|
||||||
|
isSubItem: true,
|
||||||
path: "robotic-oceanographic-surface-sampler",
|
path: "robotic-oceanographic-surface-sampler",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
navText: "LeConte Glacier Deployments",
|
navText: "LeConte Glacier Deployments",
|
||||||
|
isSubItem: true,
|
||||||
path: "leconte-glacier-deployments",
|
path: "leconte-glacier-deployments",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
navText: "OSU Sinnhuber Aquatic Research Lab",
|
||||||
navText: "OSU SARL",
|
|
||||||
path: "osu-sinnhuber-aquatic-research-laboratory",
|
path: "osu-sinnhuber-aquatic-research-laboratory",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
enabled: false,
|
navText: "Student Automation Engineer",
|
||||||
navText: "Team Lead",
|
placeholderEntry: true,
|
||||||
path: "team-lead",
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "Zebrafish Embryo Pick and Plate",
|
navText: "Zebrafish Embryo Pick and Plate",
|
||||||
|
isSubItem: true,
|
||||||
path: "zebrafish-embryo-pick-and-plate",
|
path: "zebrafish-embryo-pick-and-plate",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
enabled: false,
|
||||||
navText: "Shuttlebox Behavior System",
|
navText: "Shuttlebox Behavior System",
|
||||||
|
isSubItem: true,
|
||||||
path: "shuttlebox-behavior-system",
|
path: "shuttlebox-behavior-system",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "Dechorionator",
|
navText: "Dechorionator",
|
||||||
|
isSubItem: true,
|
||||||
path: "dechorionator",
|
path: "dechorionator",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
enabled: false,
|
||||||
navText: "Denso Embryo Pick and Plate",
|
navText: "Denso Embryo Pick and Plate",
|
||||||
|
isSubItem: true,
|
||||||
path: "denso-embryo-pick-and-plate",
|
path: "denso-embryo-pick-and-plate",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
enabled: false,
|
||||||
navText: "ZScan Processor",
|
navText: "ZScan Processor",
|
||||||
|
isSubItem: true,
|
||||||
path: "zscan-processor",
|
path: "zscan-processor",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "OSU Robotics Club",
|
navText: "OSU Robotics Club",
|
||||||
path: "osu-robotics-club",
|
path: "osu-robotics-club",
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
enabled: false,
|
|
||||||
navText: "Mars Rover Software Team Lead",
|
navText: "Mars Rover Software Team Lead",
|
||||||
path: "mars-rover-software-team-lead",
|
path: "mars-rover-software-team-lead",
|
||||||
},
|
},
|
||||||
@@ -263,7 +266,10 @@ export const getPaths = (
|
|||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
let enabled = currentEntry.enabled ?? true;
|
let enabled = currentEntry.enabled ?? true;
|
||||||
if (disabledOnly ? !enabled : enabled) {
|
if (
|
||||||
|
(disabledOnly ? !enabled : enabled) &&
|
||||||
|
!currentEntry.placeholderEntry
|
||||||
|
) {
|
||||||
foundPaths.push("/" + [...paths, currentEntry.path || ""].join("/"));
|
foundPaths.push("/" + [...paths, currentEntry.path || ""].join("/"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export interface carouselGroup {
|
export interface carouselGroup {
|
||||||
animation: "static" | "slide";
|
animation?: "static" | "slide";
|
||||||
interval?: number;
|
interval?: number;
|
||||||
images: ImageMetadata[];
|
images?: ImageMetadata[];
|
||||||
}
|
}
|
||||||
|
|||||||
32
src/interfaces/printed-circuit-board.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import type { ImageMetadata } from "astro";
|
||||||
|
import { DateTime } from "luxon";
|
||||||
|
|
||||||
|
import type { timelineEntry } from "@interfaces/timeline.ts";
|
||||||
|
import type { lineItem } from "@interfaces/ul-li.ts";
|
||||||
|
|
||||||
|
export interface printedCircuitBoardRevision {
|
||||||
|
major: number;
|
||||||
|
minor: number;
|
||||||
|
patch: number;
|
||||||
|
|
||||||
|
date: DateTime;
|
||||||
|
|
||||||
|
images?: ImageMetadata[];
|
||||||
|
notes?: lineItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface printedCircuitBoard {
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
|
||||||
|
revisions: printedCircuitBoardRevision[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export const timelineFromPrintedCircuitBoard = (
|
||||||
|
pcb: printedCircuitBoard,
|
||||||
|
): timelineEntry[] =>
|
||||||
|
pcb.revisions?.map((revision) => ({
|
||||||
|
event: `PCB Released: ${pcb.name} `,
|
||||||
|
eventDetail: `Revision: ${revision.major}.${revision.minor}.${revision.patch}`,
|
||||||
|
date: revision.date,
|
||||||
|
}));
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
export interface navLink {
|
export interface navLink {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
|
placeholderEntry?: boolean;
|
||||||
|
|
||||||
navText: string;
|
navText: string;
|
||||||
|
isSubItem?: boolean; // For visual distinction only
|
||||||
|
|
||||||
path?: string;
|
path?: string;
|
||||||
pubpath?: string;
|
pubpath?: string;
|
||||||
|
|
||||||
children?: navLink[];
|
children?: navLink[];
|
||||||
}
|
}
|
||||||
|
|||||||