diff --git a/.gitignore b/.gitignore index 54f07af..8a74b8a 100644 --- a/.gitignore +++ b/.gitignore @@ -21,4 +21,6 @@ dist-ssr *.ntvs* *.njsproj *.sln -*.sw? \ No newline at end of file +*.sw? +application/src/lib/pocketbase.ts +Dockerfile diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index d3b1f84..0000000 --- a/Dockerfile +++ /dev/null @@ -1,39 +0,0 @@ -# Stage 1: Build the frontend -FROM node:18-alpine AS frontend-builder -WORKDIR /app -COPY application/package*.json ./ -RUN npm install -COPY application/ ./ -RUN npm run build - -# Stage 2: Download PocketBase binary -FROM alpine:3.17 AS pb-builder -WORKDIR /pb -ARG PB_VERSION=0.27.2 -RUN apk add --no-cache wget unzip \ - && wget https://github.com/pocketbase/pocketbase/releases/download/v${PB_VERSION}/pocketbase_${PB_VERSION}_linux_amd64.zip \ - && unzip pocketbase_${PB_VERSION}_linux_amd64.zip \ - && chmod +x /pb/pocketbase - -# Stage 3: Final runtime image -FROM alpine:3.17 -WORKDIR /app - -# Copy PocketBase binary -COPY --from=pb-builder /pb/pocketbase /app/pocketbase - -# Copy frontend build to PocketBase public directory -COPY --from=frontend-builder /app/dist /app/pb_public - -# Copy backend files -COPY server/pb_migrations /app/pb_migrations -COPY server/pb_data /app/pb_data - -# Mark pb_data as a volume for runtime persistence -VOLUME /app/pb_data - -# Expose default PocketBase port -EXPOSE 8090 - -# Launch PocketBase and bind to 0.0.0.0 for external access -CMD ["/app/pocketbase", "serve", "--http=0.0.0.0:8090", "--dir", "/app/pb_data"] diff --git a/README.md b/README.md index c634d6e..022a873 100644 --- a/README.md +++ b/README.md @@ -24,22 +24,23 @@ CheckCle is an Open Source solution for seamless, real-time monitoring of full-s ## #️⃣ Getting Started -### Installation with Docker Compose +### Installation with Docker Run and Compose 1. Copy ready docker run command ```bash -# Create Docker Volume for data persistence - -docker volume create pb_data - - -# Docker Run Command - -docker run --name checkcle --restart unless-stopped -p 8090:8090 -v pb_data:/app/pb_data --ulimit nofile=4096:8192 operacle/checkcle:latest +docker run -d \ + --name checkcle \ + --restart unless-stopped \ + -p 8090:8090 \ + -v /opt/pb_data:/mnt/pb_data \ + --ulimit nofile=4096:8192 \ + operacle/checkcle:latest ``` 2. Docker Compose - Recommended ```bash +version: '3.9' + services: checkcle: image: operacle/checkcle:latest @@ -48,15 +49,12 @@ services: ports: - "8090:8090" # Web Application volumes: - - pb_data:/app/pb_data # Ensure persistent data across rebuilds + - /opt/pb_data:/mnt/pb_data # Host directory mapped to container path ulimits: nofile: soft: 4096 hard: 8192 -volumes: - pb_data: # Docker-managed volume for data persistence - ``` 3. Admin Web Management @@ -64,12 +62,12 @@ volumes: User: admin@example.com Passwd: Admin123456 -4. Follow the Quick Start Guide at https://docs.checkcle.com (Coming Soon) +4. Follow the Quick Start Guide at https://docs.checkcle.io ### -![Uptime Monitoring](https://pub-4a4062303020445f8f289a2fee84f9e8.r2.dev/images/checkcle-collapse-black.png) ![checkcle-collapse-black](https://pub-4a4062303020445f8f289a2fee84f9e8.r2.dev/images/checkcle-black.png) ![Service Detail Page](https://pub-4a4062303020445f8f289a2fee84f9e8.r2.dev/images/checkcle-detailpage.png) +![Schedule Maintenance](https://pub-4a4062303020445f8f289a2fee84f9e8.r2.dev/images/maintenance-dahboard.png) ## 📝 Development Roadmap @@ -80,15 +78,16 @@ volumes: - [x] Docker containerization - [x] CheckCle Website - [x] CheckCle Demo Server -- [x] SSL & Domain Monitoring - added in release of https://github.com/operacle/checkcle/releases/tag/v1.1.0 +- [x] SSL & Domain Monitoring +- [x] Schedule Maintenance +- [x] Incident Management - [ ] Uptime monitoring (PING - Inprogress) - [ ] Infrastructure Server Monitoring -- [ ] Schedule Maintenance & Incident Management - [ ] Operational Status / Public Status Pages - [ ] Uptime monitoring (TCP, PING, DNS) - [ ] User Permission Roles & Service Group - [ ] Notifications (Email/Slack/Discord/Signal) -- [ ] Open-source release with full documentation +- [x] Open-source release with full documentation ## 🌟 CheckCle for Communities? - **Built with Passion**: Created by an open-source enthusiast for the community @@ -111,6 +110,7 @@ Here are some ways you can help improve CheckCle: ## 🌍 Stay Connected - Website: [checkcle.io](https://checkcle.io) +- Documentation: [docs.checkcle.io](https://docs.checkcle.io) - GitHub Repository: ⭐ [CheckCle](https://github.com/operacle/checkcle.git) - Community Channels: Engage via discussions and issues! - Discord: Join our community [@discord](https://discord.gg/xs9gbubGwX) diff --git a/application/src/components/services/ServiceRow.tsx b/application/src/components/services/ServiceRow.tsx index 1800849..313f79e 100644 --- a/application/src/components/services/ServiceRow.tsx +++ b/application/src/components/services/ServiceRow.tsx @@ -43,22 +43,22 @@ export const ServiceRow = ({ className={`border-b ${theme === 'dark' ? 'border-gray-800 hover:bg-gray-900/60' : 'border-gray-200 hover:bg-gray-50'} cursor-pointer`} onClick={handleRowClick} > - e.stopPropagation()}> + - e.stopPropagation()} className={`text-base py-4 ${theme === 'dark' ? 'text-gray-300' : 'text-gray-700'}`}> + {service.type} - e.stopPropagation()} className="py-4"> + - e.stopPropagation()} className="py-4"> + - e.stopPropagation()}> + - e.stopPropagation()} className="py-4"> + ); -}; +}; \ No newline at end of file diff --git a/application/src/components/services/hooks/useServiceActions.ts b/application/src/components/services/hooks/useServiceActions.ts index b7f3ee8..0dc8a5e 100644 --- a/application/src/components/services/hooks/useServiceActions.ts +++ b/application/src/components/services/hooks/useServiceActions.ts @@ -1,4 +1,3 @@ - import { useState } from "react"; import { useToast } from "@/hooks/use-toast"; import { useNavigate } from "react-router-dom"; @@ -24,6 +23,7 @@ export function useServiceActions(initialServices: Service[]) { }; const handleViewDetail = (service: Service) => { + console.log(`Navigating to service detail for service ID: ${service.id}`); navigate(`/service/${service.id}`); }; @@ -202,4 +202,4 @@ export function useServiceActions(initialServices: Service[]) { confirmDelete, handleMuteAlerts }; -} +} \ No newline at end of file diff --git a/application/src/components/ssl-domain/SSLCertificateStatusCards.tsx b/application/src/components/ssl-domain/SSLCertificateStatusCards.tsx index b703a44..d449cfe 100644 --- a/application/src/components/ssl-domain/SSLCertificateStatusCards.tsx +++ b/application/src/components/ssl-domain/SSLCertificateStatusCards.tsx @@ -1,7 +1,9 @@ + import React from "react"; -import { Card } from "@/components/ui/card"; import { SSLCertificate } from "@/types/ssl.types"; import { useLanguage } from "@/contexts/LanguageContext"; +import { OverviewCard } from "@/components/schedule-incident/common/OverviewCard"; +import { Shield, ShieldAlert, ShieldX } from "lucide-react"; interface SSLCertificateStatusCardsProps { certificates: SSLCertificate[]; @@ -16,48 +18,30 @@ export const SSLCertificateStatusCards = ({ certificates }: SSLCertificateStatus const expiredCount = certificates.filter(cert => cert.status === 'expired').length; return ( -
- -
-
-
- ✓ -
-
-
-
-

