Skip to content

Commit f3ab5f3

Browse files
authored
Chore/minor bug fixes (#318)
* fix: blabsy-double message * fix: control panel selection * chore: eVoting fixes
1 parent 2f3592a commit f3ab5f3

File tree

12 files changed

+261
-31
lines changed

12 files changed

+261
-31
lines changed

infrastructure/control-panel/src/lib/fragments/TableCardHeader/TableCardHeader.svelte

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,21 +6,30 @@
66
title,
77
searchValue = $bindable(''),
88
rightTitle,
9-
placeholder
10-
}: { title: string; searchValue: string; rightTitle: string; placeholder: string } = $props();
9+
placeholder,
10+
showClearSelection = false,
11+
onClearSelection = () => {}
12+
}: {
13+
title: string;
14+
searchValue: string;
15+
rightTitle: string;
16+
placeholder: string;
17+
showClearSelection?: boolean;
18+
onClearSelection?: () => void;
19+
} = $props();
1120
</script>
1221

1322
<header class="mb-4 flex w-full items-center justify-between px-4">
1423
<div class="flex items-center gap-4">
15-
<p class="text-black-700 font-semibold whitespace-nowrap">{title}</p>
24+
<p class="text-black-700 whitespace-nowrap font-semibold">{title}</p>
1625
<div class="relative w-full">
1726
<input
1827
type="text"
1928
{placeholder}
2029
bind:value={searchValue}
2130
class="bg-black-100 text-black-700 placeholder:text-black-700 w-full rounded-[8px] border border-gray-300 px-4 py-1.5 pr-10 text-xs outline-0"
2231
/>
23-
<span class="text-black-700 absolute top-1/2 right-3 h-4 w-4 -translate-y-1/2">
32+
<span class="text-black-700 absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2">
2433
<HugeiconsIcon
2534
icon={Search01FreeIcons}
2635
size="16px"
@@ -31,6 +40,14 @@
3140
</div>
3241

