|
8 | 8 | * organizations to take some action on. |
9 | 9 | * |
10 | 10 | */ |
| 11 | +import escape from 'escape-html' |
11 | 12 |
|
12 | 13 | import { iconBase } from '../iconBase' |
| 14 | +import ns from '../ns' |
| 15 | +import kb from '../store' |
13 | 16 |
|
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