.
This commit is contained in:
+1
-9
@@ -73,42 +73,34 @@ impl Class {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn fields(&self, language: LanguageTag<&str>) -> Vec<(gl_search::Field, String)> {
|
||||
pub fn fields(&self, language: LanguageTag<String>) -> Vec<(gl_search::Field, String)> {
|
||||
match self {
|
||||
Class::RdfProperty => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("label", Some(language.primary_language())), String::from("Label")),
|
||||
(Schema::field("definition", Some(language.primary_language())), String::from("Definition")),
|
||||
],
|
||||
Class::RdfsClass => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("label", Some(language.primary_language())), String::from("Label")),
|
||||
(Schema::field("definition", Some(language.primary_language())), String::from("Definition")),
|
||||
],
|
||||
Class::SkosConcept => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("label", Some(language.primary_language())), String::from("Label")),
|
||||
(Schema::field("definition", Some(language.primary_language())), String::from("Definition")),
|
||||
],
|
||||
Class::Work => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("title", Some(language.primary_language())), String::from("Title")),
|
||||
],
|
||||
Class::Person => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("given_name", Some(language.primary_language())), String::from("Given Name")),
|
||||
(Schema::field("surname", Some(language.primary_language())), String::from("Surname")),
|
||||
],
|
||||
Class::CorporateBody => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("corporate_body", Some(language.primary_language())), String::from("Corporate Body")),
|
||||
],
|
||||
Class::Expression => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("title", Some(language.primary_language())), String::from("Title")),
|
||||
],
|
||||
Class::Manifestation => vec![
|
||||
(Schema::curie_field(), String::from("CURIE")),
|
||||
(Schema::field("title", Some(language.primary_language())), String::from("Title")),
|
||||
],
|
||||
}
|
||||
|
||||
@@ -6,12 +6,12 @@ use spargebra::algebra::{Expression, Function, GraphPattern};
|
||||
use spargebra::term::{NamedNode, NamedNodePattern, TermPattern, TriplePattern, Variable};
|
||||
use tracing::debug;
|
||||
|
||||
pub const ENGLISH_PRIMARY: &str = "en";
|
||||
pub static ENGLISH_TAG: LazyLock<LanguageTag<String>> = LazyLock::new(|| {
|
||||
LanguageTag::parse("en".to_string()).unwrap()
|
||||
});
|
||||
|
||||
pub static ENGLISH_OR_UNTAGGED: LazyLock<LanguageCondition> = LazyLock::new(|| {
|
||||
LanguageCondition::ExactMatchOrUntagged(
|
||||
LanguageTag::parse(ENGLISH_PRIMARY.to_string()).unwrap(),
|
||||
)
|
||||
LanguageCondition::ExactMatchOrUntagged(ENGLISH_TAG.clone())
|
||||
});
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
+80
-80
@@ -4,31 +4,29 @@ use crate::navigator::Navigator;
|
||||
use crate::rdf::term_helper::{TermHelper, TermHelperMut};
|
||||
use crate::widget::iri_input::iri_input;
|
||||
use crate::widget::navigation_area::navigation_area;
|
||||
use gl_graph::{language, CurieHelper};
|
||||
use gl_graph::{language, CurieHelper, vocab};
|
||||
use gl_search::{Schema, SearchIndex};
|
||||
use http::StatusCode;
|
||||
use iced::alignment::Horizontal;
|
||||
use iced::keyboard::{Event, key};
|
||||
use iced::widget::button::Style;
|
||||
use iced::widget::{
|
||||
button, center, column, combo_box, container, mouse_area, opaque, operation, pick_list,
|
||||
row, scrollable, space, stack, table, text, text_input, toggler,
|
||||
};
|
||||
use iced::widget::{button, center, column, combo_box, container, grid, mouse_area, opaque, operation, pick_list, row, scrollable, space, stack, table, text, text_input, toggler};
|
||||
use iced::window::Settings;
|
||||
use iced::{Background, Color, Element, Length, Subscription, Task, color, keyboard, window};
|
||||
use iced::advanced::text::Wrapping;
|
||||
use iced::widget::grid::Sizing;
|
||||
use ldp::middleware::BasicAuthMiddleware;
|
||||
use ldp::model::{KeyedDataset, QuadKey};
|
||||
use ldp::reqwest::{Client, Url};
|
||||
use ldp::reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
|
||||
use ldp::{RdfSource, RdfSourceUpdateResponse, ResourceRequestBuilder, SerializationOptions};
|
||||
use oxigraph::io::RdfFormat;
|
||||
use oxigraph::model::vocab::{rdf, rdfs};
|
||||
use oxigraph::model::{BaseDirection, Graph, NamedNode, NamedNodeRef, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term, TermRef, Triple, TripleRef};
|
||||
use tracing::{debug, error, trace};
|
||||
use oxigraph::model::{BaseDirection, Graph, NamedNode, NamedOrBlankNode, NamedOrBlankNodeRef, Quad, Term, TermRef, Triple, TripleRef};
|
||||
use tracing::{error, trace};
|
||||
use gl_graph::class::Class;
|
||||
use gl_graph::ontology::{ConnectedOntology, OntologyBuilder, ReadOnlyEntity, ResourceDescription};
|
||||
use gl_search::tantivy::schema::Value;
|
||||
use crate::rdf::conversion::term_to_named_node;
|
||||
use crate::tasks;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@@ -130,7 +128,7 @@ pub(crate) struct Publisher {
|
||||
impl Publisher {
|
||||
fn is_read_only<'a>(&'a self, triple: impl Into<TripleRef<'a>>) -> bool {
|
||||
let triple = triple.into();
|
||||
if triple.predicate == rdf::TYPE &&
|
||||
if triple.predicate == vocab::rdf::TYPE &&
|
||||
let TermRef::NamedNode(node) = triple.object {
|
||||
self.read_only_entities.contains(&ReadOnlyEntity::Class(node.into_owned()))
|
||||
} else {
|
||||
@@ -204,9 +202,14 @@ impl Publisher {
|
||||
}
|
||||
Message::PopulateCaches => {
|
||||
if let Some(ontology) = &mut self.ontology {
|
||||
let classes = Class::ALL.iter().map(|class| {
|
||||
class.to_named_node().into_owned()
|
||||
});
|
||||
|
||||
task = Task::batch([
|
||||
tasks::list_datatypes(ontology.clone()),
|
||||
tasks::list_read_only_entities(ontology.clone()),
|
||||
tasks::lookup_resource_descriptions(ontology.clone(), classes),
|
||||
])
|
||||
}
|
||||
}
|
||||
@@ -287,6 +290,14 @@ impl Publisher {
|
||||
});
|
||||
}
|
||||
Message::LoadDocument(document) => {
|
||||
let nodes_to_look_up = document.dataset().quads.iter().map(|(_, quad)| {
|
||||
let mut nodes = vec![ quad.predicate.clone() ];
|
||||
if let Some(object) = term_to_named_node(&quad.object) {
|
||||
nodes.push(object.clone());
|
||||
}
|
||||
nodes
|
||||
}).flatten().collect();
|
||||
|
||||
let add_row_tasks = document.dataset().quads.iter().map(|(key, quad)| {
|
||||
let datatype_state = combo_box::State::new(self.abbreviated_datatypes.clone());
|
||||
let state = RowState {
|
||||
@@ -295,7 +306,8 @@ impl Publisher {
|
||||
};
|
||||
Task::done(Message::AddRow(Some((key, state))))
|
||||
});
|
||||
task = Task::batch(add_row_tasks)
|
||||
task = Task::done(Message::LookupResourceDescriptions(nodes_to_look_up))
|
||||
.chain(Task::batch(add_row_tasks))
|
||||
.chain(Task::done(Message::RunInference))
|
||||
.chain(Task::done(Message::ResetState));
|
||||
|
||||
@@ -336,11 +348,11 @@ impl Publisher {
|
||||
}
|
||||
Message::OpenQueryWindow(action) => {
|
||||
let selected_entity_class = match action {
|
||||
SearchResultClickAction::Predicate(_) => Some(rdf::PROPERTY),
|
||||
SearchResultClickAction::Predicate(_) => Some(vocab::rdf::PROPERTY),
|
||||
SearchResultClickAction::Object(key) => {
|
||||
self.document.dataset().quads.get(key).and_then(|quad| {
|
||||
if quad.predicate == rdf::TYPE {
|
||||
Some(rdfs::CLASS)
|
||||
if quad.predicate == vocab::rdf::TYPE {
|
||||
Some(vocab::rdfs::CLASS)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
@@ -486,11 +498,11 @@ impl Publisher {
|
||||
let read_only_entities = self.read_only_entities.clone();
|
||||
let options = SerializationOptions::from_format(RdfFormat::Turtle)
|
||||
.with_filter(move |triple| {
|
||||
if triple.predicate == rdf::TYPE &&
|
||||
if triple.predicate == vocab::rdf::TYPE &&
|
||||
let TermRef::NamedNode(node) = triple.object {
|
||||
read_only_entities.contains(&ReadOnlyEntity::Class(node.into_owned()))
|
||||
!read_only_entities.contains(&ReadOnlyEntity::Class(node.into_owned()))
|
||||
} else {
|
||||
read_only_entities.contains(&ReadOnlyEntity::Property(triple.predicate.into_owned()))
|
||||
!read_only_entities.contains(&ReadOnlyEntity::Property(triple.predicate.into_owned()))
|
||||
}
|
||||
});
|
||||
let request = self
|
||||
@@ -526,28 +538,14 @@ impl Publisher {
|
||||
}
|
||||
Message::NewDocument(class) => {
|
||||
let url = Url::parse(self.url_input.as_str()).expect("Invalid URL");
|
||||
let subject = NamedNode::new_unchecked(url.as_str());
|
||||
self.document = RdfSource::new(url);
|
||||
let mut document: RdfSource<KeyedDataset<RowState>> = RdfSource::new(url);
|
||||
let mut quad = document.new_quad();
|
||||
quad.predicate = vocab::rdf::TYPE.into_owned();
|
||||
quad.object = Term::NamedNode(class);
|
||||
document.dataset_mut().quads.insert(quad);
|
||||
|
||||
/*let template_quads = self
|
||||
.ontology
|
||||
.template_triples(class.as_ref(), subject.as_ref())
|
||||
.map(|triples| {
|
||||
triples
|
||||
.map(|triple| self.document.quad_from_triple(triple))
|
||||
.collect::<Vec<_>>()
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
let mut new_quad = self.document.new_quad();
|
||||
new_quad.object = Term::NamedNode(class);
|
||||
vec![new_quad]
|
||||
});
|
||||
|
||||
task = Task::done(Message::HideNewDocumentButtons);
|
||||
|
||||
let new_keys = self.document.dataset_mut().extend(template_quads.into_iter());
|
||||
let messages = new_keys.map(|triple| Message::AddRow(Some(triple)));
|
||||
task = task.chain(Task::batch(messages.map(Task::done)));*/
|
||||
task = Task::done(Message::HideNewDocumentButtons)
|
||||
.chain(Task::done(Message::LoadDocument(document)));
|
||||
}
|
||||
Message::ResetState => {
|
||||
self.modified = false;
|
||||
@@ -763,7 +761,7 @@ impl Publisher {
|
||||
|
||||
let language = term.language().unwrap_or("en").to_owned();
|
||||
let language_input = match term.datatype() {
|
||||
Some(rdf::LANG_STRING) | Some(rdf::DIR_LANG_STRING) => Some(container(
|
||||
Some(vocab::rdf::LANG_STRING) | Some(vocab::rdf::DIR_LANG_STRING) => Some(container(
|
||||
text_input("Language", language).on_input(move |input| {
|
||||
let value = if input.is_empty() { None } else { Some(input) };
|
||||
Message::LanguageUpdated(key, value)
|
||||
@@ -811,28 +809,6 @@ impl Publisher {
|
||||
.into()
|
||||
}
|
||||
|
||||
fn view_new_entity_buttons(
|
||||
&self,
|
||||
entities: impl IntoIterator<Item = ResourceDescription>,
|
||||
) -> Element<'_, Message> {
|
||||
/*let buttons = entities.into_iter().map(|entity| {
|
||||
let abbreviation = self
|
||||
.curie_helper
|
||||
.abbreviate(None, entity.label.as_str())
|
||||
.unwrap_or_else(|| entity.as_str().to_string());
|
||||
|
||||
let label = format!("{} ({})", entity.label, abbreviation);
|
||||
button(text(label))
|
||||
.on_press(Message::NewDocument(entity.iri))
|
||||
.into()
|
||||
});
|
||||
|
||||
grid(buttons)
|
||||
.height(Sizing::EvenlyDistribute(Length::Shrink))
|
||||
.into()*/
|
||||
text("to do").into()
|
||||
}
|
||||
|
||||
pub(crate) fn view(&self, window: window::Id) -> Element<'_, Message> {
|
||||
if let Some(search_state) = &self.search_state
|
||||
&& search_state.window_id == window
|
||||
@@ -847,31 +823,35 @@ impl Publisher {
|
||||
ToString::to_string,
|
||||
).on_select(|selection| Message::UpdateQueryClass(selection));
|
||||
|
||||
let columns = vec![table::column(text("CURIE"), |document: &HashMap<gl_search::Field, gl_search::OwnedValue>| {
|
||||
let mut columns = vec![table::column(text("CURIE"), |document: &HashMap<gl_search::Field, gl_search::OwnedValue>| {
|
||||
let iri = document.get(&Schema::iri_field())
|
||||
.and_then(|value| value.as_str())
|
||||
.unwrap_or_default();
|
||||
|
||||
let abbreviated_iri = self.curie_helper
|
||||
.abbreviate(None, iri)
|
||||
.unwrap_or_else(|| iri.to_string());
|
||||
let abbreviated_iri = document.get(&Schema::curie_field())
|
||||
.and_then(|value| value.as_str())
|
||||
.unwrap_or_default();
|
||||
|
||||
button(text(abbreviated_iri).wrapping(Wrapping::Word))
|
||||
.on_press(Message::SearchResultClicked(NamedNode::new_unchecked(iri)))
|
||||
.style(button::text)
|
||||
})];
|
||||
|
||||
/*for field in {
|
||||
let field_name = field.name.clone();
|
||||
let fields = search_state.entity_class_selection
|
||||
.as_ref()
|
||||
.map(|class| {
|
||||
class.fields(language::ENGLISH_TAG.clone())
|
||||
}).unwrap_or_default();
|
||||
|
||||
for (field, label) in fields {
|
||||
columns.push(
|
||||
table::column(text(field.label), move |document: &SearchDocument| {
|
||||
let iri = document
|
||||
.get_first(Schema::iri_field())
|
||||
table::column(text(label), move |document: &HashMap<gl_search::Field, gl_search::OwnedValue>| {
|
||||
let iri = document.get(&Schema::iri_field())
|
||||
.and_then(|value| value.as_str())
|
||||
.unwrap_or_default();
|
||||
|
||||
let value = document
|
||||
.get_first(Schema::field(&field_name, Some(language::ENGLISH_PRIMARY)))
|
||||
.get(&field)
|
||||
.and_then(|value| value.as_str())
|
||||
.unwrap_or_default();
|
||||
|
||||
@@ -881,7 +861,7 @@ impl Publisher {
|
||||
})
|
||||
.width(Length::Fixed(256.0)),
|
||||
);
|
||||
}*/
|
||||
}
|
||||
|
||||
let results_table = if columns.is_empty() {
|
||||
None
|
||||
@@ -912,15 +892,35 @@ impl Publisher {
|
||||
.map(|(key, quad, state)| self.view_row(key, quad, state))
|
||||
.collect();
|
||||
|
||||
let body: Element<Message> = /*if self.show_new_document_buttons {
|
||||
let subclasses = Vec::new(); // TODO self.ontology.subclasses_of(vocab::rda::ENTITY.into_owned());
|
||||
let labeled_subclasses = subclasses
|
||||
.iter()
|
||||
.map(|iri| self.ontology.info(iri, &*language::ENGLISH_OR_UNTAGGED));
|
||||
column![self.view_new_entity_buttons(labeled_subclasses)].into()
|
||||
} else {*/
|
||||
column(rows).into();
|
||||
//};
|
||||
let body: Element<Message> = if self.show_new_document_buttons {
|
||||
let buttons = Class::ALL.iter()
|
||||
.map(|class| {
|
||||
let node = class.to_named_node().into_owned();
|
||||
let abbreviation = self.curie_helper
|
||||
.abbreviate(None, node.as_str())
|
||||
.unwrap_or(node.to_string());
|
||||
|
||||
let description = self.resource_descriptions
|
||||
.get(&node);
|
||||
|
||||
let button_text = if let Some(description) = description &&
|
||||
let Some(label) = &description.label {
|
||||
format!("{label} ({abbreviation})")
|
||||
} else {
|
||||
abbreviation
|
||||
};
|
||||
|
||||
button(text(button_text))
|
||||
.on_press(Message::NewDocument(node))
|
||||
.into()
|
||||
});
|
||||
|
||||
column![
|
||||
grid(buttons).height(Sizing::EvenlyDistribute(Length::Shrink))
|
||||
].into()
|
||||
} else {
|
||||
column(rows).into()
|
||||
};
|
||||
|
||||
let inference_table = if self.show_inferred_triples {
|
||||
let subject_column = table::column("Subject", |triple: TripleRef| {
|
||||
|
||||
Reference in New Issue
Block a user