diff --git a/.gitea/workflows/ci.yaml b/.gitea/workflows/ci.yaml index 69df48e..2b1e91d 100644 --- a/.gitea/workflows/ci.yaml +++ b/.gitea/workflows/ci.yaml @@ -31,11 +31,26 @@ jobs: - name: Publish Package to Gitea Packages run: | tar -czf naxos-ui-dist.tar.gz -C dist . - echo "Uploading naxos-ui-dist.tar.gz to Gitea Packages..." - curl -s --fail-with-body -X PUT \ - -H "Authorization: token ${{ secrets.GITEA_TOKEN }}" \ + echo "Uploading naxos-ui-dist.tar.gz to Gitea Packages registry..." + TOKEN="${{ secrets.PACKAGE_TOKEN }}" + if [ -z "$TOKEN" ]; then + TOKEN="${{ secrets.GITEA_TOKEN }}" + fi + RESPONSE=$(curl -s -w "\nHTTP_STATUS:%{http_code}" -X PUT \ + -H "Authorization: token ${TOKEN}" \ --upload-file naxos-ui-dist.tar.gz \ - "${{ github.server_url }}/api/packages/naxos/generic/naxos-ui/1.0.0/naxos-ui-dist.tar.gz" || echo "Generic package uploaded or exists" + "${{ github.server_url }}/api/packages/naxos/generic/naxos-ui/1.0.0/naxos-ui-dist.tar.gz") + STATUS=$(echo "$RESPONSE" | grep "HTTP_STATUS:" | cut -d: -f2) + BODY=$(echo "$RESPONSE" | grep -v "HTTP_STATUS:") + echo "Package upload HTTP status: $STATUS" + if [ "$STATUS" -eq 201 ] || [ "$STATUS" -eq 200 ] || [ "$STATUS" -eq 204 ]; then + echo "Successfully published naxos-ui-dist.tar.gz to Gitea Packages!" + elif [ "$STATUS" -eq 409 ]; then + echo "Package version 1.0.0 already published in Gitea Packages: $BODY" + else + echo "Failed to publish package to Gitea Packages ($STATUS): $BODY" + exit 1 + fi - name: Upload UI Assets Artifact uses: actions/upload-artifact@v3 diff --git a/README.md b/README.md index 9b69d0d..2319da0 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,13 @@ The **NaxOS Web Dashboard** is a modern, responsive, non-technical web interface ## Dashboard Showcase -| Overview & Telemetry | OpenZFS Storage & Migration | +| Overview & Telemetry | OpenZFS Storage Engine | | :---: | :---: | -| ![Dashboard Overview](public/screenshots/dashboard-overview.jpg) | ![Storage & Migration](public/screenshots/storage-management.jpg) | +| ![Dashboard Overview](public/screenshots/dashboard-overview.png) | ![Storage Management](public/screenshots/storage-management.png) | | **CNCF Perses Analytics** | **App Store & Runtimes** | -| ![Perses Analytics](public/screenshots/perses-analytics.jpg) | ![App Store](public/screenshots/app-store.jpg) | +| ![Perses Analytics](public/screenshots/perses-analytics.png) | ![App Store](public/screenshots/app-store.png) | +| **Setup & Migration Wizard** | **File Shares Management** | +| ![Migration Wizard](public/screenshots/migration-wizard.png) | ![Shares Management](public/screenshots/shares-management.png) | ## Key Features diff --git a/public/screenshots/app-store.jpg b/public/screenshots/app-store.jpg deleted file mode 100644 index 579e5e4..0000000 Binary files a/public/screenshots/app-store.jpg and /dev/null differ diff --git a/public/screenshots/app-store.png b/public/screenshots/app-store.png new file mode 100644 index 0000000..fb1a1c7 Binary files /dev/null and b/public/screenshots/app-store.png differ diff --git a/public/screenshots/dashboard-overview.jpg b/public/screenshots/dashboard-overview.jpg deleted file mode 100644 index 6a78b4e..0000000 Binary files a/public/screenshots/dashboard-overview.jpg and /dev/null differ diff --git a/public/screenshots/dashboard-overview.png b/public/screenshots/dashboard-overview.png new file mode 100644 index 0000000..e75a722 Binary files /dev/null and b/public/screenshots/dashboard-overview.png differ diff --git a/public/screenshots/gitops-sync.png b/public/screenshots/gitops-sync.png new file mode 100644 index 0000000..23ab18f Binary files /dev/null and b/public/screenshots/gitops-sync.png differ diff --git a/public/screenshots/migration-wizard.png b/public/screenshots/migration-wizard.png new file mode 100644 index 0000000..b22a38e Binary files /dev/null and b/public/screenshots/migration-wizard.png differ diff --git a/public/screenshots/perses-analytics.jpg b/public/screenshots/perses-analytics.jpg deleted file mode 100644 index a50311f..0000000 Binary files a/public/screenshots/perses-analytics.jpg and /dev/null differ diff --git a/public/screenshots/perses-analytics.png b/public/screenshots/perses-analytics.png new file mode 100644 index 0000000..39a411c Binary files /dev/null and b/public/screenshots/perses-analytics.png differ diff --git a/public/screenshots/shares-management.png b/public/screenshots/shares-management.png new file mode 100644 index 0000000..ec4cbe6 Binary files /dev/null and b/public/screenshots/shares-management.png differ diff --git a/public/screenshots/storage-management.jpg b/public/screenshots/storage-management.jpg deleted file mode 100644 index c3fdb4e..0000000 Binary files a/public/screenshots/storage-management.jpg and /dev/null differ diff --git a/public/screenshots/storage-management.png b/public/screenshots/storage-management.png new file mode 100644 index 0000000..45dfe5e Binary files /dev/null and b/public/screenshots/storage-management.png differ diff --git a/public/screenshots/system-logs.png b/public/screenshots/system-logs.png new file mode 100644 index 0000000..068064c Binary files /dev/null and b/public/screenshots/system-logs.png differ diff --git a/src/App.tsx b/src/App.tsx index 0cb6faa..1900e89 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -30,9 +30,36 @@ import type { } from './types/index.js'; export const App: React.FC = () => { - const [currentTab, setCurrentTab] = useState('overview'); + const getInitialTab = () => { + if (typeof window !== 'undefined') { + const hash = window.location.hash.replace('#', ''); + if (hash) return hash; + const params = new URLSearchParams(window.location.search); + const tab = params.get('tab'); + if (tab) return tab; + } + return 'overview'; + }; + + const [currentTab, setCurrentTab] = useState(getInitialTab); const [showRebuildModal, setShowRebuildModal] = useState(false); + useEffect(() => { + const onHashChange = () => { + const hash = window.location.hash.replace('#', ''); + if (hash) setCurrentTab(hash); + }; + window.addEventListener('hashchange', onHashChange); + return () => window.removeEventListener('hashchange', onHashChange); + }, []); + + const selectTab = (tab: string) => { + setCurrentTab(tab); + if (typeof window !== 'undefined') { + window.location.hash = tab; + } + }; + // Application state const [status, setStatus] = useState(null); const [pools, setPools] = useState([]); @@ -161,7 +188,7 @@ export const App: React.FC = () => { return (
- +
{ status={status} pools={pools} apps={installedApps} - onNavigate={setCurrentTab} + onNavigate={selectTab} /> )}