realtime kanban board
parent
4561ddcdf3
commit
122a9fe068
@ -0,0 +1,243 @@
|
|||||||
|
define([
|
||||||
|
'/bower_components/jquery/dist/jquery.min.js',
|
||||||
|
],function () {
|
||||||
|
var $ = window.jQuery;
|
||||||
|
var Board = {};
|
||||||
|
var proxy;
|
||||||
|
|
||||||
|
var Uid = function (prefix) {
|
||||||
|
return function () {
|
||||||
|
return prefix + Number(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER))
|
||||||
|
.toString(32).replace(/\./g, '');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var removeUid = function (A, e) {
|
||||||
|
var i = A.indexOf(e);
|
||||||
|
if (i === -1) { return -1; }
|
||||||
|
A.splice(i, 1);
|
||||||
|
return i;
|
||||||
|
};
|
||||||
|
|
||||||
|
var luid = Board.luid = Uid('l-'); // list-uid
|
||||||
|
var cuid = Board.cuid = Uid('c-'); // card uid
|
||||||
|
|
||||||
|
var Input = Board.Input = function (opt) {
|
||||||
|
return $('<input>', opt);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
populate the proxy with all the relevant fields
|
||||||
|
return boolean whether you are the first user
|
||||||
|
*/
|
||||||
|
Board.initialize = function (_proxy) {
|
||||||
|
proxy = _proxy;
|
||||||
|
var first = false;
|
||||||
|
|
||||||
|
['listOrder'].forEach(function (k) {
|
||||||
|
if (typeof(proxy[k]) === 'undefined') {
|
||||||
|
first = true;
|
||||||
|
proxy[k] = [];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
['lists', 'cards'].forEach(function (k) {
|
||||||
|
if (typeof(proxy[k]) === 'undefined') {
|
||||||
|
proxy[k] = {};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return first;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a list is appended to the extant order
|
||||||
|
*/
|
||||||
|
var List = Board.List = function (id) {
|
||||||
|
if (!id) {
|
||||||
|
id = List.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
var $input = Input({
|
||||||
|
type: 'text',
|
||||||
|
placeholder: 'list title',
|
||||||
|
})
|
||||||
|
.addClass('list-title')
|
||||||
|
.on('keyup change', function () {
|
||||||
|
var val = $input.val();
|
||||||
|
proxy.lists[id].title = val;
|
||||||
|
});
|
||||||
|
|
||||||
|
var $cards = $('<div>', {
|
||||||
|
|
||||||
|
})
|
||||||
|
.addClass('card-holder');
|
||||||
|
|
||||||
|
var $new = $('<a>', {
|
||||||
|
|
||||||
|
})
|
||||||
|
.addClass('add-card')
|
||||||
|
.text('add new card')
|
||||||
|
.click(function () {
|
||||||
|
// is this correct?
|
||||||
|
$cards.append(Board.Card(id));
|
||||||
|
});
|
||||||
|
|
||||||
|
var $list = $('<div>', {
|
||||||
|
id: id,
|
||||||
|
})
|
||||||
|
.addClass('list-column')
|
||||||
|
.append($input)
|
||||||
|
.append($cards)
|
||||||
|
.append($new);
|
||||||
|
|
||||||
|
return $list;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
List.create = function () {
|
||||||
|
var id = luid();
|
||||||
|
proxy.listOrder.push(id);
|
||||||
|
proxy.lists[id] = {
|
||||||
|
title: "",
|
||||||
|
cards: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
List.remove = function (id) {
|
||||||
|
var i = removeUid(proxy.listOrder, id);
|
||||||
|
if (i === -1) {
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
List.move = function () {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
List.insert = function () {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
List.draw = function ($lists, lid) {
|
||||||
|
if (!lid) {
|
||||||
|
console.log("List Id not supplied");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var $parent = $lists.find('#' + lid);
|
||||||
|
if (!$parent.length) {
|
||||||
|
console.log("Creating new list");
|
||||||
|
// doesn't exist. draw it fresh
|
||||||
|
|
||||||
|
var $list = Board.List(lid);
|
||||||
|
$lists.append($list);
|
||||||
|
|
||||||
|
//console.log("Updating list");
|
||||||
|
|
||||||
|
//var $list = Board.List(lid);
|
||||||
|
var title = proxy.lists[lid].title;
|
||||||
|
|
||||||
|
console.log(title);
|
||||||
|
|
||||||
|
$list.find('input.list-title').val(title);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// else update
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* UI element
|
||||||
|
*/
|
||||||
|
var Card = Board.Card = function (pid) {
|
||||||
|
// pid => parent id
|
||||||
|
|
||||||
|
var id = Card.create(pid);
|
||||||
|
|
||||||
|
var $input = Input({
|
||||||
|
placeholder: 'card description',
|
||||||
|
})
|
||||||
|
.addClass('card-title');
|
||||||
|
|
||||||
|
var $card = $('<div>', {
|
||||||
|
|
||||||
|
})
|
||||||
|
.addClass('card-container')
|
||||||
|
.append($input);
|
||||||
|
|
||||||
|
return $card;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a card is instantiated within a parent list
|
||||||
|
* .create(parent) adds the relevant attributes to the data structure
|
||||||
|
* and returns the created id
|
||||||
|
*/
|
||||||
|
Card.create = function (pid) {
|
||||||
|
var id = cuid();
|
||||||
|
|
||||||
|
if (typeof(proxy.lists[pid]) === 'undefined') {
|
||||||
|
console.error("Trying to create card for list which does not exist");
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
proxy.lists[pid].cards.push(id);
|
||||||
|
proxy.cards[id] = {
|
||||||
|
// TODO what goes in a card
|
||||||
|
parent: pid,
|
||||||
|
title: "",
|
||||||
|
};
|
||||||
|
|
||||||
|
return id;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
Card.move = function (uid, A, B) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
*/
|
||||||
|
Card.insert = function () {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Card.draw = function ($lists, cid) {
|
||||||
|
if (!cid) {
|
||||||
|
console.error("card id not supplied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!proxy.cards[cid]) {
|
||||||
|
console.error("no such card: ", cid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var card = proxy.cards[cid];
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var Draw = Board.Draw = function ($lists) {
|
||||||
|
proxy.listOrder.forEach(function (luid) {
|
||||||
|
List.draw($lists, luid);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return Board;
|
||||||
|
});
|
@ -0,0 +1,103 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta content="text/html; charset=utf-8" http-equiv="content-type"/>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||||
|
<title>Zero Knowledge Date Picker</title>
|
||||||
|
<link rel="icon" type="image/png"
|
||||||
|
href="/customize/main-favicon.png"
|
||||||
|
data-main-favicon="/customize/main-favicon.png"
|
||||||
|
data-alt-favicon="/customize/alt-favicon.png"
|
||||||
|
id="favicon" />
|
||||||
|
<link rel="stylesheet" href="/customize/main.css" />
|
||||||
|
<script data-main="main" src="/bower_components/requirejs/require.js"></script>
|
||||||
|
<script>
|
||||||
|
require.config({
|
||||||
|
waitSeconds: 60,
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
html, body {
|
||||||
|
width: 100;
|
||||||
|
}
|
||||||
|
.clickable {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#adduser, #addoption {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#lists {
|
||||||
|
display: inline-block;
|
||||||
|
border: 1px solid white;
|
||||||
|
height: 80vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
#create-list {
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-column {
|
||||||
|
vertical-align: top;
|
||||||
|
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: inline-block;
|
||||||
|
width: 400px;
|
||||||
|
height: 100%;
|
||||||
|
border: 1px solid white;
|
||||||
|
}
|
||||||
|
/* input */
|
||||||
|
input.list-title {
|
||||||
|
margin: 15px;
|
||||||
|
width: 80%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.card-holder {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
width: 90%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
.add-card {
|
||||||
|
background-color: green;
|
||||||
|
display: block;
|
||||||
|
height: 20px;
|
||||||
|
width: 80%;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-title {
|
||||||
|
border: 5px solid blue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-container {
|
||||||
|
display: block;
|
||||||
|
height: 50px;
|
||||||
|
width: 95%;
|
||||||
|
margin: auto;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
#board {
|
||||||
|
margin-left: 10vw;
|
||||||
|
overflow-x: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<!--<div id="main"> -->
|
||||||
|
|
||||||
|
<div id="toolbar" class="buttons">
|
||||||
|
<sub><a href="/"></a></sub>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="board">
|
||||||
|
<div id="lists"></div>
|
||||||
|
<span id="create-list">Add List</span>
|
||||||
|
</div>
|
||||||
|
|
@ -0,0 +1,95 @@
|
|||||||
|
define([
|
||||||
|
'/api/config?cb=' + Math.random().toString(16).substring(2),
|
||||||
|
'/customize/messages.js',
|
||||||
|
'/board/board.js',
|
||||||
|
'/bower_components/textpatcher/TextPatcher.js',
|
||||||
|
'/bower_components/chainpad-listmap/chainpad-listmap.js',
|
||||||
|
'/bower_components/chainpad-crypto/crypto.js',
|
||||||
|
'/common/cryptpad-common.js',
|
||||||
|
'/common/visible.js',
|
||||||
|
'/common/notify.js',
|
||||||
|
'/bower_components/file-saver/FileSaver.min.js',
|
||||||
|
'/bower_components/jquery/dist/jquery.min.js',
|
||||||
|
'/customize/pad.js'
|
||||||
|
], function (Config, Messages, Board, TextPatcher, Listmap, Crypto, Cryptpad, Visible, Notify) {
|
||||||
|
var $ = window.jQuery;
|
||||||
|
var saveAs = window.saveAs;
|
||||||
|
|
||||||
|
Cryptpad.styleAlerts();
|
||||||
|
console.log("Initializing your realtime session...");
|
||||||
|
|
||||||
|
var secret = Cryptpad.getSecrets();
|
||||||
|
|
||||||
|
var module = window.APP = {
|
||||||
|
Board: Board,
|
||||||
|
};
|
||||||
|
|
||||||
|
var unnotify = function () {
|
||||||
|
if (!(module.tabNotification &&
|
||||||
|
typeof(module.tabNotification.cancel) === 'function')) { return; }
|
||||||
|
module.tabNotification.cancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
var notify = function () {
|
||||||
|
if (!(Visible.isSupported() && !Visible.currently())) { return; }
|
||||||
|
unnotify();
|
||||||
|
module.tabNotification = Notify.tab(document.title, 1000, 10);
|
||||||
|
};
|
||||||
|
|
||||||
|
var setEditable = function (bool) {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
setEditable(false);
|
||||||
|
|
||||||
|
|
||||||
|
var $lists = $('#lists');
|
||||||
|
|
||||||
|
var $addList = $('#create-list').click(function () {
|
||||||
|
Board.List.draw($lists);
|
||||||
|
});
|
||||||
|
|
||||||
|
var firstUser = function () {
|
||||||
|
Cryptpad.log("You are the first user to visit this board");
|
||||||
|
};
|
||||||
|
|
||||||
|
var whenReady = function (opt) {
|
||||||
|
var rt = module.rt;
|
||||||
|
var proxy = rt.proxy;
|
||||||
|
|
||||||
|
var first = Board.initialize(proxy);
|
||||||
|
|
||||||
|
//var board = module.board = Board.create(proxy);
|
||||||
|
|
||||||
|
Board.Draw($lists);
|
||||||
|
|
||||||
|
if (first) { firstUser(); }
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
var config = {
|
||||||
|
websocketURL: Config.websocketURL,
|
||||||
|
channel: secret.channel,
|
||||||
|
data: {},
|
||||||
|
crypto: Crypto.createEncryptor(secret.key),
|
||||||
|
};
|
||||||
|
|
||||||
|
Cryptpad.ready(function () {
|
||||||
|
var rt = module.rt = Listmap.create(config);
|
||||||
|
var proxy = rt.proxy;
|
||||||
|
proxy
|
||||||
|
.on('create', function (info) {
|
||||||
|
var realtime = module.realtime = info.realtime;
|
||||||
|
window.location.hash = info.channel + secret.key;
|
||||||
|
})
|
||||||
|
.on('ready', function (info) {
|
||||||
|
Cryptpad.log("Ready!");
|
||||||
|
whenReady({
|
||||||
|
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.on('disconnect', function () {
|
||||||
|
Cryptpad.warn("Disconnected!");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue