Commit 29726ce2 authored by Matthieu Fesselier's avatar Matthieu Fesselier

First commit

parent e3325eb4
......@@ -4,4 +4,19 @@ sib-notifications is a component that displays all elements of an inbox, i.e. a
When the user clicks one of the notifications, a 'navigate' event is triggered with the object of the notification given as the resource parameter.
The component listens to 'read' events. These events details contain a resource and a type. When such an event is triggered, it sets all notifications with that resource and type as read, and saves these notifications back to the container.
\ No newline at end of file
The component listens to 'read' events. These events details contain a resource. When such an event is triggered, it sets all notifications with that resource as read, and saves these notifications back to the container.
To send an event, you can dispatch it like this:
```javascript
window.dispatchEvent(new CustomEvent('read', {detail: {resource: resource}}))
```
## Usage
In your template, insert the following line where you want to display the component.
```html
<sib-notifications bind-user id-suffix="inbox"></sib-notifications>
```
If you want to use the `bind-user` attribute, do not forget to use `sib-oidc` for authentication.
.sib-notifications{
box-sizing: border-box;
font-family: sans-serif;
}
.sib-notifications__container{ }
/* Counter */
.sib-notifications__counter{
position: absolute;
top: -5px;
right: -5px;
width: 20px;
height: 20px;
line-height: 20px;
background-color: #ffd759;
border-radius: 50%;
font-size: 12px;
}
/* Button */
.sib-notifications__button{
display: block;
position: relative;
width: 30px;
height: 30px;
line-height: 30px;
padding: 5px;
text-align: center;
cursor: pointer;
}
.sib-notifications__button::-webkit-details-marker {
display: none
}
.sib-notifications__button:hover{
background: #EEE;
}
.sib-notifications__button:active,
.sib-notifications__button:focus{
background: #EDEDED;
}
/* List */
.sib-notifications__list{
width: 300px;
max-height: 500px;
margin-top: 5px;
overflow: scroll;
background: white;
border: 1px solid #DDD;
border-radius: 5px;
}
/* Notification */
.sib-notifications__items sib-display{
display: block;
cursor: pointer;
}
.sib-notifications__items sib-display:hover{
background: rgba(0,0,0,0.02);
}
.sib-notifications__items sib-display:active,
.sib-notifications__items sib-display:focus{
background: rgba(0,0,0,0.03);
}
.sib-notifications__items sib-display div[name=content]{
padding: 10px;
border-bottom: 1px solid #DDD;
}
.sib-notifications__items sib-display [data-read=read] + div[name=content]{
opacity: .6;
}
.sib-notifications__items sib-display [data-read=unread] + div[name=content]{
background: rgba(255, 215, 89, 0.14)
}
/* Fields */
.sib-notifications__items sib-display-div[name="date"]{
color: #999;
font-size: 80%;
}
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M467.819 431.851l-36.651-61.056a181.486 181.486 0 0 1-25.835-93.312V224c0-82.325-67.008-149.333-149.333-149.333S106.667 141.675 106.667 224v53.483c0 32.875-8.939 65.131-25.835 93.312l-36.651 61.056a10.665 10.665 0 0 0-.149 10.731 10.704 10.704 0 0 0 9.301 5.419h405.333c3.84 0 7.403-2.069 9.301-5.419a10.665 10.665 0 0 0-.148-10.731zm-395.648-5.184l26.944-44.907A202.631 202.631 0 0 0 128 277.483V224c0-70.592 57.408-128 128-128s128 57.408 128 128v53.483c0 36.736 9.984 72.789 28.864 104.277l26.965 44.907H72.171z"/><path d="M256 0c-23.531 0-42.667 19.136-42.667 42.667v42.667C213.333 91.221 218.112 96 224 96s10.667-4.779 10.667-10.667V42.667c0-11.776 9.557-21.333 21.333-21.333s21.333 9.557 21.333 21.333v42.667C277.333 91.221 282.112 96 288 96s10.667-4.779 10.667-10.667V42.667C298.667 19.136 279.531 0 256 0zM302.165 431.936c-3.008-5.077-9.515-6.741-14.613-3.819-5.099 2.987-6.805 9.536-3.819 14.613 2.773 4.715 4.288 10.368 4.288 15.936 0 17.643-14.357 32-32 32s-32-14.357-32-32c0-5.568 1.515-11.221 4.288-15.936 2.965-5.099 1.259-11.627-3.819-14.613-5.141-2.923-11.627-1.259-14.613 3.819-4.715 8.064-7.211 17.301-7.211 26.731C202.667 488.085 226.581 512 256 512s53.333-23.915 53.376-53.333c0-9.43-2.496-18.667-7.211-26.731z"/></svg>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webcomponentsjs/1.0.20/webcomponents-loader.js"></script>
<title>SIB Notifications - Demo</title>
<script type="module" src="sib-notifications.js"></script>
<script src="https://cdn.happy-dev.fr/oidc-client/oidc-client.min.js"></script>
<script src="https://cdn.happy-dev.fr/sib-oidc/sib-oidc.js"
data-authority="http://127.0.0.1:8000/openid/"
data-client_id="782322"
data-redirect_uri="http://127.0.0.1:8001"
data-response_type="id_token token"
data-scope="openid profile email"
data-automaticSilentRenew="true"
data-loadUserInfo="true"
></script>
</head>
<h1>SIB Notifications - Demo</h1>
<body>
<sib-notifications bind-user id-suffix="inbox"></sib-notifications>
</body>
</html>
import { SIBTemplateElement, SIBDisplay, store } from 'https://unpkg.com/@startinblox/core@0.5';
import { importCSS } from 'https://cdn.happy-dev.fr/sib-core/helpers.js'
const base_url = import.meta.url.replace(/\/[^\/]*$/, '');
importCSS(`${base_url}/css/main.css`)
class SIBNotifications extends SIBTemplateElement {
constructor() {
super()
window.addEventListener('read', event => {
if(event.detail && event.detail.resource && event.detail.resource['@id']) {
this._onReadResource(event.detail.resource['@id'])
} else {
this._printError('Resource parameter is missing. Check the documentation: https://git.happy-dev.fr/startinblox/framework/sib-notifications')
}
})
this.addEventListener("click", event => {
let notif = event.target.closest('sib-display')
if (notif && notif.classList.length === 0) { // TODO: classList can be improved
this._onClickNotification(notif)
}
})
}
static get propsDefinition() {
return {
dataSrc: 'data-src',
idSuffix: 'id-suffix'
}
}
_onClickNotification(target) {
window.dispatchEvent(new CustomEvent('requestNavigation', {detail: {resource: target.resource.object}})) // TODO: implement requestNavigation withtout routeName
}
_onReadResource(resourceId) {
let markedAsRead = 0
this._getNotificationsList().forEach(notification => {
if (notification.object === resourceId) {
store.patch(notification['@id'], { read: true })
.then((e) => console.log('Notification marked as read', e))
.catch((error) => this._printError(error))
markedAsRead++
}
})
if (markedAsRead) {
this.render()
}
}
_getNotificationsList() {
return document.querySelector('#notifications-list').resource['ldp:contains']
}
_printError(error) {
console.error(error)
}
template({ dataSrc, idSuffix }) {
if (dataSrc) {
let sourceUrl = dataSrc + (idSuffix ? idSuffix + '/' : '')
return `
<div class="sib-notifications">
<details class="sib-notifications__container">
<summary class="sib-notifications__button">
<img src="./img/notification-icon.svg" />
<sib-display
data-src="${sourceUrl}"
class="sib-notifications__counter"
data-fields="none"
counter-template="\${counter}"></sib-display>
</summary>
<div class="sib-notifications__list">
<sib-display
id="notifications-list"
data-src="${sourceUrl}"
class="sib-notifications__items"
template-read="read_badge"
set-content="type, date"
data-fields="read, content"></sib-display>
</div>
<template id="read_badge">
<div data-read="\${value?'read':'unread'}"></div>
</template>
</details>
</div>
`;
}
}
}
customElements.define('sib-notifications', SIBNotifications);
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment