Skip to content

Commit

Permalink
Merge pull request #14 from MrMugame/main
Browse files Browse the repository at this point in the history
Fixes state issue & Uses more accurate events
  • Loading branch information
joekrill authored May 20, 2024
2 parents daf7a57 + e44f31d commit 25df026
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 122 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

* Include [custom styles](https://silverbullet.md/STYLES) in tree panel (requires SilverBullet 0.7.2 or greater).

### Fixed

* Fix header button tooltips ([#9](https://github.com/joekrill/silverbullet-treeview/pull/9))
Expand Down
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ treeview:
# - "rhs" - right hand side
# - "bhs" - bottom
# - "modal" - in a modal
position: lhs
position: lhs
# Must be > 0.
# Must be > 0.
# position = "lhs" | "rhs": determines the width of the panel.
# position = "modal": sets the margin around the modal window.
# position = "modal": sets the margin around the modal window.
# position = "bhs": No effect
size: 1
size: 1
dragAndDrop:
# Set to false to disable drag-and-drop
enabled: true
# Set to false to disable the confirmation prompt shown when dragging and
# Set to false to disable the confirmation prompt shown when dragging and
# dropping pages that causes them to be renamed/moved.
confirmOnRename: true
```
Expand All @@ -57,7 +57,7 @@ treeview:

![Screenshot](screenshot-action-button.png)

You can add add a button to the top bar that will toggle the tree view by adding
You can add add a button to the top bar that will toggle the tree view by adding
the following to your `actionButtons` array in your `SETTINGS` page:

```yaml
Expand Down
5 changes: 3 additions & 2 deletions assets/sortable-tree/sortable-tree.js

Large diffs are not rendered by default.

181 changes: 82 additions & 99 deletions assets/treeview.js
Original file line number Diff line number Diff line change
@@ -1,110 +1,93 @@
/**
* @typedef {import("../api.ts").TreeNode} TreeNode
*/

/**
* @typedef SortableTreeNode
* @type {Object}
* @property {TreeNode["data"]} data
*/

/**
*
* @typedef TreeViewConfig
* @type {Object}
* @property {string} currentPage - the current page shown in SilverBullet.
* @property {TreeNode[]} nodes - a tree of all pages in the current space.
* @property {Object} dragAndDrop - drag and drop related config
* @property {boolean} dragAndDrop.enabled - true if drag and drop is enabled
* @property {boolean} dragAndDrop.confirmOnRename - true if a confirmation should be shown
* when a node is dragged and dropped.
/**
* @typedef {import("../api.ts").TreeNode} TreeNode
*/

/**
* @typedef SortableTreeNode
* @type {Object}
* @property {TreeNode["data"]} data
*/

/**
*
* @typedef TreeViewConfig
* @type {Object}
* @property {string} currentPage - the current page shown in SilverBullet.
* @property {TreeNode[]} nodes - a tree of all pages in the current space.
* @property {Object} dragAndDrop - drag and drop related config
* @property {boolean} dragAndDrop.enabled - true if drag and drop is enabled
* @property {boolean} dragAndDrop.confirmOnRename - true if a confirmation should be shown
* when a node is dragged and dropped.
*/


const TREE_STATE_ID = "treeview";

/**
* Initializes the TreeView's `SortableTree` instance.
* @param {TreeViewConfig} config
* Initializes the TreeView's `SortableTree` instance.
* @param {TreeViewConfig} config
* @returns {SortableTree}
*
* There is currently a bug (still trying to narrow down the exact cause) in
* which `new SortableTree` can throw an exception because of something
* invalid with the state. So if there is an error, this clears the state
* and tries once more to create the tree.
*/
function createTreeView(config, retries = 1) {
try {
return new SortableTree({
nodes: config.nodes,
disableSorting: !config.dragAndDrop.enabled,
element: document.getElementById(config.treeElementId),
stateId: TREE_STATE_ID,
initCollapseLevel: 0,
lockRootLevel: false,

/**
* @param {SortableTreeNode} movedNode
* @param {SortableTreeNode} targetParentNode
*/
confirm: async (movedNode, targetParentNode) => {
const oldPrefix = movedNode.data.name;
const newPrefix = targetParentNode ? `${targetParentNode.data.name}/${movedNode.data.title}`: movedNode.data.title;

if (oldPrefix === newPrefix) {
return;
}
function createTreeView(config) {
return new SortableTree({
nodes: config.nodes,
disableSorting: !config.dragAndDrop.enabled,
element: document.getElementById(config.treeElementId),
stateId: TREE_STATE_ID,
initCollapseLevel: 0,
lockRootLevel: false,

const success = await syscall("system.invokeFunction", "index.renamePrefixCommand", {
oldPrefix,
newPrefix,
disableConfirmation: !config.dragAndDrop.confirmOnRename,
});
/**
* @param {SortableTreeNode} movedNode
* @param {SortableTreeNode} targetParentNode
*/
confirm: async (movedNode, targetParentNode) => {
const oldPrefix = movedNode.data.name;
const newPrefix = targetParentNode ? `${targetParentNode.data.name}/${movedNode.data.title}` : movedNode.data.title;

if (success && config.currentPage.indexOf(oldPrefix) === 0) {
// If this renamed the current page, navigate to it at it's updated name.
await syscall("editor.navigate", config.currentPage.replace(oldPrefix, newPrefix), false, false);
}
if (oldPrefix === newPrefix) {
return;
}

return success;
},

onChange: async () => {
await syscall("system.invokeFunction", "treeview.show");
},

/**
* @param {SortableTreeNode} node
*/
onClick: async (_event, node) => {
await syscall("editor.navigate", node.data.name, false, false);
},

/**
* @param {SortableTreeNode["data"]} data
* @returns {string}
*/
renderLabel: (data) => `
<span
data-current-page="${JSON.stringify(data.isCurrentPage || false)}"
data-node-type="${data.nodeType}"
data-permission="${data.perm}"
title="${data.name}" >
${data.title}
</span>`
,
});

} catch (err) {
if (retries > 0) {
// SortableTree can throw an error if the state somehow becomes invalid.
// This attempts to recover from that.
sessionStorage.removeItem(`sortableTreeState-${TREE_STATE_ID}`);
return createTreeView(config, 0);
} else {
throw err;
}
}
const success = await syscall("system.invokeFunction", "index.renamePrefixCommand", {
oldPrefix,
newPrefix,
disableConfirmation: !config.dragAndDrop.confirmOnRename,
});

if (success && config.currentPage.indexOf(oldPrefix) === 0) {
// If this renamed the current page, navigate to it at it's updated name.
await syscall("editor.navigate", config.currentPage.replace(oldPrefix, newPrefix), false, false);
}

return success;
},

onChange: async () => {
await syscall("system.invokeFunction", "treeview.show");
},

/**
* @param {SortableTreeNode} node
*/
onClick: async (_event, node) => {
await syscall("editor.navigate", node.data.name, false, false);
},

/**
* @param {SortableTreeNode["data"]} data
* @returns {string}
*/
renderLabel: (data) => `
<span
data-current-page="${JSON.stringify(data.isCurrentPage || false)}"
data-node-type="${data.nodeType}"
data-permission="${data.perm}"
title="${data.name}" >
${data.title}
</span>`
,
});
}

/**
Expand All @@ -115,7 +98,7 @@ function createTreeView(config, retries = 1) {
function initializeTreeViewPanel(config) {
const tree = createTreeView(config);
const handleAction = (action) => {
switch(action) {
switch (action) {
case "collapse-all": {
document.querySelectorAll("sortable-tree-node[open='true']").forEach((node) => node.collapse(true));
return true;
Expand Down Expand Up @@ -151,12 +134,12 @@ function initializeTreeViewPanel(config) {
}

handleAction("reveal-current-page");

document.querySelectorAll("[data-treeview-action]").forEach((el) => {
el.addEventListener("click", (e) => {
if (handleAction(el.dataset["treeviewAction"])) {
e.stopPropagation();
e.preventDefault();
e.preventDefault();
}
});
})
Expand Down
14 changes: 7 additions & 7 deletions treeview.plug.js

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions treeview.plug.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,17 @@ functions:
# API
hide:
path: "./treeview.ts:hideTree"

show:
path: "./treeview.ts:showTree"

showIfEnabled:
path: "./treeview.ts:showTreeIfEnabled"
events:
- editor:init
- editor:pageLoaded
- editor:pageReloaded
- editor:updated
- page:deleted
- editor:pageSaved
- file:deleted

# User facing
toggle:
Expand Down
4 changes: 2 additions & 2 deletions treeview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ export async function showTree() {
<head>
<link rel="stylesheet" href="/.client/main.css" />
<style>
${sortableTreeCss}
${sortableTreeCss}
${plugCss}
${customStyles ?? ""}
</style>
Expand All @@ -139,7 +139,7 @@ export async function showTree() {
</body>
</html>`,
`
// Workaound until showPanel provides the current theme
// Workaound until showPanel provides the current theme
document.documentElement.dataset.theme = ${JSON.stringify(theme)};
${sortableTreeJs}
Expand Down

0 comments on commit 25df026

Please sign in to comment.