////////////////////
////////////////////
Why High Level ? Because Shighl is based on other libs like solid-auth-client, mostly @solid/query-ldflex, (solid-file-client, tripledoc in the next future)... to give you the most common used functionnalities to deal with session, pod, chat, inbox... using the Solid Project. If you have any question, feel free to ask on the Solid Community Forum
Shighl can be integrated in any gh-page, POD or static WebPage !
use cdn.jsdelivr.net
<script src="https://cdn.jsdelivr.net/gh/scenaristeur/shighl@master/dist/vendor/solid-auth-client.bundle.js"> </script>
<script src="https://cdn.jsdelivr.net/gh/scenaristeur/shighl@master/dist/vendor/solid-query-ldflex.bundle.js"> </script>
<script src="https://cdn.jsdelivr.net/gh/scenaristeur/shighl@master/dist/window/shighl.bundle.js"> </script>
or shighl.bundle.js, solid-query-ldflex.bundle.js, solid-auth-client.bundle.js that you can find in the /dist/ folder.
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-auth-client.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-query-ldflex.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/window/shighl.bundle.js"></script>
install with npm install --save scenaristeur/shighl
and import with
import Shighl from 'shighl'
not tested yet, but there is a node version in the dist folder
You will probably also need to copy the dist/dist-popup folder that provides you the better way to connect to a Solid Pod
const sh = new Shighl()
sh.test() // optional to verify that the lib is loaded
then you must create Objects from Shighl submodules :
Often, you will need to login to your POD. Shighl.session is a simple way to connect to a POD, but you can use the basic solid-auth-client too if you prefer.
const sh = new Shighl()
let session = new sh.session()
function mycallback(webId){
console.log("WebId: ",webId)
if (webId != null){
console.log("logged with ",webId)
}else{
console.log("not logged")
session.login()
}
}
await session.track(mycallback)
Shighl.pod allows you to simply read pods informations.
let sh = new Shighl()
let pod = new sh.pod()
pod.webId = "https://spoggy.solid.community/profile/card#me" // set the webId of the pod you want to read
let name = await pod.name
let photo = await pod.photo
let role = await pod.role
let organization = await pod.organization
let friends = await pod.friends
let pti = await pod.pti
let storage = await pod.storage
console.log("Name: ", name)
console.log("Photo: ", photo)
console.log("Role:", role)
console.log("Organization:", organization)
console.log("Friends: ", friends)
console.log("publicTypeIndex & instances: ", pti)
console.log("Storage: ", storage)
//Loop through friends
friends.forEach(async function(f, i) {
console.log(f.webId)
let f_pod = new sh.pod()
f_pod.webId = f.webId
let f_name = await f_pod.name
let f_role = await f_pod.role
let f_organization = await f_pod.organization
console.log("--"+f_name+" has role "+f_role+" in "+f_organization)
});
Shighl.chat Calendar example Shighl.chat Infinite Scroll example
let pti, chat, webId, user_pod
let sh = new Shighl()
//chat instances
let pod = new sh.pod()
pod.webId = "https://solidarity.inrupt.net/profile/card#me" // set the webId of the POD you want to retrieve the chat channels
pti = await pod.pti // get the publicTypeIndex of that pod
console.log(pti.instances)
// select the first instance with shortClass="LongChat" available in the publictypeIndex
let instance = pti.instances[0]
// create a chat object & initialize it
chat = new sh.chat()
chat.instance = instance
await chat.init
chat.subscribe = on_new_message // subscribe to chat change that launch on_new_message() callback function
// get chat messages of the last day.
let messages = await chat.messages
/* get each message properties and you are free to display them as you want.
use a calendar or a infinite scroll
to display older messages
(see examples above)
*/
for(const message of messages){
console.log(message.makername+" WROTE "+message.content+" AT "+message.date)
}
// Then to interact you will need to connect
let session = new sh.session()
await session.track(mycallback)
async function mycallback(_webId){
webId = _webId
if (webId != null){
user_pod = new sh.pod()
user_pod.webId = webId
}else{
session.login()
}
}
// ... //
//so you can easily send a chat message to the chat previously initialised by
let mess = {content: content, webId: webId, postType: postType, replyTo: replyTo}
chat.message = mess
// and eventually notiy user inbox of a reply/comment on his post (see examples)
// you can create a new channel with
let params = {user_pod: user_pod , url: chat_create_input.value, discoverable: public_check.checked, shortClass: "LongChat"}
console.log(params)
user_pod.pti_new = params
to be able to receive message, you must grant "Authenticated Agent" to "Submitter"
const sh = new Shighl()
let pod = new sh.pod()
let session = new sh.session() // retrieve webId as above
let user_inbox = {}
let inbox = ""
pod.webId = webId // obtained by session callback (see example)
inbox = await pod.inbox
user_inbox = new sh.inbox()
//
inbox_url = inbox // set & get document.getElementById("inbox_input").value in example
let messages = await user_inbox.getMessages(inbox_url)
messages.forEach(function(m){
let text = [ m.senderName, m.senderImg, m.sender, m.label, m.dateSent, m.text, m.url, m.parentItem].join(' || ')
console.log (text)
})
// then you can delete a message with
await user_inbox.delete(m_url)
...
// or send a message to a friend's inbox
async function send(){
let m = {}
m.content = document.getElementById("messageContent").value
m.title = document.getElementById("title").value
m.sender = pod.webId
if (document.getElementById("parentItem").value.length > 0){
m.parentItem = document.getElementById("parentItem").value
}
let w = document.getElementById("writePan").getAttribute("webId")
let p = new sh.pod()
p.webId = w
p_inbox = new sh.inbox(document.getElementById("to").value)
p_inbox.message = m
}
const sh = new Shighl()
.sh
variable representing Shighl object, you can create a pod object with let pod = new sh.pod()
pod.webId = "https://[podname].[provider]/profile/card#me"
const sh = new Shighl()
let pod = new sh.pod()
pod.webId = "https://[podname].[provider]/profile/card#me"
let name = await pod.name;
console.log(name)
That must give you the name of the pod in 5 lines of code
You can now easily get the other properties/attributes of the pod with let photo = await pod.photo
and same with pod.friends, pod.role, pod.storage, pod.pti
pod.pti is a particular object as it represent the publicTypeIndex of the pod with the instances declared in it
An instance is a resource that the pod owner wants you to be able to discover, so that he put a reference to it. A resource could be some text, some image, or any media that is stored on his pod, by him or by someone else. It could also be a resource that is stored on another pod.
You can get each of the instances with
for (const inst of pti.instances){
console.log(inst)
}
Created this way, each instance property/attribute can be obtained by the same way that we used for the pod. To get the instance url use inst.url and to get the instance short class ... inst.shortClass !!! Yeah, yo got it !!!
And that shortClass could be something like "TextDigitalDocument", "MediaObject", "Bookmark", "Meeting", or ... "LongChat" ...
A "LongChat" is an interesting thing on a Solid pod, it allows you to create a chat, a space for discussions. You own it, host it on your pod, give it a name, and a path where you want to put it on your pod. You also can manage the right of access (read/write, person/group). This way everyone can "host" every discussion he wants... I let you imagine what you can do with such functionnality...
For example Solidarity is an UI coded by Julian-Cole and use Shighl to deal with data stored on https://solidarity.inrupt.net/public/Solidarity/ and on https://solidarity.inrupt.net/public/Shighl/ and there is a way to add other Channel that you want...
If, with the above console.log(inst)
you find some instance that have a shortClass property you can try to set that instance in a chat object that you first create from our starting "sh" variable. To create that chat object, do as above a let chat = new sh.chat()
then set the instance property of the chat with that instance chat.instance = instance
and initialize the chat with
let chat = new sh.chat()
chat.instance = [instance]
let chat_details = await chat.init
console.log(chat_details)
let messages = await chat.messages
for(const message of messages){
console.log(message)
}
message.content, message.makername, message.makerimg, message.date
{"_instance":{
"instance":"https://solidarity.inrupt.net/settings/publicTypeIndex.ttl#id1581799359461",
"url":"https://solidarity.inrupt.net/public/Shighl/Shighl/index.ttl#this",
"classe":"http://www.w3.org/ns/pim/meeting#LongChat",
"shortClass":"LongChat"
},
"_folder":"https://solidarity.inrupt.net/public/Shighl/Shighl/",
"_name":"Shighl",
"_years":["2020"],
"_year":"2020",
"_months":["02"],
"_month":"02",
"_days":["15","16","17"],
"_day":"17"
}
plural :
singulier: _year, _month, _day represent the "cursor" where you want to get the messages.
So the example above gives you the messages of the 02/17/2020 or 17/02/2020 in french. To get the message of the day before, just set the _day of your chat object to "16" with something like this
chat._day = "16"
and get the messages of the day as we did before with chat.messages
To create a new "LongChat" use
let params = {user_pod: user_pod , // a pod object of the user that you created with sh variable
url: chat_create_input.value, // the url of the chat
discoverable: public_check.checked, // if it must be in the publictypeindex or not (not implemented yet)
shortClass: "LongChat"} // to build some other things (not implemented yet)
console.log(params)
user_pod.pti_new = params
chat.subscribe = on_new_message
where on_new_message is the name of the callback function that is called when a new message arrive is posted in the chat.What a call back function could be :
function on_new_message(changement){
console.log ("new Message arrived, get it from Websocket", changement)
chatUpdate()
}
An example of this chat functionnalities is running on show INSTANCE EXAMPLE
or codepen (can't log review how to add popuplogin)
const sh = new Shighl()
let pod = new sh.pod()
pod.webId = "https://spoggy.solid.community/profile/card#me" // set "https://spoggy.solid.community/profile/card#me" to pod.webId
let name = await pod.name //get pod.name
console.log(name)
checked function are implemented
[x] pod.name
[x] pod.photo
[x] pod.friends
[x] pod.pti (return publicTypeIndex & instances)
[x] pod.role
[x] pod.storage
[x] pod.name = "New name"
[x] pod.photo = "photo_url" (photo must be stored on your pod, todo copy photo to pod/profile)
[x] pod.role = "New Role"
[ ] pod.pti = for creating a new pti instance (bookmark, notes, longchat...)
<html>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-auth-client.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-query-ldflex.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/window/shighl.bundle.js"></script>
<script>
async function init(){
let sh = new Shighl()
console.log(sh)
let pod = new sh.pod()
pod.webId = "https://spoggy.solid.community/profile/card#me"
let name = await pod.name
let photo = await pod.photo
let friends = await pod.friends
let pti = await pod.pti
let role = await pod.role
let storage = await pod.storage
console.log("Name: ",name)
console.log("Photo: ",photo)
console.log("Friends: ",friends)
console.log("publicTypeIndex & instances: ",pti)
console.log("Role:",role)
console.log("Storage: ",storage)
}
</script>
<body onload="init()">
Look the web console to see the pod infos (Ctrl+Maj+i)
</body>
</html>
what Shighl does :
let pod = new sh.pod()
pod.webId = "mywebId"
//example : pod = "https://solidarity.inrupt.net/profile/card#me"
let name = await pod.name --> return String
let photo = await pod.photo --> return String of photo url
let friends = await pod.friends --> return Array of webId
let pti = await pod.pti --> read the pod publicTypeIndex & return pti.url & pti.instances (an Array of instances)
then each pti instance has keys :
classe: "http://www.w3.org/ns/pim/meeting#LongChat"
instance: "https://spoggy.solid.community/settings/publicTypeIndex.ttl#id1579184973294"
shortClass: "LongChat"
url: "https://spoggy.solid.community/public/thirdChat/index.ttl#this"
<html>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-auth-client.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-query-ldflex.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/window/shighl.bundle.js"></script>
<body onload="init()">
Look the web console to see the pod infos (Ctrl+Maj+i)<br><br>
Session : <span id="info"></span>
<button id="login_btn" onclick="session.login()">Login</button>
<button id="logout_btn" onclick="session.logout()">Logout</button>
<script>
const info = document.getElementById("info")
const login_btn = document.getElementById("login_btn")
const logout_btn = document.getElementById("logout_btn")
const sh = new Shighl()
let session = new sh.session()
async function init(){
await session.track(mycallback)
}
function mycallback(webId){
console.log("WebId: ",webId)
if (webId != null){
info.innerHTML = webId
login_btn.style.display = "none"
logout_btn.style.display = "block"
}
else{
info.innerHTML = "No session look at https://solid.inrupt.com/get-a-solid-pod"
login_btn.style.display = "block"
logout_btn.style.display = "none"
session.login()
}
}
</script>
</body>
</html>
when you get an instance (with pod.pti) of shortClass "Notes" and once you are logged with sh.session
see sh.chat live example when you get an instance (with pod.pti) of shortClass "LongChat" and once you are logged with sh.session
let chat = new sh.chat()
chat.instance = instance
let chat_details = await chat.init
info.innerHTML = JSON.stringify(chat_details)
let messages = await chat.messages
messages_liste.innerHTML = JSON.stringify(messages)
[x] chat.init
[x] chat.messages
[x] chat.send({content: content, webId: webId, postType: postType, replyTo: replyTo})
sh.chat.messages.get(date) return Array
sh.chat.message.send({creator: webId, content:content} )
sh.chat.message.reply(parentMessageUrl)
S-olid HIGH L-evel
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-auth-client.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-query-ldflex.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/window/shighl.bundle.js"></script>
<script>
const sh = new Shighl()
sh.test()
</script>
npm install --save scenaristeur/shighl
import Shighl from 'shighl'
...
const sh = new Shighl()
sh.test()
then you should see the result of this test
async test(){
var name = await data['https://spoggy.solid.community/profile/card#me'].vcard$fn
console.log(`${name}`);
return `${name}`
}
see /dist/index.html
git clone https://github.com/scenaristeur/shighl.git
cd shighl
npm install
npm run start
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Shighl</title>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-auth-client.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/solid-query-ldflex.bundle.js"></script>
<script src="https://github.com/scenaristeur/shighl/raw/master/window/shighl.bundle.js"></script>
</head>
<body>
<h1>Shigh</h1>
<ul id="friends">
</ul>
</body>
<script>
const sh = new Shighl()
console.log(sh)
sh.test()
async function run(){
let friends = await sh.getFriends("https://spoggy.solid.community/profile/card#me")
console.log(friends)
const friends_ul = document.getElementById("friends")
friends.forEach(function(f){
var li = document.createElement("LI")
var t = document.createTextNode(f.webId);
li.appendChild(t);
friends_ul.appendChild(li)
})
}
run()
</script>
</html>
<!doctype html>
<html lang="en">
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
<title>Shighl</title>
<!-- <link rel="shortcut icon" type="image/png" href="https://github.com/scenaristeur/shighl/blob/master/favicon.png">
<link rel="manifest" href="https://github.com/scenaristeur/shighl/blob/master/manifest.json">
<link href="https://github.com/scenaristeur/shighl/blob/master/css/bootstrap/bootstrap.min.css" rel="stylesheet" >
<link href="https://github.com/scenaristeur/shighl/blob/master/css/fontawesome/css/all.css" rel="stylesheet">
<script src="https://github.com/scenaristeur/shighl/raw/master/vendor/jquery/jquery.slim.min.js"></script>-->
<script src="https://cdn.jsdelivr.net/gh/scenaristeur/shighl@master/dist/vendor/solid-auth-client.bundle.js"> </script>
<script src="https://cdn.jsdelivr.net/gh/scenaristeur/shighl@master/dist/vendor/solid-query-ldflex.bundle.js"> </script>
<script src="https://cdn.jsdelivr.net/gh/scenaristeur/shighl@master/dist/window/shighl.bundle.js"> </script>
</head>
<body>
<h1>Shigh</h1>
<ul id="friends">
</ul>
</body>
<script>
const sh = new Shighl()
console.log(sh)
sh.test()
async function run(){
let friends = await sh.getFriends("https://spoggy.solid.community/profile/card#me")
console.log(friends)
const friends_ul = document.getElementById("friends")
friends.forEach(function(f){
var li = document.createElement("LI")
var t = document.createTextNode(f.webId);
li.appendChild(t);
friends_ul.appendChild(li)
})
}
run()
</script>
</html>
General
[ X ] Session : trackSession() / login() / logout () / getWebId() return webId/null Session
Profile
[ X ] getName(webId) return String
[ X ] getPhoto(webId) return String
[ X ] getFriends(webId) return Array of friends (String)
[ X ] getPublicTypeIndex(webId) return String / Array of instances (Objects) with props subject, predicate, object, classe, shortClass Profile
publicTypeIndex
[ ] (? getDetails(webId) return Object)
LongChat
[ ] getFolder(publicTypeIndex) return String
[ ] getPath(folder) return String
[ ] getMessages(path) return Array of Messages
[ ] getDetails(messageUrl) return Object
Inbox
[ ] getInbox() return String
[ ] getMessages(inbox) return Array (with basic details ?)
[ ] getDetails(messageUrl) return Object/Array
[ ] sendMessage(inbox_dest) return result/error
Acl
[ ] getAcl(path) return Array
show only days when there are messages https://developer.mozilla.org/fr/docs/Web/HTML/Element/Input/date
templates bootstrap https://bootsnipp.com/tags/chat
build & publish to ges
npm run build
git subtree push --prefix dist origin gh-pages
https://blog.jakoblind.no/webpack-code-splitting-libraries-what-to-do-with-the-files/
build ldflex-query https://gist.github.com/bellbind/24d9a5851397d45e4fa83fa8ec30449c https://git.happy-dev.fr/startinblox/framework/sib-store/blob/master/package.json
TODO infinite scroll : https://www.youtube.com/watch?v=hSsdhUG9rBI https://googlechrome.github.io/samples/intersectionobserver/