Skip to content

Commit e6fa062

Browse files
authored
Load all nested items under a given folder to enable proper drag'n'drop functionality. (#1398)
* Load all content nested within folders. Refetch every time a folder is opened to ensure its content is always up-to-date. * Clear workspace when selected project is located within reloaded folder. * Refactor loadTreeNodesAtPath => loadTreeNodes
1 parent 43a3b94 commit e6fa062

File tree

5 files changed

+113
-138
lines changed

5 files changed

+113
-138
lines changed

web/js/codeworld.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ import {
1919
definePanelExtension,
2020
deleteFolder_,
2121
deleteProject_,
22-
discoverProjects,
2322
getNearestDirectory,
2423
initDirectoryTree,
2524
loadProject,
2625
loadSample,
26+
loadTreeNodes,
2727
markFailed,
2828
onHover,
2929
parseCompileErrors,
@@ -134,7 +134,7 @@ async function init() {
134134

135135
window.auth2.isSignedIn.listen(() => {
136136
if (Auth.signedIn()) {
137-
discoverProjects('');
137+
loadTreeNodes(DirTree.getRootNode());
138138

139139
$('#signin').hide();
140140
$('#signout, #navButton').show();
@@ -232,7 +232,7 @@ async function init() {
232232
'error'
233233
);
234234
}
235-
discoverProjects('');
235+
loadTreeNodes(DirTree.getRootNode());
236236
});
237237
});
238238
}

web/js/codeworld_shared.js

Lines changed: 90 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -721,14 +721,14 @@ function registerStandardHints(successFunc) {
721721
});
722722
}
723723

