Implemented presentation and editing for domains.
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 -->
|
||||
|
||||
@@ -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'}));
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user