Skip to content
This repository was archived by the owner on Jan 18, 2025. It is now read-only.
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/core/async.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export async function findAsync<T>(arr: Array<T>, asyncCallback: (item: T) => Pr

export const mapAsync = async <T, R>(arr: Array<T>, asyncCallback: (item: T) => Promise<R>): Promise<Array<R>> =>
Promise.all(arr.map(asyncCallback))

export const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms))
1 change: 1 addition & 0 deletions src/core/collections.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const filterNotEmpty = <T>(array: T[]): T[] => array.filter(x => x)
1 change: 1 addition & 0 deletions src/core/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const localLanguage = () => navigator.language.substr(0,2)
4 changes: 2 additions & 2 deletions src/resolver/url-match-pattern.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const URL_match_pattern: Resolver = {
const id = applicable[0].value
const ci = applicable[0].valueIsCaseInsensitive

return await this.getEntityByRegexedId(prop, id, ci)
return this.getEntityByRegexedId(prop, id, ci)
},
getEntityByRegexedId: async function(prop, id, ci = false) {
const cached = await this.checkIfCached(prop, id)
Expand Down Expand Up @@ -106,7 +106,7 @@ const URL_match_pattern: Resolver = {
cache.externalIDCache = {}
}
cache.externalIDCache[this.formCacheKey(prop, id)] = entityId
browser.storage.local.set(cache)
return browser.storage.local.set(cache)
}
}

Expand Down
127 changes: 127 additions & 0 deletions src/sidebar/components/add-property.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import './express/express.css'
import * as browser from 'webextension-polyfill'
import {useEffect, useRef, useState} from 'react'

interface Suggestion {
id: string
datatype: string
label: string
description: string
}

//todo move
export function useComponentVisible(ref, initialIsVisible = false) {
const [isComponentVisible, setIsComponentVisible] = useState(initialIsVisible)
// const ref = useRef(null)

const handleClickOutside = (event) => {
if (ref.current && !ref.current.contains(event.target)) {
setIsComponentVisible(false)
}
}

useEffect(() => {
document.addEventListener('click', handleClickOutside, true)
return () => {
document.removeEventListener('click', handleClickOutside, true)
}
}, [])

return [isComponentVisible, setIsComponentVisible]
}

export const AddProperty = () => {
const [suggestions, setSuggestions] = useState<Array<Suggestion>>([])
const [searchString, setSearchString] = useState('')
const [selectedDescription, setSelectedDescription] = useState('')
const autoCompleteRef = useRef(null)
const [showSuggestions, setShowSuggestions] = useComponentVisible(autoCompleteRef, false)

const updateAutocomplete = async function (e) {
setSearchString(e.target.value)
setShowSuggestions(true)

const response = await fetch(`https://www.wikidata.org/w/api.php?action=wbsearchentities&search=${e.target.value}&format=json&errorformat=plaintext&language=en&uselang=en&type=property`)
const result = await response.json()
console.log(result)
if (result.search) setSuggestions(result.search)
}

// todo hide suggestion on blur
return <div className="express">
<div className="express__main" ref={autoCompleteRef}>
<input
type="search"
value={searchString}
className="express__pick"
onChange={updateAutocomplete}
onFocus={updateAutocomplete}
/>

{showSuggestions &&
<ul
className="express__autocomplete"
onBlur={() => setShowSuggestions(false)}
>
{suggestions.map(it =>
<li key={it.id}
className="express__autocomplete-option"

onClick={() => {
setSearchString(it.label)
setSelectedDescription(it.description)
setShowSuggestions(false)
}}
>
<strong className="express__autocomplete__label">{it.label}</strong>
<div
className="express__autocomplete__description">{it.description + ' ' + it.datatype}</div>
</li>)}
</ul>}
<div className="express__desc">{selectedDescription}</div>
</div>
</div>
}


