Skip to content
Closed
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
69 changes: 69 additions & 0 deletions dashboard/dashboardPane.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { PaneDefinition, SolidSession } from "../types"
import solidUi, { SolidUi } from "solid-ui"
import paneRegistry from "pane-registry"
import { NamedNode, sym } from "rdflib"
import { generateHomepage } from "./homepage"

let panes: any
let UI: SolidUi

const nodeMode = (typeof module !== "undefined")

if (nodeMode) {
UI = solidUi
panes = paneRegistry
} else { // Add to existing mashlib
panes = (window as any).panes
UI = panes.UI
}

export const dashboardPane: PaneDefinition = {
icon: UI.icons.iconBase + "noun_547570.svg",
name: "dashboard",
label: (subject) => {
if (subject.uri === subject.site().uri) {
return "Dashboard"
}
return null
},
render: (subject, dom) => {
const container = dom.createElement("div")
const webId = UI.authn.currentUser()
buildPage(container, webId, dom, subject)
UI.authn.solidAuthClient.trackSession(async (session: SolidSession) => {
container.innerHTML = ""
buildPage(container, session ? sym(session.webId) : null, dom, subject)
})

return container
}
}

function buildPage (container: HTMLElement, webId: NamedNode | null, dom: HTMLDocument, subject: NamedNode) {
if (!webId) {
return buildHomePage(container, subject)
}
if (webId.site().uri === subject.site().uri) {
return buildDashboard(container, dom)
}
return buildHomePage(container, subject)
}

function buildDashboard (container: HTMLElement, dom: HTMLDocument) {
const outliner = panes.getOutliner(dom)
outliner.showDashboard(container)
}

function buildHomePage (container: HTMLElement, subject: NamedNode) {
const wrapper = document.createElement('div')
container.appendChild(wrapper)
const shadow = wrapper.attachShadow({ mode: 'open' })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the homepage is shown inside the data browser in the area reserved for the Pane, is that correct? I also just realised that Shadow DOM isn't supported in IE11, is that something we're OK with?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The data browser is currently not working with IE at all - so in my mind, it is not something we can prioritize at the moment.

But we should be mindful of this in the future, so glad that you mentioned this.

const link = document.createElement('link')
link.rel = 'stylesheet'
link.href = '/common/css/bootstrap.min.css'
shadow.appendChild(link)
generateHomepage(subject, UI.store, UI.store.fetcher).then(homepage => shadow.appendChild(homepage))
}


export default dashboardPane
67 changes: 67 additions & 0 deletions dashboard/homepage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import $rdf, { Fetcher, IndexedFormula, NamedNode } from "rdflib"
import UI from "solid-ui"

const ns = UI.ns

export async function generateHomepage(subject: NamedNode, store: IndexedFormula, fetcher: Fetcher): Promise<HTMLElement> {
const pod = subject.site().uri
const ownersProfile = await loadProfile(`${pod}/profile/card#me`, fetcher)
const name = getName(store, ownersProfile)

const wrapper = document.createElement('div')
wrapper.classList.add('container')
wrapper.appendChild(createTitle(ownersProfile.uri, name))
wrapper.appendChild(createDataSection(name))

return wrapper
}

function createDataSection(name: string): HTMLElement {
const dataSection = document.createElement('section')

const title = document.createElement('h2')
title.innerText = 'Data'
dataSection.appendChild(title)

const listGroup = document.createElement('div')
listGroup.classList.add('list-group')
dataSection.appendChild(listGroup)

const publicDataLink = document.createElement('a')
publicDataLink.classList.add('list-group-item')
publicDataLink.href = '/public/'
publicDataLink.innerText = `View ${name}'s files`
listGroup.appendChild(publicDataLink)

return dataSection
}

function createTitle(uri: string, name: string): HTMLElement {
const profileLink = document.createElement('a')
profileLink.href = uri
profileLink.innerText = name

const profileLinkPost = document.createElement('span')
profileLinkPost.innerText = `'s Pod`

const title = document.createElement('h1')
title.appendChild(profileLink)
title.appendChild(profileLinkPost)

return title
}


async function loadProfile(profileUrl: string, fetcher: Fetcher): Promise<NamedNode> {
const webId = $rdf.sym(profileUrl)
await fetcher.load(webId)
return webId
}



