mirror of
https://github.com/fosrl/pangolin.git
synced 2025-12-04 06:58:52 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6b4e52a725 | ||
|
|
e41eafd497 | ||
|
|
d70396a664 | ||
|
|
3d59556bcd | ||
|
|
c7018e92b0 | ||
|
|
a575bace39 | ||
|
|
2047aa30e1 | ||
|
|
3b10453af3 | ||
|
|
3257edc2a0 | ||
|
|
cd54e7dd38 | ||
|
|
9177eaba22 | ||
|
|
33ae2e08cc | ||
|
|
4fc61386d3 | ||
|
|
c409266954 | ||
|
|
57315a36ee | ||
|
|
63637b91a8 | ||
|
|
09238cd98a | ||
|
|
67b149ce4b | ||
|
|
96151de814 | ||
|
|
f2e461a1ee | ||
|
|
8125622c98 | ||
|
|
1a6942ccc9 | ||
|
|
7b0e1df778 | ||
|
|
7d6b114d67 | ||
|
|
a169256770 | ||
|
|
2e54afd72f | ||
|
|
26207bd951 | ||
|
|
3ed681e277 | ||
|
|
c135b5e3cf | ||
|
|
e648307f0b | ||
|
|
0e4f35e87a | ||
|
|
553dffd4ee | ||
|
|
c1fd38ac39 | ||
|
|
9f979c5019 |
11
.github/dependabot.yml
vendored
11
.github/dependabot.yml
vendored
@@ -13,10 +13,6 @@ updates:
|
||||
dependency-type: "development"
|
||||
update-types:
|
||||
- "minor"
|
||||
dev-major-updates:
|
||||
dependency-type: "development"
|
||||
update-types:
|
||||
- "major"
|
||||
prod-patch-updates:
|
||||
dependency-type: "production"
|
||||
update-types:
|
||||
@@ -25,10 +21,6 @@ updates:
|
||||
dependency-type: "production"
|
||||
update-types:
|
||||
- "minor"
|
||||
prod-major-updates:
|
||||
dependency-type: "production"
|
||||
update-types:
|
||||
- "major"
|
||||
|
||||
- package-ecosystem: "docker"
|
||||
directory: "/"
|
||||
@@ -41,6 +33,3 @@ updates:
|
||||
minor-updates:
|
||||
update-types:
|
||||
- "minor"
|
||||
major-updates:
|
||||
update-types:
|
||||
- "major"
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -32,5 +32,4 @@ installer
|
||||
bin
|
||||
.secrets
|
||||
test_event.json
|
||||
.idea/
|
||||
package-lock.json
|
||||
.idea/
|
||||
@@ -1,9 +1,12 @@
|
||||
// eslint.config.js
|
||||
export default [
|
||||
import tseslint from 'typescript-eslint';
|
||||
|
||||
export default tseslint.config(
|
||||
tseslint.configs.recommended,
|
||||
{
|
||||
files: ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"],
|
||||
rules: {
|
||||
semi: "error",
|
||||
"prefer-const": "error"
|
||||
}
|
||||
}
|
||||
];
|
||||
);
|
||||
|
||||
@@ -35,7 +35,7 @@ services:
|
||||
- 80:80 # Port for traefik because of the network_mode
|
||||
{{end}}
|
||||
traefik:
|
||||
image: traefik:v3.4.0
|
||||
image: traefik:v3.4.1
|
||||
container_name: traefik
|
||||
restart: unless-stopped
|
||||
{{if .InstallGerbil}}
|
||||
@@ -58,4 +58,4 @@ services:
|
||||
networks:
|
||||
default:
|
||||
driver: bridge
|
||||
name: pangolin
|
||||
name: pangolin
|
||||
|
||||
30199
package-lock.json
generated
30199
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -104,7 +104,7 @@
|
||||
"winston": "3.17.0",
|
||||
"winston-daily-rotate-file": "5.0.0",
|
||||
"ws": "8.18.2",
|
||||
"zod": "3.25.46",
|
||||
"zod": "3.25.56",
|
||||
"zod-validation-error": "3.4.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -112,8 +112,8 @@
|
||||
"@esbuild-plugins/tsconfig-paths": "0.1.2",
|
||||
"@tailwindcss/postcss": "^4.1.8",
|
||||
"@types/better-sqlite3": "7.6.12",
|
||||
"@types/cookie-parser": "1.4.8",
|
||||
"@types/cors": "2.8.18",
|
||||
"@types/cookie-parser": "1.4.9",
|
||||
"@types/cors": "2.8.19",
|
||||
"@types/crypto-js": "^4.2.2",
|
||||
"@types/express": "5.0.0",
|
||||
"@types/jmespath": "^0.15.2",
|
||||
@@ -122,7 +122,7 @@
|
||||
"@types/node": "^22",
|
||||
"@types/nodemailer": "6.4.17",
|
||||
"@types/react": "19.1.6",
|
||||
"@types/react-dom": "19.1.5",
|
||||
"@types/react-dom": "19.1.6",
|
||||
"@types/semver": "7.7.0",
|
||||
"@types/swagger-ui-express": "^4.1.8",
|
||||
"@types/ws": "8.18.1",
|
||||
@@ -131,11 +131,12 @@
|
||||
"esbuild": "0.25.5",
|
||||
"esbuild-node-externals": "1.18.0",
|
||||
"postcss": "^8",
|
||||
"react-email": "4.0.15",
|
||||
"react-email": "4.0.16",
|
||||
"tailwindcss": "^4.1.4",
|
||||
"tsc-alias": "1.8.16",
|
||||
"tsx": "4.19.4",
|
||||
"typescript": "^5",
|
||||
"typescript-eslint": "^8.34.0",
|
||||
"yargs": "18.0.0"
|
||||
},
|
||||
"overrides": {
|
||||
|
||||
@@ -2,7 +2,7 @@ import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
|
||||
// This is a placeholder value replaced by the build process
|
||||
export const APP_VERSION = "1.5.0";
|
||||
export const APP_VERSION = "1.5.1";
|
||||
|
||||
export const __FILENAME = fileURLToPath(import.meta.url);
|
||||
export const __DIRNAME = path.dirname(__FILENAME);
|
||||
|
||||
@@ -27,6 +27,7 @@ import { formatAxiosError } from "@app/lib/api";
|
||||
import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import CreateSiteFormModal from "./CreateSiteModal";
|
||||
import { parseDataSize } from '@app/lib/dataSize';
|
||||
|
||||
export type SiteRow = {
|
||||
id: number;
|
||||
@@ -197,7 +198,9 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
},
|
||||
sortingFn: (rowA, rowB) =>
|
||||
parseDataSize(rowA.original.mbIn) - parseDataSize(rowB.original.mbIn)
|
||||
},
|
||||
{
|
||||
accessorKey: "mbOut",
|
||||
@@ -213,7 +216,9 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
|
||||
<ArrowUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
},
|
||||
sortingFn: (rowA, rowB) =>
|
||||
parseDataSize(rowA.original.mbOut) - parseDataSize(rowB.original.mbOut),
|
||||
},
|
||||
{
|
||||
accessorKey: "type",
|
||||
|
||||
@@ -32,6 +32,8 @@ import { createApiClient } from "@app/lib/api";
|
||||
import { useEnvContext } from "@app/hooks/useEnvContext";
|
||||
import { useState } from "react";
|
||||
import { SwitchInput } from "@app/components/SwitchInput";
|
||||
import Link from "next/link";
|
||||
import { ArrowRight, ExternalLink } from "lucide-react";
|
||||
|
||||
const GeneralFormSchema = z.object({
|
||||
name: z.string().nonempty("Name is required"),
|
||||
@@ -151,8 +153,18 @@ export default function GeneralPage() {
|
||||
<FormDescription>
|
||||
Enable Docker Socket
|
||||
discovery for populating
|
||||
container information,
|
||||
useful in resource targets.
|
||||
container information.
|
||||
Socket path must be provided
|
||||
to Newt.{" "}
|
||||
<a
|
||||
href="https://docs.fossorial.io/Newt/overview#docker-socket-integration"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-primary hover:underline inline-flex items-center"
|
||||
>
|
||||
Learn more
|
||||
<ExternalLink className="ml-1 h-4 w-4" />
|
||||
</a>
|
||||
</FormDescription>
|
||||
</FormItem>
|
||||
)}
|
||||
|
||||
@@ -82,7 +82,14 @@ export default function StepperForm() {
|
||||
);
|
||||
|
||||
const generateId = (name: string) => {
|
||||
return name.toLowerCase().replace(/\s+/g, "-");
|
||||
// Replace any character that is not a letter, number, space, or hyphen with a hyphen
|
||||
// Also collapse multiple hyphens and trim
|
||||
return name
|
||||
.toLowerCase()
|
||||
.replace(/[^a-z0-9\s-]/g, "-")
|
||||
.replace(/\s+/g, "-")
|
||||
.replace(/-+/g, "-")
|
||||
.replace(/^-+|-+$/g, "");
|
||||
};
|
||||
|
||||
async function orgSubmit(values: z.infer<typeof orgSchema>) {
|
||||
@@ -207,23 +214,22 @@ export default function StepperForm() {
|
||||
type="text"
|
||||
{...field}
|
||||
onChange={(e) => {
|
||||
const orgId =
|
||||
generateId(
|
||||
e.target
|
||||
.value
|
||||
);
|
||||
// Prevent "/" in orgName input
|
||||
const sanitizedValue = e.target.value.replace(/\//g, "-");
|
||||
const orgId = generateId(sanitizedValue);
|
||||
orgForm.setValue(
|
||||
"orgId",
|
||||
orgId
|
||||
);
|
||||
orgForm.setValue(
|
||||
"orgName",
|
||||
e.target.value
|
||||
sanitizedValue
|
||||
);
|
||||
debouncedCheckOrgIdAvailability(
|
||||
orgId
|
||||
);
|
||||
}}
|
||||
value={field.value.replace(/\//g, "-")}
|
||||
/>
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
|
||||
@@ -95,7 +95,7 @@ export const ContainersSelector: FC<ContainerSelectorProps> = ({
|
||||
<CredenzaTitle>Containers in {site.name}</CredenzaTitle>
|
||||
<CredenzaDescription>
|
||||
Select any container to use as a hostname for this
|
||||
target. Click a port to use select a port.
|
||||
target. Click a port to use a port.
|
||||
</CredenzaDescription>
|
||||
</CredenzaHeader>
|
||||
<CredenzaBody>
|
||||
@@ -346,16 +346,19 @@ const DockerContainersTable: FC<{
|
||||
{
|
||||
id: "actions",
|
||||
header: "Actions",
|
||||
cell: ({ row }) => (
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
onClick={() => onContainerSelect(row.original)}
|
||||
disabled={row.original.state !== "running"}
|
||||
>
|
||||
Select
|
||||
</Button>
|
||||
)
|
||||
cell: ({ row }) => {
|
||||
const ports = getExposedPorts(row.original);
|
||||
return (
|
||||
<Button
|
||||
variant="default"
|
||||
size="sm"
|
||||
onClick={() => onContainerSelect(row.original, ports[0])}
|
||||
disabled={row.original.state !== "running"}
|
||||
>
|
||||
Select
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -21,7 +21,8 @@ export function useDockerSocket(site: Site) {
|
||||
|
||||
const api = createApiClient(useEnvContext());
|
||||
|
||||
const { dockerSocketEnabled: isEnabled = true } = site || {};
|
||||
const { dockerSocketEnabled: rawIsEnabled = true, type: siteType } = site || {};
|
||||
const isEnabled = rawIsEnabled && siteType === "newt";
|
||||
const { isAvailable = false, socketPath } = dockerSocket || {};
|
||||
|
||||
const checkDockerSocket = useCallback(async () => {
|
||||
|
||||
21
src/lib/dataSize.ts
Normal file
21
src/lib/dataSize.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
export function parseDataSize(sizeStr: string): number {
|
||||
if (typeof sizeStr !== 'string') return 0;
|
||||
|
||||
const match = /^\s*([\d.]+)\s*([KMGT]?B)\s*$/i.exec(sizeStr);
|
||||
if (!match) return 0;
|
||||
|
||||
const [ , numStr, unitRaw ] = match;
|
||||
const num = parseFloat(numStr);
|
||||
if (isNaN(num)) return 0;
|
||||
|
||||
const unit = unitRaw.toUpperCase();
|
||||
const multipliers = {
|
||||
B: 1,
|
||||
KB: 1024,
|
||||
MB: 1024 ** 2,
|
||||
GB: 1024 ** 3,
|
||||
TB: 1024 ** 4,
|
||||
} as const;
|
||||
|
||||
return num * (multipliers[unit as keyof typeof multipliers] ?? 1);
|
||||
}
|
||||
Reference in New Issue
Block a user