Skip to content

Commit b74d19d

Browse files
committed
feat(python): update 010&011 ui
1 parent 64aabfd commit b74d19d

File tree

8 files changed

+224
-76
lines changed

8 files changed

+224
-76
lines changed
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
FROM ghcr.io/build-trust/ockam-python:latest
1+
FROM ghcr.io/build-trust/ockam-python:cd3c44c50
22
COPY . .
33
ENTRYPOINT ["python", "main.py"]

examples/010/images/main/index.html

Lines changed: 93 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,69 @@
5454
padding: 6px 12px;
5555
font-size: 14px;
5656
}
57-
@keyframes pulse {
58-
0% {
59-
box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.7);
60-
}
61-
70% {
62-
box-shadow: 0 0 0 10px rgba(0, 123, 255, 0);
63-
}
64-
100% {
65-
box-shadow: 0 0 0 0 rgba(0, 123, 255, 0);
66-
}
57+
#loader {
58+
display: none;
59+
width: 15px;
60+
height: 15px;
61+
margin: 0;
62+
border: 8px solid #f3f3f3;
63+
border-radius: 50%;
64+
border-top: 8px solid #3498db;
65+
-webkit-animation: spin 2s linear infinite;
66+
animation: spin 2s linear infinite;
67+
}
68+
@-webkit-keyframes spin {
69+
0% { -webkit-transform: rotate(0deg); }
70+
100% { -webkit-transform: rotate(360deg); }
71+
}
72+
@keyframes spin {
73+
0% { transform: rotate(0deg); }
74+
100% { transform: rotate(360deg); }
6775
}
68-
.pulse {
69-
animation: pulse 1.5s infinite;
70-
border-color: #007bff;
71-
outline: none;
76+
.foo {
77+
display: flex;
78+
flex-direction: row;
79+
justify-content: flex-start;
80+
align-items: center;
81+
}
82+
#popup {
83+
display: none;
84+
background-color: rgba(0,0,0,0.5);
85+
position: fixed;
86+
z-index: 999;
87+
width: 100%;
88+
height: 100vh;
89+
flex-direction: column;
90+
justify-content: center;
91+
align-items: center;
92+
margin: 0 auto;
93+
.popup {
94+
background: white;
95+
color: #fff;
96+
padding: 10px;
97+
border-radius: 5px;
98+
display: flex;
99+
flex-direction: column;
100+
align-items: center;
101+
width: 200px;
102+
#text {
103+
color: black;
104+
}
105+
}
72106
}
73107
</style>
74108
</head>
75109
<body>
76-
<button id="run-btn">Run</button>
110+
<div id="popup">
111+
<div class="popup">
112+
<p id="text"></p>
113+
<button id="ok-btn">OK</button>
114+
</div>
115+
</div>
116+
<div class="foo">
117+
<button id="run-btn">Run</button>
118+
<div id="loader"></div>
119+
</div>
77120
<div id="container"></div>
78121
<script src="https://d3js.org/d3.v7.min.js"></script>
79122
<script>
@@ -83,18 +126,23 @@
83126

84127
const container = d3.select("#container");
85128

86-
function render(data) {
87-
const grouped = {};
88-
for (const worker of data.workers) {
89-
if (!grouped[worker.runner_name]) {
90-
grouped[worker.runner_name] = [];
91-
}
92-
grouped[worker.runner_name].push(worker.worker_name);
93-
}
129+
function sleep(ms) {
130+
return new Promise(resolve => setTimeout(resolve, ms));
131+
}
94132

133+
window.prev_data = {};
134+
function render(data) {
95135
const container = d3.select("#container");
96136

97-
const nodeColumns = container.selectAll(".node-column").data(Object.entries(grouped), (d) => d[0]);
137+
// In case some runners didn't respond due to being buse, use the previous value for that runner
138+
const new_data = {...window.prev_data, ...data};
139+
window.prev_data = {...data};
140+
141+
const data_list = Object.entries(new_data).sort((a, b) => {
142+
return a[0].localeCompare(b[0]);
143+
});
144+
145+
const nodeColumns = container.selectAll(".node-column").data(data_list, (d) => d[0]);
98146
nodeColumns.exit().remove();
99147

100148
const nodeColumnsEnter = nodeColumns.enter().append("div").attr("class", "node-column");
@@ -154,17 +202,34 @@
154202
});
155203
}
156204

