middle of refactoring server side backend stuff

master
Adam Veldhousen 2020-01-19 19:25:15 -06:00
parent 1972f9eebf
commit 168df6cfbc
Signed by: adam
GPG Key ID: 6DB29003C6DD1E4B
11 changed files with 118 additions and 80 deletions

View File

@ -1,40 +1,31 @@
import React, { PureComponent } from "react";
import { connect } from "weedux";
import { connect, bindActionCreators } from "weedux";
import { store, actions } from "./state/index.js";
import debounce from "lodash.debounce";
import NoteList from "./components/NoteList/NoteList";
import NoteContent from "./components/NoteContent/NoteContent";
import Omnibar from "./components/Omnibar/Omnibar";
import "./App.css";
import { bindActionCreators } from "weedux/lib";
import { getNotes } from "./state/api.js";
class App extends PureComponent {
defaultProps = { notes: [] };
state = { filter: "" };
async componentDidMount() {
const { getNotes } = this.props;
getNotes({ filter: "" });
}
handleSearch = text => {
const normalizedText = text.toLocaleLowerCase();
const { getNotes } = this.props;
getNotes({ filter: normalizedText });
// this.setState({
// notes: getNotes().notes.filter(
// n =>
// n.title.toLocaleLowerCase().includes(normalizedText) ||
// n.tags.find(
// x => x.toLocaleLowerCase() === normalizedText
// ) ||
// n.content.toLocaleLowerCase().includes(normalizedText)
// )
// });
};
handleSearch = text => this.setState({ filter: text.toLocaleLowerCase() });
handleCreate = title => {
const { createNote } = this.props;
createNote({ title, content: "", tags: [] });
getNotes();
};
handleSelectNote = title => {
@ -48,13 +39,22 @@ class App extends PureComponent {
};
handleTagUpdate = ({ title, newTags }) => {
// const { updateTags } = this.props;
// updateTags({ title, tags: newTags });
const { updateTags } = this.props;
updateTags({ title, tags: newTags });
};
applyFilter = (notes = [], filter = "") =>
notes.filter(
n =>
n.title.toLocaleLowerCase().includes(filter) ||
n.tags.find(x => x.toLocaleLowerCase() === filter) ||
n.content.toLocaleLowerCase().includes(filter)
);
render() {
const { notes, selectedNote } = this.props;
console.log(this.props);
const { filter } = this.state;
const handleSave = debounce(this.handleSaveNoteContent, 250);
return (
<div className="App">
@ -67,25 +67,19 @@ class App extends PureComponent {
</section>
<section className="NoteArea">
<NoteList
notes={notes}
notes={this.applyFilter(notes, filter)}
onSelect={this.handleSelectNote}
onTagUpdate={this.handleTagUpdate}
selectedNote={selectedNote}
/>
<NoteContent
note={selectedNote}
onSave={this.handleSaveNoteContent}
/>
<NoteContent note={selectedNote} onSave={handleSave} />
</section>
</div>
);
}
}
const ms2p = s => {
console.log(s);
return s;
};
const ms2p = s => s;
const md2p = dispatch => bindActionCreators({ ...actions }, dispatch);

View File

@ -22,6 +22,7 @@ export default function NoteList({
>
<NoteListItem
{...n}
selected={n.title === selectedNoteTitle}
onSelect={onSelect}
onTagUpdate={onTagUpdate}
/>
@ -41,6 +42,7 @@ const NoteListItem = ({
content,
title,
tags,
selected = false,
lastModified,
onSelect,
onTagUpdate
@ -50,7 +52,11 @@ const NoteListItem = ({
<h2>{title}</h2>
<p className="preview">-- {content}</p>
<span className="attributes">
<TagList tags={tags} onTagUpdate={onTagUpdate} />
<TagList
canEdit={selected}
tags={tags}
onTagUpdate={onTagUpdate}
/>
<span className="lastModified">
{formatRelative(new Date(lastModified), new Date())}
</span>

View File

@ -2,23 +2,27 @@ import React, { Fragment, useState } from "react";
import { noop, enterKeyPressed } from "../../utils";
import "./TagList.css";
export default function TagList({ tags = [], onTagUpdate = noop }) {
export default function TagList({
canEdit = false,
tags = [],
onTagUpdate = noop
}) {
const getTags = () => tags.join(",");
const [editMode, setEditMode] = useState(false);
const [editTags, setEditTags] = useState(getTags());
const toggleEditMode = () => {
setEditMode(!editMode);
if (editMode) {
if (editMode && canEdit) {
onTagUpdate(editTags.split(",").map(x => x.trim()));
}
setEditMode(!editMode && canEdit);
};
const updateTags = ({ target }) => setEditTags(target.value);
return (
<span className="TagList" onDoubleClick={toggleEditMode}>
{editMode ? (
{editMode && canEdit ? (
<input
type="text"
style={{ width: `${editTags.length - 2}ch` }}

44
src/server/notes/index.js Executable file
View File

@ -0,0 +1,44 @@
const { loadNotesInDirectory, saveNoteInDirectory } = require("./notes");
const { defaultSettings } = require("./settings");
function newNoteBackend(initSettings) {
let settings = { ...defaultSettings, ...initSettings };
async function onNoteCommand({ type, payload }) {
console.log(`got command: ${type} -n ${JSON.stringify(payload)}`);
const { directory } = settings;
switch (type) {
case "getNotes":
const files = await loadNotesInDirectory(directory);
return {
type: "getNotes",
payload: {
notes: files.map(f => ({ ...f, tags: [] }))
}
};
case "saveNote":
const { title, content, tags } = payload;
const result = await saveNoteInDirectory(settings, {
title,
content,
tags
});
return { type: "saveNote", payload: result };
case "getSettings":
case "saveSettings":
default:
return { type: "noop" };
}
}
function updateSettings({ directory }) {
settings.directory = directory;
}
return {
onNoteCommand,
updateSettings
};
}
module.exports = { createBackend: newNoteBackend };

View File

@ -116,11 +116,11 @@ async function saveNoteInDirectory(
) {
let fullPath = path.join(directory, `${title}.${defaultExtension}`);
const match = await listNotesInDirectory(directory).filter(
const match = (await listNotesInDirectory(directory)).filter(
f => f.friendlyName === title
);
if (match || match.length > 0) fullPath = match[0].fullPath;
if (match && match.length > 0) fullPath = match[0].path;
tagsCache[title] = tags;
return Promise.all([
@ -138,7 +138,7 @@ function newNoteBackend(initSettings) {
let settings = { ...defaultSettings, ...initSettings };
async function onNoteCommand({ type, payload }) {
console.log(`got command: ${type}`);
console.log(`got command: ${type} -n ${JSON.stringify(payload)}`);
const { directory } = settings;
switch (type) {
case "getNotes":
@ -151,7 +151,7 @@ function newNoteBackend(initSettings) {
};
case "saveNote":
const { title, content, tags } = payload;
const result = await saveNoteInDirectory(directory, {
const result = await saveNoteInDirectory(settings, {
title,
content,
tags

4
src/server/notes/settings.js Executable file
View File

@ -0,0 +1,4 @@
export const defaultSettings = {
directory: "./",
defaultExtension: "txt"
};

0
src/server/notes/tags.js Executable file
View File

View File

@ -34,8 +34,8 @@ contextBridge.exposeInMainWorld("api", {
receive,
receiveOnce,
sendLinkNav: target => ipcRenderer.send("element-clicked", target),
getNotes: async ({ filter }) => {
send("note_command", { type: "getNotes", payload: { filter } });
getNotes: async () => {
send("note_command", { type: "getNotes", payload: {} });
const response = await receiveOnce("note_response");
return JSON.parse(response);
},

View File

@ -3,7 +3,13 @@ import {
upsertNote as upsertNoteBackend
} from "./api";
export const reducer = (cs, { type, payload }) => {
const initialState = {
notes: [],
selectedNote: null,
error: null
};
export const reducer = (cs = initialState, { type, payload }) => {
switch (type) {
case "SELECT_NOTE":
return { ...cs, selectedNote: payload.selectedNote };
@ -27,14 +33,17 @@ export const reducer = (cs, { type, payload }) => {
};
const selectNote = ({ title }) => (dispatch, getState) => {
const normalizedTitle = title.toLocaleLowerCase();
const { selectedNote, notes } = getState();
let foundNote = selectedNote;
const notesFilter = notes.filter(n => n.title === title);
const notesFilter = notes.filter(
n => n.title.toLocaleLowerCase() === normalizedTitle
);
if (notesFilter.length > 0) {
foundNote = notesFilter[0];
}
dispatch({ type: "SELECT_NOTE", payload: { ...foundNote } });
dispatch({ type: "SELECT_NOTE", payload: { selectedNote: foundNote } });
};
const deleteNote = ({ title }) => (dispatch, getState) => {};
@ -52,7 +61,7 @@ const createNote = ({ title, content, tags = [] }) => async (
}
};
const getNotes = ({ filter }) => async (dispatch, getState) => {
const getNotes = () => async (dispatch, getState) => {
const { notesLoading } = getState();
if (notesLoading) {
console.warn(
@ -63,7 +72,7 @@ const getNotes = ({ filter }) => async (dispatch, getState) => {
dispatch({ type: "GET_NOTES_START" });
try {
const result = await getNotesBackend({ filter });
const result = await getNotesBackend();
console.log(result);
dispatch({ type: "GET_NOTES_SUCCESS", payload: result });
} catch (error) {
@ -71,9 +80,14 @@ const getNotes = ({ filter }) => async (dispatch, getState) => {
}
};
const updateTags = ({ title, tags }) => (dispatch, getState) => {
console.log(`adding tags ${tags} to ${title}`);
};
export const actions = {
getNotes,
deleteNote,
createNote,
selectNote
selectNote,
updateTags
};

View File

@ -14,13 +14,13 @@ const createNote = ({ title = null, content = "", tags = [] }) => {
};
};
export const getNotes = async filter => {
export const getNotes = async () => {
const { api } = window;
if (!api) return { ...notesStore };
const { getNotes } = api;
const { payload } = await getNotes({ filter });
const { payload } = await getNotes();
console.log(payload);
return {
error: null,
@ -29,7 +29,7 @@ export const getNotes = async filter => {
};
export const upsertNote = async ({ title, content, tags }) => {
const newNote = createNote({ title });
const newNote = createNote({ title, content, tags });
const { api } = window;
if (!api) {

View File

@ -20,35 +20,7 @@ export const createNote = ({ title = null, content = "", tags = [] }) => {
};
};
export const getNotes = async filter => {
const { api } = window;
if (!api) return { ...notesStore };
const { getNotes } = api;
const { payload } = await getNotes({ filter });
console.log(payload);
return {
error: null,
notes: payload.notes
};
};
export const upsertNote = async ({ title, content, tags }) => {
const newNote = createNote({ title });
const { api } = window;
if (!api) {
notesStore.notes = notesStore.notes.concat(newNote);
}
const { saveNote } = api;
await saveNote({ ...newNote });
return newNote;
};
const notesStore = {
export const dev_notes = {
error: null,
notes: [
createNote({