fix: enhance Docker build process and improve file explorer resizing functionality

pull/10/head
David Montero Crespo 2026-03-06 11:20:47 -03:00
parent 34dd56b789
commit 0d5d440a56
5 changed files with 74 additions and 26 deletions

View File

@ -3,7 +3,7 @@ name: Publish Docker Image
on: on:
push: push:
branches: [ "master" ] branches: [ "master" ]
# You can also trigger this on release tags: # Uncomment to also trigger on release tags:
# tags: [ 'v*.*.*' ] # tags: [ 'v*.*.*' ]
env: env:
@ -23,6 +23,9 @@ jobs:
with: with:
submodules: recursive submodules: recursive
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry (GHCR) - name: Log in to GitHub Container Registry (GHCR)
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
@ -36,9 +39,6 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }} username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata (tags, labels) for Docker - name: Extract metadata (tags, labels) for Docker
id: meta id: meta
uses: docker/metadata-action@v5 uses: docker/metadata-action@v5
@ -48,10 +48,12 @@ jobs:
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/velxio docker.io/${{ secrets.DOCKERHUB_USERNAME }}/velxio
- name: Build and push Docker image - name: Build and push Docker image
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
file: Dockerfile.standalone file: Dockerfile.standalone
push: true push: true
tags: ${{ steps.meta.outputs.tags }} tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }} labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

View File