205+
document.getElementById("ok-btn").addEventListener("click", async function () {
206+
const popup = document.getElementById("popup");
207+
popup.style.display = "none"
208+
});
209+
157210
document.getElementById("run-btn").addEventListener("click", async function () {
158211
const button = this;
159-
button.classList.add("pulse");
212+
const loader = document.getElementById("loader");
213+
const popup = document.getElementById("popup");
214+
const text = document.getElementById("text");
215+
button.disabled = true;
216+
loader.style.display = "block";
217+
160218
try {
219+
const start = Date.now();
161220
const response = await fetch("/analyze", { method: "POST" });
162221
const response_json = await response.json();
222+
const end = Date.now();
163223
console.log("Analysis: ", response_json);
224+
text.innerHTML = `Success in: ${Math.floor((end - start) / 1000)} s`;
164225
} catch (error) {
165226
console.error("Error fetching /analyze:", error);
227+
text.innerHTML = "Error"
166228
} finally {
167-
button.classList.remove("pulse");
229+
loader.style.display = "none";
230+
await sleep(1500);
231+
popup.style.display = "flex"
232+
button.disabled = false;
168233
}
169234
});
170235

@@ -174,7 +239,8 @@
174239
const response = await fetch("/runners/workers");
175240
if (response.ok) {
176241
const response_json = await response.json();
177-
console.log("Workers: ", response_json);
242+
const now = new Date();
243+
console.log(now.toLocaleTimeString(), "Workers:", response_json);
178244
render(response_json);
179245
}
180246
} catch (e) {

examples/010/images/main/main.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,23 @@ def split_list_into_n_parts(lst, n):
148148

149149

150150
async def list_workers(node):
151+
import ockam
152+
151153
runners = await Zone.nodes(node, filter="runner")
152-
futures = [runner.list_workers() for runner in runners]
153-
workers_per_runner = await asyncio.gather(*futures)
154-
workers = []
155-
for runner, workers_on_this_runner in zip(runners, workers_per_runner):
156-
for w in workers_on_this_runner:
157-
workers.append({"worker_name": w["name"], "runner_name": runner.name})
158-
return workers
154+
155+
async def list_per_runner(runner):
156+
workers_on_this_runner = await runner.list_workers()
157+
return {runner.name: [w["name"] for w in workers_on_this_runner]}
158+
159+
futures = [list_per_runner(runner) for runner in runners]
160+
workers_per_runner = await ockam.gather(*futures, timeout=3, return_exceptions=True)
161+
162+
# ignore errors
163+
workers_per_runner = [r for r in workers_per_runner if not isinstance(r, Exception)]
164+
# flatten
165+
workers_per_runner = {k: v for d in workers_per_runner for k, v in d.items()}
166+
167+
return workers_per_runner
159168

160169

161170
class Api:
@@ -193,7 +202,7 @@ async def post_analyze():
193202
@self.api.get("/runners/workers")
194203
async def get_workers():
195204
workers = await list_workers(node)
196-
return JSONResponse(content={"workers": workers})
205+
return JSONResponse(content=workers)
197206

198207
@self.api.get("/runners")
199208
async def get_runners():
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
FROM ghcr.io/build-trust/ockam-python:latest
1+
FROM ghcr.io/build-trust/ockam-python:cd3c44c50
22
COPY . .
33
ENTRYPOINT ["python", "main.py"]

examples/011/images/main/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
FROM ghcr.io/build-trust/ockam-python-dev:latest AS dev
1+
FROM ghcr.io/build-trust/ockam-python-dev:cd3c44c50 AS dev
22

33
ENV PATH="/app/venv/bin:$PATH"
44
COPY requirements.txt requirements.txt
55
RUN python -m venv /app/venv && pip install -r requirements.txt
66

7-
FROM ghcr.io/build-trust/ockam-python:latest
7+
FROM ghcr.io/build-trust/ockam-python:cd3c44c50
88

99
WORKDIR /app
1010

examples/011/images/main/index.html

Lines changed: 93 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -54,26 +54,69 @@
5454
padding: 6px 12px;
5555
font-size: 14px;
5656
}
57-
@keyframes pulse {
58-
0% {
59-
box-shadow: 0 0 0 0 rgba(0, 123, 255, 0.7);
60-
}
61-
70% {
62-
box-shadow: 0 0 0 10px rgba(0, 123, 255, 0);
63-
}
64-
100% {
65-
box-shadow: 0 0 0 0 rgba(0, 123, 255, 0);
66-
}
57+
#loader {
58+
display: none;
59+
width: 15px;
60+
height: 15px;
61+
margin: 0;
62+
border: 8px solid #f3f3f3;
63+
border-radius: 50%;
64+
border-top: 8px solid #3498db;
65+
-webkit-animation: spin 2s linear infinite;
66+
animation: spin 2s linear infinite;
67+
}
68+
@-webkit-keyframes spin {
69+
0% { -webkit-transform: rotate(0deg); }
70+
100% { -webkit-transform: rotate(360deg); }
71+
}
72+
@keyframes spin {
73+
0% { transform: rotate(0deg); }
74+
100% { transform: rotate(360deg); }
6775
}
68-
.pulse {
69-
animation: pulse 1.5s infinite;
70-
border-color: #007bff;
71-
outline: none;
76+
.foo {
77+
display: flex;
78+
flex-direction: row;
79+
justify-content: flex-start;
80+
align-items: center;
81+
}
82+
#popup {
83+
display: none;
84+
background-color: rgba(0,0,0,0.5);
85+
position: fixed;
86+
z-index: 999;
87+
width: 100%;
88+
height: 100vh;
89+
flex-direction: column;
90+
justify-content: center;
91+
align-items: center;
92+
margin: 0 auto;
93+
.popup {
94+
background: white;
95+
color: #fff;
96+
padding: 10px;
97+
border-radius: 5px;
98+
display: flex;
99+
flex-direction: column;
100+
align-items: center;
101+
width: 200px;
102+
#text {
103+
color: black;
104+
}
105+
}
72106
}
73107
</style>
74108
</head>
75109
<body>
76-
<button id="run-btn">Run</button>
110+
<div id="popup">
111+
<div class="popup">
112+
<p id="text"></p>
113+
<button id="ok-btn">OK</button>
114+
</div>
115+
</div>
116+
<div class="foo">
117+
<button id="run-btn">Run</button>
118+
<div id="loader"></div>
119+
</div>
77120
<div id="container"></div>
78121
<script src="https://d3js.org/d3.v7.min.js"></script>
79122
<script>
@@ -83,18 +126,23 @@
83126

