Skip to content

Commit

Permalink
fix: global settings, color changing background, argocd integration
Browse files Browse the repository at this point in the history
  • Loading branch information
jaypyles committed Dec 23, 2024
1 parent 5c11a27 commit 5cacf23
Show file tree
Hide file tree
Showing 42 changed files with 493 additions and 26 deletions.
2 changes: 2 additions & 0 deletions api/backend/integrations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .integration import INTEGRATIONS
from .qbittorrent import get_transfer_info
from .uptime_kuma import get_uptime
from .argocd import get_argocd_data

__all__ = [
"INTEGRATIONS",
Expand All @@ -13,4 +14,5 @@
"get_jellyfin_data",
"get_movies",
"get_shows",
"get_argocd_data",
]
1 change: 1 addition & 0 deletions api/backend/integrations/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ class Apps(Enum):
SONARR = "sonarr"
QBITTORRENT = "qbittorrent"
KUMA = "kuma"
ARGOCD = "argocd"
3 changes: 3 additions & 0 deletions api/backend/integrations/argocd/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .integration import get_argocd_data

__all__ = ["get_argocd_data"]
51 changes: 51 additions & 0 deletions api/backend/integrations/argocd/integration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import requests
from typing import Any

from api.backend.integrations.integration import INTEGRATIONS

argocd_integration = next(
(integration for integration in INTEGRATIONS if integration.name == "argocd"),
None,
)


def get_auth_token() -> str:
assert argocd_integration is not None

payload = {
"username": argocd_integration.config["username"],
"password": argocd_integration.config["password"],
}

response = requests.post(
f"{argocd_integration.config['url']}/api/v1/session", json=payload
)

return response.json()["token"]


def get_applications() -> list[dict[str, Any]]:
assert argocd_integration is not None

response = requests.get(
f"{argocd_integration.config['url']}/api/v1/applications",
headers={"Authorization": f"Bearer {get_auth_token()}"},
)

return response.json()["items"]


def format_application_data(application: dict[str, Any]) -> dict[str, Any]:
metadata = application["metadata"]
status = application["status"]

return {
"name": metadata["name"],
"status": status["sync"]["status"],
}


def get_argocd_data() -> list[dict[str, Any]]:
applications = get_applications()

return [format_application_data(application) for application in applications]
6 changes: 6 additions & 0 deletions api/backend/routers/integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
get_uptime,
get_jellyfin_data,
get_transfer_info,
get_argocd_data,
)

LOG = logging.getLogger(__name__)
Expand Down Expand Up @@ -64,3 +65,8 @@ async def get_radarr_movie_count():
@integration_router.get("/api/integrations/sonarr/shows")
async def get_sonarr_show_count():
return await get_shows()


@integration_router.get("/api/integrations/argocd/applications")
def get_argocd_applications():
return get_argocd_data()
77 changes: 77 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"@types/formidable": "^3.4.5",
"@types/react-color": "^3.0.13",
"axios": "^1.7.8",
"axios-cache-interceptor": "^1.6.2",
"bootstrap": "^5.3.0",
Expand All @@ -23,6 +24,7 @@
"qbittorrent-api-v2": "^1.2.2",
"react": "^18.3.1",
"react-bootstrap": "^2.8.0",
"react-color": "^2.19.3",
"react-dom": "^18.3.1",
"react-markdown": "^9.0.0",
"react-modal-image": "^2.6.0",
Expand Down
Binary file added public/icons/argocd.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/app/store.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { configureStore } from "@reduxjs/toolkit";
import integrationsReducer from "@/lib/slices/integrations";
import settingsReducer from "@/lib/slices/settings";

export const store = configureStore({
reducer: {
integrations: integrationsReducer,
settings: settingsReducer,
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./settings-control";
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { IconButton } from "@mui/material";
import SettingsIcon from "@mui/icons-material/Settings";
import React, { useState } from "react";
import { SettingsMenu } from "../settings-menu";

export type SettingsControlProps = {
className?: string;
};

export const SettingsControl = ({ className }: SettingsControlProps) => {
const [open, setOpen] = useState<boolean>(false);

return (
<div className={className}>
<label htmlFor="settings-menu">
<IconButton component="span" onClick={() => setOpen(true)}>
<SettingsIcon />
</IconButton>
</label>
<SettingsMenu open={open} onClose={() => setOpen(false)} />
</div>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./settings-menu";
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Dialog, DialogTitle, DialogContent } from "@mui/material";
import React, { useState } from "react";
import { ColorResult, SketchPicker } from "react-color";
import { useGetSettings } from "@/lib/hooks/useGetSettings";
import { setSettings } from "@/lib/slices/settings";
import { useDispatch } from "react-redux";
import { Divider } from "@mui/material";

export type SettingsMenuProps = {
open: boolean;
onClose: () => void;
};

export const SettingsMenu = ({ open, onClose }: SettingsMenuProps) => {
const settings = useGetSettings();
const dispatch = useDispatch();
const [color, setColor] = useState({ hex: settings.cardColor });

const handleChange = (color: ColorResult) => {
setColor(color);
dispatch(setSettings({ cardColor: `${color.hex}85` }));
};

return (
<Dialog open={open} onClose={onClose}>
<DialogTitle className="text-2xl font-bold">Settings</DialogTitle>
<DialogContent>
<div className="flex flex-col gap-2">
<span className="text-sm font-medium">Card Colors</span>
<Divider />
<SketchPicker
className="w-[20rem]"
color={color.hex}
onChange={handleChange}
onChangeComplete={handleChange}
/>
</div>
</DialogContent>
</Dialog>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.applications {
display: flex;
flex-direction: column;
gap: 0.5rem;
}

.application {
background-color: var(--integration-bg-color);
padding: 0.125rem;
border-radius: 0.125rem;

width: 100%;
text-align: center;

display: flex;
gap: 0.25rem;

align-items: center;
justify-content: center;
}

.applicationStatus {
font-family: monospace;
padding: 0.125rem;
border-radius: 0.125rem;
}

.synced {
background-color: var(--synced);
}

.outOfSync {
background-color: var(--outOfSync);
}
Loading

0 comments on commit 5cacf23

Please sign in to comment.