mirror of
https://github.com/narrrl/narl-workspace.git
synced 2026-11-03 16:41:27 +01:00
added document move
This commit is contained in:
1 parent
714a84089a
commit
1a37420461
4 files changed
+57
-4
No files matched your search
@@ -276,6 +276,15 @@
|
||||
event.preventDefault()
|
||||
void workspace.guard(() => workspace.openSelected())
|
||||
break
|
||||
case 'm':
|
||||
// Pick a node up here, walk to a folder, put it down with `p`.
|
||||
event.preventDefault()
|
||||
workspace.mark()
|
||||
break
|
||||
case 'p':
|
||||
event.preventDefault()
|
||||
void workspace.guard(() => workspace.drop())
|
||||
break
|
||||
case 'o':
|
||||
event.preventDefault()
|
||||
void runCommand('new')
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
['O', 'new folder here'],
|
||||
['i · a', 'edit the open document'],
|
||||
['R', 'rename what is marked — document, folder or card'],
|
||||
['m / p', 'pick a node up, then drop it into the folder you walk to'],
|
||||
['b', "open this space's board"],
|
||||
['Esc · q', 'back out to the list'],
|
||||
['/', 'full-text search, inside the current space'],
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<div class="sidebar">
|
||||
<div class="head">
|
||||
<span class="accent">~/{workspace.space?.slug ?? 'diary'}</span>
|
||||
<span class="accent name">~/{workspace.space?.slug ?? 'diary'}</span>
|
||||
<span class="faint count">
|
||||
{workspace.nodes.length} {workspace.nodes.length === 1 ? 'item' : 'items'}
|
||||
</span>
|
||||
@@ -79,6 +79,7 @@
|
||||
onclick={() => pick(index)}
|
||||
>
|
||||
<span class="caret">{index === workspace.cursor ? '>' : ' '}</span>
|
||||
{#if workspace.marked?.id === node.id}<span class="marked" title="marked — p drops it in a folder">m</span>{/if}
|
||||
<span class="time">{aside(node)}</span>
|
||||
<span class="title">{node.kind === 'document' ? '' : '/'}{label(node)}</span>
|
||||
{#if node.shared}<span class="shared" title="shared">◉</span>{/if}
|
||||
@@ -158,9 +159,13 @@
|
||||
.time { color: var(--fg-faint); flex: none; font-size: 12px; }
|
||||
.title { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1; }
|
||||
.shared { color: var(--accent); flex: none; }
|
||||
.marked { color: var(--warn); flex: none; font-weight: 700; }
|
||||
.empty { padding: 12px 10px; }
|
||||
|
||||
.count { flex: 1; text-align: right; overflow: hidden; white-space: nowrap; }
|
||||
.name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
||||
/* The count is short and fixed-width-ish; the space name is the part that
|
||||
can give way when the sidebar is narrow. */
|
||||
.count { flex: none; white-space: nowrap; }
|
||||
.tools { display: flex; gap: 2px; flex: none; }
|
||||
.tools button { padding: 0 6px; line-height: 18px; }
|
||||
.tools .board { color: var(--accent); }
|
||||
|
||||
@@ -49,6 +49,14 @@ class Workspace {
|
||||
listCursor = $state(0)
|
||||
cardCursor = $state(0)
|
||||
|
||||
/*
|
||||
* The node picked up by `m`, waiting for the `p` that drops it into whatever
|
||||
* folder the list is showing then. A move is two keystrokes apart in time
|
||||
* because the destination is somewhere else in the tree — there is no way to
|
||||
* name it and be somewhere else at once.
|
||||
*/
|
||||
marked = $state<NodeSummary | null>(null)
|
||||
|
||||
pane = $state<Pane>('list')
|
||||
vimMode = $state('normal')
|
||||
flash = $state<Flash>(null)
|
||||
@@ -279,8 +287,9 @@ class Workspace {
|
||||
await this.goTo(parent.id, from.id)
|
||||
}
|
||||
|
||||
async refresh() {
|
||||
const keepId = this.selected?.id
|
||||
/** `keep` follows a node that just arrived, instead of holding the cursor. */
|
||||
async refresh(keep?: number) {
|
||||
const keepId = keep ?? this.selected?.id
|
||||
this.nodes = this.query
|
||||
? await api.listNodes({ q: this.query, space: this.spaceId ?? undefined })
|
||||
: await api.listNodes({ parent: this.parentId ?? undefined })
|
||||
@@ -473,6 +482,35 @@ class Workspace {
|
||||
this.say(`moved #${id}`)
|
||||
}
|
||||
|
||||
/** `m`: pick the node under the cursor up, or put it back down unmoved. */
|
||||
mark() {
|
||||
const node = this.selected
|
||||
if (!node) return this.say('nothing selected', 'error')
|
||||
if (this.marked?.id === node.id) {
|
||||
this.marked = null
|
||||
return this.say('unmarked')
|
||||
}
|
||||
this.marked = node
|
||||
this.say(`marked ${node.name.trim() || node.slug} — p drops it in this folder`)
|
||||
}
|
||||
|
||||
/** `p`: drop the marked node into the folder the list is showing. */
|
||||
async drop() {
|
||||
const node = this.marked
|
||||
const parent = this.parentId
|
||||
if (!node) return this.say('nothing marked — press m on a row first', 'error')
|
||||
if (parent === null) return this.say('no folder open', 'error')
|
||||
if (node.parent_id === parent) {
|
||||
this.marked = null
|
||||
return this.say('already here')
|
||||
}
|
||||
|
||||
await api.moveNode(node.id, parent)
|
||||
this.marked = null
|
||||
await this.refresh(node.id)
|
||||
this.say(`moved ${node.name.trim() || node.slug} here`)
|
||||
}
|
||||
|
||||
/*
|
||||
* Boards. One per space, which is what makes "what am I working on" a
|
||||
* question with an answer: work and uni are asked separately, and the diary
|
||||
|
||||
Reference in new issue
Block a user