function getName (store: IndexedFormula, ownersProfile: NamedNode): string {
return (store.anyValue as any)(ownersProfile, ns.vcard("fn"), null, ownersProfile.doc())
|| (store.anyValue as any)(ownersProfile, ns.foaf("name"), null, ownersProfile.doc())
|| new URL(ownersProfile.uri).host.split('.')[0]
}
1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ if (typeof window !== 'undefined') {

let register = panes.register

register(require('./dashboard/dashboardPane').default)
register(require('issue-pane'))
register(require('contacts-pane'))

Expand Down
96 changes: 33 additions & 63 deletions outline/manager.js
Original file line number Diff line number Diff line change
Expand Up @@ -274,17 +274,20 @@ module.exports = function (doc) {
/** Render Tabbed set of home app panes
* @returns {Element} - the div
*/
function globalAppTabs () {
function globalAppTabs (selectedTab) {
const div = dom.createElement('div')
const me = UI.authn.currentUser()
if (!me) {
alert('Must be logged in for this')
throw new Error('Not logged in')
}
function renderTab (div, item) {
const map = { 'home': 'Your stuff',
'trustedApplications': 'Web apps you trust',
'profile': 'Edit your profile' }
const map = {
'home': 'Your stuff',
'trustedApplications': 'Preferences',
'profile': 'Edit your profile'
}
div.dataset.name = item
div.textContent = map[item] || item
}

Expand All @@ -304,45 +307,24 @@ module.exports = function (doc) {
renderTab,
ordered: true,
orientation: 0,
backgroundColor: '#eeeeee'} // black?
backgroundColor: '#eeeeee',
selectedTab} // black?
// options.renderTabSettings = renderTabSettings No tab-specific settings
div.appendChild(UI.tabs.tabWidget(options))
div.appendChild(UI.widgets.cancelButton(dom, event => {
div.parentNode.removeChild(div)
}))
return div
}
/** Global Navigation tool
**
** This gives the user the ability to find and do stuff sfrom no context
*/
function globalNavigationBox (tr, menuButtonId) {
const buttonStyle = 'padding: 0.3em 0.5em; border-radius:0.2em; margin: 0 0.4em; font-size: 100%;' // @@
const globalNav = dom.createElement('nav')
var expanded = false
var expandedControl
globalNav.style = 'padding: 0; margin: 0; height: 100%; max-height: 2em;' +
'display:flex; justify-content: flex-end; flex-grow: 1; align-items: center;'
// globalNav.style.backgroundColor = '#884488' // @@ placeholder

var menuButton = dom.createElement('img')
menuButton.id = menuButtonId
menuButton.setAttribute('src', UI.icons.iconBase + 'noun_547570.svg') // Lines (could also use dots or home or hamburger
menuButton.style = 'padding: 0.2em;'
menuButton.addEventListener('click', event => {
if (expanded) {
expandedControl.parentNode.removeChild(expandedControl)
} else {
if (tr.nextSibling) tr.parentElement.removeChild(tr.nextSibling) // @@ hack - should use pane code
expandedControl = tr.parentElement.appendChild(globalAppTabs())
}
expanded = !expanded
})
menuButton.style = buttonStyle
menuButton.style.maxHeight = iconHeight
globalNav.appendChild(menuButton)
return globalNav

function showDashboard (container, unselectCurrentPane, globalPaneToSelect) {
container.innerHTML = ''
// console.log(container)
const currentPane = dom.querySelector('#outline .paneShown')
if (unselectCurrentPane && currentPane) {
// eslint-disable-next-line no-undef
// currentPane.dispatchEvent(new Event('click'))
}
return container.appendChild(globalAppTabs(globalPaneToSelect))
}
this.showDashboard = showDashboard

function expandedHeaderTR (subject, requiredPane, options) {
function renderPaneIconTray (td) {
Expand Down Expand Up @@ -433,10 +415,13 @@ module.exports = function (doc) {
dom.getElementById('queryButton').removeAttribute('style')
}
var second = t.firstChild.nextSibling
if (second) t.insertBefore(paneDiv, second)
else t.appendChild(paneDiv)
paneDiv.pane = pane
paneDiv.paneButton = ico
var row = dom.createElement('tr')
var cell = row.appendChild(dom.createElement('td'))
cell.appendChild(paneDiv)
if (second) t.insertBefore(row, second)
else t.appendChild(row)
row.pane = pane
row.paneButton = ico
}
var state
state = ico.getAttribute('class')
Expand Down Expand Up @@ -501,24 +486,6 @@ module.exports = function (doc) {

header.appendChild(renderPaneIconTray(td))

if (options.solo) {
const menuButtonId = 'GlobalUserMenuButton'
td.appendChild(globalNavigationBox(tr, menuButtonId))
UI.authn.solidAuthClient.trackSession(function (session) {
const menuButton = document.getElementById(menuButtonId)
if (!menuButton) {
return
}
const isHidden = menuButton.style.display === 'none'
console.log(isHidden)
if (session) {
menuButton.style.display = 'block'
} else {
menuButton.style.display = 'none'
}
})
}

// set DOM methods
tr.firstChild.tabulatorSelect = function () {
setSelected(this, true)
Expand Down Expand Up @@ -588,12 +555,15 @@ module.exports = function (doc) {
pre.appendChild(dom.createTextNode(UI.utils.stackString(e)))
}

var row = dom.createElement('tr')
var cell = row.appendChild(dom.createElement('td'))
cell.appendChild(paneDiv)
if (tr1.firstPane.requireQueryButton && dom.getElementById('queryButton')) {
dom.getElementById('queryButton').removeAttribute('style')
}
table.appendChild(paneDiv)
paneDiv.pane = tr1.firstPane
paneDiv.paneButton = tr1.paneButton
table.appendChild(row)
row.pane = tr1.firstPane
row.paneButton = tr1.paneButton
}

return table
Expand Down
31 changes: 31 additions & 0 deletions types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,34 @@ interface NewPaneOptions {
pane: PaneDefinition;
refreshTarget: HTMLTableElement;
}

export interface SolidSession {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Time for another PR to DefinitelyTyped, I guess? :)

authorization: SolidAuthorization;
credentialType: string;
idClaims: SolidClaim;
idp: string;
issuer: string;
sessionKey: string;
webId: string;
}

interface SolidAuthorization {
access_token: string;
client_id: string;
id_token: string;
}

interface SolidClaim {
at_hash: string;
aud: string;
azp: string;
cnf: {
jwk: string;
};
exp: number;
iat: number;
iss: string;
jti: string;
nonce: string;
sub: string;
}