contacts-pane 2.7.1 → 3.0.0-6ef05c4d
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autocompleteBar.d.ts +3 -0
- package/dist/autocompleteBar.d.ts.map +1 -0
- package/dist/autocompleteBar.js +90 -0
- package/dist/autocompleteBar.js.map +1 -0
- package/dist/autocompleteField.d.ts +20 -0
- package/dist/autocompleteField.d.ts.map +1 -0
- package/dist/autocompleteField.js +165 -0
- package/dist/autocompleteField.js.map +1 -0
- package/dist/autocompletePicker.d.ts +15 -0
- package/dist/autocompletePicker.d.ts.map +1 -0
- package/dist/autocompletePicker.js +253 -0
- package/dist/autocompletePicker.js.map +1 -0
- package/dist/contactLogic.js +223 -0
- package/dist/contactLogic.js.map +1 -0
- package/dist/contactsPane.js +800 -0
- package/dist/contactsPane.js.map +1 -0
- package/dist/groupMembershipControl.js +107 -0
- package/dist/groupMembershipControl.js.map +1 -0
- package/dist/individual.js +115 -0
- package/dist/individual.js.map +1 -0
- package/dist/mintNewAddressBook.js +145 -0
- package/dist/mintNewAddressBook.js.map +1 -0
- package/dist/mugshotGallery.js +264 -0
- package/dist/mugshotGallery.js.map +1 -0
- package/dist/publicData.d.ts +82 -0
- package/dist/publicData.d.ts.map +1 -0
- package/dist/publicData.js +421 -0
- package/dist/publicData.js.map +1 -0
- package/dist/toolsPane.js +671 -0
- package/dist/toolsPane.js.map +1 -0
- package/dist/webidControl.js +320 -0
- package/dist/webidControl.js.map +1 -0
- package/package.json +36 -27
- package/Makefile +0 -19
- package/__tests__/unit/data-reformat-test.js +0 -166
- package/__tests__/unit/data-reformat-test.ts +0 -185
- package/__tests__/unit/setup.js +0 -74
- package/__tests__/unit/setup.ts +0 -77
- package/babel.config.js +0 -13
- package/card.ai +4 -982
- package/card.png +0 -0
- package/contactLogic.js +0 -232
- package/contactsPane.js +0 -962
- package/diff.txt +0 -884
- package/eslint.config.mjs +0 -28
- package/exampleOfOpenData/mit-wikidata-details.ttl +0 -104
- package/exampleOfOpenData/mit-wikidata-query.sparql +0 -37
- package/exampleOfOpenData/wikidata-get.json +0 -1
- package/groupMembershipControl.js +0 -109
- package/individual.js +0 -129
- package/individualForm.js +0 -294
- package/jest.config.js +0 -11
- package/jest.setup.ts +0 -10
- package/lib/autocompleteBar.js +0 -98
- package/lib/autocompleteBar.js.map +0 -1
- package/lib/autocompleteField.js +0 -156
- package/lib/autocompleteField.js.map +0 -1
- package/lib/autocompletePicker.js +0 -239
- package/lib/autocompletePicker.js.map +0 -1
- package/lib/forms.js +0 -315
- package/lib/instituteDetailsQuery.js +0 -38
- package/lib/publicData.js +0 -387
- package/lib/publicData.js.map +0 -1
- package/lib/vcard.js +0 -916
- package/mintNewAddressBook.js +0 -171
- package/mugshotGallery.js +0 -314
- package/organizationForm.js +0 -60
- package/organizationForm.ttl +0 -59
- package/shapes/contacts-shapes.ttl +0 -253
- package/src/autocompleteBar.ts +0 -92
- package/src/autocompleteField.ts +0 -180
- package/src/autocompletePicker.ts +0 -253
- package/src/forms.ttl +0 -313
- package/src/instituteDetailsQuery.sparql +0 -36
- package/src/publicData.ts +0 -385
- package/src/vcard.ttl +0 -914
- package/toolsPane.js +0 -772
- package/tsconfig.json +0 -16
- package/webidControl.js +0 -327
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocompleteBar.d.ts","sourceRoot":"","sources":["../src/autocompleteBar.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAgBlC,wBAAsB,yBAAyB,CAAE,GAAG,EAAC,YAAY,EAC/D,MAAM,EAAC,SAAS,EAAE,OAAO,KAAA,EAAE,kBAAkB,KAAA,GAAG,OAAO,CAAC,WAAW,CAAC,CAqErE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.renderAutocompleteControl = renderAutocompleteControl;
|
|
7
|
+
var _solidLogic = require("solid-logic");
|
|
8
|
+
var _solidUi = require("solid-ui");
|
|
9
|
+
var _autocompletePicker = require("./autocompletePicker");
|
|
10
|
+
var _publicData = require("./publicData");
|
|
11
|
+
// The Control with decorations
|
|
12
|
+
|
|
13
|
+
// dbpediaParameters
|
|
14
|
+
|
|
15
|
+
const WEBID_NOUN = 'Solid ID';
|
|
16
|
+
const kb = _solidLogic.store;
|
|
17
|
+
|
|
18
|
+
// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed
|
|
19
|
+
// const AUTOCOMPLETE_ROWS = 12 // 20?
|
|
20
|
+
|
|
21
|
+
const GREEN_PLUS = _solidUi.icons.iconBase + 'noun_34653_green.svg';
|
|
22
|
+
const SEARCH_ICON = _solidUi.icons.iconBase + 'noun_Search_875351.svg';
|
|
23
|
+
async function renderAutocompleteControl(dom, person, options, addOneIdAndRefresh) {
|
|
24
|
+
async function autoCompleteDone(object, _name) {
|
|
25
|
+
const webid = object.uri;
|
|
26
|
+
removeDecorated();
|
|
27
|
+
return addOneIdAndRefresh(person, webid);
|
|
28
|
+
}
|
|
29
|
+
async function greenButtonHandler(_event) {
|
|
30
|
+
const webid = await _solidUi.widgets.askName(dom, _solidLogic.store, creationArea, _solidUi.ns.vcard('url'), null, WEBID_NOUN);
|
|
31
|
+
if (!webid) {
|
|
32
|
+
return; // cancelled by user
|
|
33
|
+
}
|
|
34
|
+
return addOneIdAndRefresh(person, webid);
|
|
35
|
+
}
|
|
36
|
+
function removeDecorated() {
|
|
37
|
+
if (decoratedAutocomplete) {
|
|
38
|
+
creationArea.removeChild(decoratedAutocomplete);
|
|
39
|
+
decoratedAutocomplete = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
async function searchButtonHandler(_event) {
|
|
43
|
+
if (decoratedAutocomplete) {
|
|
44
|
+
creationArea.removeChild(decoratedAutocomplete);
|
|
45
|
+
decoratedAutocomplete = null;
|
|
46
|
+
} else {
|
|
47
|
+
decoratedAutocomplete = dom.createElement('div');
|
|
48
|
+
decoratedAutocomplete.setAttribute('style', 'display: flex; flex-flow: wrap;');
|
|
49
|
+
decoratedAutocomplete.appendChild(await (0, _autocompletePicker.renderAutoComplete)(dom, acOptions, autoCompleteDone));
|
|
50
|
+
decoratedAutocomplete.appendChild(acceptButton);
|
|
51
|
+
decoratedAutocomplete.appendChild(cancelButton);
|
|
52
|
+
creationArea.appendChild(decoratedAutocomplete);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function droppedURIHandler(uris) {
|
|
56
|
+
for (const webid of uris) {
|
|
57
|
+
// normally one but can be more than one
|
|
58
|
+
await addOneIdAndRefresh(person, webid);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
const queryParams = options.queryParameters || _publicData.wikidataParameters;
|
|
62
|
+
const acceptButton = _solidUi.widgets.continueButton(dom);
|
|
63
|
+
const cancelButton = _solidUi.widgets.cancelButton(dom, removeDecorated);
|
|
64
|
+
const klass = options.class;
|
|
65
|
+
const acOptions = {
|
|
66
|
+
queryParams,
|
|
67
|
+
class: klass,
|
|
68
|
+
acceptButton,
|
|
69
|
+
cancelButton
|
|
70
|
+
};
|
|
71
|
+
var decoratedAutocomplete = null;
|
|
72
|
+
// const { dom } = dataBrowserContext
|
|
73
|
+
options = options || {};
|
|
74
|
+
options.editable = kb.updater.editable(person.doc().uri, kb);
|
|
75
|
+
const creationArea = dom.createElement('div');
|
|
76
|
+
creationArea.setAttribute('style', 'display: flex; flex-flow: wrap;');
|
|
77
|
+
if (options.editable) {
|
|
78
|
+
// creationArea.appendChild(await renderAutoComplete(dom, options, autoCompleteDone)) wait for searchButton
|
|
79
|
+
creationArea.style.width = '100%';
|
|
80
|
+
const plus = creationArea.appendChild(_solidUi.widgets.button(dom, GREEN_PLUS, options.idNoun, greenButtonHandler));
|
|
81
|
+
_solidUi.widgets.makeDropTarget(plus, droppedURIHandler, null);
|
|
82
|
+
if (options.dbLookup) {
|
|
83
|
+
creationArea.appendChild(_solidUi.widgets.button(dom, SEARCH_ICON, options.idNoun, searchButtonHandler));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return creationArea;
|
|
87
|
+
} // renderAutocompleteControl
|
|
88
|
+
|
|
89
|
+
// ends
|
|
90
|
+
//# sourceMappingURL=autocompleteBar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocompleteBar.js","names":["_solidLogic","require","_solidUi","_autocompletePicker","_publicData","WEBID_NOUN","kb","store","GREEN_PLUS","icons","iconBase","SEARCH_ICON","renderAutocompleteControl","dom","person","options","addOneIdAndRefresh","autoCompleteDone","object","_name","webid","uri","removeDecorated","greenButtonHandler","_event","widgets","askName","creationArea","ns","vcard","decoratedAutocomplete","removeChild","searchButtonHandler","createElement","setAttribute","appendChild","renderAutoComplete","acOptions","acceptButton","cancelButton","droppedURIHandler","uris","queryParams","queryParameters","wikidataParameters","continueButton","klass","class","editable","updater","doc","style","width","plus","button","idNoun","makeDropTarget","dbLookup"],"sources":["../src/autocompleteBar.ts"],"sourcesContent":["// The Control with decorations\n\nimport { NamedNode } from 'rdflib'\nimport { store } from 'solid-logic'\nimport { ns, widgets, icons } from 'solid-ui'\nimport { renderAutoComplete } from './autocompletePicker' // dbpediaParameters\nimport { wikidataParameters } from './publicData'\n\nconst WEBID_NOUN = 'Solid ID'\n\nconst kb = store\n\n// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed\n// const AUTOCOMPLETE_ROWS = 12 // 20?\n\nconst GREEN_PLUS = icons.iconBase + 'noun_34653_green.svg'\nconst SEARCH_ICON = icons.iconBase + 'noun_Search_875351.svg'\n\nexport async function renderAutocompleteControl (dom:HTMLDocument,\n person:NamedNode, options, addOneIdAndRefresh): Promise<HTMLElement> {\n async function autoCompleteDone (object, _name) {\n const webid = object.uri\n removeDecorated()\n return addOneIdAndRefresh(person, webid)\n }\n\n async function greenButtonHandler (_event) {\n const webid = await widgets.askName(dom, store, creationArea, ns.vcard('url'), null, WEBID_NOUN)\n if (!webid) {\n return // cancelled by user\n }\n return addOneIdAndRefresh(person, webid)\n }\n function removeDecorated () {\n if (decoratedAutocomplete) {\n creationArea.removeChild(decoratedAutocomplete)\n decoratedAutocomplete = null\n }\n }\n async function searchButtonHandler (_event) {\n if (decoratedAutocomplete) {\n creationArea.removeChild(decoratedAutocomplete)\n decoratedAutocomplete = null\n } else {\n decoratedAutocomplete = dom.createElement('div')\n decoratedAutocomplete.setAttribute('style', 'display: flex; flex-flow: wrap;')\n decoratedAutocomplete.appendChild(await renderAutoComplete(dom, acOptions, autoCompleteDone))\n decoratedAutocomplete.appendChild(acceptButton)\n decoratedAutocomplete.appendChild(cancelButton)\n creationArea.appendChild(decoratedAutocomplete)\n }\n }\n\n async function droppedURIHandler (uris) {\n for (const webid of uris) { // normally one but can be more than one\n await addOneIdAndRefresh(person, webid)\n }\n }\n\n const queryParams = options.queryParameters || wikidataParameters\n const acceptButton = widgets.continueButton(dom)\n const cancelButton = widgets.cancelButton(dom, removeDecorated)\n const klass = options.class\n const acOptions = {\n queryParams,\n class: klass,\n acceptButton,\n cancelButton\n }\n\n var decoratedAutocomplete: HTMLDivElement | null = null\n // const { dom } = dataBrowserContext\n options = options || {}\n options.editable = kb.updater.editable(person.doc().uri, kb)\n\n const creationArea = dom.createElement('div')\n creationArea.setAttribute('style', 'display: flex; flex-flow: wrap;')\n\n if (options.editable) {\n // creationArea.appendChild(await renderAutoComplete(dom, options, autoCompleteDone)) wait for searchButton\n creationArea.style.width = '100%'\n const plus = creationArea.appendChild(widgets.button(dom, GREEN_PLUS, options.idNoun, greenButtonHandler))\n widgets.makeDropTarget(plus, droppedURIHandler, null)\n if (options.dbLookup) {\n creationArea.appendChild(widgets.button(dom, SEARCH_ICON, options.idNoun, searchButtonHandler))\n }\n }\n return creationArea\n} // renderAutocompleteControl\n\n// ends\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BlankNode, NamedNode, Variable } from 'rdflib';
|
|
2
|
+
/**
|
|
3
|
+
* Render a autocomplete form field
|
|
4
|
+
*
|
|
5
|
+
* The same function is used for many similar one-value fields, with different
|
|
6
|
+
* regexps used to validate.
|
|
7
|
+
*
|
|
8
|
+
* @param dom The HTML Document object aka Document Object Model
|
|
9
|
+
* @param container If present, the created widget will be appended to this
|
|
10
|
+
* @param already A hash table of (form, subject) kept to prevent recursive forms looping
|
|
11
|
+
* @param subject The thing about which the form displays/edits data
|
|
12
|
+
* @param form The form or field to be rendered
|
|
13
|
+
* @param doc The web document in which the data is
|
|
14
|
+
* @param callbackFunction Called when data is changed?
|
|
15
|
+
*
|
|
16
|
+
* @returns The HTML widget created
|
|
17
|
+
*/
|
|
18
|
+
export declare function autocompleteField(// @@ are they allowed too be async??
|
|
19
|
+
dom: HTMLDocument, container: HTMLElement | undefined, already: any, subject: NamedNode | BlankNode | Variable, form: NamedNode, doc: NamedNode | undefined, callbackFunction: (ok: boolean, errorMessage: string) => void): HTMLElement;
|
|
20
|
+
//# sourceMappingURL=autocompleteField.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocompleteField.d.ts","sourceRoot":"","sources":["../src/autocompleteField.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,SAAS,EAAM,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAQ3D;;;;;;;;;;;;;;;GAeG;AAEH,wBAAgB,iBAAiB,CAAG,qCAAqC;AACvE,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,WAAW,GAAG,SAAS,EAClC,OAAO,KAAA,EACP,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,QAAQ,EACzC,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,SAAS,GAAG,SAAS,EAC1B,gBAAgB,EAAE,CAAC,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,KAAK,IAAI,GAC5D,WAAW,CA2Ib"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.autocompleteField = autocompleteField;
|
|
7
|
+
var _rdflib = require("rdflib");
|
|
8
|
+
var _solidLogic = require("solid-logic");
|
|
9
|
+
var _solidUi = require("solid-ui");
|
|
10
|
+
var _autocompletePicker = require("./autocompletePicker");
|
|
11
|
+
/* Form field for doing autocompleete
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
// dbpediaParameters
|
|
15
|
+
|
|
16
|
+
// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed
|
|
17
|
+
// const AUTOCOMPLETE_ROWS = 12 // 20?
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Render a autocomplete form field
|
|
21
|
+
*
|
|
22
|
+
* The same function is used for many similar one-value fields, with different
|
|
23
|
+
* regexps used to validate.
|
|
24
|
+
*
|
|
25
|
+
* @param dom The HTML Document object aka Document Object Model
|
|
26
|
+
* @param container If present, the created widget will be appended to this
|
|
27
|
+
* @param already A hash table of (form, subject) kept to prevent recursive forms looping
|
|
28
|
+
* @param subject The thing about which the form displays/edits data
|
|
29
|
+
* @param form The form or field to be rendered
|
|
30
|
+
* @param doc The web document in which the data is
|
|
31
|
+
* @param callbackFunction Called when data is changed?
|
|
32
|
+
*
|
|
33
|
+
* @returns The HTML widget created
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
function autocompleteField(
|
|
37
|
+
// @@ are they allowed too be async??
|
|
38
|
+
dom, container, already, subject, form, doc, callbackFunction) {
|
|
39
|
+
async function addOneIdAndRefresh(result, _name) {
|
|
40
|
+
const ds = kb.statementsMatching(subject, property); // remove any multiple values
|
|
41
|
+
|
|
42
|
+
let is = ds.map(statement => (0, _rdflib.st)(statement.subject, statement.predicate, result, statement.why)); // can include >1 doc
|
|
43
|
+
if (is.length === 0) {
|
|
44
|
+
// or none
|
|
45
|
+
is = [(0, _rdflib.st)(subject, property, result, doc)];
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
await kb.updater.updateMany(ds, is);
|
|
49
|
+
} catch (err) {
|
|
50
|
+
callbackFunction(false, err);
|
|
51
|
+
box.appendChild(_solidUi.widgets.errorMessageBlock(dom, 'Autocomplete form data write error:' + err));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
callbackFunction(true, '');
|
|
55
|
+
}
|
|
56
|
+
const kb = _solidLogic.store;
|
|
57
|
+
const formDoc = form.doc ? form.doc() : null; // @@ if blank no way to know
|
|
58
|
+
|
|
59
|
+
const box = dom.createElement('tr');
|
|
60
|
+
if (container) container.appendChild(box);
|
|
61
|
+
const lhs = dom.createElement('td');
|
|
62
|
+
lhs.setAttribute('class', 'formFieldName');
|
|
63
|
+
lhs.setAttribute('style', ' vertical-align: middle;');
|
|
64
|
+
box.appendChild(lhs);
|
|
65
|
+
const rhs = dom.createElement('td');
|
|
66
|
+
rhs.setAttribute('class', 'formFieldValue');
|
|
67
|
+
box.appendChild(rhs);
|
|
68
|
+
const property = kb.any(form, _solidUi.ns.ui('property'));
|
|
69
|
+
if (!property) {
|
|
70
|
+
box.appendChild(dom.createTextNode('Error: No property given for autocomplete field: ' + form));
|
|
71
|
+
return box;
|
|
72
|
+
}
|
|
73
|
+
const searchClass = kb.any(form, _solidUi.ns.ui('searchClass'));
|
|
74
|
+
if (!searchClass) {
|
|
75
|
+
box.appendChild(dom.createTextNode('Error: No searchClass given for autocomplete field: ' + form));
|
|
76
|
+
return box;
|
|
77
|
+
}
|
|
78
|
+
const endPoint = kb.any(form, _solidUi.ns.ui('endPoint'));
|
|
79
|
+
if (!endPoint) {
|
|
80
|
+
box.appendChild(dom.createTextNode('Error: No SPARQL endPoint given for autocomplete field: ' + form));
|
|
81
|
+
return box;
|
|
82
|
+
}
|
|
83
|
+
const queryTemplate = kb.any(form, _solidUi.ns.ui('queryTemplate'));
|
|
84
|
+
if (!queryTemplate) {
|
|
85
|
+
box.appendChild(dom.createTextNode('Error: No queryTemplate given for autocomplete field: ' + form));
|
|
86
|
+
return box;
|
|
87
|
+
}
|
|
88
|
+
// It can be cleaner to just remove empty fields if you can't edit them anyway
|
|
89
|
+
const suppressEmptyUneditable = kb.anyJS(form, _solidUi.ns.ui('suppressEmptyUneditable'), null, formDoc);
|
|
90
|
+
lhs.appendChild(_solidUi.widgets.fieldLabel(dom, property, form));
|
|
91
|
+
const uri = _solidUi.widgets.mostSpecificClassURI(form);
|
|
92
|
+
let params = _solidUi.widgets.fieldParams[uri];
|
|
93
|
+
if (params === undefined) params = {}; // non-bottom field types can do this
|
|
94
|
+
// const theStyle = params.style || style.textInputStyle
|
|
95
|
+
const klass = kb.the(form, _solidUi.ns.ui('category'), null, formDoc);
|
|
96
|
+
/*
|
|
97
|
+
{ label: string;
|
|
98
|
+
logo: string;
|
|
99
|
+
searchByNameQuery?: string;
|
|
100
|
+
searchByNameURI?: string;
|
|
101
|
+
insitituteDetailsQuery?: string;
|
|
102
|
+
endPoint?: string;
|
|
103
|
+
class: object
|
|
104
|
+
}
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
const searchByNameQuery = kb.the(form, _solidUi.ns.ui('searchByNameQuery'), null, formDoc);
|
|
108
|
+
if (!klass) {
|
|
109
|
+
box.appendChild(dom.createTextNode('Error: No class given for autocomplete field: ' + form));
|
|
110
|
+
return box;
|
|
111
|
+
}
|
|
112
|
+
const queryParams = {
|
|
113
|
+
label: 'from form',
|
|
114
|
+
logo: '',
|
|
115
|
+
class: klass,
|
|
116
|
+
endPoint: endPoint.value,
|
|
117
|
+
searchByNameQuery: searchByNameQuery?.value
|
|
118
|
+
};
|
|
119
|
+
const options = {
|
|
120
|
+
// cancelButton?: HTMLElement,
|
|
121
|
+
// acceptButton?: HTMLElement,
|
|
122
|
+
class: klass,
|
|
123
|
+
queryParams
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// const acWiget = rhs.appendChild(await renderAutoComplete(dom, options, addOneIdAndRefresh))
|
|
127
|
+
|
|
128
|
+
// @@ set existing value is any
|
|
129
|
+
(0, _autocompletePicker.renderAutoComplete)(dom, options, addOneIdAndRefresh).then(acWiget => rhs.appendChild(acWiget));
|
|
130
|
+
const field = dom.createElement('input');
|
|
131
|
+
field.style = _solidUi.style.textInputStyle; // Do we have to override length etc?
|
|
132
|
+
rhs.appendChild(field);
|
|
133
|
+
field.setAttribute('type', params.type ? params.type : 'text');
|
|
134
|
+
const size = kb.any(form, _solidUi.ns.ui('size')); // Form has precedence
|
|
135
|
+
field.setAttribute('size', size ? '' + size : params.size ? '' + params.size : '20');
|
|
136
|
+
const maxLength = kb.any(form, _solidUi.ns.ui('maxLength'));
|
|
137
|
+
field.setAttribute('maxLength', maxLength ? '' + maxLength : '4096');
|
|
138
|
+
doc = doc || _solidUi.widgets.fieldStore(subject, property, doc);
|
|
139
|
+
let obj = kb.any(subject, property, undefined, doc);
|
|
140
|
+
if (!obj) {
|
|
141
|
+
obj = kb.any(form, _solidUi.ns.ui('default'));
|
|
142
|
+
}
|
|
143
|
+
if (obj) {
|
|
144
|
+
/* istanbul ignore next */
|
|
145
|
+
field.value = obj.value || obj.value || '';
|
|
146
|
+
}
|
|
147
|
+
field.setAttribute('style', _solidUi.style);
|
|
148
|
+
if (!kb.updater) {
|
|
149
|
+
throw new Error('kb has no updater');
|
|
150
|
+
}
|
|
151
|
+
if (!kb.updater.editable(doc.uri)) {
|
|
152
|
+
field.readOnly = true // was: disabled. readOnly is better
|
|
153
|
+
;
|
|
154
|
+
field.style = _solidUi.style.textInputStyleUneditable;
|
|
155
|
+
// backgroundColor = textInputBackgroundColorUneditable
|
|
156
|
+
if (suppressEmptyUneditable && field.value === '') {
|
|
157
|
+
box.style.display = 'none'; // clutter
|
|
158
|
+
}
|
|
159
|
+
return box;
|
|
160
|
+
}
|
|
161
|
+
return box;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// ends
|
|
165
|
+
//# sourceMappingURL=autocompleteField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocompleteField.js","names":["_rdflib","require","_solidLogic","_solidUi","_autocompletePicker","autocompleteField","dom","container","already","subject","form","doc","callbackFunction","addOneIdAndRefresh","result","_name","ds","kb","statementsMatching","property","is","map","statement","st","predicate","why","length","updater","updateMany","err","box","appendChild","widgets","errorMessageBlock","store","formDoc","createElement","lhs","setAttribute","rhs","any","ns","ui","createTextNode","searchClass","endPoint","queryTemplate","suppressEmptyUneditable","anyJS","fieldLabel","uri","mostSpecificClassURI","params","fieldParams","undefined","klass","the","searchByNameQuery","queryParams","label","logo","class","value","options","renderAutoComplete","then","acWiget","field","style","textInputStyle","type","size","maxLength","fieldStore","obj","Error","editable","readOnly","textInputStyleUneditable","display"],"sources":["../src/autocompleteField.ts"],"sourcesContent":["/* Form field for doing autocompleete\n */\nimport { BlankNode, NamedNode, st, Variable } from 'rdflib'\nimport { store } from 'solid-logic'\nimport { ns, style, widgets } from 'solid-ui'\nimport { renderAutoComplete } from './autocompletePicker' // dbpediaParameters\n\n// const AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed\n// const AUTOCOMPLETE_ROWS = 12 // 20?\n\n/**\n * Render a autocomplete form field\n *\n * The same function is used for many similar one-value fields, with different\n * regexps used to validate.\n *\n * @param dom The HTML Document object aka Document Object Model\n * @param container If present, the created widget will be appended to this\n * @param already A hash table of (form, subject) kept to prevent recursive forms looping\n * @param subject The thing about which the form displays/edits data\n * @param form The form or field to be rendered\n * @param doc The web document in which the data is\n * @param callbackFunction Called when data is changed?\n *\n * @returns The HTML widget created\n */\n\nexport function autocompleteField ( // @@ are they allowed too be async??\n dom: HTMLDocument,\n container: HTMLElement | undefined,\n already,\n subject: NamedNode | BlankNode | Variable,\n form: NamedNode,\n doc: NamedNode | undefined,\n callbackFunction: (ok: boolean, errorMessage: string) => void\n): HTMLElement {\n async function addOneIdAndRefresh (result, _name) {\n const ds = kb.statementsMatching(subject, property as any) // remove any multiple values\n\n let is = ds.map(statement => st(statement.subject, statement.predicate, result, statement.why)) // can include >1 doc\n if (is.length === 0) {\n // or none\n is = [st(subject, property as any, result, doc)]\n }\n try {\n await kb.updater.updateMany(ds, is)\n } catch (err) {\n callbackFunction(false, err)\n box.appendChild(widgets.errorMessageBlock(dom, 'Autocomplete form data write error:' + err))\n return\n }\n callbackFunction(true, '')\n }\n\n const kb = store\n const formDoc = form.doc ? form.doc() : null // @@ if blank no way to know\n\n const box = dom.createElement('tr')\n if (container) container.appendChild(box)\n const lhs = dom.createElement('td')\n lhs.setAttribute('class', 'formFieldName')\n lhs.setAttribute('style', ' vertical-align: middle;')\n box.appendChild(lhs)\n const rhs = dom.createElement('td')\n rhs.setAttribute('class', 'formFieldValue')\n box.appendChild(rhs)\n\n const property = kb.any(form, ns.ui('property'))\n if (!property) {\n box.appendChild(\n dom.createTextNode('Error: No property given for autocomplete field: ' + form)\n )\n return box\n }\n const searchClass = kb.any(form, ns.ui('searchClass'))\n if (!searchClass) {\n box.appendChild(\n dom.createTextNode('Error: No searchClass given for autocomplete field: ' + form)\n )\n return box\n }\n const endPoint = kb.any(form, ns.ui('endPoint'))\n if (!endPoint) {\n box.appendChild(\n dom.createTextNode('Error: No SPARQL endPoint given for autocomplete field: ' + form)\n )\n return box\n }\n const queryTemplate = kb.any(form, ns.ui('queryTemplate'))\n if (!queryTemplate) {\n box.appendChild(\n dom.createTextNode('Error: No queryTemplate given for autocomplete field: ' + form)\n )\n return box\n }\n // It can be cleaner to just remove empty fields if you can't edit them anyway\n const suppressEmptyUneditable = kb.anyJS(form, ns.ui('suppressEmptyUneditable'), null, formDoc)\n\n lhs.appendChild(widgets.fieldLabel(dom, property as any, form))\n const uri = widgets.mostSpecificClassURI(form)\n let params = widgets.fieldParams[uri]\n if (params === undefined) params = {} // non-bottom field types can do this\n // const theStyle = params.style || style.textInputStyle\n const klass = kb.the(form, ns.ui('category'), null, formDoc) as NamedNode\n /*\n { label: string;\n logo: string;\n searchByNameQuery?: string;\n searchByNameURI?: string;\n insitituteDetailsQuery?: string;\n endPoint?: string;\n class: object\n }\n*/\n\n const searchByNameQuery = kb.the(form, ns.ui('searchByNameQuery'), null, formDoc)\n\n if (!klass) {\n box.appendChild(\n dom.createTextNode('Error: No class given for autocomplete field: ' + form)\n )\n return box\n }\n\n const queryParams = { label: 'from form', logo: '', class: klass, endPoint: endPoint.value, searchByNameQuery: searchByNameQuery?.value }\n\n const options = { // cancelButton?: HTMLElement,\n // acceptButton?: HTMLElement,\n class: klass,\n queryParams\n }\n\n // const acWiget = rhs.appendChild(await renderAutoComplete(dom, options, addOneIdAndRefresh))\n\n // @@ set existing value is any\n renderAutoComplete(dom, options, addOneIdAndRefresh).then(acWiget => rhs.appendChild(acWiget))\n\n const field = dom.createElement('input')\n ;(field as any).style = style.textInputStyle // Do we have to override length etc?\n rhs.appendChild(field)\n field.setAttribute('type', params.type ? params.type : 'text')\n\n const size = kb.any(form, ns.ui('size')) // Form has precedence\n field.setAttribute(\n 'size',\n size ? '' + size : params.size ? '' + params.size : '20'\n )\n const maxLength = kb.any(form, ns.ui('maxLength'))\n field.setAttribute('maxLength', maxLength ? '' + maxLength : '4096')\n\n doc = doc || widgets.fieldStore(subject, property as any, doc)\n\n let obj = kb.any(subject, property as any, undefined, doc)\n if (!obj) {\n obj = kb.any(form, ns.ui('default'))\n }\n if (obj) {\n /* istanbul ignore next */\n field.value = obj.value || obj.value || ''\n }\n field.setAttribute('style', style)\n if (!kb.updater) {\n throw new Error('kb has no updater')\n }\n if (!kb.updater.editable((doc as NamedNode).uri)) {\n field.readOnly = true // was: disabled. readOnly is better\n ;(field as any).style = style.textInputStyleUneditable\n // backgroundColor = textInputBackgroundColorUneditable\n if (suppressEmptyUneditable && field.value === '') {\n box.style.display = 'none' // clutter\n }\n return box\n }\n return box\n}\n\n// ends\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { NamedNode } from 'rdflib';
|
|
2
|
+
import { QueryParameters } from './publicData';
|
|
3
|
+
type AutocompleteOptions = {
|
|
4
|
+
cancelButton?: HTMLElement;
|
|
5
|
+
acceptButton?: HTMLElement;
|
|
6
|
+
class: NamedNode;
|
|
7
|
+
queryParams: QueryParameters;
|
|
8
|
+
};
|
|
9
|
+
interface Callback1 {
|
|
10
|
+
(subject: NamedNode, name: string): void;
|
|
11
|
+
}
|
|
12
|
+
export declare function renderAutoComplete(dom: HTMLDocument, options: AutocompleteOptions, // subject:NamedNode, predicate:NamedNode,
|
|
13
|
+
callback: Callback1): Promise<HTMLDivElement>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=autocompletePicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocompletePicker.d.ts","sourceRoot":"","sources":["../src/autocompletePicker.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAA;AAGlC,OAAO,EACwD,eAAe,EAC7E,MAAM,cAAc,CAAA;AAqBrB,KAAK,mBAAmB,GAAG;IACzB,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,YAAY,CAAC,EAAE,WAAW,CAAC;IAC3B,KAAK,EAAE,SAAS,CAAC;IACjB,WAAW,EAAE,eAAe,CAAA;CAC7B,CAAA;AAED,UAAU,SAAS;IACjB,CAAC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C;AAGD,wBAAsB,kBAAkB,CAAE,GAAG,EAAE,YAAY,EAAE,OAAO,EAAC,mBAAmB,EAAE,0CAA0C;AAClI,QAAQ,EAAE,SAAS,2BAsNpB"}
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.renderAutoComplete = renderAutoComplete;
|
|
7
|
+
var _solidLogic = require("solid-logic");
|
|
8
|
+
var _solidUi = require("solid-ui");
|
|
9
|
+
var _publicData = require("./publicData");
|
|
10
|
+
/* Create and edit data using public data
|
|
11
|
+
**
|
|
12
|
+
** organization conveys many distinct types of thing.
|
|
13
|
+
**
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const AUTOCOMPLETE_THRESHOLD = 4; // don't check until this many characters typed
|
|
17
|
+
const AUTOCOMPLETE_ROWS = 20; // 20?
|
|
18
|
+
const AUTOCOMPLETE_ROWS_STRETCH = 40;
|
|
19
|
+
const AUTOCOMPLETE_DEBOUNCE_MS = 300;
|
|
20
|
+
|
|
21
|
+
// const autocompleteRowStyle = 'border: 0.2em solid straw;' // @@ white
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
Autocomplete happens in four phases:
|
|
25
|
+
1. The search string is too small to bother
|
|
26
|
+
2. The search string is big enough, and we have not loaded the array
|
|
27
|
+
3. The search string is big enough, and we have loaded array up to the limit
|
|
28
|
+
Display them and wait for more user input
|
|
29
|
+
4. The search string is big enough, and we have loaded array NOT to the limit
|
|
30
|
+
but including all matches. No more fetches.
|
|
31
|
+
If user gets more precise, wait for them to select one - or reduce to a single
|
|
32
|
+
5. Optionally waiting for accept button to be pressed
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
// The core of the autocomplete UI
|
|
36
|
+
async function renderAutoComplete(dom, options,
|
|
37
|
+
// subject:NamedNode, predicate:NamedNode,
|
|
38
|
+
callback) {
|
|
39
|
+
function complain(message) {
|
|
40
|
+
const errorRow = table.appendChild(dom.createElement('tr'));
|
|
41
|
+
console.log(message);
|
|
42
|
+
errorRow.appendChild(_solidUi.widgets.errorMessageBlock(dom, message, 'pink'));
|
|
43
|
+
_solidUi.style.setStyle(errorRow, 'autocompleteRowStyle');
|
|
44
|
+
errorRow.style.padding = '1em';
|
|
45
|
+
}
|
|
46
|
+
/*
|
|
47
|
+
function remove (ele?: HTMLElement) {
|
|
48
|
+
if (ele && ele.parentNode) {
|
|
49
|
+
ele.parentNode.removeChild(ele)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
*/
|
|
53
|
+
function finish(object, name) {
|
|
54
|
+
console.log('Auto complete: finish! ' + object);
|
|
55
|
+
// remove(options.cancelButton)
|
|
56
|
+
// remove(options.acceptButton)
|
|
57
|
+
// remove(div)
|
|
58
|
+
callback(object, name);
|
|
59
|
+
}
|
|
60
|
+
async function gotIt(object, name) {
|
|
61
|
+
if (options.acceptButton) {
|
|
62
|
+
options.acceptButton.disabled = false;
|
|
63
|
+
searchInput.value = name; // complete it
|
|
64
|
+
foundName = name;
|
|
65
|
+
foundObject = object;
|
|
66
|
+
console.log('Auto complete: name: ' + name);
|
|
67
|
+
console.log('Auto complete: waiting for accept ' + object);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
finish(object, name);
|
|
71
|
+
}
|
|
72
|
+
async function acceptButtonHandler(_event) {
|
|
73
|
+
if (searchInput.value === foundName) {
|
|
74
|
+
// still
|
|
75
|
+
finish(foundObject, foundName);
|
|
76
|
+
} else {
|
|
77
|
+
options.acceptButton.disabled = true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/*
|
|
82
|
+
async function cancelButtonHandler (_event) {
|
|
83
|
+
console.log('Auto complete: Canceled by user! ')
|
|
84
|
+
div.innerHTML = '' // Clear out the table
|
|
85
|
+
}
|
|
86
|
+
*/
|
|
87
|
+
|
|
88
|
+
function nameMatch(filter, candidate) {
|
|
89
|
+
const parts = filter.split(' '); // Each name part must be somewhere
|
|
90
|
+
for (let j = 0; j < parts.length; j++) {
|
|
91
|
+
const word = parts[j];
|
|
92
|
+
if (candidate.toLowerCase().indexOf(word) < 0) return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
function cancelText (_event) {
|
|
99
|
+
searchInput.value = ''
|
|
100
|
+
if (options.acceptButton) {
|
|
101
|
+
(options.acceptButton as any).disabled = true // start again
|
|
102
|
+
}
|
|
103
|
+
_candidatesLoaded = false
|
|
104
|
+
}
|
|
105
|
+
*/
|
|
106
|
+
|
|
107
|
+
function thinOut(filter) {
|
|
108
|
+
let hits = 0;
|
|
109
|
+
let pick = null;
|
|
110
|
+
let pickedName = '';
|
|
111
|
+
for (let j = table.children.length - 1; j > 0; j--) {
|
|
112
|
+
// backwards as we are removing rows
|
|
113
|
+
const row = table.children[j];
|
|
114
|
+
if (nameMatch(filter, row.textContent)) {
|
|
115
|
+
hits += 1;
|
|
116
|
+
pick = row.getAttribute('subject');
|
|
117
|
+
pickedName = row.textContent;
|
|
118
|
+
row.style.display = '';
|
|
119
|
+
row.style.color = 'blue'; // @@ chose color
|
|
120
|
+
} else {
|
|
121
|
+
;
|
|
122
|
+
row.style.display = 'none';
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (hits === 1 && pick) {
|
|
126
|
+
// Maybe require green confirmation button be clicked?
|
|
127
|
+
console.log(` auto complete elimination: "${filter}" -> "${pickedName}"`);
|
|
128
|
+
gotIt(_solidLogic.store.sym(pick), pickedName); // uri, name
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
function clearList() {
|
|
132
|
+
while (table.children.length > 1 && table.lastChild) {
|
|
133
|
+
table.removeChild(table.lastChild);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function inputEventHHandler(_event) {
|
|
137
|
+
if (runningTimeout) {
|
|
138
|
+
clearTimeout(runningTimeout);
|
|
139
|
+
}
|
|
140
|
+
setTimeout(refreshList, AUTOCOMPLETE_DEBOUNCE_MS);
|
|
141
|
+
}
|
|
142
|
+
async function refreshList() {
|
|
143
|
+
if (inputEventHandlerLock) {
|
|
144
|
+
console.log(`Ignoring "${searchInput.value}" because of lock `);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
inputEventHandlerLock = true;
|
|
148
|
+
const languagePrefs = await (0, _publicData.getPreferredLanguages)();
|
|
149
|
+
const filter = searchInput.value.trim().toLowerCase();
|
|
150
|
+
if (filter.length < AUTOCOMPLETE_THRESHOLD) {
|
|
151
|
+
// too small
|
|
152
|
+
clearList();
|
|
153
|
+
candidatesLoaded = false;
|
|
154
|
+
numberOfRows = AUTOCOMPLETE_ROWS;
|
|
155
|
+
} else {
|
|
156
|
+
if (allDisplayed && lastFilter && filter.startsWith(lastFilter)) {
|
|
157
|
+
thinOut(filter); // reversible?
|
|
158
|
+
inputEventHandlerLock = false;
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
let bindings;
|
|
162
|
+
try {
|
|
163
|
+
bindings = await (0, _publicData.queryPublicDataByName)(filter, OrgClass, options.queryParams);
|
|
164
|
+
// bindings = await queryDbpedia(sparql)
|
|
165
|
+
} catch (err) {
|
|
166
|
+
complain('Error querying db of organizations: ' + err);
|
|
167
|
+
inputEventHandlerLock = false;
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
candidatesLoaded = true;
|
|
171
|
+
const loadedEnough = bindings.length < _publicData.AUTOCOMPLETE_LIMIT;
|
|
172
|
+
if (loadedEnough) {
|
|
173
|
+
lastFilter = filter;
|
|
174
|
+
} else {
|
|
175
|
+
lastFilter = null;
|
|
176
|
+
}
|
|
177
|
+
clearList();
|
|
178
|
+
const slimmed = (0, _publicData.filterByLanguage)(bindings, languagePrefs);
|
|
179
|
+
if (loadedEnough && slimmed.length <= AUTOCOMPLETE_ROWS_STRETCH) {
|
|
180
|
+
numberOfRows = slimmed.length; // stretch if it means we get all items
|
|
181
|
+
}
|
|
182
|
+
allDisplayed = loadedEnough && slimmed.length <= numberOfRows;
|
|
183
|
+
console.log(` Filter:"${filter}" bindings: ${bindings.length}, slimmed to ${slimmed.length}; rows: ${numberOfRows}, Enough? ${loadedEnough}, All displayed? ${allDisplayed}`);
|
|
184
|
+
slimmed.slice(0, numberOfRows).forEach(binding => {
|
|
185
|
+
const row = table.appendChild(dom.createElement('tr'));
|
|
186
|
+
_solidUi.style.setStyle(row, 'autocompleteRowStyle');
|
|
187
|
+
const uri = binding.subject.value;
|
|
188
|
+
const name = binding.name?.value;
|
|
189
|
+
row.setAttribute('style', 'padding: 0.3em;');
|
|
190
|
+
row.setAttribute('subject', uri);
|
|
191
|
+
row.style.color = allDisplayed ? '#080' : '#000'; // green means 'you should find it here'
|
|
192
|
+
row.textContent = name || '';
|
|
193
|
+
row.addEventListener('click', async _event => {
|
|
194
|
+
console.log(' click row textContent: ' + row.textContent);
|
|
195
|
+
console.log(' click name: ' + name);
|
|
196
|
+
gotIt(_solidLogic.store.sym(uri), name || '');
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
inputEventHandlerLock = false;
|
|
201
|
+
} // refreshList
|
|
202
|
+
|
|
203
|
+
/* sparqlForSearch
|
|
204
|
+
*
|
|
205
|
+
* name -- e.g., "mass"
|
|
206
|
+
* theType -- e.g., <http://umbel.org/umbel/rc/EducationalOrganization>
|
|
207
|
+
*/
|
|
208
|
+
/*
|
|
209
|
+
function sparqlForSearch (name:string, theType:NamedNode):string {
|
|
210
|
+
const clean = name.replace(/\W/g, '') // Remove non alphanum so as to protect regexp
|
|
211
|
+
const sparql = `select distinct ?subject, ?name where {
|
|
212
|
+
?subject a <${theType.uri}>; rdfs:label ?name
|
|
213
|
+
FILTER regex(?name, "${clean}", "i")
|
|
214
|
+
} LIMIT ${AUTOCOMPLETE_LIMIT}`
|
|
215
|
+
return sparql
|
|
216
|
+
}
|
|
217
|
+
*/
|
|
218
|
+
const OrgClass = options.class; // kb.sym('http://umbel.org/umbel/rc/EducationalOrganization') // @@@ other
|
|
219
|
+
if (options.acceptButton) {
|
|
220
|
+
options.acceptButton.addEventListener('click', acceptButtonHandler, false);
|
|
221
|
+
}
|
|
222
|
+
if (options.cancelButton) {
|
|
223
|
+
// options.cancelButton.addEventListener('click', cancelButtonHandler, false)
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// @ts-ignore
|
|
227
|
+
let candidatesLoaded = false;
|
|
228
|
+
const runningTimeout = null;
|
|
229
|
+
let inputEventHandlerLock = false;
|
|
230
|
+
let allDisplayed = false;
|
|
231
|
+
var lastFilter = null;
|
|
232
|
+
var numberOfRows = AUTOCOMPLETE_ROWS;
|
|
233
|
+
const div = dom.createElement('div');
|
|
234
|
+
var foundName = null; // once found accepted string must match this
|
|
235
|
+
var foundObject = null;
|
|
236
|
+
var table = div.appendChild(dom.createElement('table'));
|
|
237
|
+
table.setAttribute('style', 'max-width: 30em; margin: 0.5em;');
|
|
238
|
+
const head = table.appendChild(dom.createElement('tr'));
|
|
239
|
+
_solidUi.style.setStyle(head, 'autocompleteRowStyle');
|
|
240
|
+
const cell = head.appendChild(dom.createElement('td'));
|
|
241
|
+
const searchInput = cell.appendChild(dom.createElement('input'));
|
|
242
|
+
searchInput.setAttribute('type', 'text');
|
|
243
|
+
const searchInputStyle = _solidUi.style.searchInputStyle || 'border: 0.1em solid #444; border-radius: 0.5em; width: 100%; font-size: 100%; padding: 0.1em 0.6em'; // @
|
|
244
|
+
searchInput.setAttribute('style', searchInputStyle);
|
|
245
|
+
searchInput.addEventListener('keyup', function (event) {
|
|
246
|
+
if (event.keyCode === 13) {
|
|
247
|
+
acceptButtonHandler(event);
|
|
248
|
+
}
|
|
249
|
+
}, false);
|
|
250
|
+
searchInput.addEventListener('input', inputEventHHandler);
|
|
251
|
+
return div;
|
|
252
|
+
} // renderAutoComplete22q1
|
|
253
|
+
//# sourceMappingURL=autocompletePicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autocompletePicker.js","names":["_solidLogic","require","_solidUi","_publicData","AUTOCOMPLETE_THRESHOLD","AUTOCOMPLETE_ROWS","AUTOCOMPLETE_ROWS_STRETCH","AUTOCOMPLETE_DEBOUNCE_MS","renderAutoComplete","dom","options","callback","complain","message","errorRow","table","appendChild","createElement","console","log","widgets","errorMessageBlock","style","setStyle","padding","finish","object","name","gotIt","acceptButton","disabled","searchInput","value","foundName","foundObject","acceptButtonHandler","_event","nameMatch","filter","candidate","parts","split","j","length","word","toLowerCase","indexOf","thinOut","hits","pick","pickedName","children","row","textContent","getAttribute","display","color","store","sym","clearList","lastChild","removeChild","inputEventHHandler","runningTimeout","clearTimeout","setTimeout","refreshList","inputEventHandlerLock","languagePrefs","getPreferredLanguages","trim","candidatesLoaded","numberOfRows","allDisplayed","lastFilter","startsWith","bindings","queryPublicDataByName","OrgClass","queryParams","err","loadedEnough","AUTOCOMPLETE_LIMIT","slimmed","filterByLanguage","slice","forEach","binding","uri","subject","setAttribute","addEventListener","class","cancelButton","div","head","cell","searchInputStyle","event","keyCode"],"sources":["../src/autocompletePicker.ts"],"sourcesContent":["/* Create and edit data using public data\n**\n** organization conveys many distinct types of thing.\n**\n*/\nimport { NamedNode } from 'rdflib'\nimport { store } from 'solid-logic'\nimport { style, widgets } from 'solid-ui'\nimport {\n AUTOCOMPLETE_LIMIT, filterByLanguage, getPreferredLanguages, QueryParameters, queryPublicDataByName\n} from './publicData'\n\nconst AUTOCOMPLETE_THRESHOLD = 4 // don't check until this many characters typed\nconst AUTOCOMPLETE_ROWS = 20 // 20?\nconst AUTOCOMPLETE_ROWS_STRETCH = 40\nconst AUTOCOMPLETE_DEBOUNCE_MS = 300\n\n// const autocompleteRowStyle = 'border: 0.2em solid straw;' // @@ white\n\n/*\nAutocomplete happens in four phases:\n 1. The search string is too small to bother\n 2. The search string is big enough, and we have not loaded the array\n 3. The search string is big enough, and we have loaded array up to the limit\n Display them and wait for more user input\n 4. The search string is big enough, and we have loaded array NOT to the limit\n but including all matches. No more fetches.\n If user gets more precise, wait for them to select one - or reduce to a single\n 5. Optionally waiting for accept button to be pressed\n*/\n\ntype AutocompleteOptions = {\n cancelButton?: HTMLElement,\n acceptButton?: HTMLElement,\n class: NamedNode,\n queryParams: QueryParameters\n}\n\ninterface Callback1 {\n (subject: NamedNode, name: string): void;\n}\n\n// The core of the autocomplete UI\nexport async function renderAutoComplete (dom: HTMLDocument, options:AutocompleteOptions, // subject:NamedNode, predicate:NamedNode,\n callback: Callback1) {\n function complain (message) {\n const errorRow = table.appendChild(dom.createElement('tr'))\n console.log(message)\n errorRow.appendChild(widgets.errorMessageBlock(dom, message, 'pink'))\n style.setStyle(errorRow, 'autocompleteRowStyle')\n errorRow.style.padding = '1em'\n }\n /*\n function remove (ele?: HTMLElement) {\n if (ele && ele.parentNode) {\n ele.parentNode.removeChild(ele)\n }\n }\n */\n function finish (object, name) {\n console.log('Auto complete: finish! ' + object)\n // remove(options.cancelButton)\n // remove(options.acceptButton)\n // remove(div)\n callback(object, name)\n }\n async function gotIt (object:NamedNode, name:string) {\n if (options.acceptButton) {\n (options.acceptButton as any).disabled = false\n searchInput.value = name // complete it\n foundName = name\n foundObject = object\n console.log('Auto complete: name: ' + name)\n console.log('Auto complete: waiting for accept ' + object)\n return\n }\n finish(object, name)\n }\n\n async function acceptButtonHandler (_event) {\n if (searchInput.value === foundName) { // still\n finish(foundObject, foundName)\n } else {\n (options.acceptButton as any).disabled = true\n }\n }\n\n /*\n async function cancelButtonHandler (_event) {\n console.log('Auto complete: Canceled by user! ')\n div.innerHTML = '' // Clear out the table\n }\n */\n\n function nameMatch (filter:string, candidate: string):boolean {\n const parts = filter.split(' ') // Each name part must be somewhere\n for (let j = 0; j < parts.length; j++) {\n const word = parts[j]\n if (candidate.toLowerCase().indexOf(word) < 0) return false\n }\n return true\n }\n\n /*\n function cancelText (_event) {\n searchInput.value = ''\n if (options.acceptButton) {\n (options.acceptButton as any).disabled = true // start again\n }\n _candidatesLoaded = false\n }\n */\n\n function thinOut (filter) {\n let hits = 0\n let pick: string | null = null; let pickedName = ''\n for (let j = table.children.length - 1; j > 0; j--) { // backwards as we are removing rows\n const row = table.children[j]\n if (nameMatch(filter, row.textContent)) {\n hits += 1\n pick = row.getAttribute('subject')\n pickedName = row.textContent\n ;(row as any).style.display = ''\n ;(row as any).style.color = 'blue' // @@ chose color\n } else {\n ;(row as any).style.display = 'none'\n }\n }\n if (hits === 1 && pick) { // Maybe require green confirmation button be clicked?\n console.log(` auto complete elimination: \"${filter}\" -> \"${pickedName}\"`)\n gotIt(store.sym(pick), pickedName) // uri, name\n }\n }\n\n function clearList () {\n while (table.children.length > 1 && table.lastChild) {\n table.removeChild(table.lastChild)\n }\n }\n\n async function inputEventHHandler (_event) {\n if (runningTimeout) {\n clearTimeout(runningTimeout)\n }\n setTimeout(refreshList, AUTOCOMPLETE_DEBOUNCE_MS)\n }\n\n async function refreshList () {\n if (inputEventHandlerLock) {\n console.log(`Ignoring \"${searchInput.value}\" because of lock `)\n return\n }\n inputEventHandlerLock = true\n const languagePrefs = await getPreferredLanguages()\n const filter = searchInput.value.trim().toLowerCase()\n if (filter.length < AUTOCOMPLETE_THRESHOLD) { // too small\n clearList()\n candidatesLoaded = false\n numberOfRows = AUTOCOMPLETE_ROWS\n } else {\n if (allDisplayed && lastFilter && filter.startsWith(lastFilter)) {\n thinOut(filter) // reversible?\n inputEventHandlerLock = false\n return\n }\n let bindings\n try {\n bindings = await queryPublicDataByName(filter, OrgClass, options.queryParams)\n // bindings = await queryDbpedia(sparql)\n } catch (err) {\n complain('Error querying db of organizations: ' + err)\n inputEventHandlerLock = false\n return\n }\n candidatesLoaded = true\n const loadedEnough = bindings.length < AUTOCOMPLETE_LIMIT\n if (loadedEnough) {\n lastFilter = filter\n } else {\n lastFilter = null\n }\n clearList()\n const slimmed = filterByLanguage(bindings, languagePrefs)\n if (loadedEnough && slimmed.length <= AUTOCOMPLETE_ROWS_STRETCH) {\n numberOfRows = slimmed.length // stretch if it means we get all items\n }\n allDisplayed = loadedEnough && slimmed.length <= numberOfRows\n console.log(` Filter:\"${filter}\" bindings: ${bindings.length}, slimmed to ${slimmed.length}; rows: ${numberOfRows}, Enough? ${loadedEnough}, All displayed? ${allDisplayed}`)\n slimmed.slice(0, numberOfRows).forEach(binding => {\n const row = table.appendChild(dom.createElement('tr'))\n style.setStyle(row, 'autocompleteRowStyle')\n const uri = binding.subject.value\n const name = binding.name?.value\n row.setAttribute('style', 'padding: 0.3em;')\n row.setAttribute('subject', uri)\n row.style.color = allDisplayed ? '#080' : '#000' // green means 'you should find it here'\n row.textContent = name || ''\n row.addEventListener('click', async _event => {\n console.log(' click row textContent: ' + row.textContent)\n console.log(' click name: ' + name)\n gotIt(store.sym(uri), name || '')\n })\n })\n }\n inputEventHandlerLock = false\n } // refreshList\n\n /* sparqlForSearch\n*\n* name -- e.g., \"mass\"\n* theType -- e.g., <http://umbel.org/umbel/rc/EducationalOrganization>\n*/\n /*\n function sparqlForSearch (name:string, theType:NamedNode):string {\n const clean = name.replace(/\\W/g, '') // Remove non alphanum so as to protect regexp\n const sparql = `select distinct ?subject, ?name where {\n ?subject a <${theType.uri}>; rdfs:label ?name\n FILTER regex(?name, \"${clean}\", \"i\")\n } LIMIT ${AUTOCOMPLETE_LIMIT}`\n return sparql\n }\n*/\n const OrgClass = options.class // kb.sym('http://umbel.org/umbel/rc/EducationalOrganization') // @@@ other\n if (options.acceptButton) {\n options.acceptButton.addEventListener('click', acceptButtonHandler, false)\n }\n if (options.cancelButton) {\n // options.cancelButton.addEventListener('click', cancelButtonHandler, false)\n }\n\n // @ts-ignore\n let candidatesLoaded = false\n const runningTimeout = null\n let inputEventHandlerLock = false\n let allDisplayed = false\n var lastFilter: string | null = null\n var numberOfRows = AUTOCOMPLETE_ROWS\n const div = dom.createElement('div')\n var foundName: string | null = null // once found accepted string must match this\n var foundObject: NamedNode | null = null\n var table = div.appendChild(dom.createElement('table'))\n table.setAttribute('style', 'max-width: 30em; margin: 0.5em;')\n const head = table.appendChild(dom.createElement('tr'))\n style.setStyle(head, 'autocompleteRowStyle')\n const cell = head.appendChild(dom.createElement('td'))\n const searchInput = cell.appendChild(dom.createElement('input'))\n searchInput.setAttribute('type', 'text')\n const searchInputStyle = style.searchInputStyle ||\n 'border: 0.1em solid #444; border-radius: 0.5em; width: 100%; font-size: 100%; padding: 0.1em 0.6em' // @\n searchInput.setAttribute('style', searchInputStyle)\n searchInput.addEventListener('keyup', function (event) {\n if (event.keyCode === 13) {\n acceptButtonHandler(event)\n }\n }, false)\n\n searchInput.addEventListener('input', inputEventHHandler)\n return div\n} // renderAutoComplete22q1\n"],"mappings":"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","ignoreList":[]}
|