mirror of
https://github.com/Dvorinka/Containr.git
synced 2026-10-28 15:51:26 +00:00
Overhaul: real metrics, Git integration UI, open-source hygiene, root cleanup
Backend: - GET /services/:id/metrics with real Docker container stats - DELETE /git/providers/:id and GET repo branches endpoint Frontend: - Service detail shows real telemetry or honest empty states - Live status distinguishes idle/polling/reconnecting - Git providers section in Settings; repo+branch pickers in Add Service - Real logo, compact Projects header, canvas fitView fix - index.css deduplicated (1725 -> 1384 lines) - Fixed smoke tests, lint errors, ToastProvider/context unification Repo hygiene: - Added LICENSE (MIT), CONTRIBUTING.md, SECURITY.md; rewrote README - Untracked .env.prod and data/letsencrypt secrets; fixed .gitignore - Removed legacy root src/internal/cmd and stale configs/docs/artifacts - Moved guides and design references under docs/ Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
355a97bab4
commit
9f3b196032
499 files changed
+4471
-94235
No files matched your search
@@ -184,7 +184,6 @@ export function CacheMetricCard({
|
||||
}: CacheMetricCardProps) {
|
||||
const cachePercent = Math.round((cacheMB / totalMB) * 100);
|
||||
const nonCachePercent = Math.round((nonCacheMB / totalMB) * 100);
|
||||
const freePercent = 100 - cachePercent - nonCachePercent;
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -316,7 +315,6 @@ export function PerformanceMetricCard({
|
||||
percentage,
|
||||
upSpeed,
|
||||
downSpeed,
|
||||
datasets,
|
||||
onClick,
|
||||
animationDelay = 0,
|
||||
}: PerformanceMetricCardProps) {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Component, ErrorInfo, ReactNode } from 'react';
|
||||
import { Component } from 'react';
|
||||
import type { ErrorInfo, ReactNode } from 'react';
|
||||
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import * as ToastPrimitive from '@radix-ui/react-toast';
|
||||
import { createContext, useContext, useState, ReactNode } from 'react';
|
||||
import { useState } from 'react';
|
||||
import type { ReactNode } from 'react';
|
||||
import { IconX, IconCheck, IconAlertCircle, IconInfoCircle } from '@tabler/icons-react';
|
||||
|
||||
type ToastType = 'success' | 'error' | 'info' | 'warning';
|
||||
import { ToastContext, type ToastType } from '../hooks/use-toast';
|
||||
|
||||
interface Toast {
|
||||
id: string;
|
||||
@@ -11,20 +11,6 @@ interface Toast {
|
||||
description?: string;
|
||||
}
|
||||
|
||||
interface ToastContextValue {
|
||||
showToast: (type: ToastType, title: string, description?: string) => void;
|
||||
}
|
||||
|
||||
const ToastContext = createContext<ToastContextValue | undefined>(undefined);
|
||||
|
||||
export function useToast() {
|
||||
const context = useContext(ToastContext);
|
||||
if (!context) {
|
||||
throw new Error('useToast must be used within ToastProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
interface ToastProviderProps {
|
||||
children: ReactNode;
|
||||
}
|
||||
@@ -32,7 +18,11 @@ interface ToastProviderProps {
|
||||
export function ToastProvider({ children }: ToastProviderProps) {
|
||||
const [toasts, setToasts] = useState<Toast[]>([]);
|
||||
|
||||
const showToast = (type: ToastType, title: string, description?: string) => {
|
||||
const showToast = (first: ToastType | string, second: ToastType | string, description?: string) => {
|
||||
const toastTypes: ToastType[] = ['success', 'error', 'info', 'warning'];
|
||||
const firstIsType = toastTypes.includes(first as ToastType);
|
||||
const type = (firstIsType ? first : second) as ToastType;
|
||||
const title = (firstIsType ? second : first) as string;
|
||||
const id = Math.random().toString(36).substring(7);
|
||||
setToasts((prev) => [...prev, { id, type, title, description }]);
|
||||
|
||||
|
||||
@@ -6,3 +6,5 @@ export * from './DonutChart';
|
||||
export * from './EnhancedMetricCard';
|
||||
export * from './CommandPalette';
|
||||
export * from './StatusBadge';
|
||||
export { useToast } from '../hooks/use-toast';
|
||||
export type { ToastType, ToastContextValue } from '../hooks/use-toast';
|
||||
@@ -3,7 +3,7 @@ import { createContext, useContext } from 'react';
|
||||
export type ToastType = 'success' | 'info' | 'warning' | 'error';
|
||||
|
||||
export interface ToastContextValue {
|
||||
showToast: (message: string, type?: ToastType) => void;
|
||||
showToast: (first: ToastType | string, second: ToastType | string, description?: string) => void;
|
||||
}
|
||||
|
||||
export const ToastContext = createContext<ToastContextValue | null>(null);
|
||||
@@ -11,7 +11,7 @@ export const ToastContext = createContext<ToastContextValue | null>(null);
|
||||
export function useToast() {
|
||||
const context = useContext(ToastContext);
|
||||
if (!context) {
|
||||
throw new Error('useToast must be used within a ToastProvider');
|
||||
throw new Error('useToast must be used within ToastProvider');
|
||||
}
|
||||
return context;
|
||||
}
|
||||
Reference in new issue
Block a user