Skip to content

Commit 3dbaa1e

Browse files
committed
Add delete version button
1 parent 596f9d1 commit 3dbaa1e

File tree

4 files changed

+126
-8
lines changed

4 files changed

+126
-8
lines changed

client/interactive/client.tcss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
ListKeysWidget #list-keys {
1+
DownloadNotification #list-keys {
22
layout: horizontal;
33
color: red;
44
}

client/interactive/db_connection.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,10 @@ def listVersions(stub, collection, key):
7979
assertSuccess(reply)
8080
return reply.versions
8181

82+
def deleteVersion(stub, collection, key, version):
83+
reply = stub.Delete(proto.DeleteRequest(collection=collection, key=key, version=version))
84+
assertSuccess(reply)
85+
8286

8387
def main():
8488
stub = connect()

client/interactive/modal.tcss

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
DownloadNotification {
2+
align: center middle;
3+
}
4+
5+
#dialog {
6+
padding: 0 1;
7+
margin: 5;
8+
width: 100;
9+
height: 11;
10+
border: thick $background 80%;
11+
background: $surface;
12+
}
13+
14+
#question {
15+
column-span: 2;
16+
height: 1fr;
17+
width: 1fr;
18+
content-align: center middle;
19+
}
20+
21+
#okay {
22+
margin: 3 0 0 0;
23+
}
24+
25+
Button {
26+
width: 100%;
27+
}

client/interactive/record_explorer.py

Lines changed: 94 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
from protobuf_decoder.protobuf_decoder import Parser
2-
from textual.widgets import Label, Static, Collapsible, Rule, Button, TextArea
3-
from textual.containers import Horizontal, Vertical
2+
from textual.app import ComposeResult
3+
from textual.reactive import reactive
4+
from textual.screen import Screen
5+
from textual.widgets import Label, Static, Collapsible, Rule, Button, OptionList
6+
from textual.widgets.option_list import Option
7+
from textual.containers import Horizontal, Vertical, Grid
48
import json
59

6-
from db_connection import getKey, listVersions
10+
from db_connection import deleteVersion, getKey, listVersions
711

812
class ProtobufDecoder():
913
def __init__(self):
@@ -28,9 +32,37 @@ def __init__(self, stub, key: str, collection: str, **kwargs):
2832
except Exception as e:
2933
print("Could not load versions: " + str(e))
3034

35+
selected_version = reactive(0)
36+
37+
cached_data = {}
3138
def get_data(self):
32-
data = getKey(self.stub, self.collection, self.key, self.selected_version)
33-
return data
39+
if self.selected_version in self.cached_data:
40+
return self.cached_data[self.selected_version]
41+
self.cached_data[self.selected_version] = getKey(self.stub, self.collection, self.key, self.selected_version)
42+
return self.cached_data[self.selected_version]
43+
44+
def get_filename(self):
45+
return f"{self.collection}_{self.key}_{self.selected_version}.bin"
46+
47+
def download_data(self):
48+
data = self.get_data()
49+
with open(self.get_filename(), "wb") as f:
50+
f.write(data)
51+
self.app.push_screen(DownloadNotification(filename=self.get_filename()))
52+
53+
def delete_data(self):
54+
async def delete_callback(result: bool):
55+
if result:
56+
deleteVersion(self.stub, self.collection, self.key, self.selected_version)
57+
self.versions = listVersions(self.stub, self.collection, self.key)
58+
self.versions.sort()
59+
if len(self.versions) == 0:
60+
self.app.pop_screen()
61+
else:
62+
self.selected_version = self.versions[-1]
63+
await self.recompose()
64+
65+
self.app.push_screen(DeleteModal(stub=self.stub, collection=self.collection, key=self.key, version=self.selected_version), delete_callback)
3466

3567
def display_record(self):
3668
data = self.get_data()
@@ -97,7 +129,8 @@ def render_info_panel(self):
97129
return Vertical(
98130
Static(f"Exploring record/wire for {self.collection}:{self.key}. Currently viewing version {self.selected_version}"),
99131
Rule(),
100-
Button("Download selected version"),
132+
Button("Download selected version", id="download_button"),
133+
Button("Delete selected version", id="delete_button"),
101134
Rule(),
102135
*self.render_version_buttons(),
103136
id = "record_explorer_info_panel"
@@ -109,7 +142,61 @@ def compose(self):
109142
yield self.display_record()
110143
yield self.render_info_panel()
111144

112-
145+
async def on_button_pressed(self, event):
146+
if event.button.id.startswith("version_"):
147+
version = int(event.button.id.split("_")[1])
148+
self.selected_version = version
149+
await self.recompose()
150+
if event.button.id == "download_button":
151+
self.download_data()
152+
if event.button.id == "delete_button":
153+
self.delete_data()
154+
155+
156+
class DownloadNotification(Screen):
157+
"""Screen with a note on where the downloaded file is stored."""
158+
159+
CSS_PATH = "modal.tcss"
160+
161+
def __init__(self, name = None, id = None, classes = None, filename = None, **kwargs):
162+
super().__init__(name, id, classes)
163+
self.filename = filename
164+
165+
def compose(self) -> ComposeResult:
166+
yield Vertical(
167+
Label(f"The version has been stored in {self.filename}", id="note"),
168+
Button("Okay", variant="primary", id="okay"),
169+
id="dialog",
170+
)
171+
172+
def on_button_pressed(self, event: Button.Pressed) -> None:
173+
if event.button.id == "okay":
174+
self.app.pop_screen()
175+
176+
class DeleteModal(Screen):
177+
"""Screen with a note on where the downloaded file is stored."""
178+
179+
CSS_PATH = "modal.tcss"
180+
181+
def __init__(self, name = None, id = None, classes = None,collection = None, key = None, version = None, **kwargs):
182+
super().__init__(name, id, classes)
183+
self.collection = collection
184+
self.key = key
185+
self.version = version
186+
187+
def compose(self) -> ComposeResult:
188+
yield Vertical(
189+
Label(f"Are you sure you want to delete version {self.version} of {self.collection}:{self.key}?", id="note"),
190+
Button("Yes", variant="error", id="yes"),
191+
Button("No", variant="primary", id="no"),
192+
id="dialog",
193+
)
194+
195+
def on_button_pressed(self, event: Button.Pressed) -> None:
196+
if event.button.id == "yes":
197+
self.dismiss(True)
198+
if event.button.id == "no":
199+
self.dismiss(False)
113200

114201
if __name__ == "__main__":
115202
print("Running decoder demo!")

0 commit comments

Comments
 (0)