Skip to content

Commit 90b7170

Browse files
authored
Merge pull request #13 from UNDP-Accelerator-Labs/pipe-groups
Pipe groups
2 parents 90258ba + 707acfb commit 90b7170

File tree

19 files changed

+526
-52
lines changed

19 files changed

+526
-52
lines changed

app.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ app.post('/updateMatrix', routes.matrixes.update);
7575
app.post('/updateMatrixes', routes.matrixes.updateMulti);
7676
app.delete('/removeMatrix', routes.matrixes.remove);
7777

78+
app.post('/addPipe', routes.pipes.add);
79+
app.delete('/removePipe', routes.pipes.remove);
80+
7881
app.post('/addTitle', routes.addTitle);
7982
app.post('/updateTitle', routes.updateTitle);
8083
app.post('/removeTitle', routes.removeTitle);

init.sql

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ CREATE TABLE notes (
3333
x DOUBLE PRECISION,
3434
y DOUBLE PRECISION,
3535
project INT REFERENCES projects (id) ON UPDATE CASCADE ON DELETE CASCADE,
36-
tree ltree DEFAULT text2ltree('0')
36+
tree ltree DEFAULT text2ltree('0'),
37+
pipe_from INT REFERENCES notes (id) ON UPDATE CASCADE ON DELETE CASCADE
3738
);
3839

3940
CREATE TABLE cards (
@@ -64,6 +65,12 @@ CREATE TABLE datasources (
6465
project INT REFERENCES projects (id) ON UPDATE CASCADE ON DELETE CASCADE
6566
);
6667

68+
CREATE TABLE pipes (
69+
"from" INT REFERENCES groups (id) ON UPDATE CASCADE ON DELETE CASCADE,
70+
"to" INT UNIQUE REFERENCES groups (id) ON UPDATE CASCADE ON DELETE CASCADE
71+
);
72+
73+
6774
CREATE TABLE session (
6875
sid varchar NOT NULL COLLATE "default",
6976
sess json NOT NULL,

public/css/main.css

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ h1, h2 {
1111
h2 small {
1212
font-size: .5em;
1313
}
14+
.deactivate {
15+
pointer-events: none;
16+
}
1417
div.overlay {
1518
position: absolute;
1619
display: flex;
@@ -125,6 +128,9 @@ div.origin::after {
125128
div.dragging {
126129
z-index: 1000 !important;
127130
}
131+
div.dragging *:not(.sticky-area) {
132+
pointer-events: none;
133+
}
128134
div.matrix {
129135
position: absolute;
130136
display: grid;
@@ -133,6 +139,10 @@ div.matrix {
133139
margin: 0 2rem 2rem 0;
134140
z-index: 50;
135141
}
142+
div.matrix > div.sticky-area {
143+
grid-column: span 2;
144+
background-color: rgba(51,51,51,.1);
145+
}
136146
div.matrix table {
137147
resize: both;
138148
border-collapse: collapse;
@@ -178,7 +188,7 @@ div.group {
178188
position: absolute;
179189
border: 1px solid rgba(51,51,51,.25);
180190
background-color: rgba(225,225,225,.25);
181-
padding: 4rem 0rem 2rem 2rem;
191+
padding: 0 0 2rem 2rem;
182192
margin: 0 2rem 2rem 0;
183193
z-index: 50;
184194
resize: both;
@@ -202,14 +212,40 @@ div.matrix table th.sticky-area input[type=text] {
202212
margin-bottom: 0;
203213
text-align: center;
204214
}
215+
div.group button.pipe {
216+
position: absolute;
217+
width: 2rem;
218+
height: 2rem;
219+
min-height: 30px;
220+
min-width: 30px;
221+
right: 100%;
222+
top: -1px;
223+
z-index: 1001;
224+
padding: 0;
225+
}
226+
/*div.group button.pipe.connected {
227+
height: 100% !important;
228+
}
229+
button.pipe.connected span.flip {
230+
transform: rotate(-90deg);
231+
}*/
232+
div.pipeline {
233+
position: absolute;
234+
background-color: rgba(51,51,51,.7);
235+
width: 1px;
236+
height: 5px;
237+
border-radius: 5px;
238+
transform-origin: top left;
239+
z-index: 1000;
240+
}
205241
div.note {
206242
background-color: yellow;
207243
font-family: Comic Sans MS;
208244
display: inline-block;
209245
position: absolute;
210246
min-width: 100px;
211247
min-height: 100px;
212-
padding: 2rem;
248+
/* padding-top: 2rem;*/
213249
border: 1px solid rgba(51,51,51,.05);
214250
z-index: 100;
215251
transform-origin: top center;
@@ -292,8 +328,8 @@ div.hit {
292328
padding: 2rem;
293329
}*/
294330
div.sticky-area {
295-
width: calc(100% + 4rem);
296-
margin: -2rem 0 0 -2rem;
331+
width: 100%;
332+
/* margin: -2rem 0 0 -2rem;*/
297333
min-height: 30px;
298334
height: 30px;
299335
max-height: 120px;
@@ -302,7 +338,7 @@ div.sticky-area {
302338
}
303339
div.group > div.sticky-area {
304340
width: calc(100% + 2rem);
305-
margin: -4rem 0 1rem -2rem;
341+
margin: 0 0 1rem -2rem;
306342
}
307343
div.note div.color-swatches {
308344
/*width: 150px;*/
@@ -337,11 +373,12 @@ div.card.dragging div.sticky-area {
337373
}
338374
textarea {
339375
font-family: Comic Sans MS;
376+
display: block;
340377
outline: none;
341378
border: none;
342-
width: calc(100% - 2rem);
343-
margin: 1rem 0 0 1rem;
344-
min-height: calc(100px - 1rem);
379+
width: 100%;
380+
/* margin: 1rem 0 0 1rem;*/
381+
min-height: 200px;
345382
background-color: transparent;
346383
min-width: 100px;
347384
font-size: 1rem;
@@ -350,10 +387,12 @@ textarea {
350387
/*align-items: center;*/
351388
/*justify-content: center;*/
352389
text-align: center;
353-
resize: none;
354-
position: absolute;
390+
resize: both;
391+
padding: 1rem 2rem 2rem 2rem;
392+
/* position: absolute;*/
355393
left: 0;
356394
overflow: hidden;
395+
box-sizing: border-box;
357396
}
358397
div.title {
359398
/*padding: 2rem;*/

public/js/canvas/zoom.mjs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ function zooming () {
1818
.style('transform', d => `scale(${1 / d.k})`);
1919

2020
d3.selectAll('div.sticky-area:not(.immutable)')
21-
.style('height', `${30 * 1 / t.k / 2}px`);
21+
.style('height', `${Math.min(75, 30 * 1 / t.k / 2)}px`);
22+
d3.selectAll('button.pipe')
23+
.styles({
24+
'width': `${Math.min(75, 30 * 1 / t.k / 2)}px`,
25+
'height': `${Math.min(75, 30 * 1 / t.k / 2)}px`,
26+
});
2227
d3.selectAll('div.note, div.card, div.group, div.matrix')
2328
.style('border-width', `${1 / t.k / 2}px`);
2429
}

public/js/elements/drag.mjs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,15 @@ function dragStart (d) {
3535
d.x = 0;
3636
d.y = 0;
3737
}
38+
// DEACTIVATE ALL textareas AND inputs
39+
d3.select('div.canvas').selectAll('textarea, input')
40+
.classed('deactivate', true);
41+
} else {
42+
sel.classed('dragging', false);
43+
// REACTIVATE ALL textareas AND inputs
44+
d3.select('div.canvas').selectAll('textarea, input')
45+
.classed('deactivate', false);
3846
}
39-
else sel.classed('dragging', false);
4047
}
4148

4249
let object;
@@ -110,9 +117,16 @@ async function dragEnd (d) {
110117

111118
const sel = d3.select(this)
112119
.classed('dragging', false);
120+
// REACTIVATE ALL textareas AND inputs
121+
d3.select('div.canvas').selectAll('textarea, input')
122+
.classed('deactivate', false);
123+
113124
const parent = d3.select(this.parentNode);
125+
const otree = d.tree;
114126

115127
const hit = d3.select('div.hit');
128+
let pipes = [];
129+
116130
if (hit.node()) {
117131
// 1- CHECK IF THE HIT IS AN EXISTING GROUP
118132
// OTHERWISE CREATE THE GROUP
@@ -123,13 +137,13 @@ async function dragEnd (d) {
123137
groupping = hit;
124138
d.x = null;
125139
d.y = null;
126-
const { id: gid, tree: gtree } = hit.datum();
127-
// d.tree = tree.rebase(d.tree, gid, gtree);
140+
const { id: gid, tree: gtree, pipe_to } = hit.datum();
128141
d.tree = tree.build(gtree, gid);
129-
142+
if (Array.isArray(pipe_to) && pipe_to?.length) pipes = [ ...pipes, ...pipe_to ];
143+
130144
} else if (hit.classed('note') || hit.classed('card')) {
131145
// IF THE HIT IS A NOTE OR CARD, CREATE A GROUP
132-
const { x, y, tree: ntree } = hit.datum();
146+
const { x, y, tree: ntree, piped_from } = hit.datum();
133147

134148
groupping = await Group.add({
135149
parent: d3.select(hit.node().parentNode),
@@ -141,8 +155,26 @@ async function dragEnd (d) {
141155
d.x = null;
142156
d.y = null;
143157
const { id: gid, tree: gtree } = groupping.datum();
144-
// d.tree = tree.rebase(d.tree, gid, gtree);
145158
d.tree = tree.build(gtree, gid);
159+
160+
// IF THE hit note IS INSIDE A PIPED GROUP, PIPE THE dragged NOTE
161+
if (tree.getDepth(d.tree) > 1) {
162+
// CHECK ALL THE PARENT GROUPS FOR PIPING
163+
const nodes = tree.getNodes(d.tree);
164+
let i = nodes.length - 1;
165+
166+
while (i >= 0) {
167+
const group = d3.selectAll('div.group')
168+
.filter(d => d.id === +nodes[i]);
169+
170+
if (group.node()) {
171+
const { pipe_to } = group.datum();
172+
if (Array.isArray(pipe_to) && pipe_to?.length) pipes = [ ...pipes, ...pipe_to ];
173+
}
174+
i--;
175+
}
176+
177+
}
146178
}
147179
hit.classed('hit', false);
148180
} else { // THE OBJECT IS MOVED OUT OF ALL GROUPS
@@ -155,8 +187,9 @@ async function dragEnd (d) {
155187
if (sel.classed('note')) {
156188
await Note.update({
157189
note: sel,
158-
datum: d,
190+
datum: { ...d, ...{ pipe_from: null } },
159191
bcast: true,
192+
group_pipes: pipes,
160193
});
161194
} else if (sel.classed('card')) {
162195
await Card.update({

public/js/elements/groups.mjs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Card } from './cards.mjs';
33
import { Matrix } from './matrixes.mjs';
44
import { POST, DELETE, wallId, tree, computeAbsCoordinates } from '../helpers/index.mjs';
55
import { drag } from './drag.mjs';
6+
import { pipe } from './pipe.mjs';
67
import { broadcast } from '../websocket/index.mjs';
78

89
export const Group = {
@@ -42,6 +43,12 @@ export const Group = {
4243
'transform': d => (![null, undefined].includes(d.x) && ![null, undefined].includes(d.y)) ? `translate(${d.x}px, ${d.y}px)` : null,
4344
'grid-column-start': d => d.matrix_index ? +tree.getLeaf(d.matrix_index) + 2 : null,
4445
});
46+
47+
// ADD AN OPTION TO PIPE GROUPS
48+
group.addElems('button', 'btn pipe')
49+
.html('@')
50+
.call(pipe);
51+
4552
// ADD A STICKY AREA TO MOVE THE GROUP AROUND
4653
if (!immutable) {
4754
group.addElems('div', 'sticky-area');

public/js/elements/matrixes.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ export const Matrix = {
5050
'transform': d => (![null, undefined].includes(d.x) && ![null, undefined].includes(d.y)) ? `translate(${d.x}px, ${d.y}px)` : null,
5151
// 'grid-template-columns': d => `.5fr, repeat(${d.cols.length}, 1fr)`,
5252
});
53+
// ADD GLOBAL STICKY AREA TO MOVE THE MATRIX AROUND
54+
matrix.addElems('div', 'sticky-area');
5355
const table = matrix.addElems('table');
5456
// ADD STICKY AREAS TO EACH COLUMN HEADER TO MOVE THE MATRIX AROUND
5557
const thead = table.addElems('tr', 'head');
@@ -228,7 +230,9 @@ export const Matrix = {
228230
matrix.each(d => {
229231
if (!d.cells) d.cells = [];
230232
d.cells.push(group.datum());
231-
})
233+
});
234+
// TO DO: INVESTIGATE THIS
235+
// LIKELY WHERE THE DISPATCH ISSUE IS COMING FROM
232236
}
233237
}
234238
}

0 commit comments

Comments
 (0)