mirror of
https://github.com/docker/awesome-compose.git
synced 2025-04-26 10:43:35 +02:00
Feat: add Docker+wasm examples (#309)
* Add a Docker+wasm sample application featuring a WasmEdge-based microservice, a MySQL database and an Nginx web server for frontend UI files. Signed-off-by: Michael Yuan <michael@secondstate.io> * Add a logo to indicate Docker+wasm compatibility. Add project descriptions to README. Signed-off-by: Michael Yuan <michael@secondstate.io> * Add the example for WasmEdge + Kafka / Redpanda + MySQL application to take messages from a queue and save into a database table. Signed-off-by: Michael Yuan <michael@secondstate.io> * Add a SVG icon to indicate Docker + Wasm req Signed-off-by: Michael Yuan <michael@michaelyuan.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update the docker compose files for the new Docker Desktop release Signed-off-by: Michael Yuan <michael@secondstate.io> * Use the correct platform to be compatible with Docker Desktop 4.15 Signed-off-by: Michael Yuan <michael@secondstate.io> * Update README.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-kafka-mysql/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-kafka-mysql/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-kafka-mysql/etl/Dockerfile Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Update wasmedge-mysql-nginx/README.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> * Change the Nginx port to the default non-privileged 8090 Signed-off-by: Michael Yuan <michael@secondstate.io> * My apologies. Need to correct the syntax for the Nginx port 8090. Signed-off-by: Michael Yuan <michael@secondstate.io> * Remove commented lines Signed-off-by: Michael Yuan <michael@secondstate.io> * Change wasi/wasm32 to wasi/wasm to conform with the latest spec Signed-off-by: Michael Yuan <michael@secondstate.io> * Update README.md Co-authored-by: Michael Irwin <mikesir87@gmail.com> Signed-off-by: Michael Yuan <michael@michaelyuan.com> Signed-off-by: Michael Yuan <michael@secondstate.io> Signed-off-by: Michael Yuan <michael@michaelyuan.com> Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> Co-authored-by: Michael Irwin <mikesir87@gmail.com> Signed-off-by: Andrew Maguire <andrewm4894@gmail.com>
This commit is contained in:
parent
05b8a83bc0
commit
cb3a065ee8
20 changed files with 1057 additions and 0 deletions
102
wasmedge-mysql-nginx/frontend/index.html
Normal file
102
wasmedge-mysql-nginx/frontend/index.html
Normal file
|
@ -0,0 +1,102 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Demo App</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-Zenh87qX5JnK2Jl0vWa8Ck2rdkQ2Bzep5IDxbcnCeuOxjzrPF/et3URy9Bv1WTRi" crossorigin="anonymous" />
|
||||
<style>.d-none { display: none; }</style>
|
||||
</head>
|
||||
<body class="mb-5">
|
||||
<div class="container mt-5">
|
||||
<div id="app-loading-display">
|
||||
<h1>Loading...</h1>
|
||||
</div>
|
||||
|
||||
<div id="order-display" class="d-none">
|
||||
<h1>Welcome to the Demo!</h1>
|
||||
<p>This application is served using nginx for the website, Wasm for the backend, and MariaDB for the database.</p>
|
||||
|
||||
<div id="order-empty-text" class="d-none">
|
||||
<em>There are currently no orders to display!</em>
|
||||
</div>
|
||||
|
||||
<table id="order-table" class="d-none table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Product Id</th>
|
||||
<th>Quantity</th>
|
||||
<th>Amount</th>
|
||||
<th>Shipping</th>
|
||||
<th>Tax</th>
|
||||
<th>Address</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
|
||||
<hr />
|
||||
|
||||
<div id="add-order-wrapper" class="d-none row">
|
||||
<div class="col-6">
|
||||
<div class="accordion" id="accordionExample">
|
||||
<div class="accordion-item">
|
||||
<h2 class="accordion-header" id="addOrderHeading">
|
||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#addOrder" aria-controls="addOrder">
|
||||
Add an order
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<div id="addOrder" class="accordion-collapse collapse p-3" aria-labelledby="addOrderHeading" data-bs-parent="#accordionExample">
|
||||
<form id="add-order-form">
|
||||
<div class="mb-3">
|
||||
<label for="order-id" class="form-label">Order Id</label>
|
||||
<input type="number" required class="form-control" id="order-id" aria-describedby="orderIdHelp">
|
||||
<div id="orderIdHelp" class="form-text">The ID of the order</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="product-id" class="form-label">Product Id</label>
|
||||
<input type="number" required class="form-control" id="product-id" aria-describedby="productIdHelp">
|
||||
<div id="productIdHelp" class="form-text">The ID of the product</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="quantity" class="form-label">Quantity</label>
|
||||
<input type="number" required class="form-control" id="quantity" aria-describedby="quantityHelp">
|
||||
<div id="quantityHelp" class="form-text">How many of the product?</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="amount" class="form-label">Amount</label>
|
||||
<input type="number" required class="form-control" id="amount" aria-describedby="amountHelp">
|
||||
<div id="amountHelp" class="form-text">The total amount</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="tax" class="form-label">Tax</label>
|
||||
<input type="number" required class="form-control" id="tax" aria-describedby="taxHelp">
|
||||
<div id="taxHelp" class="form-text">The total amount of tax</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="shippingAmount" class="form-label">Shipping Amount</label>
|
||||
<input type="number" required class="form-control" id="shippingAmount" aria-describedby="shippingAmountHelp">
|
||||
<div id="shippingAmountHelp" class="form-text">The total amount for shipping</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="shippingAddress" class="form-label">Shipping Address</label>
|
||||
<input type="text" required class="form-control" id="shippingAddress" aria-describedby="addressHelp">
|
||||
<div id="addressHelp" class="form-text">Where to send the order</div>
|
||||
</div>
|
||||
|
||||
<input type="submit" class="btn btn-success" value="Add Order" />
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-OERcA2EqjJCMA+/3y+gxIOqMEjwtxJY7qPCqsdltbNJuaOe923+mo//f6V8Qbsw3" crossorigin="anonymous"></script>
|
||||
<script type="text/javascript" src="/js/app.js"></script>
|
||||
</body>
|
||||
</html>
|
135
wasmedge-mysql-nginx/frontend/js/app.js
Normal file
135
wasmedge-mysql-nginx/frontend/js/app.js
Normal file
|
@ -0,0 +1,135 @@
|
|||
(function() {
|
||||
let orders = null;
|
||||
const appLoadingEle = document.getElementById("app-loading-display");
|
||||
const orderWrapperEle = document.getElementById("order-display");
|
||||
const orderEmptyTextEle = document.getElementById("order-empty-text");
|
||||
const orderTableEle = document.getElementById("order-table");
|
||||
const orderTableBodyEle = document.querySelector("#order-table tbody");
|
||||
const addOrderEle = document.getElementById("add-order-wrapper");
|
||||
const addOrderForm = document.getElementById("add-order-form");
|
||||
|
||||
const orderIdField = document.getElementById("order-id");
|
||||
const productIdField = document.getElementById("product-id");
|
||||
const quantityField = document.getElementById("quantity");
|
||||
const amountField = document.getElementById("amount");
|
||||
const taxField = document.getElementById("tax");
|
||||
const shippingField = document.getElementById("shippingAmount");
|
||||
const shippingAddressField = document.getElementById("shippingAddress");
|
||||
|
||||
function fetchOrders() {
|
||||
fetch("http://localhost:8080/orders")
|
||||
.then(r => r.json())
|
||||
.then(r => orders = r)
|
||||
.then(renderOrders)
|
||||
.catch((e) => {
|
||||
init();
|
||||
});
|
||||
}
|
||||
|
||||
function init() {
|
||||
fetch("http://localhost:8080/init")
|
||||
.then(() => fetchOrders())
|
||||
.catch((e) => displayError(e));
|
||||
}
|
||||
|
||||
function renderOrders() {
|
||||
appLoadingEle.classList.add("d-none");
|
||||
orderWrapperEle.classList.remove("d-none");
|
||||
addOrderEle.classList.remove("d-none");
|
||||
|
||||
if (orders.length === 0) {
|
||||
orderEmptyTextEle.classList.remove("d-none");
|
||||
orderTableEle.classList.add("d-none");
|
||||
return;
|
||||
}
|
||||
|
||||
orderEmptyTextEle.classList.add("d-none");
|
||||
orderTableEle.classList.remove("d-none");
|
||||
|
||||
while (orderTableBodyEle.firstChild) {
|
||||
orderTableBodyEle.removeChild(orderTableBodyEle.firstChild);
|
||||
}
|
||||
|
||||
orders.forEach((order) => {
|
||||
const orderId = order.order_id;
|
||||
|
||||
const row = document.createElement("tr");
|
||||
|
||||
row.appendChild(createCell(order.order_id));
|
||||
row.appendChild(createCell(order.product_id));
|
||||
row.appendChild(createCell(order.quantity));
|
||||
row.appendChild(createCell(order.amount));
|
||||
row.appendChild(createCell(order.shipping));
|
||||
row.appendChild(createCell(order.tax));
|
||||
row.appendChild(createCell(order.shipping_address));
|
||||
|
||||
const actionCell = document.createElement("td");
|
||||
|
||||
const deleteButton = document.createElement("button");
|
||||
deleteButton.classList.add(...["btn","btn-sm","btn-danger"]);
|
||||
deleteButton.innerText = "Delete";
|
||||
|
||||
deleteButton.addEventListener("click", (e) => {
|
||||
e.preventDefault();
|
||||
deleteOrder(orderId);
|
||||
});
|
||||
|
||||
actionCell.appendChild(deleteButton);
|
||||
|
||||
row.appendChild(actionCell);
|
||||
|
||||
orderTableBodyEle.appendChild(row);
|
||||
});
|
||||
}
|
||||
|
||||
function createCell(contents) {
|
||||
const cell = document.createElement("td");
|
||||
cell.innerText = contents;
|
||||
return cell;
|
||||
}
|
||||
|
||||
function deleteOrder(orderId) {
|
||||
fetch(`http://localhost:8080/delete_order?id=${orderId}`)
|
||||
.then(() => fetchOrders());
|
||||
}
|
||||
|
||||
function displayError(err) {
|
||||
alert("Error:" + err);
|
||||
}
|
||||
|
||||
function onAddFormSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
const data = {
|
||||
order_id : parseFloat(orderIdField.value),
|
||||
product_id : parseFloat(productIdField.value),
|
||||
quantity : parseFloat(quantityField.value),
|
||||
amount : parseFloat(amountField.value),
|
||||
shipping : parseFloat(shippingField.value),
|
||||
tax : parseFloat(taxField.value),
|
||||
shipping_address : shippingAddressField.value,
|
||||
};
|
||||
|
||||
fetch("http://localhost:8080/create_order", {
|
||||
method: "POST",
|
||||
body: JSON.stringify(data),
|
||||
headers: { "Content-type": "application/json" },
|
||||
}).then(() => fetchOrders())
|
||||
.then(() => resetAddOrderForm());
|
||||
|
||||
alert("Order added");
|
||||
}
|
||||
|
||||
function resetAddOrderForm() {
|
||||
orderIdField.value = "";
|
||||
productIdField.value = "";
|
||||
quantityField.value = "";
|
||||
amountField.value = "";
|
||||
shippingField.value = "";
|
||||
taxField.value = "";
|
||||
shippingAddressField.value = "";
|
||||
}
|
||||
|
||||
fetchOrders();
|
||||
addOrderForm.addEventListener("submit", onAddFormSubmit);
|
||||
})();
|
Loading…
Add table
Add a link
Reference in a new issue