.
This commit is contained in:
+55
-100
@@ -1,7 +1,6 @@
|
||||
use crate::rdf::ontology::{LabeledIri, Ontology};
|
||||
use crate::rdf::term_helper::{TermHelper, TermHelperMut};
|
||||
use crate::rdf::vocab::{gl, rda};
|
||||
use gl_search::{Schema, SearchDocument, SearchIndex, NamedFieldDocument, OwnedValue, doc, IndexWriter};
|
||||
use gl_search::{Schema, SearchDocument, SearchIndex, doc, IndexWriter};
|
||||
use http::StatusCode;
|
||||
use iced::alignment::Horizontal;
|
||||
use iced::widget::button::Style;
|
||||
@@ -9,7 +8,6 @@ use iced::widget::grid::Sizing;
|
||||
use iced::widget::{button, center, column, combo_box, container, grid, mouse_area, opaque, pick_list, row, scrollable, space, stack, table, text, text_input, toggler};
|
||||
use iced::window::Settings;
|
||||
use iced::{Background, Color, Element, Length, Subscription, Task, color, window};
|
||||
use iced::widget::text::Wrapping;
|
||||
use ldp::middleware::BasicAuthMiddleware;
|
||||
use ldp::model::{KeyedDataset, QuadKey};
|
||||
use ldp::reqwest::{Client, Url};
|
||||
@@ -19,10 +17,11 @@ use ldp::{RdfSource, RdfSourceUpdateResponse, ResourceRequestBuilder, Serializat
|
||||
use oxigraph::io::RdfFormat;
|
||||
use oxigraph::model::vocab::{rdf, rdfs};
|
||||
use oxigraph::model::{BaseDirection, Dataset, NamedNode, Quad, Term, TermRef};
|
||||
use tracing::{debug, error, info, info_span, span, Level};
|
||||
use tracing::{debug_span, error, trace};
|
||||
use crate::rdf::conversion;
|
||||
use crate::widget::iri_input::iri_input;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) enum Message {
|
||||
None,
|
||||
Traverse,
|
||||
@@ -43,7 +42,7 @@ pub(crate) enum Message {
|
||||
HoverRow(QuadKey),
|
||||
UnhoverRow(QuadKey),
|
||||
QueryUpdated(String),
|
||||
SetSearchResults(Vec<NamedFieldDocument>),
|
||||
SetSearchResults(Vec<SearchDocument>),
|
||||
QueryTypeUpdated(NamedNode),
|
||||
SearchResultClicked(NamedNode),
|
||||
DatatypeUpdated(QuadKey, Option<String>),
|
||||
@@ -76,7 +75,7 @@ struct SearchState {
|
||||
action: SearchResultClickAction,
|
||||
query: String,
|
||||
type_: LabeledIri,
|
||||
results: Vec<NamedFieldDocument>,
|
||||
results: Vec<SearchDocument>,
|
||||
}
|
||||
|
||||
pub(crate) struct Publisher {
|
||||
@@ -97,32 +96,31 @@ pub(crate) struct Publisher {
|
||||
|
||||
impl Publisher {
|
||||
pub(crate) fn new() -> (Self, Task<Message>) {
|
||||
let ontology = info_span!("Ontology Creation").in_scope(|| {
|
||||
let ontology = debug_span!("Ontology Creation").in_scope(|| {
|
||||
Ontology::builder()
|
||||
.with_path("/home/alex/.local/share/org.graphofliberty.desktop/ontology")
|
||||
.build()
|
||||
.expect("Failed to build ontology")
|
||||
});
|
||||
|
||||
let index = info_span!("Ontology Indexing").in_scope(|| {
|
||||
let mut index = SearchIndex::builder()
|
||||
//.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
|
||||
.build()
|
||||
.expect("Failed to build search index");
|
||||
let index = SearchIndex::builder()
|
||||
//.with_path("/home/alex/.local/share/org.graphofliberty.desktop/index")
|
||||
.build()
|
||||
.expect("Failed to build search index");
|
||||
|
||||
let writer = index.writer().expect("Failed to create search index writer");
|
||||
|
||||
let classes_to_index = [
|
||||
rdf::PROPERTY,
|
||||
rdfs::CLASS,
|
||||
];
|
||||
let classes_to_index = [
|
||||
rdf::PROPERTY,
|
||||
rdfs::CLASS,
|
||||
];
|
||||
|
||||
debug_span!("Ontology Indexing").in_scope(|| {
|
||||
let mut writer = index.writer().expect("Failed to build index writer");
|
||||
for class in &classes_to_index {
|
||||
let class = class.into_owned();
|
||||
if let Some(id) = ontology.catalog_id(&class) {
|
||||
index.remove_all_of_type(id).expect("Failed to remove documents from search index");
|
||||
writer.remove_all_of_type(id).expect("Failed to remove documents from search index");
|
||||
for individual in ontology.individuals(&class) {
|
||||
let info = ontology.info(&individual);
|
||||
let info = ontology.info(&individual, &conversion::english());
|
||||
if info.label.is_some() || info.comment.is_some() {
|
||||
let mut document = doc!(
|
||||
Schema::type_field() => id,
|
||||
@@ -137,13 +135,12 @@ impl Publisher {
|
||||
document.add_text(Schema::field(&field.name), info.comment.unwrap_or_default());
|
||||
}
|
||||
|
||||
writer.add_document(document).expect("Failed to add document to search index");
|
||||
writer.add(document).expect("Failed to add document to search index");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
index
|
||||
writer.commit().expect("Failed to commit changes to search index");
|
||||
});
|
||||
|
||||
let mut abbreviated_datatypes = ontology
|
||||
@@ -187,7 +184,7 @@ impl Publisher {
|
||||
|
||||
pub(crate) fn update(&mut self, message: Message) -> Task<Message> {
|
||||
let mut task = Task::none();
|
||||
debug!(?message);
|
||||
trace!(?message);
|
||||
|
||||
match message {
|
||||
Message::Traverse => {
|
||||
@@ -223,13 +220,14 @@ impl Publisher {
|
||||
}
|
||||
|
||||
if let Some(writer) = &self.index_writer {
|
||||
writer.add_document(document).expect("Unable to add document to search index");
|
||||
writer.add(document).expect("Unable to add document to search index");
|
||||
}
|
||||
}
|
||||
}
|
||||
Message::CommitIndex => {
|
||||
if let Some(writer) = &mut self.index_writer {
|
||||
writer.commit().expect("Unable to commit updates to search index");
|
||||
self.index_writer = None;
|
||||
}
|
||||
}
|
||||
Message::WindowClosed(id) => {
|
||||
@@ -368,15 +366,20 @@ impl Publisher {
|
||||
SearchResultClickAction::URLInput => self.ontology.catalog_id(&search_state.type_.iri),
|
||||
};
|
||||
|
||||
search_state.query = new_query.clone();
|
||||
let index = self.index.clone();
|
||||
task = Task::future(async move {
|
||||
tokio::task::spawn_blocking(move || {
|
||||
let result = index.query(catalog_id, new_query.as_str(), Schema::all_fields())
|
||||
.expect("Error encountered while querying index");
|
||||
Message::SetSearchResults(result)
|
||||
}).await.unwrap()
|
||||
let query = new_query.clone();
|
||||
let search_task = tokio::task::spawn_blocking(move || {
|
||||
index.query(catalog_id, query.as_str(), Schema::all_fields(), 25)
|
||||
});
|
||||
task = Task::future(async {
|
||||
match search_task.await {
|
||||
Ok(Ok(documents)) => Message::SetSearchResults(documents),
|
||||
Ok(Err(err)) => Message::ShowError(err.to_string()),
|
||||
Err(err) => Message::ShowError(err.to_string()),
|
||||
}
|
||||
});
|
||||
|
||||
search_state.query = new_query;
|
||||
};
|
||||
}
|
||||
Message::SetSearchResults(results) => {
|
||||
@@ -551,11 +554,11 @@ impl Publisher {
|
||||
container(space()).width(BUTTON_WIDTH)
|
||||
};
|
||||
|
||||
let property_label = "foo"; /*self
|
||||
let property_label = self
|
||||
.ontology
|
||||
.info(triple.predicate.as_ref())
|
||||
.and_then(|info| info.label.clone())
|
||||
.unwrap_or(self.ontology.abbreviate(triple.predicate.as_ref()));*/
|
||||
.info(&triple.predicate, &conversion::english())
|
||||
.label
|
||||
.unwrap_or(self.ontology.abbreviate(triple.predicate.as_ref()));
|
||||
|
||||
let property: Element<Message> = if state.read_only {
|
||||
text(property_label).into()
|
||||
@@ -572,14 +575,13 @@ impl Publisher {
|
||||
|
||||
let value_label = term.value_as_named_node().and_then(|node| {
|
||||
self.ontology
|
||||
.info(&node.into_owned())
|
||||
.info(&node.into_owned(), &conversion::english())
|
||||
.label
|
||||
.map(|label| container(text(label)))
|
||||
});
|
||||
|
||||
let value = term
|
||||
.value_as_named_node()
|
||||
//.map(|node| self.ontology.abbreviate(node))
|
||||
.map(|node| node.as_str().to_string())
|
||||
.unwrap_or(term.value().to_string());
|
||||
|
||||
@@ -591,7 +593,8 @@ impl Publisher {
|
||||
})
|
||||
.unwrap_or(Horizontal::Left);
|
||||
|
||||
let foo = iri_input(self.ontology.prefixes(), "Object", value.as_str())
|
||||
let object_input = iri_input(self.ontology.prefixes(), "Object", value.as_str())
|
||||
.align_x(value_alignment)
|
||||
.on_input(move |value| Message::ValueUpdated(key, value))
|
||||
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::Object(key)));
|
||||
|
||||
@@ -608,8 +611,7 @@ impl Publisher {
|
||||
.on_input(move |input| {
|
||||
let value = if input.is_empty() { None } else { Some(input) };
|
||||
Message::DatatypeUpdated(key, value)
|
||||
})
|
||||
.into()
|
||||
}).into()
|
||||
};
|
||||
|
||||
let language_input = match term.datatype() {
|
||||
@@ -647,9 +649,7 @@ impl Publisher {
|
||||
button_area,
|
||||
property,
|
||||
value_label,
|
||||
//value_input,
|
||||
foo,
|
||||
//search_launcher,
|
||||
object_input,
|
||||
datatype_selector,
|
||||
language_input,
|
||||
direction_slider,
|
||||
@@ -668,7 +668,7 @@ impl Publisher {
|
||||
let buttons = entities.map(|entity| {
|
||||
let label = self
|
||||
.ontology
|
||||
.info(&entity)
|
||||
.info(&entity, &conversion::english())
|
||||
.label
|
||||
.unwrap_or(entity.as_str().to_string());
|
||||
button(text(label))
|
||||
@@ -699,17 +699,15 @@ impl Publisher {
|
||||
let mut columns = vec![];
|
||||
for field in self.ontology.fields_for_class(&search_state.type_.iri) {
|
||||
let header_text = field.label.as_ref().unwrap_or(&field.name);
|
||||
columns.push(table::column(text(header_text), |document: &NamedFieldDocument| {
|
||||
let cell_value = document.0
|
||||
.get(&field.name)
|
||||
/*columns.push(table::column(text(header_text), |document: &QueryResult| {
|
||||
let cell_value = document.0.get(&field.name)
|
||||
.and_then(|values| values.first())
|
||||
.map(|value| match value {
|
||||
OwnedValue::Str(string) => string,
|
||||
_ => "???",
|
||||
}).unwrap_or("");
|
||||
|
||||
let iri = document.0
|
||||
.get("iri")
|
||||
let iri = document.get("iri")
|
||||
.and_then(|values| values.first())
|
||||
.map(|value| match value {
|
||||
OwnedValue::Str(string) => string,
|
||||
@@ -719,50 +717,9 @@ impl Publisher {
|
||||
button(text(cell_value).wrapping(Wrapping::Word))
|
||||
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
|
||||
.style(button::text)
|
||||
}).width(Length::Fixed(256.0)));
|
||||
}).width(Length::Fixed(256.0)));*/
|
||||
}
|
||||
|
||||
/*let label_column = table::column("Label", |result: &NamedNode| {
|
||||
let header_text = self
|
||||
.ontology
|
||||
.info(result.as_ref())
|
||||
.and_then(|info| info.label.clone())
|
||||
.unwrap_or("".to_string());
|
||||
|
||||
button(text(header_text))
|
||||
.on_press(Message::SearchResultClicked(result.clone()))
|
||||
.style(button::text)
|
||||
});
|
||||
|
||||
let type_column = table::column("Type", |result: &NamedNode| {
|
||||
let header_text = self
|
||||
.ontology
|
||||
.info(result.as_ref())
|
||||
.and_then(|info| self.ontology.info(info.type_.as_ref()))
|
||||
.and_then(|info| info.label.clone())
|
||||
.unwrap_or("Unknown".to_string());
|
||||
|
||||
button(text(header_text))
|
||||
.on_press(Message::SearchResultClicked(result.clone()))
|
||||
.style(button::text)
|
||||
});
|
||||
|
||||
let description_column = table::column("Description", |result: &NamedNode| {
|
||||
let header_text = self.ontology.info(result.as_ref())
|
||||
.and_then(|info| info.comment.clone())
|
||||
.unwrap_or("Unknown".to_string());
|
||||
|
||||
button(text(header_text))
|
||||
.on_press(Message::SearchResultClicked(result.clone()))
|
||||
.style(button::text)
|
||||
});
|
||||
|
||||
let iri_column = table::column("IRI", |result: &NamedNode| {
|
||||
button(text(result.as_str()))
|
||||
.on_press(Message::SearchResultClicked(result.clone()))
|
||||
.style(button::text)
|
||||
});*/
|
||||
|
||||
let results_table = if columns.is_empty() {
|
||||
None
|
||||
} else {
|
||||
@@ -779,9 +736,10 @@ impl Publisher {
|
||||
|
||||
let index_button = button("Index").on_press(Message::Traverse);
|
||||
|
||||
let search_launcher = button(text("\u{1f50e}"))
|
||||
.on_press(Message::OpenQueryWindow(SearchResultClickAction::URLInput))
|
||||
.style(button::text);
|
||||
let address_input = iri_input(self.ontology.prefixes(), "URL", &self.url_input)
|
||||
.on_input(Message::URLInputChanged)
|
||||
.on_submit(Message::URLInputSubmitted)
|
||||
.on_control_click(Message::OpenQueryWindow(SearchResultClickAction::URLInput));
|
||||
|
||||
let mut rows: Vec<Element<Message>> = vec![];
|
||||
rows = self
|
||||
@@ -812,10 +770,7 @@ impl Publisher {
|
||||
row![
|
||||
add_row_button,
|
||||
index_button,
|
||||
search_launcher,
|
||||
text_input("URL", &self.url_input)
|
||||
.on_input(Message::URLInputChanged)
|
||||
.on_submit(Message::URLInputSubmitted),
|
||||
address_input,
|
||||
save_button,
|
||||
],
|
||||
scrollable(body),
|
||||
|
||||
Reference in New Issue
Block a user