mirror of
https://github.com/dathere/ckan-devstaller.git
synced 2025-11-09 13:39:49 +00:00
feat(docs): add interactivity to Builder, sync with command, add sonner toast
This commit is contained in:
parent
25bb877fb6
commit
56ae938e6c
12 changed files with 423 additions and 80 deletions
|
|
@ -1,4 +1,5 @@
|
||||||
@import 'tailwindcss';
|
@import "tailwindcss";
|
||||||
@import 'fumadocs-ui/css/neutral.css';
|
@import "fumadocs-ui/css/neutral.css";
|
||||||
@import 'fumadocs-ui/css/ocean.css';
|
@import "fumadocs-ui/css/ocean.css";
|
||||||
@import 'fumadocs-ui/css/preset.css';
|
@import "fumadocs-ui/css/preset.css";
|
||||||
|
@import "tw-animate-css";
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import "@/app/global.css";
|
||||||
import { RootProvider } from "fumadocs-ui/provider";
|
import { RootProvider } from "fumadocs-ui/provider";
|
||||||
import localFont from "next/font/local";
|
import localFont from "next/font/local";
|
||||||
import Script from "next/script";
|
import Script from "next/script";
|
||||||
|
import { Toaster } from "@/components/ui/sonner";
|
||||||
|
|
||||||
const inter = localFont({ src: "../lib/inter.ttf" });
|
const inter = localFont({ src: "../lib/inter.ttf" });
|
||||||
|
|
||||||
|
|
@ -18,6 +19,7 @@ export default function Layout({ children }: LayoutProps<"/">) {
|
||||||
data-web-vitals="true"
|
data-web-vitals="true"
|
||||||
strategy="afterInteractive"
|
strategy="afterInteractive"
|
||||||
/>
|
/>
|
||||||
|
<Toaster closeButton richColors />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -8,17 +8,20 @@
|
||||||
"@radix-ui/react-collapsible": "^1.1.12",
|
"@radix-ui/react-collapsible": "^1.1.12",
|
||||||
"@radix-ui/react-tabs": "^1.1.13",
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"fumadocs-core": "15.8.1",
|
"fumadocs-core": "15.8.1",
|
||||||
"fumadocs-mdx": "12.0.1",
|
"fumadocs-mdx": "12.0.1",
|
||||||
"fumadocs-ui": "15.8.1",
|
"fumadocs-ui": "15.8.1",
|
||||||
"lucide-react": "^0.544.0",
|
"lucide-react": "^0.545.0",
|
||||||
"next": "15.5.4",
|
"next": "15.5.4",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^3.3.1",
|
"tailwind-merge": "^3.3.1",
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.2.5",
|
"@biomejs/biome": "2.2.6",
|
||||||
"@tailwindcss/postcss": "^4.1.13",
|
"@tailwindcss/postcss": "^4.1.13",
|
||||||
"@types/mdx": "^2.0.13",
|
"@types/mdx": "^2.0.13",
|
||||||
"@types/node": "24.5.2",
|
"@types/node": "24.5.2",
|
||||||
|
|
@ -26,6 +29,7 @@
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "^19.1.9",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"tailwindcss": "^4.1.13",
|
"tailwindcss": "^4.1.13",
|
||||||
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5.9.2",
|
"typescript": "^5.9.2",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -33,23 +37,23 @@
|
||||||
"packages": {
|
"packages": {
|
||||||
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
"@alloc/quick-lru": ["@alloc/quick-lru@5.2.0", "", {}, "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw=="],
|
||||||
|
|
||||||
"@biomejs/biome": ["@biomejs/biome@2.2.5", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.5", "@biomejs/cli-darwin-x64": "2.2.5", "@biomejs/cli-linux-arm64": "2.2.5", "@biomejs/cli-linux-arm64-musl": "2.2.5", "@biomejs/cli-linux-x64": "2.2.5", "@biomejs/cli-linux-x64-musl": "2.2.5", "@biomejs/cli-win32-arm64": "2.2.5", "@biomejs/cli-win32-x64": "2.2.5" }, "bin": { "biome": "bin/biome" } }, "sha512-zcIi+163Rc3HtyHbEO7CjeHq8DjQRs40HsGbW6vx2WI0tg8mYQOPouhvHSyEnCBAorfYNnKdR64/IxO7xQ5faw=="],
|
"@biomejs/biome": ["@biomejs/biome@2.2.6", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.2.6", "@biomejs/cli-darwin-x64": "2.2.6", "@biomejs/cli-linux-arm64": "2.2.6", "@biomejs/cli-linux-arm64-musl": "2.2.6", "@biomejs/cli-linux-x64": "2.2.6", "@biomejs/cli-linux-x64-musl": "2.2.6", "@biomejs/cli-win32-arm64": "2.2.6", "@biomejs/cli-win32-x64": "2.2.6" }, "bin": { "biome": "bin/biome" } }, "sha512-yKTCNGhek0rL5OEW1jbLeZX8LHaM8yk7+3JRGv08my+gkpmtb5dDE+54r2ZjZx0ediFEn1pYBOJSmOdDP9xtFw=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.5", "", { "os": "darwin", "cpu": "arm64" }, "sha512-MYT+nZ38wEIWVcL5xLyOhYQQ7nlWD0b/4mgATW2c8dvq7R4OQjt/XGXFkXrmtWmQofaIM14L7V8qIz/M+bx5QQ=="],
|
"@biomejs/cli-darwin-arm64": ["@biomejs/cli-darwin-arm64@2.2.6", "", { "os": "darwin", "cpu": "arm64" }, "sha512-UZPmn3M45CjTYulgcrFJFZv7YmK3pTxTJDrFYlNElT2FNnkkX4fsxjExTSMeWKQYoZjvekpH5cvrYZZlWu3yfA=="],
|
||||||
|
|
||||||
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.5", "", { "os": "darwin", "cpu": "x64" }, "sha512-FLIEl73fv0R7dI10EnEiZLw+IMz3mWLnF95ASDI0kbx6DDLJjWxE5JxxBfmG+udz1hIDd3fr5wsuP7nwuTRdAg=="],
|
"@biomejs/cli-darwin-x64": ["@biomejs/cli-darwin-x64@2.2.6", "", { "os": "darwin", "cpu": "x64" }, "sha512-HOUIquhHVgh/jvxyClpwlpl/oeMqntlteL89YqjuFDiZ091P0vhHccwz+8muu3nTyHWM5FQslt+4Jdcd67+xWQ=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-5DjiiDfHqGgR2MS9D+AZ8kOfrzTGqLKywn8hoXpXXlJXIECGQ32t+gt/uiS2XyGBM2XQhR6ztUvbjZWeccFMoQ=="],
|
"@biomejs/cli-linux-arm64": ["@biomejs/cli-linux-arm64@2.2.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-BpGtuMJGN+o8pQjvYsUKZ+4JEErxdSmcRD/JG3mXoWc6zrcA7OkuyGFN1mDggO0Q1n7qXxo/PcupHk8gzijt5g=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.5", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Ov2wgAFwqDvQiESnu7b9ufD1faRa+40uwrohgBopeY84El2TnBDoMNXx6iuQdreoFGjwW8vH6k68G21EpNERw=="],
|
"@biomejs/cli-linux-arm64-musl": ["@biomejs/cli-linux-arm64-musl@2.2.6", "", { "os": "linux", "cpu": "arm64" }, "sha512-TjCenQq3N6g1C+5UT3jE1bIiJb5MWQvulpUngTIpFsL4StVAUXucWD0SL9MCW89Tm6awWfeXBbZBAhJwjyFbRQ=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-fq9meKm1AEXeAWan3uCg6XSP5ObA6F/Ovm89TwaMiy1DNIwdgxPkNwxlXJX8iM6oRbFysYeGnT0OG8diCWb9ew=="],
|
"@biomejs/cli-linux-x64": ["@biomejs/cli-linux-x64@2.2.6", "", { "os": "linux", "cpu": "x64" }, "sha512-1HaM/dpI/1Z68zp8ZdT6EiBq+/O/z97a2AiHMl+VAdv5/ELckFt9EvRb8hDHpk8hUMoz03gXkC7VPXOVtU7faA=="],
|
||||||
|
|
||||||
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.5", "", { "os": "linux", "cpu": "x64" }, "sha512-AVqLCDb/6K7aPNIcxHaTQj01sl1m989CJIQFQEaiQkGr2EQwyOpaATJ473h+nXDUuAcREhccfRpe/tu+0wu0eQ=="],
|
"@biomejs/cli-linux-x64-musl": ["@biomejs/cli-linux-x64-musl@2.2.6", "", { "os": "linux", "cpu": "x64" }, "sha512-1ZcBux8zVM3JhWN2ZCPaYf0+ogxXG316uaoXJdgoPZcdK/rmRcRY7PqHdAos2ExzvjIdvhQp72UcveI98hgOog=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-xaOIad4wBambwJa6mdp1FigYSIF9i7PCqRbvBqtIi9y29QtPVQ13sDGtUnsRoe6SjL10auMzQ6YAe+B3RpZXVg=="],
|
"@biomejs/cli-win32-arm64": ["@biomejs/cli-win32-arm64@2.2.6", "", { "os": "win32", "cpu": "arm64" }, "sha512-h3A88G8PGM1ryTeZyLlSdfC/gz3e95EJw9BZmA6Po412DRqwqPBa2Y9U+4ZSGUAXCsnSQE00jLV8Pyrh0d+jQw=="],
|
||||||
|
|
||||||
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.5", "", { "os": "win32", "cpu": "x64" }, "sha512-F/jhuXCssPFAuciMhHKk00xnCAxJRS/pUzVfXYmOMUp//XW7mO6QeCjsjvnm8L4AO/dG2VOB0O+fJPiJ2uXtIw=="],
|
"@biomejs/cli-win32-x64": ["@biomejs/cli-win32-x64@2.2.6", "", { "os": "win32", "cpu": "x64" }, "sha512-yx0CqeOhPjYQ5ZXgPfu8QYkgBhVJyvWe36as7jRuPrKPO5ylVDfwVtPQ+K/mooNTADW0IhxOZm3aPu16dP8yNQ=="],
|
||||||
|
|
||||||
"@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
|
"@emnapi/runtime": ["@emnapi/runtime@1.5.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-97/BJ3iXHww3djw6hYIfErCZFee7qCtrneuLa20UXFCOTCfBM2cvQHjWJ2EG0s0MtdNwInarqCTz35i4wWXHsQ=="],
|
||||||
|
|
||||||
|
|
@ -495,7 +499,7 @@
|
||||||
|
|
||||||
"lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="],
|
"lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="],
|
||||||
|
|
||||||
"lucide-react": ["lucide-react@0.544.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw=="],
|
"lucide-react": ["lucide-react@0.545.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-7r1/yUuflQDSt4f1bpn5ZAocyIxcTyVyBBChSVtBKn5M+392cPmI5YJMWOJKk/HUWGm5wg83chlAZtCcGbEZtw=="],
|
||||||
|
|
||||||
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
|
"magic-string": ["magic-string@0.30.19", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw=="],
|
||||||
|
|
||||||
|
|
@ -689,6 +693,8 @@
|
||||||
|
|
||||||
"shiki": ["shiki@3.13.0", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/engine-javascript": "3.13.0", "@shikijs/engine-oniguruma": "3.13.0", "@shikijs/langs": "3.13.0", "@shikijs/themes": "3.13.0", "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g=="],
|
"shiki": ["shiki@3.13.0", "", { "dependencies": { "@shikijs/core": "3.13.0", "@shikijs/engine-javascript": "3.13.0", "@shikijs/engine-oniguruma": "3.13.0", "@shikijs/langs": "3.13.0", "@shikijs/themes": "3.13.0", "@shikijs/types": "3.13.0", "@shikijs/vscode-textmate": "^10.0.2", "@types/hast": "^3.0.4" } }, "sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g=="],
|
||||||
|
|
||||||
|
"sonner": ["sonner@2.0.7", "", { "peerDependencies": { "react": "^18.0.0 || ^19.0.0 || ^19.0.0-rc", "react-dom": "^18.0.0 || ^19.0.0 || ^19.0.0-rc" } }, "sha512-W6ZN4p58k8aDKA4XPcx2hpIQXBRAgyiWVkYhT7CvK6D3iAu7xjvVyhQHg2/iaKJZ1XVJ4r7XuwGL+WGEK37i9w=="],
|
||||||
|
|
||||||
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
|
"source-map": ["source-map@0.7.6", "", {}, "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ=="],
|
||||||
|
|
||||||
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
"source-map-js": ["source-map-js@1.2.1", "", {}, "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="],
|
||||||
|
|
@ -721,6 +727,8 @@
|
||||||
|
|
||||||
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
|
||||||
|
|
||||||
|
"tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="],
|
||||||
|
|
||||||
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
||||||
|
|
||||||
"undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="],
|
"undici-types": ["undici-types@7.12.0", "", {}, "sha512-goOacqME2GYyOZZfb5Lgtu+1IDmAlAEu5xnD3+xTzS10hT0vzpf0SPjkXwAw9Jm+4n/mQGDP3LO8CPbYROeBfQ=="],
|
||||||
|
|
|
||||||
22
docs/components.json
Normal file
22
docs/components.json
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://ui.shadcn.com/schema.json",
|
||||||
|
"style": "default",
|
||||||
|
"rsc": true,
|
||||||
|
"tsx": true,
|
||||||
|
"tailwind": {
|
||||||
|
"config": "",
|
||||||
|
"css": "app/global.css",
|
||||||
|
"baseColor": "neutral",
|
||||||
|
"cssVariables": true,
|
||||||
|
"prefix": ""
|
||||||
|
},
|
||||||
|
"iconLibrary": "lucide",
|
||||||
|
"aliases": {
|
||||||
|
"components": "@/components",
|
||||||
|
"utils": "@/lib/utils",
|
||||||
|
"ui": "@/components/ui",
|
||||||
|
"lib": "@/lib",
|
||||||
|
"hooks": "@/hooks"
|
||||||
|
},
|
||||||
|
"registries": {}
|
||||||
|
}
|
||||||
107
docs/components/builder-sections/ckan-extensions.tsx
Normal file
107
docs/components/builder-sections/ckan-extensions.tsx
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||||
|
import { SailboatIcon, TerminalSquareIcon } from "lucide-react";
|
||||||
|
import { Config, selectedCardClasses } from "../builder";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
const getExtensionClassName = (config: Config, extensionName: string) => {
|
||||||
|
return config.extensions.includes(extensionName) ? selectedCardClasses : "";
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateExtensions = (
|
||||||
|
config: Config,
|
||||||
|
setConfig: any,
|
||||||
|
extensions: string[] | string,
|
||||||
|
mode?: "add" | "remove",
|
||||||
|
) => {
|
||||||
|
const extensionsArray = Array.isArray(extensions) ? extensions : [extensions];
|
||||||
|
if (mode === "add") {
|
||||||
|
setConfig({
|
||||||
|
...config,
|
||||||
|
extensions: [...new Set([...config.extensions, ...extensionsArray])],
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const extensionName of extensionsArray) {
|
||||||
|
if (config.extensions.includes(extensionName))
|
||||||
|
setConfig({
|
||||||
|
...config,
|
||||||
|
extensions: config.extensions.filter(
|
||||||
|
(extension) => extension !== extensionName,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
else if (!config.extensions.includes(extensionName))
|
||||||
|
setConfig({
|
||||||
|
...config,
|
||||||
|
extensions: [...config.extensions, extensionName],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function CKANExtensionsBuilderSection({
|
||||||
|
config,
|
||||||
|
setConfig,
|
||||||
|
}: {
|
||||||
|
config: Config;
|
||||||
|
setConfig: any;
|
||||||
|
}) {
|
||||||
|
const { Card, Cards } = defaultMdxComponents;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3>CKAN extensions</h3>
|
||||||
|
<Cards>
|
||||||
|
<Card
|
||||||
|
className={getExtensionClassName(config, "ckanext-scheming")}
|
||||||
|
icon={<TerminalSquareIcon />}
|
||||||
|
title="ckanext-scheming"
|
||||||
|
onClick={() => {
|
||||||
|
if (
|
||||||
|
config.extensions.includes("DataPusher+") &&
|
||||||
|
config.extensions.includes("ckanext-scheming")
|
||||||
|
) {
|
||||||
|
toast.error(
|
||||||
|
"You cannot remove the ckanext-scheming extension because the DataPusher+ extension depends on it.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateExtensions(config, setConfig, "ckanext-scheming");
|
||||||
|
}}
|
||||||
|
></Card>
|
||||||
|
<Card
|
||||||
|
className={getExtensionClassName(config, "DataStore")}
|
||||||
|
icon={<TerminalSquareIcon />}
|
||||||
|
title="DataStore"
|
||||||
|
onClick={() => {
|
||||||
|
if (
|
||||||
|
config.extensions.includes("DataPusher+") &&
|
||||||
|
config.extensions.includes("DataStore")
|
||||||
|
) {
|
||||||
|
toast.error(
|
||||||
|
"You cannot remove the DataStore extension because the DataPusher+ extension depends on it.",
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateExtensions(config, setConfig, "DataStore");
|
||||||
|
}}
|
||||||
|
></Card>
|
||||||
|
<Card
|
||||||
|
className={getExtensionClassName(config, "DataPusher+")}
|
||||||
|
icon={<TerminalSquareIcon />}
|
||||||
|
title="DataPusher+"
|
||||||
|
onClick={() => {
|
||||||
|
if (config.extensions.includes("DataPusher+")) {
|
||||||
|
updateExtensions(config, setConfig, "DataPusher+");
|
||||||
|
} else {
|
||||||
|
updateExtensions(
|
||||||
|
config,
|
||||||
|
setConfig,
|
||||||
|
["DataPusher+", "ckanext-scheming", "DataStore"],
|
||||||
|
"add",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
></Card>
|
||||||
|
</Cards>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
39
docs/components/builder-sections/ckan-version.tsx
Normal file
39
docs/components/builder-sections/ckan-version.tsx
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||||
|
import { SailboatIcon } from "lucide-react";
|
||||||
|
import { selectedCardClasses } from "../builder";
|
||||||
|
|
||||||
|
export default function CKANVersionBuilderSection({ config, setConfig }: any) {
|
||||||
|
const { Card, Cards } = defaultMdxComponents;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3>CKAN version</h3>
|
||||||
|
<Cards>
|
||||||
|
<Card
|
||||||
|
icon={<SailboatIcon />}
|
||||||
|
title="2.11.3"
|
||||||
|
className={
|
||||||
|
config.ckanVersion === "2.11.3"
|
||||||
|
? selectedCardClasses
|
||||||
|
: "cursor-pointer"
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
setConfig({ ...config, ckanVersion: "2.11.3" });
|
||||||
|
}}
|
||||||
|
></Card>
|
||||||
|
<Card
|
||||||
|
icon={<SailboatIcon />}
|
||||||
|
title="2.10.8"
|
||||||
|
className={
|
||||||
|
config.ckanVersion === "2.10.8"
|
||||||
|
? selectedCardClasses
|
||||||
|
: "cursor-pointer"
|
||||||
|
}
|
||||||
|
onClick={() => {
|
||||||
|
setConfig({ ...config, ckanVersion: "2.10.8" });
|
||||||
|
}}
|
||||||
|
></Card>
|
||||||
|
</Cards>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
48
docs/components/builder-sections/features.tsx
Normal file
48
docs/components/builder-sections/features.tsx
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||||
|
import { SailboatIcon, TerminalSquareIcon } from "lucide-react";
|
||||||
|
import { Config, selectedCardClasses } from "../builder";
|
||||||
|
|
||||||
|
const getFeatureClassName = (config: Config, featureName: string) => {
|
||||||
|
return config.features.includes(featureName) ? selectedCardClasses : "";
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateFeatures = (
|
||||||
|
config: Config,
|
||||||
|
setConfig: any,
|
||||||
|
featureName: string,
|
||||||
|
) => {
|
||||||
|
if (config.features.includes(featureName))
|
||||||
|
setConfig({
|
||||||
|
...config,
|
||||||
|
features: config.features.filter((feature) => feature !== featureName),
|
||||||
|
});
|
||||||
|
else setConfig({ ...config, features: [...config.features, featureName] });
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function FeaturesBuilderSection({
|
||||||
|
config,
|
||||||
|
setConfig,
|
||||||
|
}: {
|
||||||
|
config: Config;
|
||||||
|
setConfig: any;
|
||||||
|
}) {
|
||||||
|
const { Card, Cards } = defaultMdxComponents;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3>Features</h3>
|
||||||
|
<Cards>
|
||||||
|
<Card
|
||||||
|
className={getFeatureClassName(config, "enable-ssh")}
|
||||||
|
icon={<TerminalSquareIcon />}
|
||||||
|
title="Enable SSH"
|
||||||
|
onClick={() => {
|
||||||
|
updateFeatures(config, setConfig, "enable-ssh");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Installs the openssh-server package.
|
||||||
|
</Card>
|
||||||
|
</Cards>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
63
docs/components/builder-sections/presets.tsx
Normal file
63
docs/components/builder-sections/presets.tsx
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
import { Config, selectedCardClasses } from "../builder";
|
||||||
|
import { BarChartBigIcon, SailboatIcon } from "lucide-react";
|
||||||
|
import defaultMdxComponents from "fumadocs-ui/mdx";
|
||||||
|
|
||||||
|
export default function PresetsBuilderSection({
|
||||||
|
config,
|
||||||
|
setConfig,
|
||||||
|
}: {
|
||||||
|
config: Config;
|
||||||
|
setConfig: any;
|
||||||
|
}) {
|
||||||
|
const { Card, Cards } = defaultMdxComponents;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<h3>Presets</h3>
|
||||||
|
<Cards className="grid-cols-2">
|
||||||
|
<Card
|
||||||
|
className={
|
||||||
|
config.preset === "ckan-only" &&
|
||||||
|
config.extensions.length === 0 &&
|
||||||
|
config.features.length === 0
|
||||||
|
? selectedCardClasses
|
||||||
|
: "cursor-pointer"
|
||||||
|
}
|
||||||
|
icon={<SailboatIcon />}
|
||||||
|
title="CKAN-only"
|
||||||
|
onClick={() => {
|
||||||
|
setConfig({
|
||||||
|
...config,
|
||||||
|
preset: "ckan-only",
|
||||||
|
extensions: [],
|
||||||
|
features: [],
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Installs CKAN with ckan-compose. No CKAN extensions and extra features
|
||||||
|
are installed.
|
||||||
|
</Card>
|
||||||
|
<Card
|
||||||
|
className={
|
||||||
|
config.preset === "dathere-default"
|
||||||
|
? selectedCardClasses
|
||||||
|
: "cursor-pointer"
|
||||||
|
}
|
||||||
|
icon={<BarChartBigIcon />}
|
||||||
|
title="datHere Default"
|
||||||
|
onClick={() => {
|
||||||
|
setConfig({
|
||||||
|
...config,
|
||||||
|
preset: "dathere-default",
|
||||||
|
ckanVersion: "2.11.3",
|
||||||
|
extensions: ["ckanext-scheming", "DataStore", "DataPusher+"],
|
||||||
|
features: ["enable-ssh"],
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
datHere's default preset featuring the DataPusher+ extension.
|
||||||
|
</Card>
|
||||||
|
</Cards>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -8,23 +8,60 @@ import {
|
||||||
SailboatIcon,
|
SailboatIcon,
|
||||||
TerminalSquareIcon,
|
TerminalSquareIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
|
import PresetsBuilderSection from "./builder-sections/presets";
|
||||||
|
import CKANVersionBuilderSection from "./builder-sections/ckan-version";
|
||||||
|
import CKANExtensionsBuilderSection from "./builder-sections/ckan-extensions";
|
||||||
|
import FeaturesBuilderSection from "./builder-sections/features";
|
||||||
|
|
||||||
type Config = {
|
export type Config = {
|
||||||
preset: string | undefined;
|
preset: string | undefined;
|
||||||
ckanVersion: string;
|
ckanVersion: string;
|
||||||
extensions: string[];
|
extensions: string[];
|
||||||
|
features: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const selectedCardClasses =
|
||||||
|
"bg-blue-100 dark:bg-blue-950 border-blue-300 dark:border-blue-900 border-2";
|
||||||
|
|
||||||
export default function Builder() {
|
export default function Builder() {
|
||||||
const { Card, Cards } = defaultMdxComponents;
|
const { Card, Cards } = defaultMdxComponents;
|
||||||
const [command, setCommand] = useState("./ckan-devstaller");
|
const [command, setCommand] = useState("./ckan-devstaller");
|
||||||
const [config, setConfig] = useState<Config>({
|
const [config, setConfig] = useState<Config>({
|
||||||
preset: undefined,
|
preset: "ckan-only",
|
||||||
ckanVersion: "2.11.3",
|
ckanVersion: "2.11.3",
|
||||||
extensions: [],
|
extensions: [],
|
||||||
|
features: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update command string when user changes configuration
|
||||||
|
useEffect(() => {
|
||||||
|
let presetString = "";
|
||||||
|
if (config.extensions.length === 0 && config.features.length === 0)
|
||||||
|
presetString = ` \\\n--preset ckan-only`;
|
||||||
|
else if (
|
||||||
|
config.ckanVersion === "2.11.3" &&
|
||||||
|
config.extensions.includes("DataPusher+") &&
|
||||||
|
config.extensions.includes("ckanext-scheming") &&
|
||||||
|
config.extensions.includes("DataStore") &&
|
||||||
|
config.features.includes("enable-ssh")
|
||||||
|
)
|
||||||
|
presetString = ` \\\n--preset dathere-default`;
|
||||||
|
const ckanVersionString = `--ckan-version ${config.ckanVersion}`;
|
||||||
|
const extensionsString =
|
||||||
|
config.extensions.length > 0
|
||||||
|
? ` \\\n--extensions ${config.extensions.join(" ")}`
|
||||||
|
: undefined;
|
||||||
|
const featuresString =
|
||||||
|
config.features.length > 0
|
||||||
|
? ` \\\n--features ${config.features.join(" ")}`
|
||||||
|
: undefined;
|
||||||
|
setCommand(
|
||||||
|
`./ckan-devstaller${presetString} \\
|
||||||
|
${ckanVersionString}${extensionsString ? extensionsString : ""}${featuresString ? featuresString : ""}`,
|
||||||
|
);
|
||||||
|
}, [config]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="grid grid-cols-3 gap-4">
|
<div className="grid grid-cols-3 gap-4">
|
||||||
<div className="col-span-1 border-r-2 pr-4">
|
<div className="col-span-1 border-r-2 pr-4">
|
||||||
|
|
@ -35,72 +72,38 @@ export default function Builder() {
|
||||||
</CodeBlock>
|
</CodeBlock>
|
||||||
<h2>Selected configuration</h2>
|
<h2>Selected configuration</h2>
|
||||||
<div>
|
<div>
|
||||||
<strong>CKAN version</strong>: 2.11.3
|
<strong>CKAN version</strong>: {config.ckanVersion}
|
||||||
<br />
|
<br />
|
||||||
<br />
|
<br />
|
||||||
<strong>Extensions:</strong>
|
{config.extensions.length > 0 && (
|
||||||
<ul>
|
<>
|
||||||
<li>DataStore</li>
|
<strong>Extensions:</strong>
|
||||||
<li>ckanext-scheming</li>
|
<ul>
|
||||||
<li>DataPusher+</li>
|
{config.extensions.map((extension) => (
|
||||||
</ul>
|
<li key={extension}>{extension}</li>
|
||||||
<strong>Extra features:</strong>
|
))}
|
||||||
<ul>
|
</ul>
|
||||||
<li>Enable SSH</li>
|
</>
|
||||||
</ul>
|
)}
|
||||||
|
{config.features.length > 0 && (
|
||||||
|
<>
|
||||||
|
<strong>Features:</strong>
|
||||||
|
<ul>
|
||||||
|
{config.features.map((feature) => (
|
||||||
|
<li key={feature}>{feature}</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-span-2">
|
<div className="col-span-2">
|
||||||
<h2>Configuration options</h2>
|
<h2>Configuration options</h2>
|
||||||
<h3>Presets</h3>
|
<PresetsBuilderSection config={config} setConfig={setConfig} />
|
||||||
<Cards className="grid-cols-2">
|
<CKANVersionBuilderSection config={config} setConfig={setConfig} />
|
||||||
<Card
|
<CKANExtensionsBuilderSection config={config} setConfig={setConfig} />
|
||||||
className="bg-blue-100 dark:bg-blue-950 border-blue-300 dark:border-blue-900 border-2"
|
<FeaturesBuilderSection config={config} setConfig={setConfig} />
|
||||||
icon={<SailboatIcon />}
|
|
||||||
title="CKAN-only"
|
|
||||||
>
|
|
||||||
Installs CKAN with ckan-compose.
|
|
||||||
</Card>
|
|
||||||
<Card icon={<BlocksIcon />} title="CKAN and the DataStore extension">
|
|
||||||
Installs CKAN and the DataStore extension.
|
|
||||||
</Card>
|
|
||||||
<Card icon={<BarChartBigIcon />} title="datHere Default">
|
|
||||||
Installs CKAN, the DataStore extension, the ckanext-scheming
|
|
||||||
extension, and the DataPusher+ extension.
|
|
||||||
</Card>
|
|
||||||
</Cards>
|
|
||||||
<h3>CKAN version</h3>
|
|
||||||
<Cards>
|
|
||||||
<Card icon={<SailboatIcon />} title="2.11.3"></Card>
|
|
||||||
<Card icon={<SailboatIcon />} title="2.10.8"></Card>
|
|
||||||
<Card
|
|
||||||
icon={<SailboatIcon />}
|
|
||||||
title="Install a different version"
|
|
||||||
></Card>
|
|
||||||
<Card
|
|
||||||
icon={<SailboatIcon />}
|
|
||||||
title="Clone from remote Git repository"
|
|
||||||
></Card>
|
|
||||||
</Cards>
|
|
||||||
<h3>CKAN extensions</h3>
|
|
||||||
<Cards>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="ckanext-scheming"></Card>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="ckanext-gztr"></Card>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="DataStore"></Card>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="DataPusher+"></Card>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="ckanext-spatial"></Card>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="Custom extension"></Card>
|
|
||||||
</Cards>
|
|
||||||
<h3>Extra features</h3>
|
|
||||||
<Cards>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="Enable SSH">
|
|
||||||
Installs openssh-server and net-tools.
|
|
||||||
</Card>
|
|
||||||
<Card icon={<TerminalSquareIcon />} title="Run a Bash script">
|
|
||||||
Run a Bash script before or after any step during the installation.
|
|
||||||
</Card>
|
|
||||||
</Cards>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
40
docs/components/ui/sonner.tsx
Normal file
40
docs/components/ui/sonner.tsx
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import {
|
||||||
|
CircleCheckIcon,
|
||||||
|
InfoIcon,
|
||||||
|
Loader2Icon,
|
||||||
|
OctagonXIcon,
|
||||||
|
TriangleAlertIcon,
|
||||||
|
} from "lucide-react";
|
||||||
|
import { useTheme } from "next-themes";
|
||||||
|
import { Toaster as Sonner, ToasterProps } from "sonner";
|
||||||
|
|
||||||
|
const Toaster = ({ ...props }: ToasterProps) => {
|
||||||
|
const { theme = "system" } = useTheme();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Sonner
|
||||||
|
theme={theme as ToasterProps["theme"]}
|
||||||
|
className="toaster group"
|
||||||
|
icons={{
|
||||||
|
success: <CircleCheckIcon className="size-4" />,
|
||||||
|
info: <InfoIcon className="size-4" />,
|
||||||
|
warning: <TriangleAlertIcon className="size-4" />,
|
||||||
|
error: <OctagonXIcon className="size-4" />,
|
||||||
|
loading: <Loader2Icon className="size-4 animate-spin" />,
|
||||||
|
}}
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
"--normal-bg": "var(--popover)",
|
||||||
|
"--normal-text": "var(--popover-foreground)",
|
||||||
|
"--normal-border": "var(--border)",
|
||||||
|
"--border-radius": "var(--radius)",
|
||||||
|
} as React.CSSProperties
|
||||||
|
}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export { Toaster };
|
||||||
6
docs/lib/utils.ts
Normal file
6
docs/lib/utils.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { clsx, type ClassValue } from "clsx"
|
||||||
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
|
|
@ -15,17 +15,20 @@
|
||||||
"@radix-ui/react-collapsible": "^1.1.12",
|
"@radix-ui/react-collapsible": "^1.1.12",
|
||||||
"@radix-ui/react-tabs": "^1.1.13",
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"fumadocs-core": "15.8.1",
|
"fumadocs-core": "15.8.1",
|
||||||
"fumadocs-mdx": "12.0.1",
|
"fumadocs-mdx": "12.0.1",
|
||||||
"fumadocs-ui": "15.8.1",
|
"fumadocs-ui": "15.8.1",
|
||||||
"lucide-react": "^0.544.0",
|
"lucide-react": "^0.545.0",
|
||||||
"next": "15.5.4",
|
"next": "15.5.4",
|
||||||
|
"next-themes": "^0.4.6",
|
||||||
"react": "^19.1.1",
|
"react": "^19.1.1",
|
||||||
"react-dom": "^19.1.1",
|
"react-dom": "^19.1.1",
|
||||||
|
"sonner": "^2.0.7",
|
||||||
"tailwind-merge": "^3.3.1"
|
"tailwind-merge": "^3.3.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@biomejs/biome": "2.2.5",
|
"@biomejs/biome": "2.2.6",
|
||||||
"@tailwindcss/postcss": "^4.1.13",
|
"@tailwindcss/postcss": "^4.1.13",
|
||||||
"@types/mdx": "^2.0.13",
|
"@types/mdx": "^2.0.13",
|
||||||
"@types/node": "24.5.2",
|
"@types/node": "24.5.2",
|
||||||
|
|
@ -33,6 +36,7 @@
|
||||||
"@types/react-dom": "^19.1.9",
|
"@types/react-dom": "^19.1.9",
|
||||||
"postcss": "^8.5.6",
|
"postcss": "^8.5.6",
|
||||||
"tailwindcss": "^4.1.13",
|
"tailwindcss": "^4.1.13",
|
||||||
|
"tw-animate-css": "^1.4.0",
|
||||||
"typescript": "^5.9.2"
|
"typescript": "^5.9.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue