Skip to content

Commit

Permalink
Update VALVE, improve list() handling and JavaScript
Browse files Browse the repository at this point in the history
  • Loading branch information
jamesaoverton committed Jul 29, 2024
1 parent a97f6b5 commit c1ceafd
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 82 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ rev = "f46fbd5450505644ed9970cef1ae14164699981f"
[dependencies.ontodev_valve]
# path = "../ontodev_demo/valve.rs"
git = "https://github.com/ontodev/valve.rs"
rev = "1858972dec231f874c87f3fd930cbeef47a444d3"
rev = "6025da044de289861973a62f83484d9cca03c78f"

[dependencies.ontodev_sqlrest]
git = "https://github.com/ontodev/sqlrest.rs"
Expand Down
53 changes: 40 additions & 13 deletions src/javascript/src/App.js
Original file line number Diff line number Diff line change
@@ -1,40 +1,67 @@
import { AsyncTypeahead } from 'react-bootstrap-typeahead';
import { useState } from 'react';
import { createRef, useState } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.css';
import 'react-bootstrap-typeahead/css/Typeahead.css';

function App() {
const table = document.getElementById("root").getAttribute("data-table");
const column = document.getElementById("root").getAttribute("data-column");
function App(args) {
// console.log("Starting App for", args, args.id, args.table, args.column);
const [isLoading, setIsLoading] = useState(false);
const [options, setOptions] = useState([]);

const handleSearch = (query: string) => {
// console.log("Starting search for", query);
setIsLoading(true);
console.log("FETCH", `/table?text=${query}&column=type&format=json`);
fetch(`/${table}?text=${query}&column=${column}&format=json`)
const url = `../../${args.table}?text=${query}&column=${args.column}&format=json`;
// console.log("URL", url);
fetch(url)
.then((resp) => resp.json())
.then((items) => {
// console.log("ITEMS", items);
setOptions(items);
setIsLoading(false);
});
};
// console.log("Starting App for", args, args.id, args.table, args.column);
const ref = createRef();
var value = args.value;
var selected = [{"id": args.value, "label": args.value, "order": 1}];
if (args.multiple) {
value = "";
selected = args.value.trim().split(" ").filter((item) => {
return item.trim() !== "";
}).map((item, order) => {
return {"id": item, "label": item, "order": order}
});
}
return (
<div className="App">
<AsyncTypeahead
ref={ref}
inputProps={{"name": args.name}}
minLength={0}
multiple={args.multiple}
isLoading={isLoading}
isValid={args.isValid}
isInvalid={!args.isValid}
onChange={(selected) => {
// console.log("SELECTED", selected);
// Set value of original input element to selected value.
var values = selected.map((item) => item.id);
// console.log("VALUES", values);
var value = values.join(" ");
// console.log("VALUE", value);
document.getElementById("root-value").value = value;
document.getElementById(args.id).value = values.join(" ");
}}
onFocus={(event) => {
// Search for current values.
handleSearch(event.target.value);
}}
onBlur={(event) => {
// Set value of original input element to an invalid/incomplete value.
if (!args.multiple) {
document.getElementById(args.id).value = event.target.value;
}
}}
onSearch={handleSearch}
defaultInputValue={value}
defaultSelected={selected}
options={options}
multiple="true"
/>
</div>
);
Expand Down
31 changes: 25 additions & 6 deletions src/javascript/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,28 @@ import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
var typeaheads = document.getElementsByClassName('typeahead');

// console.log('TYPEAHEADS', typeaheads);
for (var i=0; i < typeaheads.length; i++) {
const typeahead = typeaheads[i];
if (typeahead.tagName.toLowerCase() !== "input") {
continue;
}
// console.log('TYPEAHEAD', typeahead.id);
const div = document.createElement("div");
typeahead.setAttribute("type", "hidden");
typeahead.parentNode.insertBefore(div, typeahead);
const root = ReactDOM.createRoot(div);
root.render(
<React.StrictMode>
<App
id={typeahead.id}
value={typeahead.getAttribute("value")}
table={typeahead.getAttribute("data-table")}
column={typeahead.getAttribute("data-column")}
multiple={typeahead.classList.contains("multiple")}
isValid={typeahead.classList.contains("is-valid")}/>
</React.StrictMode>
);
}
49 changes: 0 additions & 49 deletions src/resources/page.html
Original file line number Diff line number Diff line change
Expand Up @@ -168,12 +168,6 @@
</div>
</nav>

<form method="GET">
<div id="root" data-table="table" data-column="type"></div>
<input id="root-value" name="root-value" type="hidden" value="def"/>
<input type="submit"/>
</form>

<div id="content" class="container-fluid">
{% if page.elapsed %}<p class="float-end">{{ page.elapsed }}ms</p>{% endif %}
{% if page.repo %}
Expand Down Expand Up @@ -224,49 +218,6 @@
});
}
friendlifyMoments();

function configure_typeahead_form(node, table) {
if (!node.id || !node.id.endsWith("-typeahead-form")) {
return;
}
var col = node.id.split("-")[0];
var bloodhound = new Bloodhound({
datumTokenizer: Bloodhound.tokenizers.obj.nonword('label'),
queryTokenizer: Bloodhound.tokenizers.nonword,
sorter: function (a, b) {
return a.order - b.order;
},
remote: {
url: `../../${table}?text=%QUERY&column=${col}&format=json`,
wildcard: '%QUERY',
transform: function (response) {
return bloodhound.sorter(response);
}
}
});
$(node).typeahead({
minLength: 0,
hint: false,
highlight: true
}, {
name: `${table}`,
source: bloodhound,
display: function (item) {
return item.label;
},
limit: 40
});
$(node).bind('click', function (e) {
$(node).select();
});
var cls = node.className;
if (cls.includes("is-invalid")) {
var parent = node.parentElement;
var parentCls = parent.className;
parent.className = parentCls + " is-invalid";
}
}
<!-- $('.typeahead').each(function () {configure_typeahead_form(this, "{{ table_name }}");}); -->
</script>
{% block body_end %}{% endblock %}
</body>
Expand Down
29 changes: 17 additions & 12 deletions src/serve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1703,16 +1703,14 @@ fn get_row_as_form_map(
let datatype = column_config.datatype;
let structure = column_config.structure.split('(').collect::<Vec<_>>()[0];

let mut html_type;
let mut allowed_values = None;
if vec!["from", "in", "tree", "under"].contains(&structure) {
html_type = Some("search".into());
} else {
(html_type, allowed_values) = get_html_type_and_values(config, &datatype, &None)?;
}

if allowed_values != None && html_type == None {
html_type = Some("search".into());
let (mut html_type, allowed_values) = get_html_type_and_values(config, &datatype, &None)?;
if html_type == None {
if allowed_values != None {
html_type = Some("search".into());
}
if vec!["from", "in", "tree", "under"].contains(&structure) {
html_type = Some("search".into());
}
}

let readonly;
Expand All @@ -1725,6 +1723,7 @@ fn get_row_as_form_map(
};

let hiccup_form_row = get_hiccup_form_row(
table_name,
cell_header,
&None,
&allowed_values,
Expand Down Expand Up @@ -1757,6 +1756,7 @@ fn get_row_as_form_map(
}

fn get_hiccup_form_row(
table_name: &str,
header: &str,
allow_delete: &Option<bool>,
allowed_values: &Option<Vec<String>>,
Expand Down Expand Up @@ -1904,17 +1904,22 @@ fn get_hiccup_form_row(
select_element.insert(2, json!(["option", {"value": "", "selected": true}]));
}
value_col.push(json!(select_element));
} else if vec!["text", "number", "search"].contains(&html_type) {
} else if vec!["text", "number", "search", "multisearch"].contains(&html_type) {
// TODO: This html type will need to be re-implemented (later).
// TODO: Support a range restriction for 'number'
classes.insert(0, "form-control");
input_attrs.insert("type".to_string(), json!(html_type));
if html_type == "search" {
if ["search", "multisearch"].contains(&html_type) {
classes.append(&mut vec!["search", "typeahead"]);
if html_type == "multisearch" {
classes.push("multiple");
}
input_attrs.insert(
"id".to_string(),
json!(format!("{}-typeahead-form", header)),
);
input_attrs.insert("data-table".to_string(), json!(table_name));
input_attrs.insert("data-column".to_string(), json!(header));
}
input_attrs.insert("class".to_string(), json!(classes.join(" ")));
match value {
Expand Down

0 comments on commit c1ceafd

Please sign in to comment.