Skip to content

Commit

Permalink
Merge pull request #14 from UNDP-Accelerator-Labs/pipe-groups
Browse files Browse the repository at this point in the history
Fix matrix broadcasting
  • Loading branch information
myjyby authored Nov 25, 2024
2 parents 90b7170 + e8433a9 commit 35aff66
Show file tree
Hide file tree
Showing 9 changed files with 154 additions and 73 deletions.
16 changes: 16 additions & 0 deletions public/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,15 @@ div.matrix table td > div.group {
height: 100%;
box-sizing: border-box;
}
div.add-row,
div.add-col {
opacity: 0;
}
div.add-row:hover,
div.add-col:hover {
opacity: 1;
}

div.add-col {
width: 4rem;
}
Expand All @@ -186,6 +195,8 @@ div.add-row button {
}*/
div.group {
position: absolute;
/* border: 1px solid #000;*/
/* background-color: rgba(255, 255, 255, .75);*/
border: 1px solid rgba(51,51,51,.25);
background-color: rgba(225,225,225,.25);
padding: 0 0 2rem 2rem;
Expand Down Expand Up @@ -301,6 +312,11 @@ div.card.focus {
div.locked {
pointer-events: none !important;
}
div.locked div.note,
div.locked div.card,
div.locked div.group {
pointer-events: all;
}
div.locked::before {
content: attr(data-locked-by);
position: absolute;
Expand Down
5 changes: 3 additions & 2 deletions public/js/canvas/zoom.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Note, Group, Card } from '../elements/index.mjs';
import { Note, Group, Card, Matrix } from '../elements/index.mjs';

function zoomstart () {
Note.releaseAll(true);
Group.releaseAll(true);
Card.releaseAll(true);
Group.releaseAll(true);
Matrix.releaseAll(true);
}
function zooming () {
if (d3.select(this).classed('adding-text') || d3.select(this).classed('changing-text')) return
Expand Down
11 changes: 6 additions & 5 deletions public/js/elements/drag.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -107,16 +107,17 @@ function dragging (d) {
});
}
async function dragEnd (d) {
const sel = d3.select(this)
.classed('dragging', false);

if (computeDistance([0, 0], [d.dx, d.dy]) <= 10) {
// Note.releaseAll(true);
Card.releaseAll(true);
Group.releaseAll(true);
// if (!(sel.classed('group') && d.persistent)) Group.releaseAll(true);
// Matrix.releaseAll(true);
return console.log('has not moved');
}

const sel = d3.select(this)
.classed('dragging', false);
// REACTIVATE ALL textareas AND inputs
d3.select('div.canvas').selectAll('textarea, input')
.classed('deactivate', false);
Expand All @@ -140,7 +141,7 @@ async function dragEnd (d) {
const { id: gid, tree: gtree, pipe_to } = hit.datum();
d.tree = tree.build(gtree, gid);
if (Array.isArray(pipe_to) && pipe_to?.length) pipes = [ ...pipes, ...pipe_to ];

} else if (hit.classed('note') || hit.classed('card')) {
// IF THE HIT IS A NOTE OR CARD, CREATE A GROUP
const { x, y, tree: ntree, piped_from } = hit.datum();
Expand Down Expand Up @@ -203,7 +204,7 @@ async function dragEnd (d) {
datum: d,
bcast: true,
});
Group.release({ group: sel, id: d.id, bcast: true });
// Group.release({ group: sel, id: d.id, bcast: true });
} else if (sel.classed('matrix')) {
await Matrix.update({
matrix: sel,
Expand Down
31 changes: 24 additions & 7 deletions public/js/elements/groups.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ export const Group = {
const constructorRef = this;
let { parent, datum, children, focus, bcast, client, immutable } = _kwargs;
if (!datum) datum = {};
let { id, label, x, y, tree: gtree, matrix_index } = datum;
let { id, label, x, y, tree: gtree, matrix_index, persistent } = datum;
if (!label) label = '';
if (x === undefined) x = 0;
if (y === undefined) y = 0;
if (matrix_index) immutable = true;
// CHECK IF THIS IS A NEW GROUP
if (!id) datum = await POST('/addGroup', { data: { label, x, y, tree: gtree, matrix_index }, project: wallId });
if (!id) datum = await POST('/addGroup', { data: { label, x, y, tree: gtree, matrix_index, persistent }, project: wallId });
// REMOVE FOCUS FROM ALL OBJECTS
constructorRef.releaseAll(bcast);
Note.releaseAll(bcast);
Expand All @@ -27,8 +27,19 @@ export const Group = {
const child = tree.getDepth(gtree) > 1;
if (!parent) {
if (child) {
const parentNode = d3.selectAll('div.group, div.matrix').filter(d => d.tree === tree.moveUp(gtree) && d.id === +tree.getLeaf(gtree)).node();
const parentNode = d3.selectAll('div.group, div.matrix table tr.row td')
.filter(function (d) {
const sel = d3.select(this);
if (sel.classed('group')) {
return d.tree === tree.moveUp(gtree)
&& d.id === +tree.getLeaf(gtree);
} else {
return d.tree === gtree
&& d.matrix_index === matrix_index;
}
}).node();
if (parentNode) parent = d3.select(parentNode);
else parent = d3.select('div.canvas');
} else parent = d3.select('div.canvas');
}
// ADD A GROUP
Expand Down Expand Up @@ -134,8 +145,14 @@ export const Group = {
let immutable = false;
if (!group) {
const { id } = datum;
group = d3.selectAll('div.group')
.filter(d => d.id === id);
if (id) {
group = d3.selectAll('div.group')
.filter(d => d.id === id);
}
// IF NO GROUP IS FOUND, CREATE THE GROUP
if (!group.node()) { // THE GROUP DOES NOT YET EXIST
return constructorRef.add({ datum, bcast });
}
}
if (datum) {
group.each(d => {
Expand All @@ -144,7 +161,7 @@ export const Group = {
}
});
};
const { tree: gtree, id: gid, matrix_index } = group.datum();
const { tree: gtree, id: gid, matrix_index, persistent } = group.datum();
if (matrix_index) immutable = true;

const child = tree.getDepth(gtree) > 1;
Expand All @@ -169,7 +186,7 @@ export const Group = {
.filter(function () {
return this.parentNode === group.node();
});
const rmGroup = children.size() <= 1 && !immutable;
const rmGroup = children.size() <= 1 && !immutable && !persistent;

const childNodes = children.nodes();
for (let i = 0; i < childNodes.length; i ++) {
Expand Down
98 changes: 70 additions & 28 deletions public/js/elements/matrixes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export const Matrix = {
if (!cols) cols = new Array(2).fill('header');;
// CHECK IF THIS IS A NEW MATRIX
if (!id) datum = await POST('/addMatrix', { data: { label, x, y, tree: mtree, rows, cols }, project: wallId });

// REMOVE FOCUS FROM ALL OBJECTS
// constructorRef.releaseAll(bcast);
Note.releaseAll(bcast);
Expand All @@ -37,6 +36,7 @@ export const Matrix = {
if (child) {
const parentNode = d3.selectAll('div.matrix').filter(d => d.tree === tree.moveUp(mtree) && d.id === +tree.getLeaf(mtree)).node();
if (parentNode) parent = d3.select(parentNode);
else parent = d3.select('div.canvas');
} else parent = d3.select('div.canvas');
}
// ADD A MATRIX
Expand Down Expand Up @@ -73,7 +73,6 @@ export const Matrix = {
// SAVE AND BROADCAST
if (bcast) {
await constructorRef.save(matrix.datum());
constructorRef.broadcast({ operation: 'add', data: matrix.datum() });
}
// THE SAVE AND BROADCAST NEEDS TO COME BEFORE HANDLING THE CHILDREN HERE
// BECAUSE OTHERWISE, THE CHILDREN GET UPDATED BEFORE THE MATRIXES IS CREATED
Expand All @@ -85,7 +84,7 @@ export const Matrix = {
for (let i = 0; i < mrows.length; i ++) {
const row = mrows[i];

const tr = table.addElems('tr', `row-${i}`)
const tr = table.addElems('tr', `row row-${i}`, d => { return [{ ...d, rowId: i }] });
tr.addElems('th', 'sticky-area immutable row-header', [{ id: mid, label: row, cidx: i }])
.call(constructorRef.addLabel, { constructorRef, axis: 'rows' });

Expand All @@ -96,36 +95,38 @@ export const Matrix = {
&& tree.getLeaf(c.matrix_index) === j.toString();
});
let group;
console.log('cell', cell)

if (cell) {
const td = tr.addElems('td', `cell-${j}`, [cell]);
group = await Group.add({
parent: td,
datum: cell,
immutable: true,
bcast, // THIS OPERATION MAY BE REDUNDANT
bcast: false, // THIS OPERATION MAY BE REDUNDANT
});
} else {
// CREATE A NEW CELL
const ctree = tree.build(mdtree, `m${mid}`);
const cidx = tree.build(i, j);
cell = { tree: ctree, matrix_index: cidx, x: null, y: null };
cell = { tree: ctree, matrix_index: cidx, x: null, y: null, persistent: true };

const td = tr.addElems('td', `cell-${j}`, [cell]);
group = await Group.add({
parent: td,
datum: cell,
immutable: true,
bcast, // THIS OPERATION MAY BE REDUNDANT
bcast: false, // THIS OPERATION MAY BE REDUNDANT
});

// ADD A MINIMUM OF TWO NOTES
const { tree: gtree, id: gid } = group.datum();
const ntree = tree.build(gtree, gid);
for (let n = 0; n < 2; n ++) {
await Note.add({
parent: group,
datum: { tree: ntree, x: null, y: null },
bcast, // THIS OPERATION MAY BE REDUNDANT
bcast: false, // HERE BROADCAST NEEDS TO BE FALSE TO AVOID DUPLICATE BROADCAST
});
}
}
Expand All @@ -145,12 +146,23 @@ export const Matrix = {
.addElems('button')
.on('click', function () {
constructorRef.addAxis({ matrix, axis: 'row' });
}).html('+')
}).html('+');

if (bcast) {
// NEED TO SEPARATE OUT THE BROADCAST HERE IN ORDER TO HAVE note IDs TO BROADCAST
// OTHERWISE THE NOTES GET CREATED AS MANY TIMES AS THERE ARE USERS CONNECTED TO THE ROOM
constructorRef.broadcast({ operation: 'add', data: matrix.datum() });
// BROADCAST ALL NOTES
matrix.selectAll('div.note')
.each(function (d) {
Note.broadcast({ operation: 'add', data: d });
});
}

matrix.call(drag);
return matrix;
},
update: async function (_kwargs) { // TO DO: IMPROVE THIS
update: async function (_kwargs) {
const constructorRef = this;
let { matrix, datum, bcast, rows, ncols } = _kwargs;

Expand Down Expand Up @@ -183,11 +195,28 @@ export const Matrix = {
return headers;
}).call(constructorRef.addLabel, { constructorRef, axis: 'cols' });

// SAVE AND BROADCAST
let rmMatrix = false;
if (rmMatrix) {
return await constructorRef.remove({ matrix, gid, bcast });
} else {
// SAVE AND BROADCAST
if (bcast) {
await constructorRef.save(matrix.datum());
// constructorRef.broadcast({ operation: 'update', data: matrix.datum() });
}
}
// THE SAVE AND BROADCAST NEEDS TO COME BEFORE HANDLING THE CHILDREN HERE
// BECAUSE OTHERWISE, THE CHILDREN GET UPDATED BEFORE THE MATRIXES IS CREATED
// IN THE DISPATCHED INSTANCES

// UPDATE THE CONTENT OF THE MATRIX
console.log(mcells)

for (let i = 0; i < mrows.length; i ++) {
const row = mrows[i];

const tr = table.addElems('tr', `row-${i}`)
const tr = table.addElems('tr', `row row-${i}`, d => { return [{ ...d, rowId: i }] });
tr.addElems('th', 'sticky-area immutable row-header', [{ id: mid, label: row, cidx: i }])
.call(constructorRef.addLabel, { constructorRef, axis: 'rows' });

Expand All @@ -197,29 +226,34 @@ export const Matrix = {
return tree.getRoot(c.matrix_index) === i.toString()
&& tree.getLeaf(c.matrix_index) === j.toString();
});


// IT IS VERY IMPORTANT TO SET THE td OUTSIDE THE CONDITION
// TO BE ABLE TO FIND IT FOR DISPATCHED GROUPS
const td = tr.addElems('td', `cell-${j}`, [cell || {}]);

if (!cell) { // ONLY ADD CELLS THAT DO NOT EXIST // IF A CELL ALREADY EXISTS, DO NOTHING
// ALL TRANSFORMATIONS SHOULD BE HANDLED BY THE Group IN THE CELL
// CREATE A NEW CELL
const ctree = tree.build(mtree, `m${mid}`);
const cidx = tree.build(i, j);
cell = { tree: ctree, matrix_index: cidx, x: null, y: null };
cell = { tree: ctree, matrix_index: cidx, x: null, y: null, persistent: true };

const td = tr.addElems('td', `cell-${j}`, [cell]);
td.datum(cell);
const group = await Group.add({
parent: td,
datum: cell,
immutable: true,
bcast, // THIS OPERATION MAY BE REDUNDANT
bcast: false,
});

// ADD A MINIMUM OF TWO NOTES
const { tree: gtree, id: gid } = group.datum();
const ntree = tree.build(gtree, gid);
for (let n = 0; n < 2; n ++) {
await Note.add({
parent: group,
datum: { tree: ntree, x: null, y: null },
bcast, // THIS OPERATION MAY BE REDUNDANT
bcast: false,
});
}

Expand All @@ -231,24 +265,31 @@ export const Matrix = {
if (!d.cells) d.cells = [];
d.cells.push(group.datum());
});
// TO DO: INVESTIGATE THIS
// LIKELY WHERE THE DISPATCH ISSUE IS COMING FROM
}
}
}

// SAVE AND BROADCAST
let rmMatrix = false;
if (rmMatrix) {
return await constructorRef.remove({ matrix, gid, bcast });
} else {
// SAVE AND BROADCAST
if (bcast) {
await constructorRef.save(matrix.datum());
constructorRef.broadcast({ operation: 'update', data: matrix.datum() });
}
return matrix;
if (bcast) {
// NEED TO SEPARATE OUT THE BROADCAST HERE IN ORDER TO HAVE note IDs TO BROADCAST
// OTHERWISE THE NOTES GET CREATED AS MANY TIMES AS THERE ARE USERS CONNECTED TO THE ROOM
constructorRef.broadcast({ operation: 'update', data: matrix.datum() });
// BROADCAST ALL GROUPS
matrix.selectAll('div.group')
.each(function (d) {
Group.broadcast({ operation: 'update', data: d });
});
// BROADCAST ALL NOTES
matrix.selectAll('div.note')
.each(function (d) {
Note.broadcast({ operation: 'update', data: d });
});
constructorRef.release({
matrix,
id: mid,
bcast: true,
})
}
return matrix;
},
remove: async function (_kwargs) {
const constructorRef = this;
Expand Down Expand Up @@ -316,6 +357,7 @@ export const Matrix = {
});
},
save: async function (data) {
console.trace()
if (wallId) await POST('/updateMatrix', { data, project: wallId });
else console.log('error: no project to save to');
},
Expand Down
Loading

0 comments on commit 35aff66

Please sign in to comment.