Implemented presentation and editing for domains.

This commit is contained in:
Revertron
2021-04-15 12:21:41 +02:00
parent da15a02e11
commit 9b093a8172
6 changed files with 139 additions and 2 deletions
+32
View File
@@ -40,6 +40,7 @@ const SQL_GET_LAST_FULL_BLOCK_FOR_KEY: &str = "SELECT * FROM blocks WHERE `trans
const SQL_GET_DOMAIN_PUBLIC_KEY_BY_ID: &str = "SELECT pub_key FROM domains WHERE identity = ? ORDER BY id DESC LIMIT 1;";
const SQL_GET_ZONE_PUBLIC_KEY_BY_ID: &str = "SELECT pub_key FROM zones WHERE identity = ? ORDER BY id DESC LIMIT 1;";
const SQL_GET_DOMAIN_BY_ID: &str = "SELECT * FROM domains WHERE identity = ? ORDER BY id DESC LIMIT 1;";
const SQL_GET_DOMAINS_BY_KEY: &str = "SELECT * FROM domains WHERE pub_key = ?;";
const SQL_GET_ZONES: &str = "SELECT data FROM zones;";
const SQL_GET_OPTIONS: &str = "SELECT * FROM options;";
@@ -521,6 +522,37 @@ impl Chain {
}
}
pub fn get_my_domains(&self, keystore: &Option<Keystore>) -> HashMap<String, (i64, DomainData)> {
if keystore.is_none() {
return HashMap::new();
}
let mut result = HashMap::new();
let keystore = keystore.clone().unwrap();
let pub_key = keystore.get_public();
let mut statement = self.db.prepare(SQL_GET_DOMAINS_BY_KEY).unwrap();
statement.bind(1, &**pub_key).expect("Error in bind");
while let State::Row = statement.next().unwrap() {
let index = statement.read::<i64>(0).unwrap() as u64;
let timestamp = statement.read::<i64>(1).unwrap();
let identity = Bytes::from_bytes(&statement.read::<Vec<u8>>(2).unwrap());
let confirmation = Bytes::from_bytes(&statement.read::<Vec<u8>>(3).unwrap());
let class = String::from("domain");
let data = statement.read::<String>(4).unwrap();
let pub_key = Bytes::from_bytes(&statement.read::<Vec<u8>>(5).unwrap());
let transaction = Transaction { identity, confirmation, class, data, pub_key };
//debug!("Found transaction for domain {}: {:?}", domain, &transaction);
if let Some(data) = transaction.get_domain_data() {
let b = self.get_block(index - 1).unwrap();
let domain = keystore.decrypt(data.domain.as_slice(), &b.hash.as_slice()[..12]);
let domain = String::from_utf8(domain.to_vec()).unwrap();
trace!("Found my domain {}", domain);
result.insert(domain, (timestamp, data));
}
}
result
}
pub fn get_zone_difficulty(&self, zone: &str) -> u32 {
let zones = self.get_zones();
for z in zones.iter() {
+7
View File
@@ -129,6 +129,7 @@ fn main() {
create_genesis_if_needed(&context, &miner);
if no_gui {
print_my_domains(&context);
let sleep = Duration::from_millis(1000);
loop {
thread::sleep(sleep);
@@ -145,6 +146,12 @@ fn main() {
}
}
fn print_my_domains(context: &Arc<Mutex<Context>>) {
let context = context.lock().unwrap();
let domains = context.chain.get_my_domains(&context.keystore);
debug!("Domains: {:?}", &domains);
}
fn create_genesis_if_needed(context: &Arc<Mutex<Context>>, miner: &Arc<Mutex<Miner>>) {
// If there is no origin in settings and no blockchain in DB, generate genesis block
let context = context.lock().unwrap();
+23 -2
View File
@@ -4,7 +4,7 @@ extern crate serde;
extern crate serde_json;
extern crate open;
use std::sync::{Arc, Mutex};
use std::sync::{Arc, Mutex, MutexGuard};
use std::thread;
use std::time::{Duration, Instant};
@@ -195,6 +195,7 @@ fn action_loaded(context: &Arc<Mutex<Context>>, web_view: &mut WebView<()>) {
let status = Arc::new(Mutex::new(Status::new(threads)));
let context_copy = Arc::clone(&context);
let mut c = context.lock().unwrap();
c.bus.register(move |_uuid, e| {
//debug!("Got event from bus {:?}", &e);
let status = Arc::clone(&status);
@@ -202,9 +203,10 @@ fn action_loaded(context: &Arc<Mutex<Context>>, web_view: &mut WebView<()>) {
let context_copy = Arc::clone(&context_copy);
let _ = thread::Builder::new().name(String::from("webui")).spawn(move || {
let mut status = status.lock().unwrap();
let context = context_copy.lock().unwrap();
let mut context = context_copy.lock().unwrap();
let eval = match e {
Event::KeyCreated { path, public, hash } => {
load_domains(&mut context, &handle);
event_handle_luck(&handle, "Key successfully created! Don\\'t forget to save it!");
let mut s = format!("keystoreChanged('{}', '{}', '{}');", &path, &public, &hash);
s.push_str(" showSuccess('New key mined successfully! Save it to a safe place!')");
@@ -212,6 +214,7 @@ fn action_loaded(context: &Arc<Mutex<Context>>, web_view: &mut WebView<()>) {
}
Event::KeyLoaded { path, public, hash } |
Event::KeySaved { path, public, hash } => {
load_domains(&mut context, &handle);
format!("keystoreChanged('{}', '{}', '{}');", &path, &public, &hash)
}
Event::MinerStarted | Event::KeyGeneratorStarted => {
@@ -319,6 +322,24 @@ fn action_loaded(context: &Arc<Mutex<Context>>, web_view: &mut WebView<()>) {
event_info(web_view, "Application loaded");
}
fn load_domains(context: &mut MutexGuard<Context>, handle: &Handle<()>) {
let _ = handle.dispatch(move |web_view|{
web_view.eval("clearMyDomains();")
});
let domains = context.chain.get_my_domains(&context.keystore);
debug!("Domains: {:?}", &domains);
for (domain, (timestamp, data)) in domains {
let d = serde_json::to_string(&data).unwrap();
let command = format!("addMyDomain('{}', {}, '{}');", &domain, timestamp, &d);
let _ = handle.dispatch(move |web_view|{
web_view.eval(&command)
});
}
let _ = handle.dispatch(move |web_view|{
web_view.eval("refreshMyDomains();")
});
}
fn action_create_domain(context: Arc<Mutex<Context>>, miner: Arc<Mutex<Miner>>, web_view: &mut WebView<()>, name: String, data: String) {
debug!("Creating domain with data: {}", &data);
let c = Arc::clone(&context);
+4
View File
@@ -116,6 +116,10 @@
<div class="list pb-3" id="domain_records">
<!-- Here will be our domain records, added by dialog -->
</div>
<div id="my_domains" class="container is-fluid cards-container">
<!-- Here will be our domains -->
</div>
</div>
<!-- Zone mining -->
+52
View File
@@ -1,5 +1,6 @@
var recordsBuffer = [];
var availableZones = [];
var myDomains = [];
var currentZone;
function addRecord(record) {
@@ -96,6 +97,57 @@ function get_record_from_dialog() {
return { type: record_type, domain: record_name, ttl: record_ttl, addr: record_data }
}
function clearMyDomains() {
myDomains = [];
}
function addMyDomain(name, timestamp, data) {
myDomains.push({name: name, timestamp: timestamp, data: data});
}
function refreshMyDomains() {
var edit_icon = '<svg viewBox="0 0 24 24" class="tag-button" onclick="editDomain(\'{domain}\');"><path d="M21.04 12.13C21.18 12.13 21.31 12.19 21.42 12.3L22.7 13.58C22.92 13.79 22.92 14.14 22.7 14.35L21.7 15.35L19.65 13.3L20.65 12.3C20.76 12.19 20.9 12.13 21.04 12.13M19.07 13.88L21.12 15.93L15.06 22H13V19.94L19.07 13.88M11 19L9 21H5C3.9 21 3 20.1 3 19V5C3 3.9 3.9 3 5 3H9.18C9.6 1.84 10.7 1 12 1C13.3 1 14.4 1.84 14.82 3H19C20.1 3 21 3.9 21 5V9L19 11V5H17V7H7V5H5V19H11M12 3C11.45 3 11 3.45 11 4C11 4.55 11.45 5 12 5C12.55 5 13 4.55 13 4C13 3.45 12.55 3 12 3Z"></path></svg>';
var card = '<div class="card is-inline-block"><div class="card-content p-3"><div class="content is-small"><h3>{title}</h3><div class="tags">{tags}{edit}</div></div></div></div>';
var tag = '<span class="tag" title="{ip}">{domain}</span>';
var cards = "";
myDomains.forEach(function(value, index, array) {
var title = value.name;
var domain_data = JSON.parse(value.data);
var tags = "";
var edit = edit_icon.replace("{domain}", title);
domain_data.records.forEach(function(v, i, a) {
if (typeof v.domain !== 'undefined') {
var buf = tag.replace("{domain}", v.domain);
if (typeof v.addr !== 'undefined') {
buf = buf.replace("{ip}", v.addr);
} else if (typeof v.host !== 'undefined') {
buf = buf.replace("{ip}", v.host);
}
tags = tags + buf;
}
});
cards = cards + card.replace("{title}", title).replace("{tags}", tags).replace("{edit}", edit);
});
document.getElementById("my_domains").innerHTML = cards;
}
function editDomain(domain) {
myDomains.forEach(function(value, index, array) {
if (domain != value.name) {
return;
}
var title = value.name;
var domain_data = JSON.parse(value.data);
recordsBuffer = [];
domain_data.records.forEach(function(v, i, a) {
recordsBuffer.push(v);
});
document.getElementById("new_domain").value = title.replace("." + domain_data.zone, "");
changeZone(domain_data.zone);
refreshRecordsList();
});
}
function onLoad() {
external.invoke(JSON.stringify({cmd: 'loaded'}));
}
+21
View File
@@ -63,6 +63,21 @@ body {
right: 10pt;
}
.container.is-fluid.cards-container {
display: flex;
flex-grow: 0;
/*gap: .8em; supported only in Firefox/Edge/Chrome */
justify-content: center !important;
padding-left: 0 !important;
padding-right: 0 !important;
margin-left: 0 !important;
margin-right: 0 !important;
}
.container.is-fluid.cards-container .card:not(:last-child) {
margin-right: 0.8rem;
}
.list {
overflow-y: auto;
}
@@ -85,4 +100,10 @@ path {
.is-danger:hover > span.icon > svg > path {
fill: #ffffff;
}
svg.tag-button {
width: 24px;
height: 24px;
margin-bottom: .5rem;
}