Compare commits

..
3 Commits
Author SHA1 Message Date
shihaam 872ebc1971 ci auto build and deploy
Build and deploy / Build and Push Docker Images (push) Has been cancelled
2025-12-13 15:35:08 +05:00
shihaam 3934cbf3ae fix typescrypt build shit 2025-12-13 15:29:17 +05:00
shihaam 36f7ce8e5d add docker prod build files 2025-12-13 15:28:55 +05:00
18 changed files with 104 additions and 51 deletions
+19
View File
@@ -0,0 +1,19 @@
FROM node:20-slim AS frontendbuilder
WORKDIR /tmp/frontendbuilder
COPY public/ .
RUN npm ci && npm run build
FROM python:3.11.4-slim-buster
WORKDIR /var/www/html/
COPY . .
RUN pip install -r requirements.txt
COPY --from=frontendbuilder /tmp/frontendbuilder/dist/ /var/www/html/public
VOLUME /var/www/html/public
CMD uvicorn app.main:app --host 0.0.0.0 --port 8000
+13
View File
@@ -0,0 +1,13 @@
services:
app:
build:
context: ../../
dockerfile: .build/prod/app.Dockerfile
hostname: mapmaker
image: git.shihaam.dev/sarlink/mapmaker/api
nginx:
build:
context: .
dockerfile: ./nginx.Dockerfile
hostname: mapmaker-nginx
image: git.shihaam.dev/sarlink/mapmaker/nginx
+10 -13
View File
@@ -6,7 +6,7 @@ server {
error_log /dev/stdout info;
location /api/ {
proxy_pass http://api:8000/api/;
proxy_pass http://mapmaker:8000/api/;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
@@ -15,7 +15,7 @@ server {
}
location /ws/ {
proxy_pass http://api:8000/ws/;
proxy_pass http://mapmaker:8000/ws/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
@@ -23,22 +23,19 @@ server {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket timeout settings
proxy_read_timeout 86400s;
proxy_send_timeout 86400s;
proxy_connect_timeout 60s;
}
location / {
# In development, proxy to Vite dev server
proxy_pass http://node:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
root /var/www/html/public;
try_files $uri $uri/ /index.html;
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
}
-5
View File
@@ -1,5 +0,0 @@
FROM node:24-bookworm-slim
WORKDIR /var/www/html/public
CMD npm run dev -- --host 0.0.0.0
-7
View File
@@ -1,7 +0,0 @@
FROM python:3.11.4-slim-buster
WORKDIR /var/www/html/
COPY requirements.txt .
RUN pip install -r requirements.txt
+45
View File
@@ -0,0 +1,45 @@
name: Build and deploy
on:
push:
branches:
- main
- master
pull_request:
branches:
- main
- master
jobs:
docker:
name: Build and Push Docker Images
runs-on: builder
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Login to Docker Registry
if: github.event_name != 'pull_request'
uses: docker/login-action@v2
with:
registry: ${{ vars.DOCKER_REGISTRY_URL }}
username: ${{ vars.DOCKER_REGISTRY_USER }}
password: ${{ secrets.DOCKER_REGISTRY_PASSWORD }}
- name: Build and push docker images
working-directory: .build/prod
run: docker compose --progress plain build --push
- name: Deploy production
if: github.event_name != 'pull_request'
run: |
ssh root@10.0.1.36 -t "cd /mnt && \
docker compose --progress plain pull && \
docker compose --progress plain down && \
docker compose --progress plain up -d"
- name: Clean up dangling images
if: github.event_name != 'pull_request'
run: ssh root@10.0.1.36 -t "docker image prune -f"
+2 -1
View File
@@ -1,4 +1,5 @@
import { useState, FormEvent } from 'react';
import { useState } from 'react';
import type { FormEvent } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import { useAuthStore } from '../../stores/authStore';
import { useUIStore } from '../../stores/uiStore';
+2 -1
View File
@@ -1,4 +1,5 @@
import { useState, FormEvent } from 'react';
import { useState } from 'react';
import type { FormEvent } from 'react';
import { useNavigate, Link } from 'react-router-dom';
import { useAuthStore } from '../../stores/authStore';
import { useUIStore } from '../../stores/uiStore';
+1 -1
View File
@@ -1,4 +1,4 @@
import { ReactNode } from 'react';
import type { ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import { useAuthStore } from '../../stores/authStore';
import { useUIStore } from '../../stores/uiStore';
+1 -7
View File
@@ -1,6 +1,5 @@
import { useEffect, useState } from 'react';
import { useMapEvents, Polyline, Marker } from 'react-leaflet';
import L from 'leaflet';
import { useDrawingStore } from '../../stores/drawingStore';
import { useUIStore } from '../../stores/uiStore';
import { mapItemService } from '../../services/mapItemService';
@@ -12,7 +11,7 @@ interface DrawingHandlerProps {
}
export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
const { activeTool, isDrawing, drawingPoints, setIsDrawing, addDrawingPoint, resetDrawing, setActiveTool } =
const { activeTool, isDrawing, drawingPoints, setIsDrawing, addDrawingPoint, resetDrawing } =
useDrawingStore();
const { showToast } = useUIStore();
const [cursorPosition, setCursorPosition] = useState<[number, number] | null>(null);
@@ -307,11 +306,6 @@ export function DrawingHandler({ mapId, onItemCreated }: DrawingHandlerProps) {
const dashArray = isWirelessTool ? '10, 10' : undefined;
// Create preview line from last point to cursor
const previewPositions = cursorPosition
? [...drawingPoints, cursorPosition]
: drawingPoints;
return (
<>
{/* Main line connecting all points */}
@@ -1,5 +1,3 @@
import { useState } from 'react';
interface LayerInfo {
name: string;
url: string;
+1 -1
View File
@@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import { createPortal } from 'react-dom';
import { Polyline, Marker, Popup, Circle, Tooltip, useMapEvents } from 'react-leaflet';
import { Polyline, Marker, Popup, Circle, useMapEvents } from 'react-leaflet';
import L from 'leaflet';
import { mapItemService } from '../../services/mapItemService';
import { uploadService } from '../../services/uploadService';
+1 -1
View File
@@ -37,7 +37,7 @@ export function MapView({ mapId, activeLayer, mapLayers, showShareDialog = false
};
// WebSocket connection for real-time updates
const { isConnected, permission } = useMapWebSocket({
const { permission } = useMapWebSocket({
mapId: mapId || '',
onItemCreated: (item) => {
console.log('Real-time item created:', item);
+1 -1
View File
@@ -51,7 +51,7 @@ export function ShareDialog({ mapId, onClose }: ShareDialogProps) {
setLoading(true);
try {
await mapShareService.shareWithUser(mapId, {
user_identifier: newUserId.trim(),
user_id: newUserId.trim(),
permission: newUserPermission,
});
setNewUserId('');
+1 -2
View File
@@ -3,7 +3,6 @@ import type { DrawingTool } from '../../types/mapItem';
import { CABLE_COLORS, CABLE_LABELS } from '../../types/mapItem';
interface ToolbarProps {
mapId: string;
readOnly?: boolean;
}
@@ -81,7 +80,7 @@ const INFO_TOOL: ToolButton = {
description: 'Information Marker',
};
export function Toolbar({ mapId, readOnly = false }: ToolbarProps) {
export function Toolbar({ readOnly = false }: ToolbarProps) {
const { activeTool, setActiveTool } = useDrawingStore();
const renderIcon = (tool: ToolButton, isDisabled: boolean) => {
+1 -1
View File
@@ -26,7 +26,7 @@ export function useMapWebSocket({
const [isConnected, setIsConnected] = useState(false);
const [permission, setPermission] = useState<'read' | 'edit' | null>(null);
const wsRef = useRef<WebSocket | null>(null);
const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const reconnectTimeoutRef = useRef<number | null>(null);
const reconnectAttemptsRef = useRef(0);
// Use refs for callbacks to avoid reconnecting when they change
+2 -2
View File
@@ -76,7 +76,7 @@ export function Dashboard() {
{selectedMapId && (
<>
<div className="border-t border-gray-200 dark:border-gray-700">
<Toolbar mapId={selectedMapId} />
<Toolbar />
</div>
{/* Map Style section */}
@@ -84,7 +84,7 @@ export function Dashboard() {
<h3 className="text-sm font-semibold text-gray-700 dark:text-gray-300 px-1 mb-2">Map Style</h3>
<LayerSwitcher
activeLayer={activeLayer}
onLayerChange={setActiveLayer}
onLayerChange={(layer) => setActiveLayer(layer as MapLayer)}
layers={MAP_LAYERS}
/>
</div>
+4 -6
View File
@@ -1,12 +1,11 @@
import { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import { MapContainer, TileLayer, useMap } from 'react-leaflet';
import 'leaflet/dist/leaflet.css';
import { LayerSwitcher } from '../components/map/LayerSwitcher';
import { DrawingHandler } from '../components/map/DrawingHandler';
import { MapItemsLayer } from '../components/map/MapItemsLayer';
import { Toolbar } from '../components/map/Toolbar';
import { MapView } from '../components/map/MapView';
import { useMapWebSocket } from '../hooks/useMapWebSocket';
import { apiClient } from '../services/api';
import { useUIStore } from '../stores/uiStore';
@@ -49,7 +48,6 @@ function MapController() {
export function SharedMap() {
const { token } = useParams<{ token: string }>();
const navigate = useNavigate();
const { darkMode, toggleDarkMode } = useUIStore();
const [activeLayer, setActiveLayer] = useState<MapLayer>('osm');
const [refreshTrigger, setRefreshTrigger] = useState(0);
@@ -201,7 +199,7 @@ export function SharedMap() {
style={{ zIndex: 9999 }}
>
<div className="border-t border-gray-200 dark:border-gray-700">
<Toolbar mapId={mapData.id} readOnly={isReadOnly} />
<Toolbar readOnly={isReadOnly} />
</div>
{/* Map Style section */}
@@ -209,7 +207,7 @@ export function SharedMap() {
<h3 className="text-sm font-semibold text-gray-700 dark:text-gray-300 px-1 mb-2">Map Style</h3>
<LayerSwitcher
activeLayer={activeLayer}
onLayerChange={setActiveLayer}
onLayerChange={(layer) => setActiveLayer(layer as MapLayer)}
layers={MAP_LAYERS}
/>
</div>
@@ -229,7 +227,7 @@ export function SharedMap() {
url={MAP_LAYERS[activeLayer].url}
attribution={MAP_LAYERS[activeLayer].attribution}
maxZoom={MAP_LAYERS[activeLayer].maxZoom}
maxNativeZoom={MAP_LAYERS[activeLayer].maxNativeZoom}
maxNativeZoom={(MAP_LAYERS[activeLayer] as any).maxNativeZoom}
/>
{/* Drawing handler for edit access */}