-
Notifications
You must be signed in to change notification settings - Fork 210
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement support for editing notes' metadata, and ability to move no…
…tes into other directories. Create separate pinia store for the editor cache functionality.
- Loading branch information
Showing
11 changed files
with
512 additions
and
52 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,274 @@ | ||
<script> | ||
import slugify from '@sindresorhus/slugify'; | ||
import { toRaw } from 'vue'; | ||
import { mapState, mapActions } from 'pinia' | ||
import { useNotesStore } from "../stores/notes-store" | ||
import FolderSelector from './folder-selector/FolderSelector.vue' | ||
export default { | ||
data() { | ||
return { | ||
name: "", | ||
filename: "", | ||
tags: [], | ||
directoryTree: null, | ||
parentPath: "", | ||
errors: { | ||
name: null, | ||
}, | ||
} | ||
}, | ||
components: { | ||
FolderSelector | ||
}, | ||
async mounted() { | ||
this.$refs.nameInput.focus() | ||
this.updateNotes() | ||
console.log("EditNote mounted", this.currentNote) | ||
this.name = this.currentNote.name | ||
// build directory tree | ||
const directories = await window.heynote.buffer.getDirectoryList() | ||
const rootNode = { | ||
name: "Heynote Root", | ||
path: "", | ||
children: [], | ||
open: true, | ||
} | ||
const getNodeFromList = (list, part) => list.find(node => node.name === part) | ||
directories.forEach((path) => { | ||
const parts = path.split("/") | ||
let currentLevel = rootNode | ||
let currentParts = [] | ||
parts.forEach(part => { | ||
currentParts.push(part) | ||
let node = getNodeFromList(currentLevel.children, part) | ||
if (node) { | ||
currentLevel = node | ||
} else { | ||
const currentPath = currentParts.join("/") | ||
node = { | ||
name: part, | ||
children: [], | ||
path: currentPath, | ||
open: this.currentNotePath.startsWith(currentPath), | ||
} | ||
currentLevel.children.push(node) | ||
currentLevel = node | ||
} | ||
}) | ||
}) | ||
//console.log("tree:", rootNode) | ||
this.directoryTree = rootNode | ||
}, | ||
computed: { | ||
...mapState(useNotesStore, [ | ||
"notes", | ||
"currentNotePath", | ||
]), | ||
currentNote() { | ||
return this.notes[this.currentNotePath] | ||
}, | ||
currentNoteDirectory() { | ||
return this.currentNotePath.split("/").slice(0, -1).join("/") | ||
}, | ||
nameInputClass() { | ||
return { | ||
"name-input": true, | ||
"error": this.errors.name, | ||
} | ||
} | ||
}, | ||
methods: { | ||
...mapActions(useNotesStore, [ | ||
"updateNotes", | ||
"updateNoteMetadata", | ||
]), | ||
onKeydown(event) { | ||
if (event.key === "Escape") { | ||
this.$emit("close") | ||
event.preventDefault() | ||
} if (event.key === "Enter") { | ||
this.submit() | ||
event.preventDefault() | ||
} | ||
}, | ||
onInputKeydown(event) { | ||
// redirect arrow keys and page up/down to folder selector | ||
const redirectKeys = ["ArrowDown", "ArrowUp", "PageDown", "PageUp"] | ||
if (redirectKeys.includes(event.key)) { | ||
this.$refs.folderSelect.$el.dispatchEvent(new KeyboardEvent("keydown", {key: event.key})) | ||
event.preventDefault() | ||
} | ||
}, | ||
submit() { | ||
let slug = slugify(this.name) | ||
if (slug === "") { | ||
this.errors.name = true | ||
return | ||
} | ||
const parentPathPrefix = this.parentPath === "" ? "" : this.parentPath + "/" | ||
let path; | ||
for (let i=0; i<1000; i++) { | ||
let filename = slug + ".txt" | ||
path = parentPathPrefix + filename | ||
if (path === this.currentNotePath || !this.notes[path]) { | ||
// file name is ok if it's the current note, or if it doesn't exist | ||
break | ||
} | ||
slug = slugify(this.name + "-" + i) | ||
} | ||
if (path !== this.currentNotePath && this.notes[path]) { | ||
console.error("Failed to edit note, path already exists", path) | ||
this.errors.name = true | ||
return | ||
} | ||
console.log("Update note", path) | ||
this.updateNoteMetadata(this.currentNotePath, this.name, path) | ||
this.$emit("close") | ||
//this.$emit("create", this.$refs.input.value) | ||
}, | ||
} | ||
} | ||
</script> | ||
|
||
<template> | ||
<div class="fader" @keydown.stop="onKeydown" tabindex="-1"> | ||
<form class="new-note" tabindex="-1" @focusout="onFocusOut" ref="container" @submit.prevent="submit"> | ||
<div class="container"> | ||
<h1>Edit Note</h1> | ||
<input | ||
placeholder="Name" | ||
type="text" | ||
v-model="name" | ||
:class="nameInputClass" | ||
ref="nameInput" | ||
@keydown="onInputKeydown" | ||
@input="errors.name = false" | ||
/> | ||
|
||
<label for="folder-select">Move to</label> | ||
<FolderSelector | ||
v-if="directoryTree" | ||
:directoryTree="directoryTree" | ||
:selectedPath="currentNoteDirectory" | ||
id="folder-select" | ||
v-model="parentPath" | ||
ref="folderSelect" | ||
/> | ||
</div> | ||
<div class="bottom-bar"> | ||
<button type="submit">Create Note</button> | ||
</div> | ||
</form> | ||
</div> | ||
</template> | ||
|
||
<style scoped lang="sass"> | ||
.fader | ||
position: fixed | ||
top: 0 | ||
left: 0 | ||
bottom: 0 | ||
right: 0 | ||
background: rgba(0,0,0, 0.2) | ||
.new-note | ||
font-size: 13px | ||
//background: #48b57e | ||
background: #efefef | ||
width: 420px | ||
position: absolute | ||
top: 0 | ||
left: 50% | ||
transform: translateX(-50%) | ||
border-radius: 0 0 5px 5px | ||
box-shadow: 0 0 10px rgba(0,0,0,0.3) | ||
display: flex | ||
flex-direction: column | ||
max-height: 100% | ||
&:focus | ||
outline: none | ||
+dark-mode | ||
background: #151516 | ||
box-shadow: 0 0 10px rgba(0,0,0,0.5) | ||
color: rgba(255,255,255, 0.7) | ||
+webapp-mobile | ||
max-width: calc(100% - 80px) | ||
.container | ||
padding: 10px | ||
min-height: 0 | ||
display: flex | ||
flex-direction: column | ||
h1 | ||
font-weight: bold | ||
margin-bottom: 14px | ||
label | ||
display: block | ||
margin-bottom: 6px | ||
//padding-left: 2px | ||
font-size: 12px | ||
font-weight: 600 | ||
.name-input | ||
width: 100% | ||
background: #fff | ||
padding: 4px 5px | ||
border: 1px solid #ccc | ||
box-sizing: border-box | ||
border-radius: 2px | ||
margin-bottom: 16px | ||
&:focus | ||
outline: none | ||
border: 1px solid #fff | ||
outline: 2px solid #48b57e | ||
&.error | ||
background: #ffe9e9 | ||
+dark-mode | ||
background: #3b3b3b | ||
color: rgba(255,255,255, 0.9) | ||
border: 1px solid #5a5a5a | ||
&:focus | ||
border: 1px solid #3b3b3b | ||
+webapp-mobile | ||
font-size: 16px | ||
max-width: 100% | ||
.bottom-bar | ||
border-radius: 0 0 5px 5px | ||
//background: #e3e3e3 | ||
padding: 10px | ||
padding-top: 0 | ||
display: flex | ||
justify-content: flex-end | ||
button | ||
font-size: 12px | ||
height: 28px | ||
border: 1px solid #c5c5c5 | ||
border-radius: 3px | ||
padding-left: 10px | ||
padding-right: 10px | ||
&:focus | ||
outline-color: #48b57e | ||
+dark-mode | ||
background: #444 | ||
border: none | ||
color: rgba(255,255,255, 0.75) | ||
</style> |
Oops, something went wrong.