3342
<div class="flex items-center gap-2">
43+
{#if showClearSelection}
44+
<button
45+
onclick={onClearSelection}
46+
class="rounded bg-red-100 px-3 py-1 text-xs font-medium text-red-700 transition-colors hover:bg-red-200"
47+
>
48+
Clear Selection
49+
</button>
50+
{/if}
3451
<span class="bg-secondary inline-block h-2 w-2 rounded-full"></span>
3552
<p class="text-black-700 text-sm">{rightTitle}</p>
3653
</div>

infrastructure/control-panel/src/lib/ui/Table/Table.svelte

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
sortBy?: string;
6969
sortOrder?: 'asc' | 'desc';
7070
onSelectionChange?: (index: number, checked: boolean) => void;
71+
onSelectAllChange?: (checked: boolean) => void;
7172
}
7273
7374
let {
@@ -90,6 +91,7 @@
9091
sortBy,
9192
sortOrder,
9293
onSelectionChange,
94+
onSelectAllChange,
9395
...restProps
9496
}: ITableProps = $props();
9597
@@ -100,7 +102,17 @@
100102
101103
function toggleCheckAll(checked: boolean) {
102104
checkAll = checked;
103-
checkItems = checkItems.map(() => checked);
105+
106+
// Call the onSelectAllChange callback if provided
107+
if (onSelectAllChange) {
108+
onSelectAllChange(checked);
109+
}
110+
111+
// Update all individual checkboxes without calling onSelectionChange for each
112+
// since onSelectAllChange already handles the bulk selection
113+
for (let i = 0; i < tableData.length; i++) {
114+
checkItems[i] = checked;
115+
}
104116
}
105117
106118
function toggleCheckItem(i: number, checked: boolean) {

infrastructure/control-panel/src/routes/+page.svelte

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,48 @@
8888
sessionStorage.setItem('selectedPlatforms', JSON.stringify(selectedPlatformData));
8989
}
9090
91+
// Handle select all eVaults
92+
function handleSelectAllEVaults(checked: boolean) {
93+
if (checked) {
94+
// Select all eVaults
95+
selectedEVaults = Array.from({ length: evaults.length }, (_, i) => i);
96+
} else {
97+
// Deselect all eVaults
98+
selectedEVaults = [];
99+
}
100+
101+
// Store selections immediately in sessionStorage
102+
const selectedEVaultData = selectedEVaults.map((i) => evaults[i]);
103+
sessionStorage.setItem('selectedEVaults', JSON.stringify(selectedEVaultData));
104+
}
105+
106+
// Handle select all platforms
107+
function handleSelectAllPlatforms(checked: boolean) {
108+
if (checked) {
109+
// Select all platforms
110+
selectedPlatforms = Array.from({ length: platforms.length }, (_, i) => i);
111+
} else {
112+
// Deselect all platforms
113+
selectedPlatforms = [];
114+
}
115+
116+
// Store selections immediately in sessionStorage
117+
const selectedPlatformData = selectedPlatforms.map((i) => platforms[i]);
118+
sessionStorage.setItem('selectedPlatforms', JSON.stringify(selectedPlatformData));
119+
}
120+
121+
// Clear eVault selection
122+
function clearEVaultSelection() {
123+
selectedEVaults = [];
124+
sessionStorage.removeItem('selectedEVaults');
125+
}
126+
127+
// Clear platform selection
128+
function clearPlatformSelection() {
129+
selectedPlatforms = [];
130+
sessionStorage.removeItem('selectedPlatforms');
131+
}
132+
91133
// Navigate to monitoring with selected items
92134
function goToMonitoring() {
93135
const selectedEVaultData = selectedEVaults.map((i) => evaults[i]);
@@ -185,7 +227,11 @@
185227
title="eVaults"
186228
placeholder="Search eVaults"
187229
bind:searchValue={evaultsSearchValue}
188-
rightTitle="Monitoring all eVault pods across Kubernetes clusters"
230+
rightTitle={selectedEVaults.length > 0
231+
? `${selectedEVaults.length} eVault${selectedEVaults.length === 1 ? '' : 's'} selected`
232+
: 'Monitoring all eVault pods across Kubernetes clusters'}
233+
showClearSelection={selectedEVaults.length > 0}
234+
onClearSelection={clearEVaultSelection}
189235
/>
190236

191237
{#if isLoading}
@@ -215,6 +261,7 @@
215261
{handleNextPage}
216262
handleSelectedRow={handleEVaultRowClick}
217263
onSelectionChange={handleEVaultSelectionChange}
264+
onSelectAllChange={handleSelectAllEVaults}
218265
/>
219266
{/if}
220267
</TableCard>
@@ -224,7 +271,11 @@
224271
title="Platforms"
225272
placeholder="Search Platforms"
226273
bind:searchValue={platformsSearchQuery}
227-
rightTitle="No platform selected. Select a platform to monitor logs"
274+
rightTitle={selectedPlatforms.length > 0
275+
? `${selectedPlatforms.length} platform${selectedPlatforms.length === 1 ? '' : 's'} selected`
276+
: 'No platform selected. Select a platform to monitor logs'}
277+
showClearSelection={selectedPlatforms.length > 0}
278+
onClearSelection={clearPlatformSelection}
228279
/>
229280
{#if platformsLoading}
230281
<div class="flex justify-center py-8">
@@ -252,6 +303,7 @@
252303
{handlePreviousPage}
253304
{handleNextPage}
254305
onSelectionChange={handlePlatformSelectionChange}
306+
onSelectAllChange={handleSelectAllPlatforms}
255307
/>
256308
{/if}
257309
</TableCard>

platforms/blabsy-w3ds-auth-api/src/controllers/WebhookController.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,15 @@ export class WebhookController {
9292
axios.post(new URL("blabsy", process.env.ANCHR_URL).toString(), req.body)
9393
}
9494

95-
if (adapter.lockedIds.includes(id)) return;
96-
console.log("processing -- not skipped");
95+
// Early duplicate check
96+
if (adapter.lockedIds.includes(id)) {
97+
console.log(`Webhook skipped - ID ${id} already locked`);
98+
return res.status(200).json({ success: true, skipped: true });
99+
}
100+
101+
console.log(`Processing webhook for ID: ${id}`);
102+
103+
// Lock the global ID immediately to prevent duplicates
97104
adapter.addToLockedIds(id);
98105

99106
const mapping = Object.values(adapter.mapping).find(
@@ -105,16 +112,17 @@ export class WebhookController {
105112
const local = await adapter.fromGlobal({ data, mapping });
106113

107114
console.log(local);
108-
//
115+
109116
// Get the local ID from the mapping database
110117
const localId = await adapter.mappingDb.getLocalId(id);
111118

112119
if (localId) {
113-
console.log("LOCAL, updating");
120+
console.log(`LOCAL, updating - ID: ${id}, LocalID: ${localId}`);
121+
// Lock local ID early to prevent duplicate processing
114122
adapter.addToLockedIds(localId);
115123
await this.updateRecord(tableName, localId, local.data);
116124
} else {
117-
console.log("NOT LOCAL, creating");
125+
console.log(`NOT LOCAL, creating - ID: ${id}`);
118126
await this.createRecord(tableName, local.data, req.body.id);
119127
}
120128

platforms/blabsy-w3ds-auth-api/src/index.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import path from "path";
66
import { AuthController } from "./controllers/AuthController";
77
import { initializeApp, cert, applicationDefault } from "firebase-admin/app";
88
import { Web3Adapter } from "./web3adapter";
9-
import { WebhookController } from "./controllers/WebhookController";
9+
import { WebhookController, adapter } from "./controllers/WebhookController";
1010

1111
config({ path: path.resolve(__dirname, "../../../.env") });
1212

@@ -47,6 +47,35 @@ app.post("/api/auth", authController.login);
4747
app.get("/api/auth/sessions/:id", authController.sseStream);
4848
app.post("/api/webhook", webhookController.handleWebhook);
4949

50+
// Debug endpoints for monitoring duplicate prevention
51+
app.get("/api/debug/watcher-stats", (req, res) => {
52+
try {
53+
const stats = web3Adapter.getWatcherStats();
54+
res.json({ success: true, stats });
55+
} catch (error) {
56+
res.status(500).json({ success: false, error: "Failed to get watcher stats" });
57+
}
58+
});
59+
60+
app.post("/api/debug/clear-processed-ids", (req, res) => {
61+
try {
62+
web3Adapter.clearAllProcessedIds();
63+
res.json({ success: true, message: "All processed IDs cleared" });
64+
} catch (error) {
65+
res.status(500).json({ success: false, error: "Failed to clear processed IDs" });
66+
}
67+
});
68+
69+
app.get("/api/debug/locked-ids", (req, res) => {
70+
try {
71+
// Access locked IDs from the exported adapter
72+
const lockedIds = adapter.lockedIds || [];
73+
res.json({ success: true, lockedIds, count: lockedIds.length });
74+
} catch (error) {
75+
res.status(500).json({ success: false, error: "Failed to get locked IDs" });
76+
}
77+
});
78+
5079
// Graceful shutdown
5180
process.on("SIGTERM", async () => {
5281
console.log("SIGTERM received. Shutting down...");

platforms/blabsy-w3ds-auth-api/src/web3adapter/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,4 +104,23 @@ export class Web3Adapter {
104104
console.log(`Successfully restarted watcher for ${collectionName}`);
105105
}
106106
}
107+
108+
// Method to get stats from all watchers
109+
getWatcherStats(): Record<string, { processed: number; processing: number }> {
110+
const stats: Record<string, { processed: number; processing: number }> = {};
111+
for (const [name, watcher] of this.watchers.entries()) {
112+
stats[name] = watcher.getStats();
113+
}
114+
return stats;
115+
}
116+
117+
// Method to clear processed IDs from all watchers
118+
clearAllProcessedIds(): void {
119+
console.log("Clearing processed IDs from all watchers...");
120+
for (const [name, watcher] of this.watchers.entries()) {
121+
console.log(`Clearing processed IDs for ${name}...`);
122+
watcher.clearProcessedIds();
123+
}
124+
console.log("All processed IDs cleared");
125+
}
107126
}

0 commit comments

Comments
 (0)