diff --git a/bun.lockb b/bun.lockb
index ab143e7..2e137e3 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/client/script.js b/client/script.js
index 3150ab7..4245789 100644
--- a/client/script.js
+++ b/client/script.js
@@ -98,9 +98,24 @@ function getMessage(m) {
break
case 'editBoardMetas':
- sendAction('editBoardMetas', { prop: 'opacity', value: 0.5 })
+ if (data.prop === 'imageUrl') {
+ document.body.style.backgroundImage = data.value ? `url("${data.value}")` : 'none'
+
+ if (data.value.startsWith('/images/')) {
+ $('.bg').removeClass('selected')
+ $(`.bg[src="${data.value}"]`).addClass('selected')
+ } else {
+ $('.bg').removeClass('selected')
+ $('.bgurl').val(data.value)
+ }
+ } else if (data.prop === 'opacity') {
+ document.documentElement.style.setProperty('--board-opacity', data.value)
+ const slider = document.getElementById('opacity-range')
+ if (slider) slider.value = data.value
+ }
break
+
case 'moveCard':
moveCard($(`#${data.id}`), data.position)
break
@@ -740,6 +755,18 @@ $(() => {
// disable image dragging
// window.ondragstart = function() { return false; };
+ const slider = document.getElementById('opacity-range');
+ if (slider) {
+ slider.addEventListener('input', function () {
+ document.documentElement.style.setProperty('--board-opacity', slider.value);
+ sendAction('editBoardMetas', {
+ id: 'opacity',
+ prop: 'opacity',
+ value: slider.value
+ });
+ });
+ }
+
if (boardInitialized === false) blockUI('
')
// setTimeout($.unblockUI, 2000);
@@ -1125,25 +1152,44 @@ $(() => {
return false
})
$('.backgrounds .bg').on('click', function() {
+ const imageUrl = `/${$(this).attr('src')}`
+
if ($(this).hasClass('selected')) {
$('body').css('background-image', 'none')
$(this).removeClass('selected')
+ sendAction('editBoardMetas', {
+ id: 'background',
+ prop: 'imageUrl',
+ value: ''
+ })
} else {
$('.selected').removeClass('selected')
$('.bgurl').val('')
- $('body').css('background-image', `url("/${$(this).attr('src')}")`)
+ $('body').css('background-image', `url("${imageUrl}")`)
$(this).addClass('selected')
+ sendAction('editBoardMetas', {
+ id: 'background',
+ prop: 'imageUrl',
+ value: imageUrl
+ })
}
})
+
$('.bgurl').on('change', function() {
const url = $(this).val()
if (url) {
$('.selected').removeClass('selected')
$('body').css('background-image', `url("${url}")`)
+ sendAction('editBoardMetas', {
+ id: 'background',
+ prop: 'imageUrl',
+ value: url
+ })
}
})
})
+
function toggleNav(target) {
if ($('#site-wrapper').hasClass('show-nav') && target === false) {
$('#site-wrapper').removeClass('show-nav')
@@ -1156,3 +1202,9 @@ function toggleNav(target) {
}
return false
}
+
+function takescreenshot(selector) {
+ html2canvas(document.querySelector(selector)).then(canvas => {
+ document.body.appendChild(canvas)
+ });
+}
diff --git a/lib/data/redis.js b/lib/data/redis.js
index e8a3b47..9adc0fe 100644
--- a/lib/data/redis.js
+++ b/lib/data/redis.js
@@ -112,21 +112,31 @@ db.prototype = {
},
// Board metadata commands
- createBoardMetas(room, id, board) {
- const boardString = JSON.stringify(board)
+ createBoardMetas(room, id, metaObj) {
redisClient.hset(
`${REDIS_PREFIX}-room:${room}-board`,
id,
- boardString
+ JSON.stringify(metaObj)
)
},
+
getBoardMetas(room, callback) {
redisClient.hgetall(`${REDIS_PREFIX}-room:${room}-board`, (err, res) => {
- console.log('board metas', res)
- callback(JSON.parse(res))
+ const metas = {}
+ if (res) {
+ for (const key in res) {
+ try {
+ metas[key] = JSON.parse(res[key])
+ } catch (e) {
+ console.error('JSON error in board metas', key, res[key])
+ }
+ }
+ }
+ callback(metas)
})
},
+
editBoardMetas(room, id, prop, value) {
redisClient.hget(`${REDIS_PREFIX}-room:${room}-board`, id, (err, res) => {
const board = JSON.parse(res)
diff --git a/server.js b/server.js
index 35aaffe..44368bb 100644
--- a/server.js
+++ b/server.js
@@ -135,24 +135,27 @@ io.sockets.on('connection', (client) => {
break
case 'editBoardMetas':
- clean_data = {}
- // TODO: test if prop is in ['title', opacity, 'imageUrl']
- clean_data.id = message.data.id
- clean_data.prop = message.data.prop
- clean_data.value = scrub(message.data.value)
+ const id = scrub(message.data.id)
+ const prop = scrub(message.data.prop)
+ const value = scrub(message.data.value)
+
+ const clean_data = { id, prop, value }
- // send update to database
getRoom(client, (room) => {
- db.editBoardMetas(room, clean_data.id, clean_data.prop, clean_data.value)
+ const boardMeta = {
+ prop,
+ value
+ }
+ // Enregistre les metas dans Redis
+ db.createBoardMetas(room, id, boardMeta)
})
- message_out = {
+ const message_out = {
action: 'editBoardMetas',
data: clean_data
}
broadcastToRoom(client, message_out)
-
break
case 'moveCard':
@@ -388,7 +391,9 @@ io.sockets.on('connection', (client) => {
************* */
function initClient(client) {
// console.log ('initClient Started');
+
getRoom(client, (room) => {
+
db.getAllCards(room, (cards) => {
client.json.send({
action: 'initCards',
@@ -428,6 +433,23 @@ function initClient(client) {
}
})
+ db.getBoardMetas(room, (metas) => {
+ if (metas) {
+ for (const id in metas) {
+ const meta = metas[id]
+ client.json.send({
+ action: 'editBoardMetas',
+ data: {
+ id,
+ prop: meta.prop,
+ value: meta.value
+ }
+ })
+ }
+ }
+ })
+
+
roommates_clients = rooms.room_clients(room)
roommates = []
diff --git a/views/index.jade b/views/index.jade
index 558639d..e2360c5 100644
--- a/views/index.jade
+++ b/views/index.jade
@@ -48,9 +48,10 @@ block header
path(d="M9.405 1.05c-.413-1.4-2.397-1.4-2.81 0l-.1.34a1.464 1.464 0 0 1-2.105.872l-.31-.17c-1.283-.698-2.686.705-1.987 1.987l.169.311c.446.82.023 1.841-.872 2.105l-.34.1c-1.4.413-1.4 2.397 0 2.81l.34.1a1.464 1.464 0 0 1 .872 2.105l-.17.31c-.698 1.283.705 2.686 1.987 1.987l.311-.169a1.464 1.464 0 0 1 2.105.872l.1.34c.413 1.4 2.397 1.4 2.81 0l.1-.34a1.464 1.464 0 0 1 2.105-.872l.31.17c1.283.698 2.686-.705 1.987-1.987l-.169-.311a1.464 1.464 0 0 1 .872-2.105l.34-.1c1.4-.413 1.4-2.397 0-2.81l-.34-.1a1.464 1.464 0 0 1-.872-2.105l.17-.31c.698-1.283-.705-2.686-1.987-1.987l-.311.169a1.464 1.464 0 0 1-2.105-.872l-.1-.34zM8 10.93a2.929 2.929 0 1 1 0-5.86 2.929 2.929 0 0 1 0 5.858z")
block body
- div(style="margin: 1em;")
+ div(style="margin: 1em;", data-html2canvas-ignore)
label(for="opacity-range") Transparence du tableau :
input#opacity-range(type="range", min="0", max="1", step="0.01", value="1")
+ input(type="button", name="screenshot", value="Prendre une capture d'écran", onclick="takescreenshot('body')")
div.container
div.board-container
div.board-outline
@@ -62,11 +63,3 @@ block body
span(style="font-weight:bold; font-size:16px;") +
div#delete-col.col-icon(title="Supprimer une colonne", style="width:20px; height:20px; display:flex; justify-content:center; align-items:center; border:1px solid #000; cursor:pointer; margin-top:4px;")
span(style="font-weight:bold; font-size:16px;") −
-
- script.
- document.addEventListener('DOMContentLoaded', function () {
- const slider = document.getElementById('opacity-range');
- slider.addEventListener('input', function () {
- document.documentElement.style.setProperty('--board-opacity', slider.value);
- });
- });
diff --git a/views/layout.jade b/views/layout.jade
index 5a10b16..797a0bd 100644
--- a/views/layout.jade
+++ b/views/layout.jade
@@ -11,7 +11,7 @@ html(lang="fr")
body
div#site-wrapper
div#site-canvas
- div#site-menu
+ div#site-menu(data-html2canvas-ignore)
a.toggle-nav.pull-right.close-link(href="#") Fermer
svg(xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x-lg" viewBox="0 0 16 16")
path(d="M2.146 2.854a.5.5 0 1 1 .708-.708L8 7.293l5.146-5.147a.5.5 0 0 1 .708.708L8.707 8l5.147 5.146a.5.5 0 0 1-.708.708L8 8.707l-5.146 5.147a.5.5 0 0 1-.708-.708L7.293 8 2.146 2.854Z")
@@ -80,8 +80,8 @@ html(lang="fr")
input(type="file")#import-input.form-control
button#import-file.btn.btn-primary Importer
div.credits Logiciel libre basé sur Framemo et Scrumblr - Code source
- div#header-bar(data-url=locals.headerBarUrl)
- header.container.main-header
+ div
+ header.container.main-header(data-html2canvas-ignore)
div.title
a(href="/", title="Retour à la page d'accueil")
if locals.logoUrl
@@ -107,4 +107,5 @@ html(lang="fr")
script(src="lib/marked.min.js")
script(src="lib/moment-with-locales.min.js")
script(src="socket.io/socket.io.js")
+ script(src="html2canvas/dist/html2canvas.min.js")
script(src="script.js")