Merge pull request #66 from Mishalabdullah/feature/beckn_ui

GUI for beckn-onix
This commit is contained in:
Venkatesh Babu
2024-05-06 08:09:51 +05:30
committed by GitHub
43 changed files with 6708 additions and 2 deletions

View File

@@ -10,6 +10,7 @@ Refer to the following documents for more information:
- [Step by step walkthrough of a setup](./docs/setup_walkthrough.md) - [Step by step walkthrough of a setup](./docs/setup_walkthrough.md)
- [Frequently asked questions (FAQ)](./docs/faq.md) - [Frequently asked questions (FAQ)](./docs/faq.md)
- [release notes](./install/RELEASE.md) - [release notes](./install/RELEASE.md)
- [GUI Installation Guide](./onix-gui/GUI/README.md)
Experience the convenience and efficiency of Beckn-ONIX as you embark on your journey with Beckn protocols and open networks. Experience the convenience and efficiency of Beckn-ONIX as you embark on your journey with Beckn protocols and open networks.

View File

@@ -6,7 +6,7 @@ source $SCRIPT_DIR/variables.sh
get_keys() { get_keys() {
docker pull fidedocker/protocol-server > /dev/null 2>&1 docker pull fidedocker/protocol-server > /dev/null 2>&1
docker run --name temp -itd fidedocker/protocol-server > /dev/null 2>&1 docker run --name temp -itd fidedocker/protocol-server > /dev/null 2>&1
output=$(docker exec -it temp node /usr/src/app/scripts/generate-keys 2>&1) output=$(docker exec -i temp node /usr/src/app/scripts/generate-keys 2>&1)
docker stop temp > /dev/null 2>&1 docker stop temp > /dev/null 2>&1
docker rm temp > /dev/null 2>&1 docker rm temp > /dev/null 2>&1
# Check if the script executed successfully # Check if the script executed successfully
@@ -24,4 +24,4 @@ else
fi fi
} }
#get_keys #get_keys

57
onix-gui/GUI/README.md Normal file
View File

@@ -0,0 +1,57 @@
# beckn-onix-gui
The GUI for the beckn-onix cli tool.
## Pre-requisites
1. 4 server/instances
2. 4 sub-domains mapped to each instance
3. Local Tunnel
`npm i -g localtunnel`
## User Guide
### Step 1: Run the `start.sh` script
```
cd .. && ./start.sh
```
### Step 2: Accessing the GUI.
You will be getting a URL and password as on output of the script. Open the url in the browser and then
paste the password.
### Step 3: Install and setup your network
Note: Port 3000 is being used by onix, so we're using port 3005 instead.
### Step 4: Configure a reverse proxy using NGINX
Map port 3005 to a domain or use your machine IP:3005 to access the GUI from your browser.
### Step 5: Secure with certbot
Use certbot to obtain an SSL certificate and secure your GUI.
## Contributing
Contributions are welcome! If you'd like to contribute to the beckn-onix-gui project, please fork the repo and submit a pull request.
## License
The beckn-onix-gui project is licensed under the MIT License. See the LICENSE file for more information.
## Contact
If you have any questions or issues with the beckn-onix-gui project, please don't hesitate to reach out.
### Made with ❤️
built by the [Mulearn Team](https://mulearn.org/)
1. [Mishal Abdullah](https://github.com/Mishalabdullah/)
2. [Aswin Asok](https://github.com/AswinAsok)
3. [Viraj Prabhu ](https://github.com/viraka)
4. [Adasrsh](https://adarshmohanks.framer.website/)

Binary file not shown.

View File

@@ -0,0 +1,66 @@
import { exec } from "child_process";
import { NextResponse } from "next/server";
export async function POST(req) {
const request = await req.json();
const containerName = request.checked ? "bpp-network" : "bap-network";
const fileToCheck = request.fileName;
const executeShellCommand = (command) => {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
console.error("Error:", error);
reject(error);
return;
}
if (stderr) {
console.error("Error:", stderr);
reject(new Error(stderr));
return;
}
const output = stdout;
console.log("Output:", output);
resolve(output);
});
});
};
try {
const containerExists = await executeShellCommand(
`docker ps -a --filter "name=${containerName}" --format "{{.Names}}"`
);
if (!containerExists.trim()) {
return new NextResponse(`Error: ${containerName} server not present`, {
status: 500,
});
}
const result = await executeShellCommand(
`docker exec ${containerName} /bin/sh -c "[ -f '/usr/src/app/schemas/${fileToCheck}' ] && echo 'File found' || echo 'File not found'"`
);
if (result.trim() === "File found") {
return NextResponse.json(
{ message: true },
{
status: 200,
}
);
} else {
return NextResponse.json(
{ message: false },
{
status: 200,
}
);
}
} catch (error) {
console.error(`exec error: ${error}`);
return NextResponse.json(
{ message: `Error executing shell command: ${error}` },
{
status: 500,
}
);
}
}

View File

@@ -0,0 +1,36 @@
import { spawn } from "child_process";
import { NextResponse } from "next/server";
import os from "os";
import path from "path";
// This function is used to clone the github repository of beckn-onix
export async function GET(req) {
console.log("Cloning GitHub repository...");
const repoUrl = "https://github.com/beckn/beckn-onix";
const destination = path.join(os.homedir(), "beckn-onix");
const gitProcess = spawn("git", ["clone", repoUrl, destination]);
gitProcess.stdout.on("data", (data) => {
console.log(`stdout: ${data}`);
});
gitProcess.stderr.on("data", (data) => {
console.error(`stderr: ${data}`);
});
return new Promise((resolve, reject) => {
gitProcess.on("close", (code) => {const destination = "~/beckn-onix";
if (code === 0) {
console.log("Repository cloned successfully");
resolve(
NextResponse.json(
{ success: true, data: "Repo Cloned Successfully" },
{ status: 200 }
)
);
} else {
console.error(`git process exited with code ${code}`);
resolve(NextResponse.json({ success: false }, { status: 500 }));
}
});
});
}

View File

@@ -0,0 +1,118 @@
import { exec } from "child_process";
import { NextResponse } from "next/server";
import { promises as fs } from "fs";
import { join } from "path";
import os from "os";
const pathDir = join(os.homedir(), "beckn-onix");
const executeCommand = (command) => {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
console.error("Error:", error);
reject(error);
return;
}
const output = stdout + stderr;
console.log("Output:", output);
resolve(output);
});
});
};
async function directoryExists(path) {
try {
await fs.access(path);
return true;
} catch (error) {
return false;
}
}
export async function startSupportServices() {
try {
process.env.COMPOSE_IGNORE_ORPHANS = "1";
const result1 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-app.yml up -d mongo_db`
);
console.log("Result 1:", result1);
const result2 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-app.yml up -d queue_service`
);
console.log("Result 2:", result2);
const result3 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-app.yml up -d redis_db`
);
console.log("Result 3:", result3);
await executeCommand("docker volume create registry_data_volume");
await executeCommand("docker volume create registry_database_volume");
await executeCommand("docker volume create gateway_data_volume");
await executeCommand("docker volume create gateway_database_volume");
return NextResponse.json({ result1, result2, result3 });
} catch (error) {
console.error("An error occurred:", error);
return NextResponse.json({ error: "An error occurred" }, { status: 500 });
}
}
export async function POST(req) {
const becknOnixDirExists = await directoryExists(pathDir);
if (!becknOnixDirExists) {
console.log(`Directory "${pathDir}" does not exist. Cloning repository...`);
try {
const response = await fetch(`${req.nextUrl.origin}/api/clonning-repo`);
if (!response.ok) {
console.error(
`Failed to clone repository: ${response.status} ${response.statusText}`
);
return NextResponse.json(
{
error: `Failed to clone repository: ${response.status} ${response.statusText}`,
},
{ status: 500 }
);
}
console.log("Repository cloned successfully.");
} catch (error) {
console.error("An error occurred while cloning the repository:", error);
return NextResponse.json(
{ error: "An error occurred while cloning the repository" },
{ status: 500 }
);
}
}
try {
await startSupportServices();
const data = await req.json();
const registryUrl = data.registryUrl;
const bapSubscriberId = data.subscriberId;
const bapSubscriberUrl = data.subscriberUrl;
const networkconfigurl = data.networkconfigurl;
// generating unqiuekey for bap subscriberId
const uniqueKeyId = bapSubscriberId + "-key";
let updateBapConfigCommand = `bash ${pathDir}/install/scripts/update_bap_config.sh ${registryUrl} ${bapSubscriberId} ${uniqueKeyId} ${bapSubscriberUrl} ${networkconfigurl}`;
const result1 = await executeCommand(updateBapConfigCommand);
console.log("Result 1:", result1);
const result3 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-v2.yml up -d "bap-client"`
);
console.log("Result 3:", result3);
const result4 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-v2.yml up -d "bap-network"`
);
console.log("Result 4:", result4);
return NextResponse.json({ result1, result3, result4 });
} catch (error) {
console.error("An error occurred:", error);
return NextResponse.json({ error: "An error occurred" }, { status: 500 });
}
}

View File

@@ -0,0 +1,124 @@
import { exec } from "child_process";
import { NextResponse } from "next/server";
import { promises as fs } from "fs";
import { join } from "path";
import os from "os";
const pathDir = join(os.homedir(), "beckn-onix");
async function directoryExists(path) {
try {
await fs.access(path);
return true;
} catch (error) {
return false;
}
}
const executeCommand = (command) => {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
console.error("Error:", error);
reject(error);
return;
}
const output = stdout + stderr;
console.log("Output:", output);
resolve(output);
});
});
};
export async function startSupportServices() {
try {
process.env.COMPOSE_IGNORE_ORPHANS = "1";
const result1 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-app.yml up -d mongo_db`
);
console.log("Result 1:", result1);
const result2 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-app.yml up -d queue_service`
);
console.log("Result 2:", result2);
const result3 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-app.yml up -d redis_db`
);
console.log("Result 3:", result3);
await executeCommand("docker volume create registry_data_volume");
await executeCommand("docker volume create registry_database_volume");
await executeCommand("docker volume create gateway_data_volume");
await executeCommand("docker volume create gateway_database_volume");
return NextResponse.json({ result1, result2, result3 });
} catch (error) {
console.error("An error occurred:", error);
return NextResponse.json({ error: "An error occurred" }, { status: 500 });
}
}
export async function POST(req, res) {
const becknOnixDirExists = await directoryExists(pathDir);
console.log("Installing Beckn Onix...", becknOnixDirExists);
if (!becknOnixDirExists) {
console.log(`Directory beckn-onix does not exist. Cloning repository...`);
try {
const response = await fetch(`${req.nextUrl.origin}/api/clonning-repo`);
if (!response.ok) {
console.error(
`Failed to clone repository: ${response.status} ${response.statusText}`
);
return NextResponse.json(
{
error: `Failed to clone repository: ${response.status} ${response.statusText}`,
},
{ status: 500 }
);
}
console.log("Repository cloned successfully.");
} catch (error) {
console.error("An error occurred while cloning the repository:", error);
return NextResponse.json(
{ error: "An error occurred while cloning the repository" },
{ status: 500 }
);
}
}
try {
await startSupportServices();
const data = await req.json();
const registryUrl = data.registryUrl;
const bppSubscriberId = data.subscriberId;
const bppSubscriberUrl = data.subscriberUrl;
const webhookUrl = data.webhookUrl;
// generating unqiuekey for bpp subscriberId
const uniqueKeyId = bppSubscriberId + "-key";
let updateBppConfigCommand = `bash ${pathDir}/install/scripts/update_bpp_config.sh ${registryUrl} ${bppSubscriberId} ${uniqueKeyId} ${bppSubscriberUrl} ${webhookUrl}`;
const result1 = await executeCommand(updateBppConfigCommand);
console.log("Result 1:", result1);
const result2 = await executeCommand("sleep 10");
console.log("Result 2:", result2);
const result3 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-v2.yml up -d bpp-client`
);
console.log("Result 3:", result3);
const result4 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-v2.yml up -d bpp-network`
);
console.log("Result 4:", result4);
const result5 = await executeCommand("sleep 10");
console.log("Result 5:", result5);
return NextResponse.json({ result1, result2, result3, result4, result5 });
} catch (error) {
console.error("An error occurred:", error);
return NextResponse.json({ error: "An error occurred" }, { status: 500 });
}
}

View File

@@ -0,0 +1,92 @@
import { exec } from "child_process";
import { NextResponse } from "next/server";
import { promises as fs } from "fs";
import { join } from "path";
import os from "os";
async function directoryExists(path) {
try {
await fs.access(path);
return true;
} catch (error) {
return false;
}
}
export async function POST(req, res) {
const pathDir = join(os.homedir(), "beckn-onix");
const becknOnixDirExists = await directoryExists(pathDir);
console.log("Installing Beckn Onix...", becknOnixDirExists);
if (!becknOnixDirExists) {
console.log(`Directory beckn-onix does not exist. Cloning repository...`);
try {
const response = await fetch(`${req.nextUrl.origin}/api/clonning-repo`);
if (!response.ok) {
console.error(
`Failed to clone repository: ${response.status} ${response.statusText}`
);
return NextResponse.json(
{
error: `Failed to clone repository: ${response.status} ${response.statusText}`,
},
{ status: 500 }
);
}
console.log("Repository cloned successfully.");
} catch (error) {
console.error("An error occurred while cloning the repository:", error);
return NextResponse.json(
{ error: "An error occurred while cloning the repository" },
{ status: 500 }
);
}
}
const data = await req.json();
const executeCommand = (command) => {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
console.error("Error:", error);
reject(error);
return;
}
const output = stdout + stderr;
console.log("Output:", output);
resolve(output);
});
});
};
try {
const result1 = await executeCommand(
`bash ${pathDir}/install/scripts/package_manager.sh`
);
console.log("Result 1:", result1);
await executeCommand("docker volume create registry_data_volume");
await executeCommand("docker volume create registry_database_volume");
const result2 = await executeCommand(
` bash ${pathDir}/install/scripts/update_gateway_details.sh ${data.registryUrl} ${data.gatewayUrl}`
);
console.log("Result 2:", result2);
const result3 = await executeCommand(
`docker-compose -f ${pathDir}/install/docker-compose-v2.yml up -d gateway`
);
console.log("Result 3:", result3);
const result4 = await executeCommand(`sleep 2`);
console.log("Result 4:", result4);
const result5 = await executeCommand(
`bash ${pathDir}/install/scripts/register_gateway.sh ${data.gatewayUrl}`
);
console.log("Result 5:", result5);
return NextResponse.json({ result1, result2, result3, result4, result5 });
} catch (error) {
console.error("An error occurred:", error);
return NextResponse.json({ error: "An error occurred" }, { status: 500 });
}
}

View File

@@ -0,0 +1,50 @@
import { exec } from "child_process";
import { NextResponse } from "next/server";
export async function POST(req) {
const request = await req.json();
const fileURL = request.yamlUrl;
const containerName = request.container;
const executeShellCommand = (command) => {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
console.error("Error:", error);
reject(error);
return;
}
if (stderr) {
console.error("Error:", stderr);
reject(new Error(stderr));
return;
}
const output = stdout;
console.log("Output:", output);
resolve(output);
});
});
};
try {
await executeShellCommand(
`docker exec ${
containerName + "-client"
} wget -P /usr/src/app/schemas/ ${fileURL}`
);
} catch (error) {
console.error(`exec error: ${error}`);
}
try {
await executeShellCommand(
`docker exec ${
containerName + "-network"
} wget -P /usr/src/app/schemas/ ${fileURL}`
);
return NextResponse.json({ status: 200 });
} catch (error) {
console.error(`exec error: ${error}`);
return NextResponse.json({ status: 500 });
}
}

View File

@@ -0,0 +1,156 @@
import { exec } from "child_process";
import { NextResponse } from "next/server";
import { promises as fs } from "fs";
import { tmpdir } from "os";
import { join } from "path";
import os from "os";
async function directoryExists(path) {
try {
await fs.access(path);
return true;
} catch (error) {
return false;
}
}
export async function POST(req, res) {
const pathDir = join(os.homedir(), "beckn-onix");
const becknOnixDirExists = await directoryExists(pathDir);
console.log("Installing Beckn Onix...", becknOnixDirExists);
if (!becknOnixDirExists) {
console.log(`Directory beckn-onix does not exist. Cloning repository...`);
try {
const response = await fetch(`${req.nextUrl.origin}/api/clonning-repo`);
if (!response.ok) {
console.error(
`Failed to clone repository: ${response.status} ${response.statusText}`
);
return NextResponse.json(
{
error: `Failed to clone repository: ${response.status} ${response.statusText}`,
},
{ status: 500 }
);
}
console.log("Repository cloned successfully.");
} catch (error) {
console.error("An error occurred while cloning the repository:", error);
return NextResponse.json(
{ error: "An error occurred while cloning the repository" },
{ status: 500 }
);
}
}
const data = await req.json();
const executeCommand = (command) => {
return new Promise((resolve, reject) => {
exec(command, (error, stdout, stderr) => {
if (error) {
console.error("Error:", error);
reject(error);
return;
}
const output = stdout + stderr;
console.log("Output:", output);
resolve(output);
});
});
};
const updateRegistryDetails = async (url) => {
let registryUrl = "";
let registryPort = "";
let protocol = "";
if (url) {
if (url.startsWith("https://")) {
registryUrl = url.replace("https://", "");
registryPort = "443";
protocol = "https";
} else if (url.startsWith("http://")) {
registryUrl = url.replace("http://", "");
registryPort = "80";
protocol = "http";
}
} else {
registryUrl = "registry";
registryPort = "3030";
protocol = "http";
}
console.log("Registry URL:", registryUrl);
const configFile = join(
pathDir,
"install",
"registry_data",
"config",
"swf.properties"
);
const sampleFile = join(
pathDir,
"install",
"registry_data",
"config",
"swf.properties-sample"
);
try {
await fs.copyFile(sampleFile, configFile);
const tempDir = join(os.homedir(), "beckn-onix", "tmp");
await fs.mkdir(tempDir, { recursive: true }); // Create the temporary directory if it doesn't exist
const tempFile = join(tempDir, "tempfile.XXXXXXXXXX");
const configData = await fs.readFile(configFile, "utf8");
const updatedConfigData = configData
.replace(/REGISTRY_URL/g, registryUrl)
.replace(/REGISTRY_PORT/g, registryPort)
.replace(/PROTOCOL/g, protocol);
await fs.writeFile(tempFile, updatedConfigData);
await fs.rename(tempFile, configFile);
await executeCommand("docker volume create registry_data_volume");
await executeCommand("docker volume create registry_database_volume");
await executeCommand("docker volume create gateway_data_volume");
await executeCommand("docker volume create gateway_database_volume");
await executeCommand(
`docker run --rm -v ${join(
pathDir,
"install",
"registry_data",
"config"
)}:/source -v registry_data_volume:/target busybox sh -c "cp /source/envvars /target/ && cp /source/logger.properties /target/ && cp /source/swf.properties /target/"`
);
// Start the registry container
await executeCommand(
`docker-compose -f ${join(
pathDir,
"install",
"docker-compose-v2.yml"
)} up -d registry`
);
// Wait for 10 seconds
await new Promise((resolve) => setTimeout(resolve, 10000));
console.log("Registry installation successful");
} catch (error) {
console.error("Error updating registry details:", error);
throw error;
}
};
try {
const url = data.registryUrl;
await updateRegistryDetails(url);
return NextResponse.json({
message: "Registry details updated successfully",
});
} catch (error) {
console.error("An error occurred:", error);
return NextResponse.json({ error: "An error occurred" }, { status: 500 });
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View File

@@ -0,0 +1,19 @@
* {
padding: 0;
margin: 0;
}
body{
min-width: 100vw;
min-height: 100vh;
background-color: #000000;
color: white;
font-family: "Ubuntu Mono", monospace;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}

View File

@@ -0,0 +1,58 @@
"use client";
import Link from "next/link";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Image from "next/image";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>Configure Existing Network</p>
<div className={styles.boxesContainer}>
<Link
href="/setup/gateway"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Gateway</p>
</div>
</Link>
<Link
href="/setup/bap"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BAP Adapter</p>
</div>
</Link>
<Link
href="/setup/bpp"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BPP Adapter</p>
</div>
</Link>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,67 @@
"use client";
import Link from "next/link";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Image from "next/image";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>Create a Production Network</p>
<div className={styles.boxesContainer}>
<Link
href="/setup/gateway"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Gateway</p>
</div>
</Link>
<Link href="/setup/bap">
<div
className={styles.box}
style={{ textDecoration: "underline", color: "white" }}
>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BAP Adapter</p>
</div>
</Link>
<Link href="/setup/bpp">
<div
className={styles.box}
style={{ textDecoration: "underline", color: "white" }}
>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BPP Adapter</p>
</div>
</Link>
<Link
href="/setup/registry"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Registry</p>
</div>
</Link>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,68 @@
"use client";
import Link from "next/link";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Image from "next/image";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>Join an existing network</p>
<div className={styles.boxesContainer}>
<Link
href="/setup/gateway"
style={{
textDecoration: "underline",
color: "white",
}}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Gateway</p>
</div>
</Link>
<Link
href="/setup/bap"
style={{
textDecoration: "underline",
color: "white",
}}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BAP Adapter</p>
</div>
</Link>
<Link
href="/setup/bpp"
style={{
textDecoration: "underline",
color: "white",
}}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BPP Adapter</p>
</div>
</Link>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,60 @@
"use client";
import Link from "next/link";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Image from "next/image";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>
Set up a network on your local machine
</p>
<div className={styles.boxesContainer}>
<Link
href="/setup/gateway"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Gateway</p>
</div>
</Link>
<Link
href="/setup/bap"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BAP Adapter</p>
</div>
</Link>
<Link
href="/setup/bpp"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BPP Adapter</p>
</div>
</Link>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,58 @@
"use client";
import Link from "next/link";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Image from "next/image";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>Merge multiple networks</p>
<div className={styles.boxesContainer}>
<Link
href="/setup/gateway"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Gateway</p>
</div>
</Link>
<Link
href="/setup/bap"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BAP</p>
</div>
</Link>
<Link
href="/setup/bpp"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>BPP</p>
</div>
</Link>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,54 @@
"use client";
import Link from "next/link";
import styles from "../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Image from "next/image";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainHeading}>ONIX</p>
<p className={styles.mainText}>
Open Network In A Box, is a project designed to effortlessly set up
and maintain Beckn network that is scalable, secure and easy to
maintain.
</p>
<div className={styles.boxesContainer}>
<Link
href="/install/join"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Join an existing network</p>
</div>
</Link>
<Link
href="/install/create"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Create new production network</p>
</div>
</Link>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,22 @@
import { Inter } from "next/font/google";
import "./globals.css";
import { ToastContainer, toast } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { Bounce } from "react-toastify";
const inter = Inter({ subsets: ["latin"] });
export const metadata = {
title: "ONIX GUI",
description: "Generated by create next app",
};
export default function RootLayout({ children }) {
return (
<html lang="en">
<body className={inter.className}>
{children}
<ToastContainer />
</body>
</html>
);
}

55
onix-gui/GUI/app/page.js Normal file
View File

@@ -0,0 +1,55 @@
import Link from "next/link";
import styles from "./page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Image from "next/image";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<p className={styles.mainHeading}>ONIX</p>
<p className={styles.mainText}>
Open Network In A Box, is a project designed to effortlessly set up
and maintain Beckn network that is scalable, secure and easy to
maintain.
</p>
<div className={styles.boxesContainer}>
<Link
href="/install"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Installation Wizard</p>
</div>
</Link>
{/* <Link
href="/monitor"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={5} height={3} src="/arrow.png" />
<p className={styles.boxText}>Network Monitor</p>
</div>
</Link> */}
<Link
href="/yaml-gen/"
style={{ textDecoration: "underline", color: "white" }}
>
<div className={styles.box}>
<Image alt="arrow" width={20} height={20} src="/arrow.png" />
<p className={styles.boxText}>Layer 2 Tester </p>
</div>
</Link>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,182 @@
.mainHeading {
font-size: 5rem;
margin-bottom: 1rem;
text-align: center;
}
.mainText {
font-size: 1.5rem;
max-width: 55rem;
text-align: center;
margin: auto;
margin-bottom: 1rem;
}
.boxesContainer {
margin-top: 2rem;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.secondBoxesContainer {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
flex-wrap: wrap;
}
.box {
position: relative;
width: 15rem;
height: 15rem;
border: 1px solid rgb(61, 61, 61);
display: flex;
flex-direction: column;
justify-content: flex-end;
align-self: center;
text-align: center;
font-size: 1.25rem;
padding: 1rem;
}
.box p {
max-width: 12rem;
margin: 0 auto;
}
.box img {
width: 2rem;
position: absolute;
top: 1rem;
right: 1rem;
}
.smallbox {
position: relative;
width: 12rem;
height: 12rem;
border: 1px solid rgb(61, 61, 61);
display: flex;
flex-direction: column;
justify-content: flex-end;
align-self: center;
text-align: center;
font-size: 1.25rem;
padding: 1rem;
}
.smallbox p {
max-width: 12rem;
margin: 0 auto;
}
.smallbox img {
width: 2rem;
position: absolute;
top: 1rem;
right: 1rem;
}
.formContainer {
padding: 1rem;
border: 1px solid rgb(61, 61, 61);
border-radius: 30px;
}
.buttonsContainer {
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
column-gap: 0.5rem;
margin-top: 1rem;
margin-bottom: 1rem;
}
.currentRoute {
margin-bottom: 6rem;
font-family: "Ubuntu Mono", monospace;
font-size: 1.25rem;
font-weight: 600;
text-align: center;
}
.backButton {
position: absolute;
top: 1rem;
left: 1rem;
font-size: 1.25rem;
padding: 0.5rem;
border: 1px solid rgb(61, 61, 61);
background-color: transparent;
color: white;
cursor: pointer;
}
.dashboard {
margin-bottom: 2rem;
}
.dashboardHeading {
font-size: 2rem;
margin-bottom: 1rem;
text-align: center;
}
.dashboardTable {
width: 100%;
border-collapse: collapse;
font-size: 1.25rem;
font-family: "Ubuntu Mono", monospace;
border: 1px solid rgb(61, 61, 61);
}
.dashboardTable th,
.dashboardTable td {
padding: 1rem;
text-align: left;
border-bottom: 1px solid rgb(61, 61, 61);
}
.dashboardTable th {
font-weight: 600;
}
@media screen and (max-width: 600px) {
.dashboardTable {
font-size: 1rem;
}
.dashboardTable th,
.dashboardTable td {
padding: 0.5rem;
}
}
.counts {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-top: 1rem;
margin-bottom: 2rem;
}
.count {
max-width: 10rem;
}

View File

@@ -0,0 +1,132 @@
"use client";
import InputField from "@/components/InputField/InputField";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import SecondaryButton from "@/components/Buttons/SecondaryButton";
import PrimaryButton from "@/components/Buttons/PrimaryButton";
import { useState, useCallback } from "react";
import { toast } from "react-toastify";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
const [subscriberUrl, setSubscriberUrl] = useState("");
const [subscriberId, setSubscriberId] = useState("");
const [registryUrl, setRegistryUrl] = useState("");
const [buttonDisable, setButtonDisable] = useState(false);
const [networkconfigurl, setNetworkconfigurl] = useState("");
const handleSubscriberUrlChange = (event) => {
setSubscriberUrl(event.target.value);
};
const handleSubscriberIdChange = (event) => {
setSubscriberId(event.target.value);
};
const handleRegistryUrlChange = (event) => {
setRegistryUrl(event.target.value);
};
const handleNetworkconfigurlChange = (event) => {
setNetworkconfigurl(event.target.value);
};
const installBap = useCallback(async () => {
const toastId = toast.loading("Installing BAP...");
setButtonDisable(true);
try {
const response = await fetch("/api/install-bap", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
subscriberUrl,
subscriberId,
registryUrl,
networkconfigurl,
}),
});
if (response.ok) {
console.log("BPP installed successfully");
toast.update(toastId, {
render: "BPP installed successfully 👌",
type: "success",
isLoading: false,
autoClose: 5000,
});
} else {
console.error("Failed to install BAP");
toast.update(toastId, {
render: "Failed to install BAP 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
} catch (error) {
console.error("An error occurred:", error);
toast.update(toastId, {
render: "Bap installation done",
type: "success",
isLoading: false,
autoClose: 5000,
});
}
setButtonDisable(false);
}, [subscriberUrl, subscriberId, registryUrl, networkconfigurl]);
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>BAP</p>
<div className={styles.formContainer}>
<InputField
label={"Subscriber ID"}
value={subscriberId}
onChange={handleSubscriberIdChange}
/>
<InputField
label={"Subscriber URL"}
value={subscriberUrl}
onChange={handleSubscriberUrlChange}
/>
<InputField
label={"Registry URL"}
value={registryUrl}
onChange={handleRegistryUrlChange}
/>
<InputField
label={"Network Configuration URL"}
value={networkconfigurl}
onChange={handleNetworkconfigurlChange}
/>
<div className={styles.buttonsContainer}>
{/* <SecondaryButton text={"Cancel"} /> */}
<PrimaryButton
disabled={buttonDisable}
onClick={installBap}
text={"Continue"}
/>
</div>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,146 @@
"use client";
import InputField from "@/components/InputField/InputField";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import SecondaryButton from "@/components/Buttons/SecondaryButton";
import PrimaryButton from "@/components/Buttons/PrimaryButton";
import { useState, useCallback } from "react";
import { toast } from "react-toastify";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
const [subscriberUrl, setSubscriberUrl] = useState("");
const [subscriberId, setSubscriberId] = useState("");
const [registryUrl, setRegistryUrl] = useState("");
const [networkconfigurl, setNetworkconfigurl] = useState("");
const [webhookUrl, setWebhookUrl] = useState("");
const [buttonDisable, setButtonDisable] = useState(false);
const handleSubscriberUrlChange = (event) => {
setSubscriberUrl(event.target.value);
};
const handleSubscriberIdChange = (event) => {
setSubscriberId(event.target.value);
};
const handleRegistryUrlChange = (event) => {
setRegistryUrl(event.target.value);
};
const handleNetworkconfigurlChange = (event) => {
setNetworkconfigurl(event.target.value);
};
const handleWebhookUrlChange = (event) => {
setWebhookUrl(event.target.value);
};
const installBpp = useCallback(async () => {
const toastId = toast.loading("Installing BPP...");
setButtonDisable(true);
try {
const response = await toast.promise(
fetch("/api/install-bpp", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
subscriberUrl: subscriberUrl,
subscriberId: subscriberId,
registryUrl: registryUrl,
networkconfigurl: networkconfigurl,
webhookUrl: webhookUrl,
}),
}),
{
success: "BPP installed successfully 👌",
error: "Failed to install BPP 🤯",
}
);
if (response.ok) {
console.log("BPP installed successfully");
toast.update(toastId, {
render: "BPP installed successfully 👌",
type: "success",
isLoading: false,
autoClose: 5000,
});
} else {
console.error("Failed to install BPP");
toast.update(toastId, {
render: "Failed to install BPP 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
} catch (error) {
console.error("An error occurred:", error);
toast.update(toastId, {
render: "An error occurred while installing BPP 😥",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
setButtonDisable(false);
}, [subscriberUrl, subscriberId, registryUrl, networkconfigurl, webhookUrl]);
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>BPP</p>
<div className={styles.formContainer}>
<InputField
label={"Subscriber ID"}
value={subscriberId}
onChange={handleSubscriberIdChange}
/>
<InputField
label={"Subscriber URL"}
value={subscriberUrl}
onChange={handleSubscriberUrlChange}
/>
<InputField
label={"Registry URL"}
value={registryUrl}
onChange={handleRegistryUrlChange}
/>
<InputField
label={"Webhook URL"}
value={webhookUrl}
onChange={handleWebhookUrlChange}
/>
<InputField
label={"Network Configuration URL"}
value={networkconfigurl}
onChange={handleNetworkconfigurlChange}
/>
<div className={styles.buttonsContainer}>
{/* <SecondaryButton text={"Cancel"} /> */}
<PrimaryButton
disable={buttonDisable}
onClick={installBpp}
text={"Continue"}
/>
</div>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,126 @@
"use client";
import InputField from "@/components/InputField/InputField";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import { useState, useCallback } from "react";
import SecondaryButton from "@/components/Buttons/SecondaryButton";
import PrimaryButton from "@/components/Buttons/PrimaryButton";
import { usePathname } from "next/navigation";
import { toast } from "react-toastify";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
let pathname = usePathname();
const [gatewayUrl, setGatewayUrl] = useState("");
const [registryUrl, setRegistryUrl] = useState("");
const [networkconfigurl, setNetworkconfigurl] = useState("");
const handleGatewayUrlChange = (event) => {
setGatewayUrl(event.target.value);
};
const handleRegistryUrlChange = (event) => {
setRegistryUrl(event.target.value);
};
const handleNetworkconfigurlChange = (event) => {
setNetworkconfigurl(event.target.value);
};
const installGateway = useCallback(async () => {
const toastId = toast.loading("Installing gateway...");
try {
const response = await toast.promise(
fetch("/api/install-gateway", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
gatewayUrl: gatewayUrl,
registryUrl: registryUrl,
networkconfigurl: networkconfigurl,
}),
}),
{
success: "gateway installed successfully 👌",
error: "Failed to install BAP 🤯",
}
);
if (response.ok) {
console.log("Gateway installed successfully");
toast.update(toastId, {
render: "Gateway installed successfully 👌",
type: "success",
isLoading: false,
autoClose: 5000,
});
} else {
console.error("Failed to install gateway");
toast.update(toastId, {
render: "Failed to install gateway 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
} catch (error) {
console.error("An error occurred:", error);
toast.update(toastId, {
render: "An error occurred while installing the gateway 😥",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
}, [gatewayUrl, registryUrl, networkconfigurl]);
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>Gateway</p>
<div className={styles.formContainer}>
{/* To do todo
1. Create a check function so that the url formats are correct
2. Send response when installing and also erros that happen when an envet happens to the user
3. a gear dialog where the user's can specify to where the beckn repo to be cloned.
*/}
<InputField
label={"Publicly Accessible Gateway URL"}
value={gatewayUrl}
onChange={handleGatewayUrlChange}
/>
<InputField
label={"Registry URL"}
value={registryUrl}
onChange={handleRegistryUrlChange}
/>
<InputField
label={"Network Configuration URL"}
value={networkconfigurl}
onChange={handleNetworkconfigurlChange}
/>
<div className={styles.buttonsContainer}>
{/* <SecondaryButton text={"Cancel"} /> */}
<PrimaryButton onClick={installGateway} text={"Continue"} />
</div>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,96 @@
"use client";
import SecondaryButton from "@/components/Buttons/SecondaryButton";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import PrimaryButton from "@/components/Buttons/PrimaryButton";
import InputField from "@/components/InputField/InputField";
import { useState, useCallback } from "react";
import { toast } from "react-toastify";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function Home() {
const [registryUrl, setRegistryUrl] = useState("");
const handleRegistryUrlChange = (event) => {
setRegistryUrl(event.target.value);
};
const installRegistry = useCallback(async () => {
const toastId = toast.loading("Installing registry...");
try {
const response = await toast.promise(
fetch("/api/install-registry", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ registryUrl: registryUrl }),
}),
{
success: "registry installed successfully 👌",
error: "Failed to install registry 🤯",
}
);
console.log("console.log of response", response);
if (response.ok) {
console.log("Repository cloned successfully");
toast.update(toastId, {
render: "Registry installed successfully 👌",
type: "success",
isLoading: false,
autoClose: 5000,
});
} else {
console.error("Failed to clone repository");
toast.update(toastId, {
render: "Failed to install registry 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
} catch (error) {
console.error("An error occurred:", error);
toast.update(toastId, {
render: "An error occurred while installing the registry 😥",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
}, [registryUrl]);
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>Registry</p>
<div className={styles.formContainer}>
<InputField
label={"Public Registry URL"}
value={registryUrl}
onChange={handleRegistryUrlChange}
/>
<div className={styles.buttonsContainer}>
{/* <SecondaryButton text={"Cancel"} /> */}
<PrimaryButton onClick={installRegistry} text={"Continue"} />
</div>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1 @@
name,email,phone_number,district,category,organization,customfile,checkbox_field,date_field,datetime_field,time_field,number_field,rating_field
1 name email phone_number district category organization customfile checkbox_field date_field datetime_field time_field number_field rating_field

View File

@@ -0,0 +1,105 @@
"use client";
import SecondaryButton from "@/components/Buttons/SecondaryButton";
import styles from "../../page.module.css";
import { Ubuntu_Mono } from "next/font/google";
import Slider from "@/components/Slider/Slider";
import PrimaryButton from "@/components/Buttons/PrimaryButton";
import InputField from "@/components/InputField/InputField";
import { useState, useCallback } from "react";
import { toast } from "react-toastify";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function InstallYaml() {
const [yamlUrl, setYamlUrl] = useState("");
const [checked, setChecked] = useState(false);
const container = checked ? "bpp" : "bap";
const handleRegistryUrlChange = (event) => {
setYamlUrl(event.target.value);
};
const installYaml = useCallback(async () => {
const toastId = toast.loading("Installing Layer 2 Config file...");
try {
const response = await fetch("/api/install-layer2", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ container, yamlUrl }),
});
if (response.ok) {
const data = await response.json();
console.log(data);
const FileFound = data.message;
if (FileFound == false) {
setShowDownloadLayer2Button(true);
toast.update(toastId, {
render: "No Layer 2 Config Present 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
} else {
toast.update(toastId, {
render: "Yaml File Downloaded 👌",
type: "success",
isLoading: false,
autoClose: 5000,
});
}
} else {
console.error("Failed to check yaml");
toast.update(toastId, {
render: "Container Not Found 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
} catch (error) {
console.error("An error occurred:", error);
}
});
return (
<>
<main className={ubuntuMono.className}>
<div className={styles.mainContainer}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<p className={styles.mainText}>Install Yaml</p>
<div className={styles.formContainer}>
<Slider
label={checked ? "BPP" : "BAP"}
checked={checked}
toggleChecked={setChecked}
/>
<InputField
label={"Enter Layer 2 URL"}
value={yamlUrl}
onChange={handleRegistryUrlChange}
placeholder="https://github/user/repo/blob/main/layer2.yaml"
/>
<div className={styles.buttonsContainer}>
{/* <SecondaryButton text={"Cancel"} /> */}
<PrimaryButton onClick={installYaml} text={"Continue"} />
</div>
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,144 @@
"use client";
import { useState } from "react";
import { Ubuntu_Mono } from "next/font/google";
import PrimaryButton from "@/components/Buttons/PrimaryButton";
import InputField from "@/components/InputField/InputField";
import Slider from "@/components/Slider/Slider";
import styles from "../page.module.css";
import { toast } from "react-toastify";
import Link from "next/link";
const ubuntuMono = Ubuntu_Mono({
weight: "400",
style: "normal",
subsets: ["latin"],
});
export default function CheckYaml() {
const [domainName, setDomainName] = useState("");
const [versionNumber, setversionNumber] = useState("");
const [checked, setChecked] = useState(false);
const [showDownloadLayer2Button, setShowDownloadLayer2Button] =
useState(false);
const [propertyLink, setPropertyLink] = useState("");
const handleYamlChange = (event) => {
setPropertyLink(event.target.value);
};
const handledomainNameChange = (event) => {
setDomainName(event.target.value);
};
const handleVersionChange = (event) => {
setversionNumber(event.target.value);
};
const nameGenerator = async () => {
const parts = domainName.split(":");
const domainNameWithoutVersion = parts[0];
let filename;
if (parts[1] === undefined || parts[1] === "") {
filename = `${domainNameWithoutVersion}_${versionNumber}.yaml`;
} else {
filename = `${domainNameWithoutVersion}_${parts[1]}_${versionNumber}.yaml`;
}
console.log(filename);
return filename;
};
const handleOnclick = async () => {
const fileName = await nameGenerator();
const toastId = toast.loading("Checking for layer2 yaml file");
try {
const response = await fetch("/api/check-layer2", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ checked, fileName }),
});
if (response.ok) {
const data = await response.json();
const FileFound = data.message;
if (FileFound == false) {
setShowDownloadLayer2Button(true);
toast.update(toastId, {
render: "No Layer 2 Config Present 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
} else {
toast.update(toastId, {
render: "Yaml File Present 👌",
type: "success",
isLoading: false,
autoClose: 5000,
});
}
} else {
console.error("Failed to check yaml");
toast.update(toastId, {
render: "Container Not Found 🤯",
type: "error",
isLoading: false,
autoClose: 5000,
});
}
} catch (error) {
console.error("An error occurred:", error);
}
};
return (
<>
<main className={ubuntuMono.className}>
<button
onClick={() => window.history.back()}
className={styles.backButton}
>
Back
</button>
<div className={styles.mainContainer}>
<p className={styles.mainText}>
<b>Yaml File Checker</b>
</p>
<div className={styles.formContainer}>
<Slider
label={checked ? "BPP" : "BAP"}
checked={checked}
toggleChecked={setChecked}
/>
<InputField
label={"Container Name"}
value={checked ? "bpp-network" : "bap-network"}
readOnly
/>
<InputField
label={"Domain Name"}
value={domainName}
onChange={handledomainNameChange}
placeholder="Retail"
/>
<InputField
label={"Version Number"}
value={versionNumber}
onChange={handleVersionChange}
placeholder="1.1.0"
/>
<div className={styles.buttonsContainer}>
<PrimaryButton label={"Check"} onClick={handleOnclick} />
</div>
{showDownloadLayer2Button && (
<div className={styles.buttonsContainer}>
<a href={`/yaml-gen/install-yaml`}>Download Layer 2 Config</a>
</div>
)}
</div>
</div>
</main>
</>
);
}

View File

@@ -0,0 +1,24 @@
.primaryButton {
background-color: #abd4fa;
color: #000000;
padding: 0.5rem 1rem;
border-radius: 10px;
border: none;
font-size: 1rem;
cursor: pointer;
padding: 0.75rem 2rem;
}
.secondaryButton {
background-color: #000000;
color: #abd4fa;
padding: 0.5rem 1rem;
border-radius: 10px;
border: none;
font-size: 1rem;
cursor: pointer;
border: 1px solid #abd4fa;
padding: 0.75rem 2.25rem;
}

View File

@@ -0,0 +1,16 @@
import React from "react";
import styles from "./Buttons.module.css";
const PrimaryButton = ({ label = "continue", onClick, disabled = false }) => {
return (
<button
className={styles.primaryButton}
onClick={onClick}
disabled={disabled}
>
{label}
</button>
);
};
export default PrimaryButton;

View File

@@ -0,0 +1,8 @@
import React from "react";
import styles from "./Buttons.module.css";
const SecondaryButton = () => {
return <button className={styles.secondaryButton}>Cancel</button>;
};
export default SecondaryButton;

View File

@@ -0,0 +1,19 @@
import React from "react";
import styles from "./InputField.module.css";
const InputField = ({ label, value, onChange, placeholder = "Input Text" }) => {
return (
<div className={styles.inputContainer}>
<label className={styles.inputLabel}>{label}</label>
<input
placeholder={placeholder}
className={styles.inputField}
type="text"
value={value}
onChange={onChange}
/>
</div>
);
};
export default InputField;

View File

@@ -0,0 +1,23 @@
.inputContainer {
display: flex;
flex-direction: column;
margin: 1.5rem 1rem;
}
.inputLabel {
font-size: 1rem;
font-weight: bold;
margin-bottom: 0.5rem;
}
.inputField {
padding: 1rem;
font-family: "Ubuntu Mono", sans-serif;
color: white;
font-size: 1rem;
border-radius: 15px;
border: 1px solid rgb(61, 61, 61);
background: #000000;
min-width:15rem
}

View File

@@ -0,0 +1,20 @@
import React from "react";
import styles from "./Slider.module.css";
const Slider = ({ label, checked, toggleChecked }) => {
return (
<div className={styles.inputContainer}>
<label className={styles.inputLabel}>{label}</label>
<label className={styles.switch}>
<input
type="checkbox"
checked={checked}
onChange={() => toggleChecked(!checked)}
/>
<span className={`${styles.slider} ${styles.round}`}></span>
</label>
</div>
);
};
export default Slider;

View File

@@ -0,0 +1,67 @@
.switch {
transform: scale(0.75);
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
.inputContainer {
display: flex;
align-items: center;
justify-content: space-around;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: black;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #9dc5e6;
}
input:focus+.slider {
box-shadow: 0 0 1px white;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}

View File

@@ -0,0 +1,7 @@
{
"compilerOptions": {
"paths": {
"@/*": ["./*"]
}
}
}

View File

@@ -0,0 +1,4 @@
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default nextConfig;

4247
onix-gui/GUI/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

22
onix-gui/GUI/package.json Normal file
View File

@@ -0,0 +1,22 @@
{
"name": "onix-gui",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"child_process": "^1.0.2",
"next": "14.1.4",
"react": "^18",
"react-dom": "^18",
"react-toastify": "^10.0.5"
},
"devDependencies": {
"eslint": "^8",
"eslint-config-next": "14.1.4"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

77
onix-gui/README.md Normal file
View File

@@ -0,0 +1,77 @@
# Beckn-Onix Installation Wizard
The below provides an overview of the installation wizard and layer 2 tester & downloader features of Beckn-Onix. Follow the steps outlined below to successfully utilize these features.
### Home Page
- Visit the home page of the Beckn-Onix installation wizard.
![Home Page](https://github.com/beckn/beckn-onix/assets/85678545/e8674a29-b6e2-4fb2-a5ad-c76166bf1174)
### Installation Wizard
- Navigate to the installation wizard section.
- Fill in the required details as prompted.
![Installation Wizard](https://github.com/beckn/beckn-onix/assets/85678545/e9cec587-299f-4793-9045-c7c01551ad51)
### Continue Installation
- Click on the "Continue" button to proceed with the installation.
- Repeat the same process for all components.
## Layer 2
![Layer 2](https://github.com/beckn/beckn-onix/assets/85678545/32978858-5303-43b2-b0b5-517ee98ec6c3)
### Setup Configuration File
- Select whether you want to set up the layer 2 config file in BAP or BPP.
- Fill in the Domain and version number of the layer 2 config file.
### Check File Presence
- If the file is present, a success toast will be displayed.
- If the file is not present, a link for downloading the layer 2 file to the protocol server will be provided.
![Check File Presence](https://github.com/beckn/beckn-onix/assets/85678545/31aaf210-9fef-4c33-b651-7231cd900f0a)
### Download File
- Click on the download link to be redirected to another page for downloading.
- Paste the YAML file URL and click "Continue".
- If successful, a success toast will be displayed. If unsuccessful, an error toast will be shown.
![Download File](https://github.com/beckn/beckn-onix/assets/85678545/0dd9d456-66ca-4e2a-abc1-ba8dd98719c1)

79
onix-gui/start.sh Executable file
View File

@@ -0,0 +1,79 @@
#!/bin/bash
# Installing dependencies
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo curl -L https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
echo "installing node"
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash &&
source ~/.bashrc &&
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion" # This loads nvm bash_completion
nvm install 20 &&
npm i -g localtunnel &&
# Add user to the docker group and apply permissions
sudo groupadd docker &
sudo usermod -aG docker $USER &
newgrp docker &
# Set script variables
PROJECT_DIR="GUI"
PORT=3005
TUNNEL_SERVICE="lt"
# Change to the project directory
cd "$PROJECT_DIR" || exit
nvm use 20 &&
npm i &&
# Build and start the Next.js app
echo "installing Dependencies"
echo "Building and starting Next.js app..."
npx next build &&
echo "Builing Web App = True"
sleep 3
npx next start -p "$PORT" &
# Wait for the Next.js app to start
# Install the tunnel service if not installed
sleep 3
echo "Exposing local port $PORT using $TUNNEL_SERVICE..."
lt --port "$PORT" > /tmp/lt.log 2>&1 &
# Wait for the tunnel service to start
echo "Waiting for tunnel service to start..."
sleep 5
# Get the tunnel URL from the log file
TUNNEL_URL=$(grep -o 'https://[^[:blank:]]*' /tmp/lt.log)
#Get the tunnel password
echo "Getting Tunnel Password"
TUNNEL_PASSWORD=$(curl https://loca.lt/mytunnelpassword) &&
# Print the tunnel URL and password
echo "---------------------------------------"
echo "Next.js app is running locally on port $PORT"
echo "Tunnel Service URL: $TUNNEL_URL"
echo "Tunnel Password: $TUNNEL_PASSWORD"
echo "---------------------------------------"