Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
c58df3d
Switch IndexedDB
peterjuma Feb 22, 2021
5e25d97
Notes List - Change div tag to ul
peterjuma Feb 22, 2021
b2c388f
Generate autolink on save
peterjuma Feb 22, 2021
b97d575
Feat: Copy note
peterjuma Feb 22, 2021
153cdf7
Feat: Copy note
peterjuma Feb 22, 2021
5cd034c
Feat: Sort Notes List #2
peterjuma Feb 22, 2021
47375dd
Feat: Sort Notes List #3
peterjuma Feb 22, 2021
f4bf50f
Feat: Sort Notes List
peterjuma Feb 22, 2021
c1c2f82
Fix: Sort Notes List
peterjuma Feb 22, 2021
33b3890
Fix: HTML <base> target Attribute
peterjuma Feb 22, 2021
ada6ca3
Fix: AutoLinks
peterjuma Feb 22, 2021
c99c355
Fix: Package.json
peterjuma Feb 22, 2021
7e36a10
Fix: Textarea sizing
peterjuma Feb 23, 2021
a2429fa
UI tweaks
peterjuma Feb 23, 2021
283b160
UI tweaks
peterjuma Feb 23, 2021
0dd4241
UI tweaks
peterjuma Feb 23, 2021
7ca9ba9
Merge conflict
peterjuma Feb 23, 2021
0556388
UI tweaks
peterjuma Feb 23, 2021
4645aa8
UI tweaks
peterjuma Feb 23, 2021
c9a29f4
Fix: Sort select
peterjuma Feb 23, 2021
1a552a8
Copy MD content
peterjuma Feb 24, 2021
15760ae
Fix: Copy btn
peterjuma Feb 25, 2021
6f09d34
Style: List
peterjuma Feb 26, 2021
6cfaf6f
Style: List #2
peterjuma Feb 26, 2021
ea46aaf
Style: List #3
peterjuma Feb 26, 2021
8e31f24
Style: List #4
peterjuma Feb 26, 2021
eae4a23
Style: List #5
peterjuma Feb 26, 2021
b60f1c9
Style: List #6
peterjuma Mar 1, 2021
cb69da5
Style: Font weights
peterjuma Mar 1, 2021
59715e6
Style: Font weights
peterjuma Mar 1, 2021
5d38215
Style UI Editor
peterjuma Mar 8, 2021
b1c5856
Refac buttons
peterjuma Mar 9, 2021
6a85c55
Refac buttons #2
peterjuma Mar 9, 2021
9c6bacb
Feat: Download MD file button
peterjuma Mar 10, 2021
e543595
Merge pull request #2 from peterjuma/downloadbtn
peterjuma Mar 15, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"starter"
],
"main": "src/index.js",
"homepage": "https://apps.peterjuma.com/noteAppReact",
"homepage": "https://apps.peterjuma.com/noteApp",
"dependencies": {
"@github/markdown-toolbar-element": "^1.3.2",
"@tailwindcss/postcss7-compat": "^2.0.2",
Expand Down
2 changes: 2 additions & 0 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<base target="_blank">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.6.0/styles/github.min.css">
<link rel="stylesheet" href="https://unpkg.com/primer@latest/build/build.css"/>
Expand Down
196 changes: 159 additions & 37 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React, { Component } from "react";
import NavbarSidebar from "./NavbarSidebar"
import NoteSort from "./NoteSort"
import NavbarMain from "./NavbarMain"
import NoteList from "./NoteList"
import NoteMain from "./NoteMain"
Expand Down Expand Up @@ -34,7 +35,8 @@ class App extends Component {
notetitle: '',
notebody: '',
activepage: "viewnote", // editnote // previewnote // viewnote
action:'', // addnote // updatenote
action: '', // addnote // updatenote
sortby: '4', //"0" - Title: A-Z, "1" - Title: Z-A, "2" - Created: Newest, "3" - Created: Oldest, "4" - Modified: Newest, "5" - Modified: Oldest
allnotes: []
};
this.handleNoteListItemClick = this.handleNoteListItemClick.bind(this)
Expand All @@ -43,25 +45,29 @@ class App extends Component {
this.handleEditNote = this.handleEditNote.bind(this)
this.handleSaveNote = this.handleSaveNote.bind(this)
this.handleDeleteNote = this.handleDeleteNote.bind(this)
this.handleDownloadNote = this.handleDownloadNote.bind(this)
this.handlePaste = this.handlePaste.bind(this)
this.processInput = this.processInput.bind(this)
this.handleKeyEvent = this.handleKeyEvent.bind(this)
this.setSelectionRange = this.setSelectionRange.bind(this)
this.handleSearchNotes = this.handleSearchNotes.bind(this)
this.handleIndexedDB = this.handleIndexedDB.bind(this)
this.handleCancel = this.handleCancel.bind(this)
this.handleCopyNote = this.handleCopyNote.bind(this)
this.handleCopyEvent = this.handleCopyEvent.bind(this)
this.handleSortNotes = this.handleSortNotes.bind(this)
this.updateCodeSyntaxHighlighting();
}

async componentDidMount() {
const getnotesdb = await this.handleIndexedDB("getall")
if(getnotesdb.length == 0){
const getnotes = await this.handleIndexedDB("getall")
if(getnotes.length == 0){
this.handleClickHomeBtn()
} else {
this.setState({
allnotes: getnotesdb
allnotes: getnotes
})
document.getElementById(getnotesdb[0].noteid).click();
document.getElementById(getnotes[0].noteid).click();
}
this.updateCodeSyntaxHighlighting();
}
Expand All @@ -78,46 +84,46 @@ class App extends Component {

// Indexed DB class
async handleIndexedDB (cmd = "", note = "") {
const db = await openDB('Notes', 1, {
const db = await openDB('notesdb', 1, {
upgrade(db) {
// Create a store of objects
const store = db.createObjectStore('notesdb', {
const store = db.createObjectStore('notes', {
// The 'noteid' property of the object will be the key.
keyPath: 'noteid',
// If it isn't explicitly set, create a value by auto incrementing.
autoIncrement: true,
});
// Create an index on the 'noteid' & date property of the objects.
store.createIndex('created_at', 'date');
// Create an index on all fields of the objects.
store.createIndex('created_at', 'created_at');
store.createIndex('noteid', 'noteid');
}
});
// 1. Create single note
if(cmd==="addnote"){
await db.add("notesdb", note)
await db.add("notes", note)
}
// 2.1 Read all notes
if(cmd==="getall"){
let notes = await db.getAll('notesdb')
let notes = await db.getAll('notes')
return notes
}
// 2.2 Read single note
if(cmd==="getone"){
const db = await openDB('Notes', 1);
const tx = db.transaction('notesdb');
const db = await openDB('notesdb', 1);
const tx = db.transaction('notes');
const idx = tx.store.index('noteid');
let onenote = await idx.get(note)
return onenote
}
// 3. Update single note
if(cmd==="update"){
const db = await openDB('Notes', 1);
db.put('notesdb', note)
const db = await openDB('notesdb', 1);
db.put('notes', note)
}
// 4. Delete single note
if(cmd==="delete"){
const db = await openDB('Notes', 1);
db.delete('notesdb', note.noteid)
const db = await openDB('notesdb', 1);
db.delete('notes', note.noteid)
}
db.close()
}
Expand Down Expand Up @@ -173,13 +179,54 @@ class App extends Component {
})
}

handleSortNotes = (sortby) => {
// "0" - Title: A-Z, "1" - Title: Z-A, "2" - Created: Newest, "3" - Created: Oldest, "4" - Modified: Newest, "5" - Modified: Oldest
var notesArray = [...this.state.allnotes]
var sortvalue = event ? event.target.value : sortby;
switch (sortvalue) {
case "0":
notesArray.sort(function (a, b) {
let x = a.title.toUpperCase(),
y = b.title.toUpperCase();
return x == y ? 0 : x > y ? 1 : -1;
});
break;
case "1":
notesArray.sort(function (a, b) {
let x = a.title.toUpperCase(),
y = b.title.toUpperCase();
return x == y ? 0 : x > y ? -1 : 1;
});
break;
case "2":
notesArray.sort((a, b) => b.created_at - a.created_at)
break;
case "3":
notesArray.sort((a, b) => a.created_at - b.created_at)
break;
case "4":
notesArray.sort((a, b) => b.updated_at - a.updated_at)
break;
case "5":
notesArray.sort((a, b) => a.updated_at - b.updated_at)
break;
default:
}
this.setState({
sortby: sortvalue,
allnotes: notesArray
})
document.getElementById(notesArray[0].noteid).click();
}

handleCancel = (e, note) => {
if(note.action === "updatenote") {
document.getElementById(note.noteid).click();
} else {
document.querySelectorAll(".note-list-item")[0].click();
return document.getElementById(note.noteid).click();
}
if(document.querySelectorAll(".note-list-item").length > 0){
return document.querySelectorAll(".note-list-item")[0].click();
}

return this.handleClickHomeBtn()
}
handleEditNote = (e, note) => {
this.setState(
Expand Down Expand Up @@ -219,48 +266,52 @@ class App extends Component {
}

handleSaveNote(e, note) {
var notebody = turndownService.turndown(marked(marked(document.getElementById('notebody').value)));
this.setState((prevState) => {
const updatedNotes = prevState.allnotes.map((noteitem) => {
if (noteitem.noteid === note.noteid) {
noteitem.title = document.getElementById('notetitle').value
noteitem.body = document.getElementById('notebody').value
noteitem.body = notebody
noteitem.activepage = "viewnote"
}
return noteitem;
});
return {
noteid: note.noteid,
notetitle: document.getElementById('notetitle').value,
notebody: document.getElementById('notebody').value,
notebody: notebody,
activepage: "viewnote",
action: note.action,
allnotes: updatedNotes
};
});
// Update List View
if(note.action == "addnote"){
this.state.allnotes.push(
{
noteid: note.noteid,
notetitle: document.getElementById('notetitle').value,
notebody: document.getElementById('notebody').value,
notebody: notebody,
activepage: "viewnote",
created_at: Date.now(),
updated_at: Date.now(),
action: note.action
})

// Update IndexedDB
this.handleIndexedDB("addnote",
{
noteid: note.noteid,
title: document.getElementById('notetitle').value,
body: document.getElementById('notebody').value,
body: notebody,
created_at: Date.now(),
updated_at: ""
updated_at: Date.now()
})
} else { // if note.action == "editnote"
this.handleIndexedDB("update",
{
noteid: note.noteid,
title: document.getElementById('notetitle').value,
body: document.getElementById('notebody').value,
body: notebody,
updated_at: Date.now()
})
}
Expand All @@ -281,10 +332,8 @@ class App extends Component {
? (e.originalEvent || e).clipboardData.getData('text/html')
// For IE
: (window.clipboardData ? window.clipboardData.getData('Html') : '');
// var pasteData = html ? turndownService.turndown(marked(html)) : turndownService.turndown(text)
// /<:__|[*#]|\[.*?\]\(.*>/.test(val) // detect MD
let pasteData;


let pasteData;
if(html) {
pasteData = turndownService.turndown(html)
} else {
Expand Down Expand Up @@ -312,6 +361,56 @@ class App extends Component {
}
};

handleCopyNote(e, content) {
var textArea = document.createElement("textarea");
// Place in top-left corner of screen regardless of scroll position.
textArea.style.position = 'fixed';
textArea.style.top = 0;
textArea.style.left = 0;
// Ensure it has a small width and height. Setting to 1px / 1em
// doesn't work as this gives a negative w/h on some browsers.
textArea.style.width = '2em';
textArea.style.height = '2em';
// We don't need padding, reducing the size if it does flash render.
textArea.style.padding = 0;
// Clean up any borders.
textArea.style.border = 'none';
textArea.style.outline = 'none';
textArea.style.boxShadow = 'none';
// Avoid flash of white box if rendered for any reason.
textArea.style.background = 'transparent';
textArea.value = ((typeof content === "object")? `## ${content.notetitle}\n${content.notebody}` : content)
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
var successful = document.execCommand('copy');
} catch (err) {
console.log('Oops, unable to copy');
}
document.body.removeChild(textArea);
}

handleCopyEvent(e) {
e.preventDefault();
var html = "";
if (typeof window.getSelection != "undefined") {
var sel = window.getSelection();
if (sel.rangeCount) {
var container = document.createElement("div");
for (var i = 0, len = sel.rangeCount; i < len; ++i) {
container.appendChild(sel.getRangeAt(i).cloneContents());
}
html = container.innerHTML;
}
} else if (typeof document.selection != "undefined") {
if (document.selection.type == "Text") {
html = document.selection.createRange().htmlText;
}
}
this.handleCopyNote("",turndownService.turndown(html));
}

handleKeyEvent(event) {
if ( event.code === "Tab" ) {
this.processInput('tab')
Expand Down Expand Up @@ -422,8 +521,26 @@ class App extends Component {
}
DisplayList.length > 0 && DisplayList[0].click();
}

handleDownloadNote(e) {
const html = document.getElementById("notebody-view").innerHTML;
const data = turndownService.turndown(marked(html));
const title = turndownService.turndown(marked(document.getElementById("notetitle-view").innerHTML)).replace(/ /g,"_");
const fileName = `${title || "note"}.md`
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
var blob = new Blob([data], { type: "text/plain;charset=utf-8" }),
url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
e.preventDefault();
}

render() {
const noteListItems = this.state.allnotes.map((note) => (
const noteListItems = (this.state.allnotes).map((note) => (
<NoteList key={note.noteid} note={note}
handleClick={this.handleNoteListItemClick}
handleMouseOver={this.handleNoteListItemMouseOver}
Expand All @@ -437,9 +554,12 @@ class App extends Component {
notesData={{noteid: this.state.noteid, notetitle: this.state.notetitle, notebody: this.state.notebody, action:this.state.action}}
handleEditNote={this.handleEditNote}
handleDeleteNote={this.handleDeleteNote}
handleCopyNote={this.handleCopyNote}
handleDownloadNote = {this.handleDownloadNote}
/>
ActivePage = <NoteMain
notesData={{noteid: this.state.noteid, notetitle: this.state.notetitle, notebody: this.state.notebody, action:this.state.action}}
notesData={{noteid: this.state.noteid, notetitle: this.state.notetitle, notebody: this.state.notebody, action:this.state.action}}
handleCopyEvent={this.handleCopyEvent}
/>
}
if (this.state.activepage === "editnote"){
Expand All @@ -453,6 +573,7 @@ class App extends Component {
handleKeyEvent={this.handleKeyEvent}
processInput={this.processInput}
handleCancel={this.handleCancel}
handleImageUpload={this.handleImageUpload}
/>
}

Expand All @@ -464,9 +585,10 @@ class App extends Component {
handleEditNote={this.handleEditNote}
handleSearchNotes={this.handleSearchNotes}
/>
<div className="note-list">
{noteListItems}
</div>
<ul className="note-list">
{noteListItems}
</ul>
<NoteSort handleSortNotes={this.handleSortNotes}/>
</div>
<div className="right">
{RightNavbar}
Expand Down
5 changes: 3 additions & 2 deletions src/NavbarMain.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ function NavbarMain(props) {
return (
<div className={isActive===true? "nav-bar":"hidden"}>
<div className="nav-right-icon">
<i className="far fa-edit fa-lg btn" id="editbtn" data-action="updatenote" style={{float: "left"}} onClick={((e) => props.handleEditNote(e, note))}> </i>
<i className="far fa-copy fa-lg btn" id="copyBtn" onClick={((e) => props.handleCopyNote(e, note))}></i>
<i className="far fa-edit fa-lg btn" id="editbtn" data-action="updatenote" onClick={((e) => props.handleEditNote(e, note))}> </i>
<i className="far fa-trash-alt fa-lg btn" aria-hidden="true" style={{float: "right"}} onClick={((e) => props.handleDeleteNote(e, note))}></i>
<i className="far fa-arrow-alt-circle-down fa-lg btn" aria-hidden="true" style={{float: "right"}} onClick={((e) => props.handleDownloadNote(e, note))}></i>
</div>
</div>
)
}

export default NavbarMain
Loading