Merge pull request 'minio-coconnection' (#3) from minio-coconnection into master

Reviewed-on: #3

fix pipeline
This commit is contained in:
dvirlabs 2025-06-03 21:56:47 +00:00
commit 804a95f1b1
8 changed files with 80 additions and 18 deletions

View File

@ -14,7 +14,7 @@ steps:
- echo "TAGS=latest,$TAG_DATE-$SHORT_SHA" > .tags.env - echo "TAGS=latest,$TAG_DATE-$SHORT_SHA" > .tags.env
- name: build-frontend - name: build-frontend
image: woodpeckerci/plugin-docker image: woodpeckerci/plugin-docker-buildx
settings: settings:
repo: harbor.dvirlabs.com/my-apps/navix-frontend repo: harbor.dvirlabs.com/my-apps/navix-frontend
tag_file: .tags.env tag_file: .tags.env
@ -27,7 +27,7 @@ steps:
from_secret: harbor_password from_secret: harbor_password
- name: build-backend - name: build-backend
image: woodpeckerci/plugin-docker image: woodpeckerci/plugin-docker-buildx
settings: settings:
repo: harbor.dvirlabs.com/my-apps/navix-backend repo: harbor.dvirlabs.com/my-apps/navix-backend
tag_file: .tags.env tag_file: .tags.env

4
backend/.env Normal file
View File

@ -0,0 +1,4 @@
MINIO_ACCESS_KEY=TDJvsBmbkpUXpCw5M7LA
MINIO_SECRET_KEY=n9scR7W0MZy6FF0bznV98fSgXpdebIQjqZvEr1Yu
MINIO_ENDPOINT=s3.dvirlabs.com
MINIO_BUCKET=navix-icons

Binary file not shown.

View File

@ -1,27 +1,25 @@
sections: sections:
- apps: - apps:
- description: Dashboards - description: Dashboards
icon: http://192.168.10.118:1111/icons/grafana.svg icon: grafana.svg
name: Grafana name: Grafana
url: https://grafana.dvirlabs.com url: https://grafana.dvirlabs.com
- description: Monitoring - description: Monitoring
icon: http://192.168.10.118:1111/icons/prometheus.svg icon: prometheus.svg
name: Prometheus name: Prometheus
url: https://prometheus.dvirlabs.com url: https://prometheus.dvirlabs.com
name: Monitoring name: Monitoring
- apps: - apps:
- description: Git server - description: Git server
icon: http://192.168.10.118:1111/icons/gitea.svg icon: gitea.svg
name: Gitea name: Gitea
url: https://git.dvirlabs.com url: https://git.dvirlabs.com
- description: Container registry - description: Container registry
icon: http://192.168.10.118:1111/icons/harbor.svg icon: harbor.svg
name: Harbor name: Harbor
url: https://harbor.dvirlabs.com url: https://harbor.dvirlabs.com
- description: CI/CD - description: CI/CD
icon: http://192.168.10.118:1111/icons/woodpecker-ci.svg icon: woodpecker-ci.svg
name: Woodpecker name: Woodpecker
url: https://woodpecker.dvirlabs.com url: https://woodpecker.dvirlabs.com
name: Dev-tools name: Dev-tools

View File

@ -1,8 +1,13 @@
from fastapi import FastAPI from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import os
from dotenv import load_dotenv
import yaml import yaml
from pathlib import Path from pathlib import Path
from pydantic import BaseModel from pydantic import BaseModel
from minio import Minio
from datetime import timedelta
app = FastAPI() app = FastAPI()
@ -15,6 +20,24 @@ app.add_middleware(
allow_headers=["*"], allow_headers=["*"],
) )
load_dotenv()
# Load ENV variables
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT")
MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY")
MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY")
MINIO_BUCKET = os.getenv("MINIO_BUCKET")
# MinIO connection with access and secret keys
minio_client = Minio(
MINIO_ENDPOINT,
access_key=MINIO_ACCESS_KEY,
secret_key=MINIO_SECRET_KEY,
secure=True
)
BUCKET = "navix-icons"
@app.get("/") @app.get("/")
async def root(): async def root():
return {"message": "Welcome to the FastAPI application!"} return {"message": "Welcome to the FastAPI application!"}
@ -63,6 +86,12 @@ def add_app(entry: AppEntry):
return {"status": "added"} return {"status": "added"}
@app.get("/icon/{filename}")
def get_public_icon_url(filename: str):
url = f"https://{MINIO_ENDPOINT}/{MINIO_BUCKET}/{filename}"
return JSONResponse(content={"url": url})
if __name__ == "__main__": if __name__ == "__main__":
import uvicorn import uvicorn

View File

@ -1,14 +1,37 @@
import { useEffect, useState } from 'react';
import '../style/AppCard.css'; import '../style/AppCard.css';
import { getIconUrl } from '../services/api';
function AppCard({ app }) { function AppCard({ app }) {
const [iconUrl, setIconUrl] = useState(null);
useEffect(() => {
if (app.icon) {
getIconUrl(app.icon)
.then((url) => {
console.log('Presigned icon URL for', app.name, ':', url);
setIconUrl(url);
})
.catch((err) => {
console.error(`Failed to load icon for ${app.name}:`, err);
});
}
}, [app.icon, app.name]);
return ( return (
<div className="app-card-wrapper">
<a href={app.url} className="app-card" target="_blank" rel="noreferrer"> <a href={app.url} className="app-card" target="_blank" rel="noreferrer">
<div className="app-icon-wrapper"> <div className="app-icon-wrapper">
<img src={app.icon} alt={app.name} className="app-icon" /> {iconUrl ? (
<img src={iconUrl} alt={app.name} className="app-icon" />
) : (
<span className="icon-placeholder"></span>
)}
</div> </div>
<h3>{app.name}</h3> <h3>{app.name}</h3>
<p>{app.description}</p> <p>{app.description}</p>
</a> </a>
</div>
); );
} }

View File

@ -13,3 +13,10 @@ export async function addAppToSection({ section, app }) {
if (!res.ok) throw new Error(await res.text()); if (!res.ok) throw new Error(await res.text());
return res.json(); return res.json();
} }
export async function getIconUrl(filename) {
const res = await fetch(`/icon/${filename}`);
if (!res.ok) throw new Error(`Failed to fetch icon for ${filename}`);
const data = await res.json();
return data.url; // ✅ must return the actual URL string
}

View File

@ -8,6 +8,7 @@ export default defineConfig({
proxy: { proxy: {
'/apps': 'http://localhost:8000', '/apps': 'http://localhost:8000',
'/add_app': 'http://localhost:8000', '/add_app': 'http://localhost:8000',
'/icon': 'http://localhost:8000',
} }
} }
}); });