Skip to content

Commit 7c3b194

Browse files
committed
Add "Create new..." item to the note selector dialog
1 parent 84b4fce commit 7c3b194

File tree

3 files changed

+147
-98
lines changed

3 files changed

+147
-98
lines changed

src/components/NewNote.vue

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,16 @@
2424
},
2525
2626
async mounted() {
27-
this.$refs.nameInput.focus()
27+
if (!!this.createNoteParams.name) {
28+
this.name = this.createNoteParams.name
29+
this.$refs.nameInput.focus()
30+
this.$nextTick(() => {
31+
this.$refs.nameInput.select()
32+
})
33+
} else {
34+
this.$refs.nameInput.focus()
35+
}
36+
2837
this.updateNotes()
2938
3039
// build directory tree
@@ -67,7 +76,7 @@
6776
...mapState(useNotesStore, [
6877
"notes",
6978
"currentNotePath",
70-
"createNoteMode",
79+
"createNoteParams",
7180
]),
7281
7382
currentNoteDirectory() {
@@ -82,7 +91,7 @@
8291
},
8392
8493
dialogTitle() {
85-
return this.createNoteMode === "currentBlock" ? "New Note from Block" : "New Note"
94+
return this.createNoteParams.mode === "currentBlock" ? "New Note from Block" : "New Note"
8695
},
8796
},
8897
@@ -147,12 +156,12 @@
147156
return
148157
}
149158
console.log("Creating note", path)
150-
if (this.createNoteMode === "currentBlock") {
159+
if (this.createNoteParams.mode === "currentBlock") {
151160
this.createNewNoteFromActiveBlock(path, this.name)
152-
} else if (this.createNoteMode === "new") {
161+
} else if (this.createNoteParams.mode === "new") {
153162
this.createNewNote(path, this.name)
154163
} else {
155-
throw new Error("Unknown createNoteMode: " + this.createNoteMode)
164+
throw new Error("Unknown createNote Mode: " + this.createNoteParams.mode)
156165
}
157166
158167
this.$emit("close")

src/components/NoteSelector.vue

Lines changed: 123 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,15 @@
6060
},
6161
6262
filteredItems() {
63+
let items
6364
if (this.filter === "") {
64-
return this.orderedItems
65+
items = this.orderedItems
66+
6567
} else {
6668
const searchResults = fuzzysort.go(this.filter, this.items, {
6769
keys: ["name", "folder"],
6870
})
69-
return searchResults.map((result) => {
71+
items = searchResults.map((result) => {
7072
const obj = {...result.obj}
7173
const nameHighlight = result[0].highlight("<b>", "</b>")
7274
const folderHighlight = result[1].highlight("<b>", "</b>")
@@ -75,6 +77,15 @@
7577
return obj
7678
})
7779
}
80+
81+
const newNoteItem = {
82+
name: "Create new…",
83+
createNew:true,
84+
}
85+
return [
86+
...items,
87+
newNoteItem,
88+
]
7889
},
7990
},
8091
@@ -83,6 +94,7 @@
8394
"updateNotes",
8495
"editNote",
8596
"deleteNote",
97+
"openCreateNote",
8698
]),
8799
88100
buildItems() {
@@ -99,7 +111,6 @@
99111
100112
onKeydown(event) {
101113
if (event.key === "Escape") {
102-
console.log("escape")
103114
event.preventDefault()
104115
if (this.actionButton !== 0) {
105116
this.hideActionButtons()
@@ -112,20 +123,18 @@
112123
if (this.filteredItems.length === 0) {
113124
return
114125
}
115-
116-
const path = this.filteredItems[this.selected].path
126+
127+
const item = this.filteredItems[this.selected]
117128
if (event.key === "ArrowDown") {
118129
if (this.selected === this.filteredItems.length - 1) {
119130
this.selected = 0
120131
} else {
121132
this.selected = Math.min(this.selected + 1, this.filteredItems.length - 1)
122133
}
123134
event.preventDefault()
124-
if (this.selected === this.filteredItems.length - 1) {
125-
this.$refs.container.scrollIntoView({block: "end"})
126-
} else {
127-
this.$refs.item[this.selected].scrollIntoView({block: "nearest"})
128-
}
135+
this.$nextTick(() => {
136+
this.$refs.container.querySelector(".selected").scrollIntoView({block: "nearest"})
137+
})
129138
this.actionButton = 0
130139
} else if (event.key === "ArrowUp") {
131140
if (this.selected === 0) {
@@ -134,28 +143,32 @@
134143
this.selected = Math.max(this.selected - 1, 0)
135144
}
136145
event.preventDefault()
137-
if (this.selected === 0) {
138-
this.$refs.container.scrollIntoView({block: "start"})
139-
} else {
140-
this.$refs.item[this.selected].scrollIntoView({block: "nearest"})
141-
}
146+
this.$nextTick(() => {
147+
this.$refs.container.querySelector(".selected").scrollIntoView({block: "nearest"})
148+
})
142149
this.actionButton = 0
143-
} else if (event.key === "ArrowRight" && path !== SCRATCH_FILE_NAME) {
150+
} else if (event.key === "ArrowRight" && this.itemHasActionButtons(item)) {
144151
event.preventDefault()
145152
this.actionButton = Math.min(2, this.actionButton + 1)
146-
} else if (event.key === "ArrowLeft" && path !== SCRATCH_FILE_NAME) {
153+
} else if (event.key === "ArrowLeft" && this.itemHasActionButtons(item)) {
147154
event.preventDefault()
148155
this.actionButton = Math.max(0, this.actionButton - 1)
149156
this.deleteConfirm = false
150157
} else if (event.key === "Enter") {
151158
event.preventDefault()
152-
if (this.actionButton === 1) {
153-
console.log("edit file:", path)
154-
this.editNote(path)
159+
if (item.createNew) {
160+
if (this.filteredItems.length === 1) {
161+
this.openCreateNote("new", this.filter)
162+
} else {
163+
this.openCreateNote("new", "")
164+
}
165+
} else if (this.actionButton === 1) {
166+
//console.log("edit file:", path)
167+
this.editNote(item.path)
155168
} else if (this.actionButton === 2) {
156-
this.deleteConfirmNote(path)
169+
this.deleteConfirmNote(item.path)
157170
} else {
158-
this.selectItem(path)
171+
this.selectItem(item.path)
159172
}
160173
}
161174
},
@@ -164,6 +177,10 @@
164177
this.$emit("openNote", path)
165178
},
166179
180+
itemHasActionButtons(item) {
181+
return !item.createNew && item.path !== SCRATCH_FILE_NAME
182+
},
183+
167184
onInput(event) {
168185
// reset selection
169186
this.selected = 0
@@ -178,9 +195,11 @@
178195
179196
getItemClass(item, idx) {
180197
return {
198+
"item": true,
181199
"selected": idx === this.selected,
182200
"action-buttons-visible": this.actionButton > 0,
183201
"scratch": item.scratch,
202+
"new-note": item.createNew,
184203
}
185204
},
186205
@@ -198,7 +217,7 @@
198217
199218
async deleteConfirmNote(path) {
200219
if (this.deleteConfirm) {
201-
console.log("delete file:", path)
220+
//console.log("delete file:", path)
202221
await this.deleteNote(path)
203222
this.hideActionButtons()
204223
this.buildItems()
@@ -214,8 +233,8 @@
214233
</script>
215234

216235
<template>
217-
<div class="scroller">
218-
<form class="note-selector" tabindex="-1" @focusout="onFocusOut" ref="container">
236+
<form class="note-selector" tabindex="-1" @focusout="onFocusOut" ref="container">
237+
<div class="input-container">
219238
<input
220239
type="text"
221240
ref="input"
@@ -224,57 +243,55 @@
224243
v-model="filter"
225244
autocomplete="off"
226245
/>
227-
<ul class="items">
228-
<li
246+
</div>
247+
<div class="scroller">
248+
<ul class="items" ref="itemsContainer">
249+
<template
229250
v-for="item, idx in filteredItems"
230251
:key="item.path"
231-
:class="getItemClass(item, idx)"
232-
@click="selectItem(item.path)"
233-
ref="item"
234252
>
235-
<span class="name" v-html="item.name" />
236-
<span class="path" v-html="item.folder" />
237-
<span :class="{'action-buttons':true, 'visible':actionButton > 0 && idx === selected}">
238-
<button
239-
v-if="actionButton > 0 && idx === selected"
240-
:class="{'selected':actionButton === 1}"
241-
@click.stop.prevent="editNote(item.path)"
242-
>Edit</button>
243-
<button
244-
v-if="actionButton > 0 && idx === selected"
245-
:class="{'delete':true, 'selected':actionButton === 2, 'confirm':deleteConfirm}"
246-
@click.stop.prevent="deleteConfirmNote(item.path)"
247-
>
248-
<template v-if="deleteConfirm">
249-
Really Delete?
250-
</template>
251-
<template v-else>
252-
Delete
253-
</template>
254-
</button>
255-
<button
256-
class="show-actions"
257-
v-if="item.path !== SCRATCH_FILE_NAME && (actionButton === 0 || idx !== selected)"
258-
@click.stop.prevent="showActionButtons(idx)"
259-
></button>
260-
</span>
261-
</li>
253+
<li v-if="item.createNew" class="line-separator"></li>
254+
<li
255+
:class="getItemClass(item, idx)"
256+
@click="selectItem(item.path)"
257+
ref="item"
258+
>
259+
<span class="name" v-html="item.name" />
260+
<span class="path" v-html="item.folder" />
261+
<span :class="{'action-buttons':true, 'visible':actionButton > 0 && idx === selected}">
262+
<button
263+
v-if="actionButton > 0 && idx === selected"
264+
:class="{'selected':actionButton === 1}"
265+
@click.stop.prevent="editNote(item.path)"
266+
>Edit</button>
267+
<button
268+
v-if="actionButton > 0 && idx === selected"
269+
:class="{'delete':true, 'selected':actionButton === 2, 'confirm':deleteConfirm}"
270+
@click.stop.prevent="deleteConfirmNote(item.path)"
271+
>
272+
<template v-if="deleteConfirm">
273+
Really Delete?
274+
</template>
275+
<template v-else>
276+
Delete
277+
</template>
278+
</button>
279+
<button
280+
class="show-actions"
281+
v-if="itemHasActionButtons(item) && (actionButton === 0 || idx !== selected)"
282+
@click.stop.prevent="showActionButtons(idx)"
283+
></button>
284+
</span>
285+
</li>
286+
</template>
262287
</ul>
263-
</form>
264-
</div>
288+
</div>
289+
</form>
265290
</template>
266291

267292
<style scoped lang="sass">
268-
.scroller
269-
//overflow: auto
270-
//position: fixed
271-
//top: 0
272-
//left: 0
273-
//bottom: 0
274-
//right: 0
275293
.note-selector
276294
font-size: 13px
277-
padding: 10px
278295
//background: #48b57e
279296
background: #efefef
280297
position: absolute
@@ -294,37 +311,52 @@
294311
+webapp-mobile
295312
max-width: calc(100% - 80px)
296313
297-
input
298-
background: #fff
299-
padding: 4px 5px
300-
border: 1px solid #ccc
301-
box-sizing: border-box
302-
border-radius: 2px
303-
width: 100%
304-
margin-bottom: 10px
305-
&:focus
306-
outline: none
307-
border: 1px solid #fff
308-
outline: 2px solid #48b57e
309-
+dark-mode
310-
background: #3b3b3b
311-
color: rgba(255,255,255, 0.9)
312-
border: 1px solid #5a5a5a
314+
.input-container
315+
padding: 10px
316+
input
317+
background: #fff
318+
padding: 4px 5px
319+
border: 1px solid #ccc
320+
box-sizing: border-box
321+
border-radius: 2px
322+
width: 100%
313323
&:focus
314-
border: 1px solid #3b3b3b
315-
+webapp-mobile
316-
font-size: 16px
317-
max-width: 100%
324+
outline: none
325+
border: 1px solid #fff
326+
outline: 2px solid #48b57e
327+
+dark-mode
328+
background: #3b3b3b
329+
color: rgba(255,255,255, 0.9)
330+
border: 1px solid #5a5a5a
331+
&:focus
332+
border: 1px solid #3b3b3b
333+
+webapp-mobile
334+
font-size: 16px
335+
max-width: 100%
318336
319-
.items
337+
.scroller
320338
overflow-y: auto
321-
> li
339+
padding: 0 10px 5px 10px
340+
341+
.items
342+
> li.line-separator
343+
height: 1px
344+
background: rgba(0,0,0, 0.05)
345+
margin-left: -10px
346+
margin-right: -10px
347+
margin-top: 3px
348+
margin-bottom: 3px
349+
+dark-mode
350+
background: rgba(255,255,255, 0.1)
351+
> li.item
322352
position: relative
323353
border-radius: 3px
324354
padding: 3px 12px
325355
line-height: 18px
326356
display: flex
327357
align-items: center
358+
scroll-margin-top: 6px
359+
scroll-margin-bottom: 6px
328360
&:hover
329361
background: #e2e2e2
330362
.action-buttons .show-actions
@@ -357,6 +389,8 @@
357389
color: rgba(255,255,255, 0.65)
358390
&.scratch
359391
font-weight: 600
392+
&.new-note
393+
font-size: 12px
360394
.name
361395
margin-right: 12px
362396
flex-shrink: 0

0 commit comments

Comments
 (0)