Skip to content

Commit d225fd7

Browse files
committed
WIP people picker
1 parent 2af622d commit d225fd7

3 files changed

Lines changed: 120 additions & 4 deletions

File tree

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
],
1010
"scripts": {
1111
"build-lib": "babel src -d lib",
12-
"build-browserified": "browserify -r ./src/index.js:solid-ui -t babelify --exclude 'xhr2' --exclude 'rdflib' > dist/solid-ui.js",
13-
"build-minified": "browserify -r ./src/index.js:solid-ui -t babelify --exclude 'xhr2' --exclude 'rdflib' -d -p [minifyify --no-map] > dist/solid.min.js",
12+
"build-browserified": "browserify -r ./src/index.js:solid-ui -t babelify --exclude 'xhr2' > dist/solid-ui.js",
13+
"build-minified": "browserify -r ./src/index.js:solid-ui -t babelify --exclude 'xhr2' -d -p [minifyify --no-map] > dist/solid.min.js",
1414
"prebuild": "npm run clean && mkdir -p dist",
1515
"build": "npm run build-lib && npm run build-browserified && npm run build-minified",
1616
"clean": "rm -rf dist/ && rm -rf lib/",
@@ -43,6 +43,7 @@
4343
},
4444
"homepage": "https://github.com/linkeddata/solid-ui",
4545
"dependencies": {
46+
"escape-html": "^1.0.3",
4647
"rdflib": "^0.12.1",
4748
"solid-client": "^0.22.4"
4849
},

src/widgets/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
var widgets = module.exports = Object.assign(
2222
{},
2323
{
24-
peoplePicker: require('./peoplePicker').default
24+
PeoplePicker: require('./peoplePicker').default
2525
}
2626
)
2727

src/widgets/peoplePicker.js

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,122 @@
88
* organizations to take some action on.
99
*
1010
*/
11+
import escape from 'escape-html'
1112

1213
import { iconBase } from '../iconBase'
14+
import ns from '../ns'
15+
import kb from '../store'
1316

14-
export default class PeoplePicker {}
17+
// Note: it's the established pattern to stick all semantic data in the global store.
18+
// This probably means that I'm going to:
19+
// 1) stick all new webIds in the global store
20+
// 2) fetch and store metadata about those webIds in the global store
21+
// 3) keep local track (an ordered set of webIds, for example) of which of those global
22+
// webIds belong to the people picker.
23+
24+
export default class PeoplePicker {
25+
constructor (element, handleDonePicking) {
26+
this.element = element
27+
this.handleDonePicking = handleDonePicking
28+
this.pickedWebIds = new Set()
29+
}
30+
31+
render () {
32+
// This could be more efficient and readable using a view library
33+
const dropContainer = document.createElement('div')
34+
dropContainer.style.maxWidth = '75%'
35+
dropContainer.style.minHeight = '200px'
36+
dropContainer.style.outline = '1px solid black'
37+
38+
dropContainer.addEventListener('dragOver', event => {
39+
// This is required to allow a drop; the 'default' handling of a drop is
40+
// to prevent it
41+
event.preventDefault()
42+
// One thing to do is to check the type of the thing being dragged
43+
// and only prevent default if it's the type of thing we want to allow
44+
// being dropped
45+
console.log('drag over!')
46+
console.log(event)
47+
})
48+
49+
dropContainer.addEventListener('dragEnter', event => {
50+
event.preventDefault()
51+
console.log('drag enter!')
52+
console.log(event)
53+
})
54+
55+
dropContainer.addEventListener('drop', event => {
56+
console.log('dropped!')
57+
console.log(event)
58+
})
59+
60+
const peopleUl = document.createElement('ul')
61+
this.pickedWebIds
62+
.forEach(webId => {
63+
const personLi = document.createElement('li')
64+
new Person(personLi, webId, () => { console.log('not yet handling remove') }).render()
65+
peopleUl.appendChild(personLi)
66+
})
67+
68+
dropContainer.appendChild(peopleUl)
69+
70+
this.element.innerHTML = ''
71+
this.element.appendChild(dropContainer)
72+
return this
73+
}
74+
75+
// TODO: make this handle URIs
76+
// TODO: validate the webIds
77+
// - check the solid spec; pretty sure must at least be a foaf:person?
78+
add (webId) {
79+
return new Promise((resolve, reject) => {
80+
kb.fetcher.nowOrWhenFetched(webId, (ok, err) => {
81+
if (!ok) {
82+
// TODO: render an error widget with the 'err' message
83+
reject(err)
84+
} else {
85+
this.pickedWebIds.add(webId)
86+
this.render()
87+
resolve(webId)
88+
}
89+
})
90+
})
91+
}
92+
}
93+
94+
class Person {
95+
constructor (element, webId, handleRemove) {
96+
this.webId = webId
97+
this.element = element
98+
this.handleRemove = handleRemove
99+
}
100+
101+
render () {
102+
const personDiv = document.createElement('div')
103+
104+
// TODO: take a look at UI.widgets.setName
105+
const imgSrc = this.getWithDefault(ns.foaf('img'), iconBase + 'noun_15059.svg')
106+
const profileImg = document.createElement('img')
107+
profileImg.src = escape(imgSrc)
108+
109+
// TODO: take a look at UI.widgets.setImage
110+
const name = this.getWithDefault(ns.foaf('name'), `[${this.webId}]`)
111+
const nameSpan = document.createElement('span')
112+
nameSpan.innerHTML = escape(name)
113+
114+
const removeButton = document.createElement('button')
115+
removeButton.addEventListener('click', event => this.handleRemove())
116+
117+
personDiv.appendChild(profileImg)
118+
personDiv.appendChild(nameSpan)
119+
personDiv.appendChild(removeButton)
120+
121+
this.element.innerHTML = ''
122+
this.element.appendChild(personDiv)
123+
return this
124+
}
125+
126+
getWithDefault (predicate, defaultValue) {
127+
return kb.anyValue($rdf.namedNode(this.webId), predicate) || defaultValue
128+
}
129+
}

0 commit comments

Comments
 (0)