diff --git a/src/public/javascripts/services/info.js b/src/public/javascripts/services/info.js index d48ddaf3c..fd47338b0 100644 --- a/src/public/javascripts/services/info.js +++ b/src/public/javascripts/services/info.js @@ -2,7 +2,7 @@ import messagingService from "./messaging.js"; import utils from "./utils.js"; function showMessage(message) { - console.log(utils.now(), "message: ", message); + console.debug(utils.now(), "message: ", message); $.notify({ // options diff --git a/src/public/javascripts/services/note_detail_relation_map.js b/src/public/javascripts/services/note_detail_relation_map.js index 99d082d68..6b632c561 100644 --- a/src/public/javascripts/services/note_detail_relation_map.js +++ b/src/public/javascripts/services/note_detail_relation_map.js @@ -1,5 +1,6 @@ import server from "./server.js"; import noteDetailService from "./note_detail.js"; +import linkService from "./link.js"; import libraryLoader from "./library_loader.js"; const $noteDetailRelationMap = $("#note-detail-relation-map"); @@ -18,7 +19,7 @@ const uniDirectionalOverlays = [ length: 14, foldback: 0.8 } ], - [ "Label", { label: "", id: "label", cssClass: "aLabel" }] + [ "Label", { label: "", id: "label", cssClass: "connection-label" }] ]; const biDirectionalOverlays = [ @@ -28,7 +29,7 @@ const biDirectionalOverlays = [ length: 14, foldback: 0.8 } ], - [ "Label", { label: "", id: "label", cssClass: "aLabel" }], + [ "Label", { label: "", id: "label", cssClass: "connection-label" }], [ "Arrow", { location: 0, id: "arrow2", @@ -86,7 +87,7 @@ async function loadNotesAndRelations() { mapData.notes = mapData.notes.filter(note => note.id in data.noteTitles); - instance.batch(function () { + instance.batch(async function () { const maxY = mapData.notes.filter(note => !!note.y).map(note => note.y).reduce((a, b) => Math.max(a, b), 0); let curX = 100; let curY = maxY + 200; @@ -95,9 +96,9 @@ async function loadNotesAndRelations() { const title = data.noteTitles[note.id]; if (note.x && note.y) { - newNode(note.id, title, note.x, note.y); + await newNode(note.id, title, note.x, note.y); } else { - newNode(note.id, title, curX, curY); + await newNode(note.id, title, curX, curY); if (curX > 1000) { curX = 100; @@ -159,46 +160,11 @@ async function initJsPlumb () { Container: "relation-map-canvas" }); - instance.registerConnectionType("uniDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: uniDirectionalOverlays }); instance.registerConnectionType("biDirectional", { anchor:"Continuous", connector:"StateMachine", overlays: biDirectionalOverlays }); - instance.bind("connection", async function (info, originalEvent) { - // if there's no event, then this has been triggered programatically - if (!originalEvent) { - return; - } - - const name = prompt("Specify new relation name:"); - - if (!name || !name.trim()) { - return; - } - - const connection = info.connection; - - const targetNoteId = connection.target.id; - const sourceNoteId = connection.source.id; - - const existing = relations.some(rel => - rel.targetNoteId === targetNoteId - && rel.sourceNoteId === sourceNoteId - && rel.name === name); - - if (existing) { - alert("Connection '" + name + "' between these notes already exists."); - - return; - } - - await server.put(`notes/${sourceNoteId}/relations/${name}/to/${targetNoteId}`); - - relations.push({ targetNoteId, sourceNoteId, name }); - - connection.setType("uniDirectional"); - connection.getOverlay("label").setLabel(name); - }); + instance.bind("connection", connectionCreatedHandler); $relationMapCanvas.contextmenu({ delegate: ".note-box", @@ -212,7 +178,7 @@ async function initJsPlumb () { $.widget("moogle.contextmenuRelation", $.moogle.contextmenu, {}); $relationMapCanvas.contextmenuRelation({ - delegate: ".aLabel,.jtk-connector", + delegate: ".connection-label,.jtk-connector", autoTrigger: false, // it doesn't open automatically, needs to be triggered explicitly by .open() call menu: [ {title: "Remove relation", cmd: "remove", uiIcon: "ui-icon-trash"}, @@ -230,13 +196,53 @@ async function initJsPlumb () { await loadNotesAndRelations(); // so that canvas is not panned when clicking/dragging note box - $relationMapCanvas.on('mousedown touchstart', '.note-box, .aLabel', e => e.stopPropagation()); + $relationMapCanvas.on('mousedown touchstart', '.note-box, .connection-label', e => e.stopPropagation()); jsPlumb.fire("jsPlumbDemoLoaded", instance); initPanZoom(); } +async function connectionCreatedHandler(info, originalEvent) { + // if there's no event, then this has been triggered programatically + if (!originalEvent) { + return; + } + + const name = prompt("Specify new relation name:"); + + if (!name || !name.trim()) { + instance.deleteConnection(connection); + + return; + } + + const connection = info.connection; + + const targetNoteId = connection.target.id; + const sourceNoteId = connection.source.id; + + const existing = relations.some(rel => + rel.targetNoteId === targetNoteId + && rel.sourceNoteId === sourceNoteId + && rel.name === name); + + if (existing) { + alert("Connection '" + name + "' between these notes already exists."); + + instance.deleteConnection(connection); + + return; + } + + await server.put(`notes/${sourceNoteId}/relations/${name}/to/${targetNoteId}`); + + relations.push({ targetNoteId, sourceNoteId, name }); + + connection.setType("uniDirectional"); + connection.getOverlay("label").setLabel(name); +} + function relationContextMenuHandler(event, ui) { const {connection} = ui.extraData; @@ -347,12 +353,12 @@ function initNode(el) { instance.fire("jsPlumbDemoNodeAdded", el); } -function newNode(id, title, x, y) { +async function newNode(id, title, x, y) { const $noteBox = $("
") .addClass("note-box") .prop("id", id) .append($("
").addClass("handle")) - .append($("").addClass("title").text(title)) + .append($("").addClass("title").html(await linkService.createNoteLink(id, title))) .append($("
").addClass("endpoint")) .css("left", x + "px") .css("top", y + "px"); @@ -379,7 +385,7 @@ $addChildNotesButton.click(async () => { mapData.notes.push(note); - newNode(note.id, note.title, curX, curY); + await newNode(note.id, note.title, curX, curY); if (curX > 1000) { curX = 100; diff --git a/src/public/stylesheets/relation-map.css b/src/public/stylesheets/relation-map.css index f16082f2b..259314dc6 100644 --- a/src/public/stylesheets/relation-map.css +++ b/src/public/stylesheets/relation-map.css @@ -3,6 +3,11 @@ overflow: hidden; } +/* this is removing dotted border around focused/active relation map */ +#note-detail-relation-map, #note-detail-relation-map:active, #note-detail-relation-map:focus { + outline: none; +} + #relation-map-canvas { position: absolute; /* needs to be absolute otherwise connections will be misplaced */ } @@ -31,16 +36,21 @@ color: white; } -.aLabel { +.note-box .title { + font-size: larger; + font-weight: 600; +} + +.connection-label { transition: background-color 0.25s ease-in; } -.aLabel.jtk-hover, .jtk-source-hover, .jtk-target-hover { +.connection-label.jtk-hover, .jtk-source-hover, .jtk-target-hover { background-color: #1e8151; color: white; } -.aLabel { +.connection-label { background-color: white; opacity: 0.8; padding: 0.3em;