{t('validCertificates')}

-

{validCount}

-
-
+
+ } + color="green" + className="hover:scale-105 transition-transform duration-200" + /> - -
-
-
- ! -
-
-
-
-

{t('expiringSoon')}

-

{expiringCount}

-
-
+ } + color="amber" + className="hover:scale-105 transition-transform duration-200" + /> - -
-
-
- ✗ -
-
-
-
-

{t('expired')}

-

{expiredCount}

-
-
+ } + color="red" + className="hover:scale-105 transition-transform duration-200" + />
); }; \ No newline at end of file diff --git a/application/src/contexts/LanguageContext.tsx b/application/src/contexts/LanguageContext.tsx index 2c79f64..b70f3dc 100644 --- a/application/src/contexts/LanguageContext.tsx +++ b/application/src/contexts/LanguageContext.tsx @@ -37,7 +37,7 @@ export const LanguageProvider = ({ children }: { children: ReactNode }) => { } return key; -git fetch origin }; + }; return ( diff --git a/application/src/lib/pocketbase.ts b/application/src/lib/pocketbase.ts index 8baea56..4ad1dfb 100644 --- a/application/src/lib/pocketbase.ts +++ b/application/src/lib/pocketbase.ts @@ -1,16 +1,17 @@ import PocketBase from 'pocketbase'; -// Auto-detect base URL from browser location +// Dynamically detect API base URL from current host (for use in browser) const dynamicBaseUrl = typeof window !== 'undefined' - ? window.location.origin + ? `${window.location.protocol}//${window.location.hostname}:8090` : 'http://localhost:8090'; -// Define API endpoints +// Define available API endpoints export const API_ENDPOINTS = { REMOTE: dynamicBaseUrl }; +// Get the current endpoint from localStorage or use remote as default export const getCurrentEndpoint = (): string => { if (typeof window !== 'undefined') { const savedEndpoint = localStorage.getItem('pocketbase_endpoint'); @@ -19,19 +20,26 @@ export const getCurrentEndpoint = (): string => { return API_ENDPOINTS.REMOTE; }; +// Set the API endpoint and reinitialize PocketBase export const setApiEndpoint = (endpoint: string): void => { if (typeof window !== 'undefined') { localStorage.setItem('pocketbase_endpoint', endpoint); - window.location.reload(); + window.location.reload(); // Reload to reinitialize PocketBase with new endpoint } }; +// Initialize the PocketBase client with the current API URL export const pb = new PocketBase(getCurrentEndpoint()); -export const isAuthenticated = () => pb.authStore.isValid; +// Helper to check if user is authenticated +export const isAuthenticated = () => { + return pb.authStore.isValid; +}; +// Export the auth store for use in components export const authStore = pb.authStore; +// Configure PocketBase to persist authentication between page reloads if (typeof window !== 'undefined') { const storedAuthData = localStorage.getItem('pocketbase_auth'); if (storedAuthData) { @@ -44,15 +52,13 @@ if (typeof window !== 'undefined') { } } + // Subscribe to authStore changes to persist authentication pb.authStore.onChange(() => { if (pb.authStore.isValid) { - localStorage.setItem( - 'pocketbase_auth', - JSON.stringify({ - token: pb.authStore.token, - model: pb.authStore.model - }) - ); + localStorage.setItem('pocketbase_auth', JSON.stringify({ + token: pb.authStore.token, + model: pb.authStore.model + })); } else { localStorage.removeItem('pocketbase_auth'); } diff --git a/docker-compose.yml b/docker-compose.yml index cd6c374..d624b38 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,3 +1,4 @@ +version: '3.9' services: checkcle: image: operacle/checkcle:latest @@ -6,11 +7,8 @@ services: ports: - "8090:8090" # Web Application volumes: - - pb_data:/app/pb_data # Ensure persistent data across rebuilds + - /opt/pb_data:/mnt/pb_data # Host directory mapped to container path ulimits: nofile: soft: 4096 - hard: 8192 - -volumes: - pb_data: # Docker-managed volume for data persistence + hard: 8192 \ No newline at end of file diff --git a/docker/docker-compose-dev.yml b/docker/docker-compose-dev.yml index c66736e..41cab01 100644 --- a/docker/docker-compose-dev.yml +++ b/docker/docker-compose-dev.yml @@ -1,3 +1,5 @@ +version: '3.9' + services: checkcle: build: @@ -6,13 +8,10 @@ services: container_name: checkcle restart: unless-stopped ports: - - "8090:8090" # Allow access to frontend + PocketBase + - "8090:8090" volumes: - - pb_data:/app/pb_data # Ensure persistent data across rebuilds + - /var/pb_data:/mnt/pb_data # Updated mount target to match CMD in Dockerfile ulimits: nofile: soft: 4096 hard: 8192 - -volumes: - pb_data: # Docker-managed volume for persistence diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index cd6c374..93a9f75 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -1,3 +1,5 @@ +version: '3.9' + services: checkcle: image: operacle/checkcle:latest @@ -6,11 +8,8 @@ services: ports: - "8090:8090" # Web Application volumes: - - pb_data:/app/pb_data # Ensure persistent data across rebuilds + - /opt/pb_data:/mnt/pb_data # Host directory mapped to container path ulimits: nofile: soft: 4096 - hard: 8192 - -volumes: - pb_data: # Docker-managed volume for data persistence + hard: 8192 \ No newline at end of file