implemented Simpleline in studyplan editor

This commit is contained in:
PMKuipers 2023-07-17 23:04:21 +02:00
parent 886a244520
commit 2a845a961a
4 changed files with 53 additions and 79 deletions

View File

@ -124,10 +124,28 @@ export class SimpleLine {
this.resizeObserver.observe(this.start); this.resizeObserver.observe(this.start);
this.resizeObserver.observe(this.end); this.resizeObserver.observe(this.end);
// Setup the mutationobserver so we can remove the line if it's start or end is removed.
this.mutationObserver = new MutationObserver(function(mutations_list) {
mutations_list.forEach(function(mutation) {
mutation.removedNodes.forEach(function(removed_node) {
if(removed_node == this.start || removed_node == this.end) {
console.warning("Element removed",removed_node);
this.remove();
}
});
});
});
this.mutationObserver.observe(this.start.parentElement, { subtree: false, childList: true });
this.mutationObserver.observe(this.end.parentElement, { subtree: false, childList: true });
// Setup the position checker
this.positionCheck(); // Initialize refresh this.positionCheck(); // Initialize refresh
if(this.specs.autorefresh > 0){ if(this.specs.autorefresh > 0){
this.refreshTimer = setInterval(()=>{this.positionCheck();},this.specs.autorefresh); this.refreshTimer = setInterval(()=>{this.positionCheck();},this.specs.autorefresh);
} }
this.active = true;
this.update(); // fist draw this.update(); // fist draw
} }
@ -213,7 +231,7 @@ export class SimpleLine {
// Validate or determine container // Validate or determine container
let container = this.start.offsetParent; let container = this.start.offsetParent;
if(!container) { if(!container) {
if(document.getComputedStyle(this.start).position == "fixed"){ if(getComputedStyle(this.start).position == "fixed"){
container = document.querySelector("body"); container = document.querySelector("body");
} else { } else {
console.error("Start element has no offsetParent. likely "); console.error("Start element has no offsetParent. likely ");
@ -276,6 +294,8 @@ export class SimpleLine {
update(){ update(){
if(!this.active){ return;} // don't do this if we are no longer active
const container = this.getContainer(); const container = this.getContainer();
if (!container) { return; } // Do not create any svg if container is empty if (!container) { return; } // Do not create any svg if container is empty
@ -401,7 +421,8 @@ export class SimpleLine {
// clear the refresh timer // clear the refresh timer
clearInterval(this.refreshTimer); clearInterval(this.refreshTimer);
// stop the observers // stop the observers
this.resizeObserver.unobserve(this.start); this.resizeObserver.disconnect();
this.resizeObserver.unobserve(this.end); this.mutationObserver.disconnect();
this.active = false;
} }
} }

View File

@ -6,7 +6,7 @@
/*eslint-env es6*/ /*eslint-env es6*/
// Put this file in path/to/plugin/amd/src // Put this file in path/to/plugin/amd/src
import LeaderLine from './leaderline'; import {SimpleLine} from "./simpleline";
import {call} from 'core/ajax'; import {call} from 'core/ajax';
import notification from 'core/notification'; import notification from 'core/notification';
import {debounce} from './debounce'; import {debounce} from './debounce';
@ -43,7 +43,6 @@ export default {
// Create new eventbus for interaction between item components // Create new eventbus for interaction between item components
const ItemEventBus = new Vue(); const ItemEventBus = new Vue();
const LineGravity = 70;
let string_keys = load_stringkeys({ let string_keys = load_stringkeys({
conditions: [ conditions: [
@ -1895,13 +1894,8 @@ export default {
dragelement.style.position = 'fixed'; dragelement.style.position = 'fixed';
dragelement.style.left = event.position.x+'px'; dragelement.style.left = event.position.x+'px';
dragelement.style.top = event.position.y+'px'; dragelement.style.top = event.position.y+'px';
this.dragLine = new LeaderLine(start,dragelement,{ this.dragLine = new SimpleLine(start,dragelement,{
color: '#777', color: "#777"
positionByWindowResize: false,
startSocket: 'right',
endSocket: 'left',
startSocketGravity: LineGravity,
endSocketGravity: LineGravity,
}); });
// Add separate event listener to reposition mouse move // Add separate event listener to reposition mouse move
document.addEventListener("mousemove",this.onMouseMove); document.addEventListener("mousemove",this.onMouseMove);
@ -1921,12 +1915,12 @@ export default {
dragelement.style.position = 'fixed'; dragelement.style.position = 'fixed';
dragelement.style.left = event.clientX+'px'; dragelement.style.left = event.clientX+'px';
dragelement.style.top = event.clientY+'px'; dragelement.style.top = event.clientY+'px';
this.dragLine.position(); // line will follow automatically
},5), },20),
onDrop(event){ onDrop(event){
let from_id = event.data.id; let from_id = event.data.id;
let to_id = this.value.id; let to_id = this.value.id;
this.redrawLines();
call([{ call([{
methodname: 'local_treestudyplan_connect_studyitems', methodname: 'local_treestudyplan_connect_studyitems',
args: { 'from_id': from_id, 'to_id': to_id } args: { 'from_id': from_id, 'to_id': to_id }
@ -1938,49 +1932,21 @@ export default {
}).fail(notification.exception); }).fail(notification.exception);
}, },
redrawLine(conn){ redrawLine(conn){
let lineColor = "#383"; const lineColor = "var(--success)";
const start = document.getElementById(`studyitem-${conn.from_id}`);
const end = document.getElementById(`studyitem-${conn.to_id}`);
// prepare lineinfo link or delete old line // delete old line
let lineinfo = this.lines[conn.to_id]; if(this.lines[conn.to_id]){
if(lineinfo){ this.lines[conn.to_id].remove();
if(lineinfo.line){ delete this.lines[conn.to_id];
if(lineinfo.lineElm ){
lineinfo.lineElm.parentNode.removeChild(lineinfo.lineElm);
lineinfo.lineElm = undefined;
} else {
lineinfo.line.remove();
} }
lineinfo.line = undefined; // create a new line if the start and finish items are visible
}
} else {
lineinfo = {};
this.lines[conn.to_id] = lineinfo;
}
// draw new line
let start = document.getElementById('studyitem-'+conn.from_id);
let end= document.getElementById('studyitem-'+conn.to_id);
LeaderLine.positionByWindowResize = false;
if(start !== null && end !== null && isVisible(start) && isVisible(end)){ if(start !== null && end !== null && isVisible(start) && isVisible(end)){
lineinfo.line = new LeaderLine(start,end,{ this.lines[conn.to_id] = new SimpleLine( start,end,{color: lineColor,}
color: lineColor, );
startSocket: 'right', }
endSocket: 'left',
startSocketGravity: LineGravity,
endSocketGravity: LineGravity,
});
let elmWrapper = (this.plan.id >=0)?document.getElementById('studyplan-linewrapper-'+this.plan.id):null;
if(elmWrapper !== null){
let elmLine = document.querySelector('body > .leader-line:last-child');
elmWrapper.appendChild(elmLine);
lineinfo.lineElm = elmLine; // store line element so it can more easily be removed from the dom
}
setTimeout(function(){
if(lineinfo.line !== undefined){
lineinfo.line.position();
}
},1);
}
}, },
deleteLine(conn){ deleteLine(conn){
const self = this; const self = this;
@ -2000,15 +1966,13 @@ export default {
}).fail(notification.exception); }).fail(notification.exception);
}, },
highlight(conn){ highlight(conn){
let lineinfo = this.lines[conn.to_id]; if(this.lines[conn.to_id]){
if(lineinfo && lineinfo.line){ this.lines[conn.to_id].setConfig({color:"var(--danger)",});
lineinfo.line.setOptions({color:"#f33",});
} }
}, },
normalize(conn){ normalize(conn){
let lineinfo = this.lines[conn.to_id]; if(this.lines[conn.to_id]){
if(lineinfo && lineinfo.line){ this.lines[conn.to_id].setConfig({color:"var(--success)",});
lineinfo.line.setOptions({color:"#383",});
} }
}, },
updateItem() { updateItem() {
@ -2056,9 +2020,7 @@ export default {
onRePositioned(){ onRePositioned(){
for(let i in this.value.connections.out){ for(let i in this.value.connections.out){
let conn = this.value.connections.out[i]; let conn = this.value.connections.out[i];
//if(conn.to_id == re_id){
this.redrawLine(conn); this.redrawLine(conn);
//}
} }
}, },
// When an item is disPositioned - (temporarily) removed from the list, // When an item is disPositioned - (temporarily) removed from the list,
@ -2068,8 +2030,6 @@ export default {
let conn = this.value.connections.out[i]; let conn = this.value.connections.out[i];
if(conn.to_id == re_id){ if(conn.to_id == re_id){
this.removeLine(conn); this.removeLine(conn);
} else {
this.redrawLine(conn);
} }
} }
}, },
@ -2098,17 +2058,9 @@ export default {
}, },
removeLine(conn){ removeLine(conn){
let lineinfo = this.lines[conn.to_id]; if(this.lines[conn.to_id]){
if(lineinfo){ this.lines[conn.to_id].remove();
if(lineinfo.line){ delete this.lines[conn.to_id];
if(lineinfo.lineElm ){
lineinfo.lineElm.parentNode.removeChild(lineinfo.lineElm);
lineinfo.lineElm = undefined;
} else {
lineinfo.line.remove();
}
lineinfo.line = undefined;
}
} }
}, },

View File

@ -23,6 +23,7 @@
.t-studyplan-timeline { .t-studyplan-timeline {
display: grid; display: grid;
position: relative; /* make sure this grid is the offset for all arrows that are drawn by SimpleLine */
/* grid-template-columns will be set in the style attribute */ /* grid-template-columns will be set in the style attribute */
/* Use the variables below to specify width for filter spots and course spots */ /* Use the variables below to specify width for filter spots and course spots */
--studyplan-filter-width: auto; /* better leave this at auto for now*/ --studyplan-filter-width: auto; /* better leave this at auto for now*/

View File

@ -1,6 +1,6 @@
<?php <?php
$plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494) $plugin->component = 'local_treestudyplan'; // Recommended since 2.0.2 (MDL-26035). Required since 3.0 (MDL-48494)
$plugin->version = 2023071400; // YYYYMMDDHH (year, month, day, iteration) $plugin->version = 2023071700; // YYYYMMDDHH (year, month, day, iteration)
$plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11) $plugin->requires = 2021051700; // YYYYMMDDHH (This is the release version for Moodle 3.11)
$plugin->dependencies = [ $plugin->dependencies = [