// const updateAutocompleteO = async function (e) {
// let response = await fetch(`https://www.wikidata.org/w/api.php?action=wbsearchentities&search=${e.target.value}&format=json&errorformat=plaintext&language=en&uselang=en&type=property`)
// response = await response.json()
// for (const suggestion of response.search) {
//
// const item = document.createElement('li')
// if (!supportedProperties.includes(suggestion.datatype)) {
// item.classList.add('express__autocomplete-option--unsupported')
// item.setAttribute('title', 'Data type not supported')
// } else {
// item.setAttribute('tabindex', '0')
// const activationEvent = () => {
// wrapper.setAttribute('data-prop', suggestion.id)
// wrapper.setAttribute('data-datatype', suggestion.datatype)
//
// browser.storage.local.set({
// lastUsedProp: {
// prop: suggestion.id,
// name: suggestion.label,
// desc: suggestion.description,
// datatype: suggestion.datatype,
// },
// })
// wrapper.dispatchEvent(new Event('change'))
// }
// item.addEventListener('keydown', (e) => {
// if (e.key === 'Enter') {
// activationEvent()
// }
// })
// }
// }
// }

const supportedProperties = [
'monolingualtext',
'string',
'wikibase-item',
'wikibase-lexeme',
'wikibase-property',
]
45 changes: 45 additions & 0 deletions src/sidebar/components/claims.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {useEffect, useRef} from 'react'
import {Claim, renderStatement} from "../render-claims"
import {AddProperty} from "./add-property"

export interface ClaimsProps {
statements: {id: string, claims: Claim[]}[]
renderingCache: any
}

export const Claims = (props: ClaimsProps) => {
return <div>
<ExistingClaims {...props}/>
<AddClaims></AddClaims>
</div>
}

// Integration based on https://reactjs.org/docs/integrating-with-other-libraries.html
export const ExistingClaims = ({statements, renderingCache}: ClaimsProps) => {
const reference = useRef<HTMLDivElement>(null)
useEffect(() => {
const rendered = statements
.map(it => renderStatement(it.claims, renderingCache))
.filter(Boolean)
.map(claim => claim.rendered)

reference.current?.append(...rendered)
})

return <div className='claims' ref={reference}/>
}

/**
* todo have a shortcut
* in "edit mode" - automatically add an empty claim field when prev is filled
* see example in https://github.com/openshift/angular-key-value-editor
*
* saving incrementally vs saving on exiting edit mode?
*/
const AddClaims = () => {
return <div className='remark'>

<AddProperty></AddProperty>
</div>

}
14 changes: 4 additions & 10 deletions src/sidebar/components/express/express.tpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { getValueByLang } from '../../get-value-by-lang.js';
import { getAutodesc } from '../../get-autodesc.js';
import browser from 'webextension-polyfill'

import './express.css'


const express = (vars) => {

const supportedProperties = [
Expand Down Expand Up @@ -87,12 +90,6 @@ const express = (vars) => {

main.appendChild(input);

let style = document.createElement('link');
style.setAttribute('rel', "stylesheet");
style.setAttribute('href', "components/express/express.css");

wrapper.appendChild(style);

main.appendChild(autocomplete);
main.appendChild(desc);

Expand Down Expand Up @@ -182,11 +179,8 @@ const express = (vars) => {
selection: selection,
options: options,
composer: composer,
// todo pass in setLanguage instead
languagePicker: languagePicker,
loadingFinished: function() {
progress.remove();
input.focus();
}
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/sidebar/components/join/join.tpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import { getAutodesc } from '../../get-autodesc.js';

let joinCounter = 0;

const join = (vars) => {
const join = (vars) => {
let wrapper = document.createElement('div');
wrapper.classList.add('join');

let humanField = document.createElement('input');
humanField.classList.add('join__field');
humanField.setAttribute('type', 'search');
Expand Down Expand Up @@ -50,7 +50,7 @@ const join = (vars) => {
});
}

if (suggestions) {
if (suggestions) {
for (let suggestion of suggestions) {
let item = document.createElement('button');
item.setAttribute('tabindex', '0');
Expand All @@ -76,13 +76,12 @@ const join = (vars) => {
});
}
}
for (let placeholder of proposals.querySelectorAll('.join__proposal__desc--placeholder')) {
for (let placeholder of proposals.querySelectorAll('.join__proposal__desc--placeholder')) {
let entityWithoutDesc = placeholder.parentNode.getAttribute('data-entity');
placeholder.innerText = await getAutodesc(entityWithoutDesc);
}
}

//humanField.addEventListener('change', updateList);
humanField.addEventListener('focus', updateList);
humanField.addEventListener('keyup', updateList);

Expand Down
Loading