feat: Add initial local Docker Swarm deployment setup and frontend application structure with project state management.
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled

This commit is contained in:
gitmuhammedalbayrak
2025-11-24 05:15:49 +03:00
parent 84a265ea14
commit 066c16221d
4 changed files with 153 additions and 2 deletions

52
deploy/local/README.md Normal file
View File

@@ -0,0 +1,52 @@
# Local Development with Docker Swarm
This directory contains the configuration to run the Evrak application locally using Docker Swarm on Windows 11.
## Prerequisites
1. **Docker Desktop**: Ensure Docker Desktop is installed and running.
2. **Swarm Mode**: Enable Swarm mode if not already enabled:
```powershell
docker swarm init
```
## How to Deploy
### 1. Build Images
First, build the Docker images locally. `docker stack deploy` does not build images, so this step is required.
```powershell
docker compose -f deploy/local/docker-compose.yml build
```
### 2. Deploy to Swarm
Deploy the stack to your local Swarm cluster.
```powershell
docker stack deploy -c deploy/local/docker-compose.yml evrak
```
### 3. Verify
Check if the services are running:
```powershell
docker service ls
docker stack ps evrak
```
Access the application:
* **Frontend**: http://localhost
* **Backend API**: http://localhost:3000
* **Database**: localhost:5432
### 4. Remove Stack
To stop and remove the application:
```powershell
docker stack rm evrak
```
## Troubleshooting
* **Image not found**: Make sure you ran the build step.
* **Ports occupied**: Ensure ports 80, 3000, and 5432 are free on your host machine.

View File

@@ -0,0 +1,68 @@
version: '3.8'
services:
postgres:
image: postgres:14-alpine
environment:
POSTGRES_USER: evrak_user
POSTGRES_PASSWORD: evrak_password
POSTGRES_DB: evrak
ports:
- "5432:5432"
volumes:
- db_data:/var/lib/postgresql/data
networks:
- evrak-net
deploy:
replicas: 1
restart_policy:
condition: on-failure
backend:
# Note: 'docker stack deploy' ignores 'build'. You must run 'docker compose build' first.
build:
context: ../../backend
dockerfile: Dockerfile
image: evrak-backend:local
environment:
DB_HOST: postgres
DB_PORT: 5432
DB_USERNAME: evrak_user
DB_PASSWORD: evrak_password
DB_DATABASE: evrak
PORT: 3000
ports:
- "3000:3000"
depends_on:
- postgres
networks:
- evrak-net
deploy:
replicas: 1
restart_policy:
condition: on-failure
frontend:
build:
context: ../../frontend
dockerfile: Dockerfile
image: evrak-frontend:local
ports:
- "80:80"
depends_on:
- backend
networks:
- evrak-net
deploy:
replicas: 1
restart_policy:
condition: on-failure
volumes:
db_data:
networks:
evrak-net:
driver: overlay
attachable: true

View File

@@ -2,17 +2,24 @@ import React from 'react';
import { Layout } from 'antd'; import { Layout } from 'antd';
import Sidebar from './components/Sidebar'; import Sidebar from './components/Sidebar';
import MindMap from './components/MindMap'; import MindMap from './components/MindMap';
import { useProjectStore } from './store/useProjectStore';
const { Sider, Content } = Layout; const { Sider, Content } = Layout;
const App: React.FC = () => { const App: React.FC = () => {
const { fetchProjects } = useProjectStore();
React.useEffect(() => {
fetchProjects();
}, [fetchProjects]);
return ( return (
<Layout style={{ height: '100vh' }}> <Layout style={{ height: '100vh' }}>
<Sider width={300} theme="light"> <Sider width={300} theme="light" style={{ borderRight: '1px solid #f0f0f0' }}>
<Sidebar /> <Sidebar />
</Sider> </Sider>
<Layout> <Layout>
<Content> <Content style={{ background: '#fff' }}>
<MindMap /> <MindMap />
</Content> </Content>
</Layout> </Layout>

View File

@@ -16,8 +16,17 @@ interface ProjectState {
setExpandedKeys: (keys: string[]) => void; setExpandedKeys: (keys: string[]) => void;
setSelectedKey: (key: string | null) => void; setSelectedKey: (key: string | null) => void;
expandNode: (key: string) => void; expandNode: (key: string) => void;
fetchProjects: () => Promise<void>;
} }
const DUMMY_PROJECTS: Project[] = [
{ id: '1', name: 'Genel Merkez', path: 'root', parentId: null },
{ id: '2', name: 'Yazılım Departmanı', path: 'root.software', parentId: '1' },
{ id: '3', name: 'İnsan Kaynakları', path: 'root.hr', parentId: '1' },
{ id: '4', name: 'Evrak Projesi', path: 'root.software.evrak', parentId: '2' },
{ id: '5', name: 'Website Yenileme', path: 'root.software.website', parentId: '2' },
];
export const useProjectStore = create<ProjectState>((set) => ({ export const useProjectStore = create<ProjectState>((set) => ({
projects: [], projects: [],
expandedKeys: [], expandedKeys: [],
@@ -31,4 +40,19 @@ export const useProjectStore = create<ProjectState>((set) => ({
? state.expandedKeys ? state.expandedKeys
: [...state.expandedKeys, key], : [...state.expandedKeys, key],
})), })),
fetchProjects: async () => {
try {
const response = await fetch('http://localhost:3000/projects');
if (response.ok) {
const data = await response.json();
set({ projects: data });
} else {
console.error('Failed to fetch projects');
set({ projects: DUMMY_PROJECTS });
}
} catch (error) {
console.error('Error fetching projects:', error);
set({ projects: DUMMY_PROJECTS });
}
},
})); }));