84127
const container = d3.select("#container");
85128

86-
function render(data) {
87-
const grouped = {};
88-
for (const worker of data.workers) {
89-
if (!grouped[worker.runner_name]) {
90-
grouped[worker.runner_name] = [];
91-
}
92-
grouped[worker.runner_name].push(worker.worker_name);
93-
}
129+
function sleep(ms) {
130+
return new Promise(resolve => setTimeout(resolve, ms));
131+
}
94132

133+
window.prev_data = {};
134+
function render(data) {
95135
const container = d3.select("#container");
96136

97-
const nodeColumns = container.selectAll(".node-column").data(Object.entries(grouped), (d) => d[0]);
137+
// In case some runners didn't respond due to being buse, use the previous value for that runner
138+
const new_data = {...window.prev_data, ...data};
139+
window.prev_data = {...data};
140+
141+
const data_list = Object.entries(new_data).sort((a, b) => {
142+
return a[0].localeCompare(b[0]);
143+
});
144+
145+
const nodeColumns = container.selectAll(".node-column").data(data_list, (d) => d[0]);
98146
nodeColumns.exit().remove();
99147

100148
const nodeColumnsEnter = nodeColumns.enter().append("div").attr("class", "node-column");
@@ -154,17 +202,34 @@
154202
});
155203
}
156204

205+
document.getElementById("ok-btn").addEventListener("click", async function () {
206+
const popup = document.getElementById("popup");
207+
popup.style.display = "none"
208+
});
209+
157210
document.getElementById("run-btn").addEventListener("click", async function () {
158211
const button = this;
159-
button.classList.add("pulse");
212+
const loader = document.getElementById("loader");
213+
const popup = document.getElementById("popup");
214+
const text = document.getElementById("text");
215+
button.disabled = true;
216+
loader.style.display = "block";
217+
160218
try {
219+
const start = Date.now();
161220
const response = await fetch("/analyze", { method: "POST" });
162221
const response_json = await response.json();
222+
const end = Date.now();
163223
console.log("Analysis: ", response_json);
224+
text.innerHTML = `Success in: ${Math.floor((end - start) / 1000)} s`;
164225
} catch (error) {
165226
console.error("Error fetching /analyze:", error);
227+
text.innerHTML = "Error"
166228
} finally {
167-
button.classList.remove("pulse");
229+
loader.style.display = "none";
230+
await sleep(1500);
231+
popup.style.display = "flex"
232+
button.disabled = false;
168233
}
169234
});
170235

@@ -174,7 +239,8 @@
174239
const response = await fetch("/runners/workers");
175240
if (response.ok) {
176241
const response_json = await response.json();
177-
console.log("Workers: ", response_json);
242+
const now = new Date();
243+
console.log(now.toLocaleTimeString(), "Workers:", response_json);
178244
render(response_json);
179245
}
180246
} catch (e) {

0 commit comments

Comments
 (0)