@nextjs-cms-plugins/cpanel-dashboard 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client/DashboardPage.d.ts.map +1 -1
- package/dist/client/DashboardPage.js +20 -3
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/router.d.ts +4 -0
- package/dist/router.d.ts.map +1 -1
- package/dist/router.js +46 -0
- package/package.json +7 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DashboardPage.d.ts","sourceRoot":"","sources":["../../src/client/DashboardPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"DashboardPage.d.ts","sourceRoot":"","sources":["../../src/client/DashboardPage.tsx"],"names":[],"mappings":"AAuBA,eAAO,MAAM,mBAAmB,+CA0N/B,CAAA;AAkFD,eAAe,mBAAmB,CAAA"}
|
|
@@ -3,15 +3,32 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
3
3
|
import { humanReadableFileSize } from 'nextjs-cms/utils';
|
|
4
4
|
import { trpc as trpcClient } from 'nextjs-cms/api/trpc/client';
|
|
5
5
|
import { useI18n } from 'nextjs-cms/translations/client';
|
|
6
|
+
// import { LucideIcon } from 'lucide-react'
|
|
7
|
+
import { HardDriveIcon, NetworkIcon, MailIcon, DatabaseIcon, ServerIcon, FolderIcon, HexagonIcon, PackageIcon } from 'lucide-react';
|
|
6
8
|
export const CpanelDashboardPage = () => {
|
|
7
9
|
const t = useI18n();
|
|
8
10
|
const trpc = trpcClient;
|
|
9
11
|
const query = trpc?.cpanelDashboard?.getData.useQuery;
|
|
10
12
|
const { data, isLoading, isError, error } = query ? query() : { isLoading: true, isError: true, error: null };
|
|
11
13
|
if (!query) {
|
|
12
|
-
return _jsx("div", { className: '
|
|
14
|
+
return (_jsx("div", { className: 'flex min-h-[200px] items-center justify-center p-6', children: _jsx("div", { className: 'rounded-lg border border-destructive/30 bg-destructive/5 px-6 py-4 text-sm text-destructive', children: t('cpanelPluginMisconfigured') }) }));
|
|
13
15
|
}
|
|
14
|
-
return (_jsxs("div", { className: 'w-full', children: [_jsx("div", { className: 'bg-
|
|
16
|
+
return (_jsxs("div", { className: 'w-full', children: [_jsx("div", { className: 'bg-orange-400 dark:bg-orange-800 p-8 font-extrabold text-foreground', children: _jsx("div", { className: 'relative', children: _jsx("h1", { className: 'text-3xl font-bold tracking-tight text-white', children: t('cPanelDashboard') }) }) }), _jsxs("div", { className: 'flex flex-col gap-6 p-6', children: [isLoading && (_jsx("div", { className: 'grid grid-cols-1 gap-4 md-sidebar:grid-cols-2 2xl-sidebar:grid-cols-4', children: [...Array(4)].map((_, i) => (_jsxs("div", { className: 'animate-pulse rounded-xl border bg-card p-5', children: [_jsxs("div", { className: 'mb-4 flex items-center gap-3', children: [_jsx("div", { className: 'size-10 rounded-lg bg-muted' }), _jsx("div", { className: 'h-4 w-24 rounded bg-muted' })] }), _jsx("div", { className: 'mb-2 h-8 w-20 rounded bg-muted' }), _jsx("div", { className: 'h-2 rounded-full bg-muted' })] }, i))) })), isError && !isLoading && (_jsxs("div", { className: 'flex items-center gap-3 rounded-lg border border-destructive/30 bg-destructive/5 p-4', children: [_jsx("div", { className: 'flex size-10 shrink-0 items-center justify-center rounded-full bg-destructive/10', children: _jsx("svg", { className: 'size-5 text-destructive', fill: 'none', stroke: 'currentColor', viewBox: '0 0 24 24', children: _jsx("path", { strokeLinecap: 'round', strokeLinejoin: 'round', strokeWidth: 2, d: 'M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z' }) }) }), _jsxs("div", { children: [_jsx("p", { className: 'font-medium text-destructive', children: t('unableToLoadCpanelData') }), error instanceof Error && (_jsx("p", { className: 'mt-0.5 text-sm text-destructive/80', children: error.message }))] })] })), data && (_jsxs(_Fragment, { children: [_jsxs("div", { className: 'grid grid-cols-1 gap-4 md-sidebar:grid-cols-2 2xl-sidebar:grid-cols-4', children: [_jsx(StatCard, { icon: _jsx(HardDriveIcon, { color: 'blue' }), title: t('diskSpace'), used: data.diskSpaceUsage, total: data.diskSpaceLimit, formatFn: humanReadableFileSize }), _jsx(StatCard, { icon: _jsx(NetworkIcon, { color: 'green' }), title: t('thisMothBandwidth'), used: data.bandwidthUsage, total: data.bandwidthLimit, formatFn: humanReadableFileSize }), _jsx(StatCard, { icon: _jsx(MailIcon, { color: 'red' }), title: t('emailAccounts'), used: data.emailsUsage, total: data.emailsLimit }), _jsx(StatCard, { icon: _jsx(DatabaseIcon, { color: 'purple' }), title: t('mysqlDatabases'), used: data.dbsCount, total: data.dbsLimit })] }), _jsxs("div", { className: 'grid grid-cols-1 gap-6 lg-sidebar:grid-cols-2', children: [_jsxs("div", { className: 'overflow-hidden rounded-xl border bg-card shadow-sm', children: [_jsxs("div", { className: 'flex items-center gap-3 border-b bg-gradient-to-r from-cyan-500/10 via-transparent to-transparent px-6 py-5', children: [_jsx("div", { className: 'flex size-10 items-center justify-center rounded-xl bg-cyan-500/15 text-cyan-600 dark:bg-cyan-500/20 dark:text-cyan-400', children: _jsx(ServerIcon, {}) }), _jsx("h2", { className: 'text-lg font-semibold text-card-foreground', children: t('accountInformation') })] }), _jsxs("div", { className: 'divide-y p-2', children: [_jsx(InfoRow, { icon: _jsx(HexagonIcon, {}), iconColor: 'text-green-800', label: t('nodeVersion'), value: data?.nodeVersion ?? 'N/A', valueColor: 'text-green-600 dark:text-green-400' }), _jsx(InfoRow, { icon: _jsx(PackageIcon, {}), iconColor: 'text-red-800', label: t('pnpmVersion'), value: data?.pnpmVersion ?? 'N/A', valueColor: 'text-green-600 dark:text-green-400' }), _jsx(InfoRow, { icon: _jsx(PackageIcon, {}), iconColor: 'text-red-800', label: t('npmVersion'), value: data?.npmVersion ?? 'N/A', valueColor: 'text-green-600 dark:text-green-400' }), _jsx(InfoRow, { icon: _jsx(PackageIcon, {}), iconColor: 'text-red-800', label: t('bunVersion'), value: data?.bunVersion ?? 'N/A', valueColor: 'text-green-600 dark:text-green-400' }), _jsx(InfoRow, { icon: _jsx("span", { className: 'font-mono text-xs font-bold text-indigo-600 dark:text-indigo-400', children: "PHP" }), label: t('phpVersion'), value: data?.phpVersion ?? 'N/A', valueColor: 'text-indigo-600 dark:text-indigo-400' }), _jsx(InfoRow, { icon: _jsx(FolderIcon, {}), iconColor: 'text-amber-500', label: t('documentRoot'), value: data?.documentRoot ?? 'N/A', mono: true })] })] }), _jsxs("div", { className: 'overflow-hidden rounded-xl border bg-card shadow-sm', children: [_jsxs("div", { className: 'flex items-center gap-3 border-b bg-gradient-to-r from-purple-500/10 via-transparent to-transparent px-6 py-5', children: [_jsx("div", { className: 'flex size-10 items-center justify-center rounded-xl bg-purple-500/15 text-purple-600 dark:bg-purple-500/20 dark:text-purple-400', children: _jsx(DatabaseIcon, {}) }), _jsx("h2", { className: 'text-lg font-semibold text-card-foreground', children: t('database') })] }), data?.dbInfo ? (_jsxs(_Fragment, { children: [_jsxs("div", { className: 'divide-y border-b p-2', children: [_jsx(InfoRow, { label: t('version'), value: data.dbInfo.version, valueColor: 'text-purple-600 dark:text-purple-400 font-semibold' }), _jsx(InfoRow, { label: t('remote'), value: _jsx("span", { className: `inline-flex items-center rounded-full px-2.5 py-1 text-xs font-semibold ${data.dbInfo.is_remote ? 'bg-blue-100 text-blue-700 dark:bg-blue-900/40 dark:text-blue-400' : 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-400'}`, children: data.dbInfo.is_remote ? t('yes') : t('no') }) })] }), data?.dbsList?.length > 0 && (_jsxs("div", { className: 'p-4', children: [_jsxs("p", { className: 'mb-4 text-xs font-semibold uppercase tracking-wider text-purple-600 dark:text-purple-400', children: [t('databases'), " (", data.dbsList.length, ")"] }), _jsx("div", { className: 'space-y-3', children: data.dbsList.map((db, index) => (_jsxs("div", { className: 'flex items-center justify-between rounded-xl border border-purple-200/50 bg-gradient-to-r from-purple-50 to-transparent p-4 transition-all hover:border-purple-300 hover:shadow-sm dark:border-purple-800/30 dark:from-purple-900/20 dark:hover:border-purple-700', children: [_jsxs("div", { className: 'flex items-center gap-3', children: [_jsx("div", { className: 'flex size-10 items-center justify-center rounded-lg bg-purple-500/15 text-purple-600 dark:bg-purple-500/25 dark:text-purple-400', children: _jsx(DatabaseIcon, {}) }), _jsxs("div", { children: [_jsx("p", { className: 'font-semibold text-card-foreground', children: db.database }), _jsxs("p", { className: 'text-xs text-muted-foreground', children: [db.users?.length ?? 0, " ", t('users')] })] })] }), _jsxs("div", { className: 'text-right', children: [_jsx("p", { className: 'text-sm font-bold text-purple-600 dark:text-purple-400', children: humanReadableFileSize(db.disk_usage) }), _jsx("p", { className: 'text-xs text-muted-foreground', children: t('diskUsage') })] })] }, `${db.name}_${db.database}_${index}`))) })] }))] })) : (_jsx("div", { className: 'flex items-center justify-center py-12 text-sm text-muted-foreground', children: t('mysqlNotInstalled') }))] })] })] }))] })] }));
|
|
15
17
|
};
|
|
16
|
-
const StatCard = ({ title, used, total
|
|
18
|
+
const StatCard = ({ icon, title, used, total, formatFn }) => {
|
|
19
|
+
const t = useI18n();
|
|
20
|
+
const percentage = total > 0 ? Math.min((used / total) * 100, 100) : 0;
|
|
21
|
+
const displayUsed = formatFn ? formatFn(used) : used.toString();
|
|
22
|
+
const displayTotal = formatFn ? formatFn(total) : total.toString();
|
|
23
|
+
// Warning colors for high usage
|
|
24
|
+
const getProgressColor = () => {
|
|
25
|
+
if (percentage >= 90)
|
|
26
|
+
return 'bg-red-500';
|
|
27
|
+
if (percentage >= 75)
|
|
28
|
+
return 'bg-yellow-500';
|
|
29
|
+
return 'bg-green-500';
|
|
30
|
+
};
|
|
31
|
+
return (_jsx("div", { className: `group relative overflow-hidden rounded-xl border border-l-4 bg-card p-6 shadow-sm transition-all hover:shadow-lg`, children: _jsxs("div", { className: 'flex flex-col relative', children: [_jsxs("div", { className: 'mb-4 flex items-center justify-between', children: [_jsx("span", { className: 'text-sm font-medium text-muted-foreground', children: title }), _jsx("div", { className: `flex size-11 items-center justify-center rounded-xl`, children: icon })] }), _jsxs("div", { className: 'flex items-end gap-2 justify-start content-end mb-4 text-start w-full', children: [_jsx("span", { dir: 'ltr', className: 'text-3xl font-bold tracking-tight text-card-foreground', children: displayUsed }), _jsx("span", { children: "/" }), _jsxs("span", { dir: 'ltr', className: 'text-sm text-muted-foreground', children: [" ", displayTotal] })] }), _jsx("div", { className: 'h-2.5 overflow-hidden rounded-full bg-muted/50', children: _jsx("div", { className: `h-full rounded-full transition-all duration-500 ${getProgressColor()}`, style: { width: `${percentage}%` } }) }), _jsxs("div", { className: 'flex flex-row gap-2 pt-3 text-xs font-medium text-muted-foreground', children: [_jsxs("span", { className: percentage >= 75 ? 'text-amber-600 dark:text-amber-400' : percentage >= 90 ? 'text-red-600 dark:text-red-400' : '', children: [percentage.toFixed(1), "%"] }), _jsx("span", { children: t('usedLabel') })] })] }) }));
|
|
32
|
+
};
|
|
33
|
+
const InfoRow = ({ icon, iconColor, label, value, valueColor, mono }) => (_jsxs("div", { className: 'flex items-center justify-between rounded-lg px-4 py-4 transition-colors hover:bg-muted/30', children: [_jsxs("div", { className: 'flex items-center gap-3 text-sm text-muted-foreground', children: [icon && _jsx("span", { className: iconColor || 'text-muted-foreground/70', children: icon }), _jsx("span", { className: 'font-medium', children: label })] }), _jsx("span", { className: `text-sm ${valueColor || 'text-card-foreground'} ${mono ? 'font-mono text-xs' : 'font-medium'}`, children: value })] }));
|
|
17
34
|
export default CpanelDashboardPage;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare function createPlugin(): import("nextjs-cms/plugins").CMSPluginSingleRoute;
|
|
1
|
+
export declare function createPlugin(): import("nextjs-cms/plugins/server").CMSPluginSingleRoute;
|
|
2
2
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,6DAc3B"}
|
package/dist/index.js
CHANGED
package/dist/router.d.ts
CHANGED
|
@@ -34,6 +34,10 @@ export declare const cpanelDashboardRouter: import("@trpc/server").TRPCBuiltRout
|
|
|
34
34
|
dbInfo: any;
|
|
35
35
|
dbsList: any;
|
|
36
36
|
phpVersion: any;
|
|
37
|
+
nodeVersion: string | null;
|
|
38
|
+
pnpmVersion: string | null;
|
|
39
|
+
npmVersion: string | null;
|
|
40
|
+
bunVersion: string | null;
|
|
37
41
|
passengerAppList: never[];
|
|
38
42
|
documentRoot: any;
|
|
39
43
|
};
|
package/dist/router.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AA0CA,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;gBAsBvB,CAAC;iBACA,CAAH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoEP,CAAA"}
|
package/dist/router.js
CHANGED
|
@@ -1,7 +1,44 @@
|
|
|
1
1
|
import { TRPCError } from '@trpc/server';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
2
3
|
import getString from 'nextjs-cms/translations';
|
|
3
4
|
import { CpanelAPI } from 'nextjs-cms/utils';
|
|
4
5
|
import { pluginProcedure, router } from 'nextjs-cms/api/trpc';
|
|
6
|
+
const getNodeVersion = () => {
|
|
7
|
+
try {
|
|
8
|
+
const version = execSync('node -v', { encoding: 'utf-8' }).trim();
|
|
9
|
+
return version; // Returns something like "v20.10.0"
|
|
10
|
+
}
|
|
11
|
+
catch {
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const getPnpmVersion = () => {
|
|
16
|
+
try {
|
|
17
|
+
const version = execSync('pnpm -v', { encoding: 'utf-8' }).trim();
|
|
18
|
+
return version; // Returns something like "10.10.0"
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const getNpmVersion = () => {
|
|
25
|
+
try {
|
|
26
|
+
const version = execSync('npm -v', { encoding: 'utf-8' }).trim();
|
|
27
|
+
return version; // Returns something like "10.10.0"
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
const getBunVersion = () => {
|
|
34
|
+
try {
|
|
35
|
+
const version = execSync('bun -v', { encoding: 'utf-8' }).trim();
|
|
36
|
+
return version; // Returns something like "10.10.0"
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
5
42
|
export const cpanelDashboardRouter = router({
|
|
6
43
|
getData: pluginProcedure('plugin_cpanel_dashboard').query(async ({ ctx }) => {
|
|
7
44
|
if (!process.env.CPANEL_USER || !process.env.CPANEL_PASSWORD || !process.env.CPANEL_DOMAIN) {
|
|
@@ -53,6 +90,11 @@ export const cpanelDashboardRouter = router({
|
|
|
53
90
|
break;
|
|
54
91
|
}
|
|
55
92
|
});
|
|
93
|
+
// Get Node.js version from the server
|
|
94
|
+
const nodeVersion = getNodeVersion();
|
|
95
|
+
const pnpmVersion = getPnpmVersion();
|
|
96
|
+
const npmVersion = getNpmVersion();
|
|
97
|
+
const bunVersion = getBunVersion();
|
|
56
98
|
return {
|
|
57
99
|
dbsLimit,
|
|
58
100
|
dbsCount,
|
|
@@ -65,6 +107,10 @@ export const cpanelDashboardRouter = router({
|
|
|
65
107
|
dbInfo: dbInfo.data,
|
|
66
108
|
dbsList: dbsList.data,
|
|
67
109
|
phpVersion: domainInfoData?.phpversion,
|
|
110
|
+
nodeVersion,
|
|
111
|
+
pnpmVersion,
|
|
112
|
+
npmVersion,
|
|
113
|
+
bunVersion,
|
|
68
114
|
passengerAppList: [],
|
|
69
115
|
documentRoot: domainInfoData?.documentroot,
|
|
70
116
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nextjs-cms-plugins/cpanel-dashboard",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -24,13 +24,14 @@
|
|
|
24
24
|
"zod": "4.1.12"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"react": "
|
|
28
|
-
"react
|
|
29
|
-
"
|
|
27
|
+
"lucide-react": "^0.563.0",
|
|
28
|
+
"react": "19.2.3",
|
|
29
|
+
"react-dom": "19.2.3",
|
|
30
|
+
"nextjs-cms": "0.6.2"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
|
-
"@types/react": "
|
|
33
|
-
"@types/react-dom": "^19.
|
|
33
|
+
"@types/react": "^19.2.7",
|
|
34
|
+
"@types/react-dom": "^19.2.3",
|
|
34
35
|
"typescript": "^5.9.2"
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|