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,8 +3,8 @@ name: Publish Docker Image
on:
push:
branches: [ "master" ]
# You can also trigger this on release tags:
# tags: [ 'v*.*.*' ]
# Uncomment to also trigger on release tags:
# tags: [ 'v*.*.*' ]
env:
REGISTRY_GHCR: ghcr.io
@ -23,6 +23,9 @@ jobs:
with:
submodules: recursive
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to GitHub Container Registry (GHCR)
uses: docker/login-action@v3
with:
@ -36,9 +39,6 @@ jobs:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
@ -48,10 +48,12 @@ jobs:
docker.io/${{ secrets.DOCKERHUB_USERNAME }}/velxio
- name: Build and push Docker image
uses: docker/build-push-action@v5
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile.standalone
push: true
tags: ${{ steps.meta.outputs.tags }}
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 ----
FROM node:20 AS frontend-builder
FROM node:20-slim AS frontend-builder
WORKDIR /app
# Copy package.json for metadata generation and common dependencies
# Copy root package.json (metadata/scripts)
COPY package.json .
RUN npm install
@ -22,35 +22,34 @@ COPY wokwi-libs/wokwi-elements/ wokwi-libs/wokwi-elements/
WORKDIR /app/wokwi-libs/wokwi-elements
RUN npm install && npm run build
# Build frontend and generate metadata
# Build frontend
WORKDIR /app
COPY frontend/ frontend/
COPY scripts/ scripts/
WORKDIR /app/frontend
# Explicitly install frontend dependencies
RUN npm install
# Now run the build which includes metadata generation
RUN npm run build
RUN npm install && npm run build
# ---- Stage 2: Final Production Image ----
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 \
curl \
ca-certificates \
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 \
&& rm -rf /var/lib/apt/lists/*
# Initialize arduino-cli and install AVR & RP2040 cores
RUN arduino-cli core update-index \
# Install arduino-cli into /usr/local/bin directly (avoids touching /bin)
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 rp2040:rp2040
@ -73,7 +72,6 @@ COPY --from=frontend-builder /app/frontend/dist /usr/share/nginx/html
COPY deploy/entrypoint.sh /app/entrypoint.sh
RUN chmod +x /app/entrypoint.sh
# Expose port 80 for the unified web server
EXPOSE 80
CMD ["/app/entrypoint.sh"]

View File

@ -108,6 +108,22 @@ body {
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 {
flex: 1;
overflow: hidden;

View File

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

View File

@ -22,6 +22,10 @@ const BOTTOM_PANEL_MIN = 80;
const BOTTOM_PANEL_MAX = 600;
const BOTTOM_PANEL_DEFAULT = 200;
const EXPLORER_MIN = 120;
const EXPLORER_MAX = 500;
const EXPLORER_DEFAULT = 210;
const resizeHandleStyle: React.CSSProperties = {
height: 5,
flexShrink: 0,
@ -42,6 +46,7 @@ export const EditorPage: React.FC = () => {
const [saveModalOpen, setSaveModalOpen] = useState(false);
const [loginPromptOpen, setLoginPromptOpen] = useState(false);
const [explorerOpen, setExplorerOpen] = useState(true);
const [explorerWidth, setExplorerWidth] = useState(EXPLORER_DEFAULT);
const user = useAuthStore((s) => s.user);
const handleSaveClick = useCallback(() => {
@ -110,6 +115,27 @@ export const EditorPage: React.FC = () => {
document.addEventListener('mouseup', onUp);
}, [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 (
<div className="app">
<AppHeader />
@ -120,8 +146,15 @@ export const EditorPage: React.FC = () => {
className="editor-panel"
style={{ width: `${editorWidthPct}%`, display: 'flex', flexDirection: 'row' }}
>
{/* File explorer sidebar */}
{explorerOpen && <FileExplorer onSaveClick={handleSaveClick} />}
{/* File explorer sidebar + resize handle */}
{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 */}
<div style={{ flex: 1, display: 'flex', flexDirection: 'column', overflow: 'hidden', minWidth: 0 }}>