724-
function loadTreeNodesAtPath(path, node, callback) {
724+
function loadTreeNodes(atNode) {
725725
const data = new FormData();
726726
data.append('mode', window.projectEnv);
727-
data.append('path', path);
727+
data.append('path', getNearestDirectory(atNode));
728728

729-
showLoadingAnimation(node);
729+
showLoadingAnimation(atNode);
730730

731-
sendHttp('POST', 'listFolder', data, (request) => {
731+
sendHttp('POST', 'listFolders', data, (request) => {
732732
if (request.status === 200) {
733733
const treeNodes = JSON.parse(request.responseText);
734734

@@ -741,58 +741,29 @@ function loadTreeNodesAtPath(path, node, callback) {
741741
$('#directoryTree').tree(
742742
'loadData',
743743
treeNodes.sort((a, b) => a.index > b.index),
744-
node
744+
atNode
745745
);
746746

747-
if (node) {
748-
$('#directoryTree').tree('openNode', node);
749-
}
750-
751-
if (callback) {
752-
callback();
753-
}
747+
$('#directoryTree').tree('openNode', atNode);
754748
}
755749

756750
hideLoadingAnimation();
757751
});
758752
}
759753

760-
function loadSubTree(node, callback) {
761-
if (Auth.signedIn()) {
762-
// Root node already loaded
763-
if (node === $('#directoryTree').tree('getTree') && callback) {
764-
callback();
765-
} else if (DirTree.isDirectory(node)) {
766-
loadTreeNodesAtPath(getNearestDirectory(node), node, callback);
767-
}
768-
}
769-
}
770-
771-
function discoverProjects(path) {
772-
if (Auth.signedIn()) {
773-
loadTreeNodesAtPath(path);
774-
}
775-
}
776-
777-
function moveDirTreeNode(
778-
moveFrom,
779-
moveTo,
780-
isFile,
781-
name,
782-
buildMode,
783-
successFunc
784-
) {
754+
function moveDirTreeNode(moveFrom, moveTo, node, successFunc) {
785755
if (!Auth.signedIn()) {
786756
sweetAlert('Oops!', 'You must sign in before moving.', 'error');
787757
return;
788758
}
789759
const data = new FormData();
790-
data.append('mode', buildMode);
760+
data.append('mode', window.projectEnv);
791761
data.append('moveTo', moveTo);
792762
data.append('moveFrom', moveFrom);
793-
if (isFile) {
763+
764+
if (DirTree.isProject(node)) {
794765
data.append('isFile', 'true');
795-
data.append('name', name);
766+
data.append('name', node.name);
796767
} else {
797768
data.append('isFile', 'false');
798769
}
@@ -1541,7 +1512,7 @@ function initDirectoryTree(isEditorClean, loadProjectHandler, clearEditor) {
15411512

15421513
$('#directoryTree').tree({
15431514
data: [],
1544-
autoOpen: true,
1515+
autoOpen: false,
15451516
saveState: treeStateStorageKey,
15461517
dragAndDrop: true,
15471518
keyboardSupport: false,
@@ -1631,86 +1602,92 @@ function initDirectoryTree(isEditorClean, loadProjectHandler, clearEditor) {
16311602
updateChildrenIndexes(toNode);
16321603
return;
16331604
}
1634-
// Load content of directory before move something inside
1635-
loadSubTree(toNode, () => {
1636-
let toPath = pathToRootDir(toNode);
1637-
if (toPath) {
1638-
toPath = `${toPath}/${toNode.name}`;
1605+
1606+
let toPath = pathToRootDir(toNode);
1607+
if (toPath) {
1608+
toPath = `${toPath}/${toNode.name}`;
1609+
} else {
1610+
toPath = toNode.name;
1611+
}
1612+
if (haveChildWithSameNameAndType(movedNode, toNode)) {
1613+
// Replacement of existing project
1614+
let msg, confirmText;
1615+
if (DirTree.isProject(movedNode)) {
1616+
msg = `${
1617+
'Are you sure you want to save over another project?\n\n' +
1618+
'The previous contents of '
1619+
}${name} will be permanently destroyed!`;
1620+
confirmText = 'Yes, overwrite it!';
16391621
} else {
1640-
toPath = toNode.name;
1622+
msg = 'Are you sure you want to merge content of these directories?';
1623+
confirmText = 'Yes, merge them!';
16411624
}
1642-
if (haveChildWithSameNameAndType(movedNode, toNode)) {
1643-
// Replacement of existing project
1644-
let msg, confirmText;
1645-
if (DirTree.isProject(movedNode)) {
1646-
msg = `${
1647-
'Are you sure you want to save over another project?\n\n' +
1648-
'The previous contents of '
1649-
}${name} will be permanently destroyed!`;
1650-
confirmText = 'Yes, overwrite it!';
1651-
} else {
1652-
msg =
1653-
'Are you sure you want to merge content of these directories?';
1654-
confirmText = 'Yes, merge them!';
1655-
}
16561625

1657-
sweetAlert({
1658-
title: Alert.title('Warning'),
1659-
text: msg,
1660-
type: 'warning',
1661-
showCancelButton: true,
1662-
confirmButtonColor: '#DD6B55',
1663-
confirmButtonText: confirmText,
1664-
}).then((result) => {
1665-
if (result && result.value) {
1666-
moveDirTreeNode(
1667-
fromPath,
1668-
toPath,
1669-
isFile,
1670-
name,
1671-
window.projectEnv,
1672-
() => {
1673-
toNode.children = toNode.children.filter((n) => {
1674-
return (
1675-
movedNode === n ||
1676-
n.name !== movedNode.name ||
1677-
n.type !== movedNode.type
1678-
);
1679-
});
1680-
event.move_info.do_move();
1681-
updateChildrenIndexes(toNode);
1682-
if (DirTree.isDirectory(movedNode)) {
1683-
loadSubTree(movedNode);
1684-
clearEditor();
1685-
}
1686-
}
1687-
);
1688-
}
1689-
});
1690-
} else {
1691-
// Regular moving
1692-
moveDirTreeNode(
1693-
fromPath,
1694-
toPath,
1695-
isFile,
1696-
name,
1697-
window.projectEnv,
1698-
() => {
1626+
sweetAlert({
1627+
title: Alert.title('Warning'),
1628+
text: msg,
1629+
type: 'warning',
1630+
showCancelButton: true,
1631+
confirmButtonColor: '#DD6B55',
1632+
confirmButtonText: confirmText,
1633+
}).then((result) => {
1634+
if (result && result.value) {
1635+
moveDirTreeNode(fromPath, toPath, movedNode, () => {
1636+
toNode.children = toNode.children.filter((n) => {
1637+
return (
1638+
movedNode === n ||
1639+
n.name !== movedNode.name ||
1640+
n.type !== movedNode.type
1641+
);
1642+
});
16991643
event.move_info.do_move();
17001644
updateChildrenIndexes(toNode);
1701-
}
1702-
);
1703-
}
1704-
});
1645+
1646+
if (DirTree.isDirectory(movedNode)) {
1647+
loadTreeNodes(movedNode);
1648+
clearEditor();
1649+
}
1650+
});
1651+
}
1652+
});
1653+
} else {
1654+
// Regular moving
1655+
moveDirTreeNode(fromPath, toPath, movedNode, () => {
1656+
event.move_info.do_move();
1657+
updateChildrenIndexes(toNode);
1658+
});
1659+
}
17051660
});
17061661
});
17071662
$('#directoryTree').on('tree.open', (event) => {
1708-
const folderIcon = event.node.element.getElementsByClassName(
1663+
const { node: openedNode } = event;
1664+
1665+
const folderIcon = openedNode.element.getElementsByClassName(
17091666
'mdi-folder'
17101667
)[0];
17111668
if (folderIcon) {
17121669
folderIcon.classList.replace('mdi-folder', 'mdi-folder-open');
17131670
}
1671+
1672+
loadTreeNodes(openedNode);
1673+
1674+
const selectedNode = DirTree.getSelectedNode();
1675+
1676+
if (selectedNode) {
1677+
for (
1678+
let parent = selectedNode.parent;
1679+
parent !== null;
1680+
parent = parent.parent
1681+
) {
1682+
if (parent.id === openedNode.id) {
1683+
DirTree.clearSelectedNode();
1684+
updateDocumentTitle();
1685+
clearEditor();
1686+
1687+
break;
1688+
}
1689+
}
1690+
}
17141691
});
17151692
$('#directoryTree').on('tree.close', (event) => {
17161693
const folderIcon = event.node.element.getElementsByClassName(
@@ -1737,17 +1714,12 @@ function initDirectoryTree(isEditorClean, loadProjectHandler, clearEditor) {
17371714
}
17381715
warnIfUnsaved(isEditorClean, () => {
17391716
if (isProjectNode) {
1740-
const path = pathToRootDir(node);
1741-
1742-
loadProjectHandler(node.name, path);
1743-
$('#directoryTree').tree('selectNode', node);
1744-
} else if (DirTree.isDirectory(node)) {
1745-
if (node.children.length === 0) {
1746-
loadSubTree(node);
1747-
}
1717+
loadProjectHandler(node.name, pathToRootDir(node));
1718+
} else {
17481719
clearEditor();
1749-
$('#directoryTree').tree('selectNode', node);
17501720
}
1721+
1722+
$('#directoryTree').tree('selectNode', node);
17511723
});
17521724
});
17531725
$('#directoryTree').on('tree.select', (event) => {
@@ -2057,11 +2029,11 @@ export {
20572029
definePanelExtension,
20582030
deleteFolder_,
20592031
deleteProject_,
2060-
discoverProjects,
20612032
getNearestDirectory,
20622033
initDirectoryTree,
20632034
loadProject,
20642035
loadSample,
2036+
loadTreeNodes,
20652037
markFailed,
20662038
onHover,
20672039
parseCompileErrors,

web/js/funblocks.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ import {
1818
createFolder,
1919
deleteFolder_,
2020
deleteProject_,
21-
discoverProjects,
2221
getNearestDirectory,
2322
initDirectoryTree,
2423
loadProject,
2524
loadSample,
25+
loadTreeNodes,
2626
markFailed,
2727
printMessage,
2828
registerStandardHints,
@@ -109,7 +109,7 @@ async function init() {
109109

110110
window.auth2.isSignedIn.listen(() => {
111111
if (Auth.signedIn()) {
112-
discoverProjects('');
112+
loadTreeNodes(DirTree.getRootNode());
113113

114114
$('#signin').hide();
115115
$('#signout, #navButton').show();
@@ -183,7 +183,7 @@ async function init() {
183183
);
184184
}
185185
initCodeworld();
186-
discoverProjects('');
186+
loadTreeNodes(DirTree.getRootNode());
187187
});
188188
});
189189
} else {

web/js/utils/auth.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*/
1616

1717
import { sendHttp } from './network.js';
18-
import { discoverProjects, warnIfUnsaved } from '../codeworld_shared.js';
18+
import { warnIfUnsaved } from '../codeworld_shared.js';
1919

2020
function LocalAuth() {
2121
const mine = {};
@@ -484,8 +484,6 @@ function onAuthDisabled() {
484484
window.auth2 = null;
485485

486486
$('#signin').css('display', 'none');
487-
488-
discoverProjects('');
489487
}
490488

491489
function init(initCallback) {

0 commit comments

Comments
 (0)