lucos_search_component 0.1.1 → 0.1.3
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/README.md +38 -4
- package/dist/index.js +73 -17
- package/example/index.html +25 -19
- package/package.json +1 -1
- package/web-components/lucos-lang.js +73 -17
package/README.md
CHANGED
|
@@ -6,22 +6,56 @@ Web Component for searching lucOS data
|
|
|
6
6
|
* Web Components
|
|
7
7
|
|
|
8
8
|
## Usage
|
|
9
|
+
|
|
9
10
|
Include the following in your javascript:
|
|
10
11
|
```
|
|
11
12
|
import 'lucos_search_component';
|
|
12
13
|
```
|
|
13
14
|
|
|
15
|
+
Then pick the relevant component
|
|
16
|
+
### Search
|
|
17
|
+
|
|
18
|
+
Searches all items available in [lucos_arachne](https://github.com/lucas42/lucos_arachne)
|
|
19
|
+
|
|
14
20
|
Include the following in your html:
|
|
15
21
|
```
|
|
16
22
|
<span is="lucos-search">
|
|
17
|
-
<select>
|
|
18
|
-
<option>
|
|
19
|
-
<option>
|
|
20
|
-
<option>
|
|
23
|
+
<select multiple>
|
|
24
|
+
<option selected>https://contacts.l42.eu/people/2</option>
|
|
25
|
+
<option selected>https://eolas.l42.eu/metadata/place/2/</option>
|
|
26
|
+
<option selected>https://media-metadata.l42.eu/tracks/13713</option>
|
|
21
27
|
</select>
|
|
22
28
|
</span>
|
|
23
29
|
```
|
|
30
|
+
Selected options use the item's URI as their value.
|
|
31
|
+
|
|
32
|
+
The following attributes can be added to the lucos-search span:
|
|
33
|
+
* **data-api-key** \[required\] — a valid API key for the production instance of [lucos_arachne](https://github.com/lucas42/lucos_arachne), as generated by [lucos_creds](https://github.com/lucas42/lucos_creds).
|
|
34
|
+
* **data-types** — A comma separated list of item types to search for (defaults to all types).
|
|
35
|
+
* **data-exclude-types** — A comma separated list of item types to exclude from the search (ignored if `data-types` is set).
|
|
36
|
+
|
|
37
|
+
### Languages
|
|
38
|
+
|
|
39
|
+
Language selector, grouped by language families.
|
|
40
|
+
|
|
41
|
+
Include the following in your html:
|
|
42
|
+
```
|
|
43
|
+
<span is="lucos-lang">
|
|
44
|
+
<select multiple>
|
|
45
|
+
<option selected>en</option>
|
|
46
|
+
<option selected>ga</option>
|
|
47
|
+
<option selected>ain</option>
|
|
48
|
+
</select>
|
|
49
|
+
</span>
|
|
50
|
+
```
|
|
51
|
+
Selected options use a language's ISO 639 code.
|
|
52
|
+
Note: [lucos_arachne](https://github.com/lucas42/lucos_arachne) has a mixture of ISO 639-1, ISO 639-2, ISO 639-3 and ISO 639-6 codes as well as some custom codes for artificial languages. The code used must match what's in lucos_arachne.
|
|
53
|
+
|
|
24
54
|
|
|
55
|
+
The following attributes can be added to the lucos-lang span:
|
|
56
|
+
* **data-api-key** \[required\] — a valid API key for the production instance of [lucos_arachne](https://github.com/lucas42/lucos_arachne), as generated by [lucos_creds](https://github.com/lucas42/lucos_creds).
|
|
57
|
+
* **data-no-lang** — The name to give for a "no language" option. Defaults to not having a no language option. If selected, the code returned will be `zxx` (The ISO 639 code which denotes absence of linguistic content)
|
|
58
|
+
* **data-common** — A comma separated list of language codes to put in a separate "Common Languages" group at the top of the selections. This removes the provided languages from their normal family; they'll only be listed under Common Languages. Unrecognised language codes in this list are ignored.
|
|
25
59
|
|
|
26
60
|
## Manual Testing
|
|
27
61
|
|
package/dist/index.js
CHANGED
|
@@ -5823,7 +5823,7 @@ customElements.define('lucos-search', LucosSearchComponent, { extends: "span" })
|
|
|
5823
5823
|
|
|
5824
5824
|
class LucosLangComponent extends HTMLSpanElement {
|
|
5825
5825
|
static get observedAttributes() {
|
|
5826
|
-
return ['data-api-key'];
|
|
5826
|
+
return ['data-api-key','data-no-lang', 'data-common'];
|
|
5827
5827
|
}
|
|
5828
5828
|
constructor() {
|
|
5829
5829
|
super();
|
|
@@ -5869,6 +5869,9 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
5869
5869
|
color: inherit;
|
|
5870
5870
|
text-decoration: none;
|
|
5871
5871
|
}
|
|
5872
|
+
.optgroup-header {
|
|
5873
|
+
text-transform: capitalize;
|
|
5874
|
+
}
|
|
5872
5875
|
`;
|
|
5873
5876
|
shadow.appendChild(mainStyle);
|
|
5874
5877
|
|
|
@@ -5880,6 +5883,8 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
5880
5883
|
valueField: 'code',
|
|
5881
5884
|
labelField: 'label',
|
|
5882
5885
|
searchField: ['code','label'],
|
|
5886
|
+
optgroupField: 'family',
|
|
5887
|
+
lockOptgroupOrder: true,
|
|
5883
5888
|
closeAfterSelect: true,
|
|
5884
5889
|
plugins: {
|
|
5885
5890
|
remove_button:{
|
|
@@ -5893,10 +5898,35 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
5893
5898
|
},
|
|
5894
5899
|
// On startup, update any existing options with latest data from search
|
|
5895
5900
|
onInitialize: async function() {
|
|
5896
|
-
const
|
|
5897
|
-
|
|
5898
|
-
|
|
5899
|
-
|
|
5901
|
+
const families = await component.getLanguageFamilies();
|
|
5902
|
+
const languages = await component.getLanguages();
|
|
5903
|
+
|
|
5904
|
+
// If there's an attribute for a no language option, put that top of the list
|
|
5905
|
+
if (component.hasAttribute("data-no-lang")) {
|
|
5906
|
+
languages.unshift({
|
|
5907
|
+
code: 'zxx', // ISO 639 code to denote absence of linguistic content
|
|
5908
|
+
label: component.getAttribute("data-no-lang"),
|
|
5909
|
+
});
|
|
5910
|
+
}
|
|
5911
|
+
if (component.hasAttribute("data-common")) {
|
|
5912
|
+
const commonLangs = component.getAttribute("data-common").split(",");
|
|
5913
|
+
console.log(commonLangs);
|
|
5914
|
+
families.unshift({ // Put common languages as top option
|
|
5915
|
+
code: 'x-common',
|
|
5916
|
+
label: 'common languages',
|
|
5917
|
+
});
|
|
5918
|
+
languages.forEach(language => {
|
|
5919
|
+
if (commonLangs.includes(language.code)) {
|
|
5920
|
+
language.family = 'x-common';
|
|
5921
|
+
}
|
|
5922
|
+
});
|
|
5923
|
+
}
|
|
5924
|
+
families.forEach(family => {
|
|
5925
|
+
this.addOptionGroup(family.code, family);
|
|
5926
|
+
});
|
|
5927
|
+
languages.forEach(language => {
|
|
5928
|
+
this.updateOption(language.code, language); // Updates any existing options which are selected with the correct label
|
|
5929
|
+
this.addOption(language); // Makes the option available for new selections
|
|
5900
5930
|
});
|
|
5901
5931
|
},
|
|
5902
5932
|
onItemSelect: function (item) {
|
|
@@ -5905,7 +5935,11 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
5905
5935
|
},
|
|
5906
5936
|
render:{
|
|
5907
5937
|
item: function(data, escape) {
|
|
5908
|
-
|
|
5938
|
+
if (data.url) {
|
|
5939
|
+
return `<div class="lozenge" data-url="${escape(data.url)}"><a href="${escape(data.url)}" target="_blank">${escape(data.label)}</a></div>`;
|
|
5940
|
+
} else {
|
|
5941
|
+
return `<div class="lozenge">${escape(data.label)}</div>`;
|
|
5942
|
+
}
|
|
5909
5943
|
},
|
|
5910
5944
|
},
|
|
5911
5945
|
});
|
|
@@ -5913,17 +5947,9 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
5913
5947
|
shadow.append(selector.nextElementSibling);
|
|
5914
5948
|
}
|
|
5915
5949
|
}
|
|
5916
|
-
async searchRequest() {
|
|
5950
|
+
async searchRequest(searchParams) {
|
|
5917
5951
|
const key = this.getAttribute("data-api-key");
|
|
5918
5952
|
if (!key) throw new Error("No `data-api-key` attribute set on `lucos-search` component");
|
|
5919
|
-
const searchParams = new URLSearchParams({
|
|
5920
|
-
filter_by: 'type:=Language',
|
|
5921
|
-
query_by: "pref_label",
|
|
5922
|
-
include_fields: "id,pref_label",
|
|
5923
|
-
sort_by: "pref_label:asc",
|
|
5924
|
-
enable_highlight_v1: false,
|
|
5925
|
-
per_page: 200,
|
|
5926
|
-
});
|
|
5927
5953
|
const response = await fetch("https://arachne.l42.eu/search?"+searchParams.toString(), {
|
|
5928
5954
|
headers: { 'X-TYPESENSE-API-KEY': key },
|
|
5929
5955
|
signal: AbortSignal.timeout(900),
|
|
@@ -5932,14 +5958,44 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
5932
5958
|
if (!response.ok) {
|
|
5933
5959
|
throw new Error(`Recieved ${response.status} error from search endpoint: ${data["message"]}`);
|
|
5934
5960
|
}
|
|
5935
|
-
|
|
5961
|
+
return data;
|
|
5962
|
+
}
|
|
5963
|
+
async getLanguages() {
|
|
5964
|
+
const searchParams = new URLSearchParams({
|
|
5965
|
+
filter_by: 'type:=Language',
|
|
5966
|
+
query_by: "pref_label",
|
|
5967
|
+
include_fields: "id,pref_label,lang_family",
|
|
5968
|
+
sort_by: "pref_label:asc",
|
|
5969
|
+
enable_highlight_v1: false,
|
|
5970
|
+
per_page: 200,
|
|
5971
|
+
});
|
|
5972
|
+
const data = await this.searchRequest(searchParams);
|
|
5973
|
+
return data.hits.map(result => {
|
|
5936
5974
|
return {
|
|
5937
5975
|
code: result.document.id.split("/").reverse()[1],
|
|
5938
5976
|
label: result.document.pref_label,
|
|
5939
5977
|
url: result.document.id,
|
|
5978
|
+
family: result.document.lang_family || 'qli', // If no language family is given, using `qli` code as language isolate
|
|
5979
|
+
}
|
|
5980
|
+
});
|
|
5981
|
+
}
|
|
5982
|
+
async getLanguageFamilies() {
|
|
5983
|
+
const searchParams = new URLSearchParams({
|
|
5984
|
+
filter_by: 'type:=Language Family',
|
|
5985
|
+
query_by: "pref_label",
|
|
5986
|
+
include_fields: "id,pref_label",
|
|
5987
|
+
sort_by: "pref_label:asc",
|
|
5988
|
+
enable_highlight_v1: false,
|
|
5989
|
+
per_page: 200,
|
|
5990
|
+
});
|
|
5991
|
+
const data = await this.searchRequest(searchParams);
|
|
5992
|
+
return data.hits.map(result => {
|
|
5993
|
+
return {
|
|
5994
|
+
code: result.document.id.split("/").pop() || 'qli',
|
|
5995
|
+
label: result.document.pref_label,
|
|
5996
|
+
url: result.document.id,
|
|
5940
5997
|
}
|
|
5941
5998
|
});
|
|
5942
|
-
return results;
|
|
5943
5999
|
}
|
|
5944
6000
|
}
|
|
5945
6001
|
customElements.define('lucos-lang', LucosLangComponent, { extends: "span" });
|
package/example/index.html
CHANGED
|
@@ -8,33 +8,39 @@
|
|
|
8
8
|
<label for="search2">No Tracks:</label><span is="lucos-search" data-api-key="${KEY_LUCOS_ARACHNE}" data-exclude_types="Track"><select id="search2"></select></span>
|
|
9
9
|
<label for="search3">Only Cites and Rivers:</label><span is="lucos-search" data-api-key="${KEY_LUCOS_ARACHNE}" data-types="City,River"><select id="search3"></select></span>
|
|
10
10
|
<label for="search4">Load with existing items:</label><span is="lucos-search" data-api-key="${KEY_LUCOS_ARACHNE}"><select id="search4" multiple>
|
|
11
|
-
<option
|
|
12
|
-
<option
|
|
13
|
-
<option
|
|
11
|
+
<option selected>https://contacts.l42.eu/people/2</option>
|
|
12
|
+
<option selected>https://eolas.l42.eu/metadata/place/2/</option>
|
|
13
|
+
<option selected>https://media-metadata.l42.eu/tracks/13713</option>
|
|
14
14
|
</select></span>
|
|
15
15
|
<label for="search5">More than 10:</label>
|
|
16
16
|
<span is="lucos-search" data-api-key="${KEY_LUCOS_ARACHNE}" data-exclude_types="Track"><select id="search5" multiple>
|
|
17
|
-
<option
|
|
18
|
-
<option
|
|
19
|
-
<option
|
|
20
|
-
<option
|
|
21
|
-
<option
|
|
22
|
-
<option
|
|
23
|
-
<option
|
|
24
|
-
<option
|
|
25
|
-
<option
|
|
26
|
-
<option
|
|
27
|
-
<option
|
|
28
|
-
<option
|
|
29
|
-
<option
|
|
17
|
+
<option selected>https://eolas.l42.eu/metadata/place/125/</option>
|
|
18
|
+
<option selected>https://eolas.l42.eu/metadata/place/126/</option>
|
|
19
|
+
<option selected>https://eolas.l42.eu/metadata/place/28/</option>
|
|
20
|
+
<option selected>https://eolas.l42.eu/metadata/place/307/</option>
|
|
21
|
+
<option selected>https://eolas.l42.eu/metadata/place/308/</option>
|
|
22
|
+
<option selected>https://eolas.l42.eu/metadata/place/310/</option>
|
|
23
|
+
<option selected>https://eolas.l42.eu/metadata/place/311/</option>
|
|
24
|
+
<option selected>https://eolas.l42.eu/metadata/place/312/</option>
|
|
25
|
+
<option selected>https://eolas.l42.eu/metadata/place/313/</option>
|
|
26
|
+
<option selected>https://eolas.l42.eu/metadata/place/314/</option>
|
|
27
|
+
<option selected>https://eolas.l42.eu/metadata/place/315/</option>
|
|
28
|
+
<option selected>https://eolas.l42.eu/metadata/place/316/</option>
|
|
29
|
+
<option selected>https://eolas.l42.eu/metadata/place/317/</option>
|
|
30
30
|
</select></span>
|
|
31
31
|
<h1>lucos-lang</h1>
|
|
32
32
|
<label for="lang1">Blank:</label><span is="lucos-lang" data-api-key="${KEY_LUCOS_ARACHNE}"><select id="lang1"></select></span>
|
|
33
33
|
<label for="lang2">Load with existing:</label><span is="lucos-lang" data-api-key="${KEY_LUCOS_ARACHNE}"><select id="lang2" multiple>
|
|
34
|
-
<option
|
|
35
|
-
<option
|
|
36
|
-
<option
|
|
34
|
+
<option selected>ga</option>
|
|
35
|
+
<option selected>emen</option>
|
|
36
|
+
<option selected>art-x-simlish</option>
|
|
37
37
|
</select></span>
|
|
38
|
+
<label for="lang3">No lang option</label><span is="lucos-lang" data-api-key="${KEY_LUCOS_ARACHNE}" data-no-lang="No Language">
|
|
39
|
+
<select id="lang3" multiple><option selected>zxx</option></select>
|
|
40
|
+
</span>
|
|
41
|
+
<label for="lang3">Common languages option</label><span is="lucos-lang" data-api-key="${KEY_LUCOS_ARACHNE}" data-no-lang="No Language" data-common="en,ga,zxx">
|
|
42
|
+
<select id="lang3"></select>
|
|
43
|
+
</span>
|
|
38
44
|
<script src="./built.js"></script>
|
|
39
45
|
</body>
|
|
40
46
|
</html>
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@ import tomSelectStylesheet from 'tom-select/dist/css/tom-select.default.css';
|
|
|
3
3
|
|
|
4
4
|
class LucosLangComponent extends HTMLSpanElement {
|
|
5
5
|
static get observedAttributes() {
|
|
6
|
-
return ['data-api-key'];
|
|
6
|
+
return ['data-api-key','data-no-lang', 'data-common'];
|
|
7
7
|
}
|
|
8
8
|
constructor() {
|
|
9
9
|
super();
|
|
@@ -49,6 +49,9 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
49
49
|
color: inherit;
|
|
50
50
|
text-decoration: none;
|
|
51
51
|
}
|
|
52
|
+
.optgroup-header {
|
|
53
|
+
text-transform: capitalize;
|
|
54
|
+
}
|
|
52
55
|
`;
|
|
53
56
|
shadow.appendChild(mainStyle);
|
|
54
57
|
|
|
@@ -60,6 +63,8 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
60
63
|
valueField: 'code',
|
|
61
64
|
labelField: 'label',
|
|
62
65
|
searchField: ['code','label'],
|
|
66
|
+
optgroupField: 'family',
|
|
67
|
+
lockOptgroupOrder: true,
|
|
63
68
|
closeAfterSelect: true,
|
|
64
69
|
plugins: {
|
|
65
70
|
remove_button:{
|
|
@@ -73,10 +78,35 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
73
78
|
},
|
|
74
79
|
// On startup, update any existing options with latest data from search
|
|
75
80
|
onInitialize: async function() {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
81
|
+
const families = await component.getLanguageFamilies();
|
|
82
|
+
const languages = await component.getLanguages();
|
|
83
|
+
|
|
84
|
+
// If there's an attribute for a no language option, put that top of the list
|
|
85
|
+
if (component.hasAttribute("data-no-lang")) {
|
|
86
|
+
languages.unshift({
|
|
87
|
+
code: 'zxx', // ISO 639 code to denote absence of linguistic content
|
|
88
|
+
label: component.getAttribute("data-no-lang"),
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
if (component.hasAttribute("data-common")) {
|
|
92
|
+
const commonLangs = component.getAttribute("data-common").split(",");
|
|
93
|
+
console.log(commonLangs);
|
|
94
|
+
families.unshift({ // Put common languages as top option
|
|
95
|
+
code: 'x-common',
|
|
96
|
+
label: 'common languages',
|
|
97
|
+
});
|
|
98
|
+
languages.forEach(language => {
|
|
99
|
+
if (commonLangs.includes(language.code)) {
|
|
100
|
+
language.family = 'x-common';
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
}
|
|
104
|
+
families.forEach(family => {
|
|
105
|
+
this.addOptionGroup(family.code, family);
|
|
106
|
+
});
|
|
107
|
+
languages.forEach(language => {
|
|
108
|
+
this.updateOption(language.code, language); // Updates any existing options which are selected with the correct label
|
|
109
|
+
this.addOption(language); // Makes the option available for new selections
|
|
80
110
|
});
|
|
81
111
|
},
|
|
82
112
|
onItemSelect: function (item) {
|
|
@@ -85,7 +115,11 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
85
115
|
},
|
|
86
116
|
render:{
|
|
87
117
|
item: function(data, escape) {
|
|
88
|
-
|
|
118
|
+
if (data.url) {
|
|
119
|
+
return `<div class="lozenge" data-url="${escape(data.url)}"><a href="${escape(data.url)}" target="_blank">${escape(data.label)}</a></div>`;
|
|
120
|
+
} else {
|
|
121
|
+
return `<div class="lozenge">${escape(data.label)}</div>`;
|
|
122
|
+
}
|
|
89
123
|
},
|
|
90
124
|
},
|
|
91
125
|
});
|
|
@@ -93,17 +127,9 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
93
127
|
shadow.append(selector.nextElementSibling);
|
|
94
128
|
}
|
|
95
129
|
}
|
|
96
|
-
async searchRequest() {
|
|
130
|
+
async searchRequest(searchParams) {
|
|
97
131
|
const key = this.getAttribute("data-api-key");
|
|
98
132
|
if (!key) throw new Error("No `data-api-key` attribute set on `lucos-search` component");
|
|
99
|
-
const searchParams = new URLSearchParams({
|
|
100
|
-
filter_by: 'type:=Language',
|
|
101
|
-
query_by: "pref_label",
|
|
102
|
-
include_fields: "id,pref_label",
|
|
103
|
-
sort_by: "pref_label:asc",
|
|
104
|
-
enable_highlight_v1: false,
|
|
105
|
-
per_page: 200,
|
|
106
|
-
});
|
|
107
133
|
const response = await fetch("https://arachne.l42.eu/search?"+searchParams.toString(), {
|
|
108
134
|
headers: { 'X-TYPESENSE-API-KEY': key },
|
|
109
135
|
signal: AbortSignal.timeout(900),
|
|
@@ -112,14 +138,44 @@ class LucosLangComponent extends HTMLSpanElement {
|
|
|
112
138
|
if (!response.ok) {
|
|
113
139
|
throw new Error(`Recieved ${response.status} error from search endpoint: ${data["message"]}`);
|
|
114
140
|
}
|
|
115
|
-
|
|
141
|
+
return data;
|
|
142
|
+
}
|
|
143
|
+
async getLanguages() {
|
|
144
|
+
const searchParams = new URLSearchParams({
|
|
145
|
+
filter_by: 'type:=Language',
|
|
146
|
+
query_by: "pref_label",
|
|
147
|
+
include_fields: "id,pref_label,lang_family",
|
|
148
|
+
sort_by: "pref_label:asc",
|
|
149
|
+
enable_highlight_v1: false,
|
|
150
|
+
per_page: 200,
|
|
151
|
+
});
|
|
152
|
+
const data = await this.searchRequest(searchParams);
|
|
153
|
+
return data.hits.map(result => {
|
|
116
154
|
return {
|
|
117
155
|
code: result.document.id.split("/").reverse()[1],
|
|
118
156
|
label: result.document.pref_label,
|
|
119
157
|
url: result.document.id,
|
|
158
|
+
family: result.document.lang_family || 'qli', // If no language family is given, using `qli` code as language isolate
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
async getLanguageFamilies() {
|
|
163
|
+
const searchParams = new URLSearchParams({
|
|
164
|
+
filter_by: 'type:=Language Family',
|
|
165
|
+
query_by: "pref_label",
|
|
166
|
+
include_fields: "id,pref_label",
|
|
167
|
+
sort_by: "pref_label:asc",
|
|
168
|
+
enable_highlight_v1: false,
|
|
169
|
+
per_page: 200,
|
|
170
|
+
});
|
|
171
|
+
const data = await this.searchRequest(searchParams);
|
|
172
|
+
return data.hits.map(result => {
|
|
173
|
+
return {
|
|
174
|
+
code: result.document.id.split("/").pop() || 'qli',
|
|
175
|
+
label: result.document.pref_label,
|
|
176
|
+
url: result.document.id,
|
|
120
177
|
}
|
|
121
178
|
});
|
|
122
|
-
return results;
|
|
123
179
|
}
|
|
124
180
|
}
|
|
125
181
|
customElements.define('lucos-lang', LucosLangComponent, { extends: "span" });
|