@ -1,9 +1,9 @@
# ---- Stage 1: Build frontend and wokwi-libs ---- # ---- Stage 1: Build frontend and wokwi-libs ----
FROM node:20 AS frontend-builder FROM node:20-slim AS frontend-builder
WORKDIR /app WORKDIR /app
# Copy package.json for metadata generation and common dependencies # Copy root package.json (metadata/scripts)
COPY package.json . COPY package.json .
RUN npm install RUN npm install
@ -22,35 +22,34 @@ COPY wokwi-libs/wokwi-elements/ wokwi-libs/wokwi-elements/
WORKDIR /app/wokwi-libs/wokwi-elements WORKDIR /app/wokwi-libs/wokwi-elements
RUN npm install && npm run build RUN npm install && npm run build
# Build frontend and generate metadata # Build frontend
WORKDIR /app WORKDIR /app
COPY frontend/ frontend/ COPY frontend/ frontend/
COPY scripts/ scripts/ COPY scripts/ scripts/
WORKDIR /app/frontend WORKDIR /app/frontend
# Explicitly install frontend dependencies RUN npm install && npm run build
RUN npm install
# Now run the build which includes metadata generation
RUN npm run build
# ---- Stage 2: Final Production Image ---- # ---- Stage 2: Final Production Image ----
FROM python:3.12-slim FROM python:3.12-slim
# Install system dependencies, arduino-cli, and nginx # Install system dependencies and nginx
RUN apt-get update && apt-get install -y --no-install-recommends \ RUN apt-get update && apt-get install -y --no-install-recommends \
curl \ curl \
ca-certificates \ ca-certificates \
nginx \ nginx \
&& curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh \
&& mv bin/arduino-cli /usr/local/bin/ \
&& rm -rf bin \
&& apt-get purge -y curl \
&& apt-get autoremove -y \
&& apt-get clean \ && apt-get clean \
&& rm -rf /var/lib/apt/lists/* && rm -rf /var/lib/apt/lists/*
# Initialize arduino-cli and install AVR & RP2040 cores # Install arduino-cli into /usr/local/bin directly (avoids touching /bin)
RUN arduino-cli core update-index \ RUN curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh \
| BINDIR=/usr/local/bin sh
# Initialize arduino-cli config, add RP2040 board manager URL, then install cores
RUN arduino-cli config init \
&& arduino-cli config add board_manager.additional_urls \
https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json \
&& arduino-cli core update-index \
&& arduino-cli core install arduino:avr \ && arduino-cli core install arduino:avr \
&& arduino-cli core install rp2040:rp2040 && arduino-cli core install rp2040:rp2040
@ -73,7 +72,6 @@ COPY --from=frontend-builder /app/frontend/dist /usr/share/nginx/html
COPY deploy/entrypoint.sh /app/entrypoint.sh COPY deploy/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh RUN chmod +x /app/entrypoint.sh
# Expose port 80 for the unified web server
EXPOSE 80 EXPOSE 80
CMD ["/app/entrypoint.sh"] CMD ["/app/entrypoint.sh"]

View File

@ -108,6 +108,22 @@ body {
color: #ccc; color: #ccc;
} }
/* Resize handle for the file explorer sidebar */
.explorer-resize-handle {
width: 4px;
flex-shrink: 0;
cursor: col-resize;
background: #2a2a2a;
transition: background 0.15s;
position: relative;
z-index: 5;
}
.explorer-resize-handle:hover,
.explorer-resize-handle:active {
background: #007acc;
}
.editor-wrapper { .editor-wrapper {
flex: 1; flex: 1;
overflow: hidden; overflow: hidden;

View File

@ -1,6 +1,5 @@
.file-explorer { .file-explorer {
width: 195px; width: 100%;
flex-shrink: 0;
background: #252526; background: #252526;
border-right: 1px solid #333; border-right: 1px solid #333;
display: flex; display: flex;

View File

@ -22,6 +22,10 @@ const BOTTOM_PANEL_MIN = 80;
const BOTTOM_PANEL_MAX = 600; const BOTTOM_PANEL_MAX = 600;
const BOTTOM_PANEL_DEFAULT = 200; const BOTTOM_PANEL_DEFAULT = 200;
const EXPLORER_MIN = 120;
const EXPLORER_MAX = 500;
const EXPLORER_DEFAULT = 210;
const resizeHandleStyle: React.CSSProperties = { const resizeHandleStyle: React.CSSProperties = {
height: 5, height: 5,
flexShrink: 0, flexShrink: 0,
@ -42,6 +46,7 @@ export const EditorPage: React.FC = () => {
const [saveModalOpen, setSaveModalOpen] = useState(false); const [saveModalOpen, setSaveModalOpen] = useState(false);
const [loginPromptOpen, setLoginPromptOpen] = useState(false); const [loginPromptOpen, setLoginPromptOpen] = useState(false);
const [explorerOpen, setExplorerOpen] = useState(true); const [explorerOpen, setExplorerOpen] = useState(true);
const [explorerWidth, setExplorerWidth] = useState(EXPLORER_DEFAULT);
const user = useAuthStore((s) => s.user); const user = useAuthStore((s) => s.user);
const handleSaveClick = useCallback(() => { const handleSaveClick = useCallback(() => {
@ -110,6 +115,27 @@ export const EditorPage: React.FC = () => {
document.addEventListener('mouseup', onUp); document.addEventListener('mouseup', onUp);
}, [bottomPanelHeight]); }, [bottomPanelHeight]);
const handleExplorerResizeMouseDown = useCallback((e: React.MouseEvent) => {
e.preventDefault();
const startX = e.clientX;
const startWidth = explorerWidth;
const onMove = (ev: MouseEvent) => {
const delta = ev.clientX - startX;
setExplorerWidth(Math.max(EXPLORER_MIN, Math.min(EXPLORER_MAX, startWidth + delta)));
};
const onUp = () => {
document.body.style.cursor = '';
document.body.style.userSelect = '';
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
};
document.body.style.cursor = 'col-resize';
document.body.style.userSelect = 'none';
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
}, [explorerWidth]);
return ( return (
<div className="app"> <div className="app">
<AppHeader /> <AppHeader />
@ -120,8 +146,15 @@ export const EditorPage: React.FC = () => {
className="editor-panel" className="editor-panel"
style={{ width: `${editorWidthPct}%`, display: 'flex', flexDirection: 'row' }} style={{ width: `${editorWidthPct}%`, display: 'flex', flexDirection: 'row' }}
> >
{/* File explorer sidebar */} {/* File explorer sidebar + resize handle */}
{explorerOpen && <FileExplorer onSaveClick={handleSaveClick} />} {explorerOpen && (
<>
<div style={{ width: explorerWidth, flexShrink: 0, display: 'flex', overflow: 'hidden' }}>
<FileExplorer onSaveClick={handleSaveClick} />
</div>
<div className="explorer-resize-handle" onMouseDown={handleExplorerResizeMouseDown} />
</>
)}
{/* Editor main area */} {/* Editor main area */}
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minWidth: 0 }}> <div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minWidth: 0 }}>