mirror of
https://github.com/streetwriters/notesnook.git
synced 2026-09-01 19:49:54 +02:00
web: ui and some functuanality is added.
This commit is contained in:
6
packages/ui/src/components/menu/datepicker.css
Normal file
6
packages/ui/src/components/menu/datepicker.css
Normal file
@@ -0,0 +1,6 @@
|
||||
.react-datepicker-wrapper,
|
||||
.react-datepicker__input-container,
|
||||
.react-datepicker__input-container input {
|
||||
display: block;
|
||||
width: auto;
|
||||
}
|
||||
327
packages/ui/src/components/menu/filterinput.js
Normal file
327
packages/ui/src/components/menu/filterinput.js
Normal file
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { useEffect, forwardRef, useRef } from "react";
|
||||
import { hexToRGB } from "../../utils/color";
|
||||
import DatePicker from "react-datepicker";
|
||||
import "react-datepicker/dist/react-datepicker.css";
|
||||
import "./datepicker.css";
|
||||
import { filterSearchEngine } from "./search";
|
||||
import { Text } from "@theme-ui/components";
|
||||
import { mainSearchEngine } from "./search";
|
||||
|
||||
export function FilterInput(props) {
|
||||
const {
|
||||
filters,
|
||||
focusInput,
|
||||
index,
|
||||
setFilters,
|
||||
item,
|
||||
getSuggestions,
|
||||
setSuggestions,
|
||||
onFocus,
|
||||
onBlur,
|
||||
inputRef,
|
||||
searchDefinitions
|
||||
} = props;
|
||||
|
||||
useEffect(() => {
|
||||
focusInput(filters.length - 1);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [filters.length]);
|
||||
|
||||
console.log();
|
||||
// useEffect(() => {
|
||||
// (async () => {
|
||||
// console.log(filterRef.current.target.innerText);
|
||||
// //await checkErrors(props, inputRef.filter.target.innerText);
|
||||
// //addDefinition(item.input, searchDefinitions);
|
||||
// })();
|
||||
// // eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
// }, [filterRef.current.target.innerText]);
|
||||
|
||||
const setCalenderState = (state) => {
|
||||
setFilters((filters) => {
|
||||
let inputs = [...filters];
|
||||
inputs[index].input.isCalenderOpen = state;
|
||||
return inputs;
|
||||
});
|
||||
};
|
||||
|
||||
const setCalenderDate = () => {
|
||||
document.getElementById(`inputId_${index}`).textContent =
|
||||
filters[index].input.date.formatted;
|
||||
};
|
||||
return !item.input.isDateFilter ? (
|
||||
<CustomInput
|
||||
{...props}
|
||||
id={`inputId_${index}`}
|
||||
bg={item.input.state.error ? "errorBg" : hexToRGB("#9E9E9E", 0.1)}
|
||||
onFocus={async (e) => {
|
||||
await checkErrors(props, e.target.textContent);
|
||||
setSuggestions(await getSuggestions(e.target.textContent, item.input));
|
||||
onFocus(e);
|
||||
}}
|
||||
onBlur={onBlur}
|
||||
onKeyDown={async (e) => {
|
||||
(await onKeyPress(e, props))[e.key]();
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<DatePicker
|
||||
{...props}
|
||||
customInput={<CustomInput />}
|
||||
peekNextMonth
|
||||
showMonthDropdown
|
||||
showYearDropdown
|
||||
dropdownMode="select"
|
||||
id={`inputId_${index}`}
|
||||
selected={filters[index].input.date.orignal}
|
||||
onCalendarClose={() => {
|
||||
setCalenderDate();
|
||||
document.getElementById(`inputId_${index}`).focus();
|
||||
}}
|
||||
onCalendarOpen={() => {
|
||||
setCalenderDate();
|
||||
}}
|
||||
onChange={(date) => {
|
||||
let inputs = [...filters];
|
||||
inputs[index].input.date.formatted = `${date.getDate()}/${
|
||||
date.getMonth() + 1
|
||||
}/${date.getFullYear()}`;
|
||||
inputs[index].input.date.orignal = date;
|
||||
setFilters(inputs);
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
setCalenderState(false);
|
||||
onBlur(e);
|
||||
}}
|
||||
onFocus={async (e) => {
|
||||
setCalenderState(true);
|
||||
setSuggestions(
|
||||
//shift to top
|
||||
await getSuggestions(e.target.textContent, item.input)
|
||||
);
|
||||
onFocus(e);
|
||||
}}
|
||||
onKeyDown={async (e) => {
|
||||
(await onKeyPress(e, props))[e.key]();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const CustomInput = forwardRef((props, refs) => (
|
||||
<Text
|
||||
ref={refs}
|
||||
tabIndex={0}
|
||||
as="span"
|
||||
contentEditable="true"
|
||||
type="text"
|
||||
sx={{
|
||||
width: "10%",
|
||||
py: "2.5px",
|
||||
px: "6px",
|
||||
fontSize: "input",
|
||||
flexShrink: 0,
|
||||
flexGrow: 1,
|
||||
boxShadow: "none",
|
||||
outline: "none",
|
||||
":focus": {
|
||||
boxShadow: "none",
|
||||
border: "none"
|
||||
},
|
||||
":hover:not(:focus)": {
|
||||
boxShadow: "none"
|
||||
}
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
));
|
||||
CustomInput.displayName = "CustomInput";
|
||||
|
||||
const getCursorPosition = (editableDiv) => {
|
||||
//it is a general method, it should be somehwre else
|
||||
var caretPos = 0,
|
||||
sel,
|
||||
range;
|
||||
if (window.getSelection) {
|
||||
sel = window.getSelection();
|
||||
if (sel.rangeCount) {
|
||||
range = sel.getRangeAt(0);
|
||||
if (range.commonAncestorContainer.parentNode == editableDiv) {
|
||||
caretPos = range.endOffset;
|
||||
}
|
||||
}
|
||||
} else if (document.selection && document.selection.createRange) {
|
||||
range = document.selection.createRange();
|
||||
if (range.parentElement() == editableDiv) {
|
||||
var tempEl = document.createElement("span");
|
||||
editableDiv.insertBefore(tempEl, editableDiv.firstChild);
|
||||
var tempRange = range.duplicate();
|
||||
tempRange.moveToElementText(tempEl);
|
||||
tempRange.setEndPoint("EndToEnd", range);
|
||||
caretPos = tempRange.text.length;
|
||||
}
|
||||
}
|
||||
return caretPos;
|
||||
};
|
||||
|
||||
const addDefinition = (input, definitions) => {
|
||||
//hard to understand// minimize if else
|
||||
//for (let filter of filters) console.log(filter.input.state.result);
|
||||
if (input.state.result) {
|
||||
let isArrayEmpty = false;
|
||||
for (let index = 0; index < definitions.length; index++) {
|
||||
if (definitions[index].srNo === input.id) {
|
||||
isArrayEmpty = true;
|
||||
input.state.result.srNo = input.id;
|
||||
definitions[index] = input.state.result;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isArrayEmpty) {
|
||||
input.state.result.srNo = input.id;
|
||||
definitions.push(input.state.result);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onClick = (props, query) => {
|
||||
checkErrors(props, query);
|
||||
};
|
||||
|
||||
const checkErrors = async (props, query) => {
|
||||
const { setFilters, index, item } = props;
|
||||
query = query.trim();
|
||||
let input = item.input;
|
||||
let result = await (await mainSearchEngine(input.type, query)).result;
|
||||
setFilters((filters) => {
|
||||
let _filters = [...filters];
|
||||
_filters[index].input.state = filterInputState(input, result, query);
|
||||
return _filters;
|
||||
});
|
||||
};
|
||||
|
||||
const filterInputState = (input, result, query) => {
|
||||
console.log(
|
||||
"filterInputState",
|
||||
input.id,
|
||||
query,
|
||||
!input.hasSuggestions,
|
||||
result.length > 0
|
||||
);
|
||||
if (!input.hasSuggestions)
|
||||
return {
|
||||
error: false,
|
||||
message: "",
|
||||
result: { type: input.type, value: query }
|
||||
};
|
||||
|
||||
if (result.length > 0)
|
||||
return { error: false, message: "", result: result[0] };
|
||||
|
||||
return {
|
||||
error: true,
|
||||
message: `This ${input.type.replace(
|
||||
"s",
|
||||
""
|
||||
)} is not present in the database.`,
|
||||
result: undefined
|
||||
};
|
||||
};
|
||||
|
||||
const deleteDefinition = (definitions, id) => {
|
||||
let index = 0;
|
||||
for (let definition of definitions) {
|
||||
if (definition.srNo === id) {
|
||||
definitions.splice(index, 1);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
};
|
||||
|
||||
const deleteFilter = (advanceInputs, index) => {
|
||||
advanceInputs.splice(index, 1);
|
||||
return advanceInputs;
|
||||
};
|
||||
|
||||
const onKeyPress = async (e, props) => {
|
||||
const {
|
||||
filters,
|
||||
focusInput,
|
||||
index,
|
||||
setFilters,
|
||||
item,
|
||||
getSuggestions,
|
||||
setSuggestions,
|
||||
onSearch,
|
||||
searchDefinitions,
|
||||
setSelectionIndex,
|
||||
suggestions,
|
||||
moveSelection
|
||||
} = props;
|
||||
setSuggestions(await getSuggestions(e.target.textContent, item.input));
|
||||
await checkErrors(props, e.target.textContent);
|
||||
return {
|
||||
Enter: async () => {
|
||||
props.onKeyDown(e);
|
||||
focusInput(index + 1);
|
||||
let results = await filterSearchEngine(searchDefinitions);
|
||||
onSearch(results);
|
||||
setSuggestions([]);
|
||||
//await checkErrors(props, e.target.innerText);
|
||||
addDefinition(item.input, searchDefinitions, filters);
|
||||
e.preventDefault();
|
||||
},
|
||||
Escape: () => {
|
||||
setSuggestions([]);
|
||||
},
|
||||
ArrowDown: () => {
|
||||
moveSelection(suggestions, setSelectionIndex).Down();
|
||||
e.preventDefault();
|
||||
},
|
||||
ArrowUp: () => {
|
||||
moveSelection(suggestions, setSelectionIndex).Up();
|
||||
e.preventDefault();
|
||||
},
|
||||
ArrowLeft: () => {
|
||||
if (getCursorPosition(document.getElementById(e.target.id)) == 0) {
|
||||
addDefinition(item.input, searchDefinitions);
|
||||
focusInput(index - 1);
|
||||
}
|
||||
},
|
||||
ArrowRight: () => {
|
||||
if (
|
||||
getCursorPosition(document.getElementById(e.target.id)) ==
|
||||
e.target.textContent.length
|
||||
) {
|
||||
addDefinition(item.input, searchDefinitions);
|
||||
focusInput(index + 1);
|
||||
}
|
||||
},
|
||||
Backspace: () => {
|
||||
if (e.target.textContent === "") {
|
||||
setSuggestions([]);
|
||||
setFilters(deleteFilter(filters, index));
|
||||
deleteDefinition(searchDefinitions, item.input.id);
|
||||
focusInput(index - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
113
packages/ui/src/components/menu/maininput.js
Normal file
113
packages/ui/src/components/menu/maininput.js
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { useEffect, useState } from "react";
|
||||
import { db } from "../../common/db";
|
||||
import { addToSearchHistory } from "./search";
|
||||
import { Input } from "@theme-ui/components";
|
||||
|
||||
export function MainInput(props) {
|
||||
const [searchHistory, setSearchHistory] = useState();
|
||||
|
||||
useEffect(async () => {
|
||||
//correct all the useEffects
|
||||
//history file to be added in core for search history
|
||||
let list = await db.searchHistory.getHistory();
|
||||
if (props.filters.length < 1) {
|
||||
setSearchHistory(list);
|
||||
} else {
|
||||
setSearchHistory([]);
|
||||
}
|
||||
}, [db.searchHistory, props.filters.length]);
|
||||
|
||||
return (
|
||||
<Input
|
||||
{...props}
|
||||
id="general_input"
|
||||
key="general_input"
|
||||
placeholder={"Type your query here"}
|
||||
bg={"none"}
|
||||
autoFocus
|
||||
as="input"
|
||||
name="search"
|
||||
autoComplete="off"
|
||||
type="text"
|
||||
variant="clean"
|
||||
sx={{
|
||||
wordWrap: "break-word",
|
||||
minWidth: 0,
|
||||
width: 0,
|
||||
flex: 1
|
||||
}}
|
||||
onChange={async (e) => {
|
||||
props.refreshFilters(e.target.value, props.setFilters);
|
||||
props.setSuggestions(
|
||||
await props.getSuggestions(e.target.value, undefined, searchHistory)
|
||||
);
|
||||
}}
|
||||
onFocus={async (e) => {
|
||||
//shift to index
|
||||
props.setSuggestions(
|
||||
await props.getSuggestions(e.target.value, undefined, searchHistory)
|
||||
);
|
||||
props.onFocus(e);
|
||||
}}
|
||||
onKeyDown={async (e) => {
|
||||
//keyActions(e);
|
||||
props.onKeyDown(e);
|
||||
await onKeyPress[e.key](e, props);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const onKeyPress = {
|
||||
Enter: async (e, props) => {
|
||||
props.onSearch(e.target.value);
|
||||
await addToSearchHistory(e.target.value);
|
||||
props.setSuggestions([]);
|
||||
props.refreshFilters(e.target.value, props.setFilters);
|
||||
e.preventDefault();
|
||||
},
|
||||
Escape: (e, props) => {
|
||||
props.setSuggestions([]);
|
||||
},
|
||||
ArrowDown: (e, props) => {
|
||||
props.moveSelection(props.suggestions, props.setSelectionIndex).Down();
|
||||
e.preventDefault();
|
||||
},
|
||||
ArrowUp: (e, props) => {
|
||||
props.moveSelection(props.suggestions, props.setSelectionIndex).Up();
|
||||
e.preventDefault();
|
||||
},
|
||||
ArrowLeft: (e, props) => {
|
||||
if (e.target.selectionStart == 0) {
|
||||
props.focusInput(props.filters.length - 1);
|
||||
}
|
||||
},
|
||||
ArrowRight: (e, props) => {
|
||||
if (e.target.selectionStart == e.target.value.length) {
|
||||
props.focusInput(0);
|
||||
}
|
||||
},
|
||||
Backspace: (e, props) => {
|
||||
if (e.target.selectionStart == 0) {
|
||||
props.focusInput(props.filters.length - 1);
|
||||
}
|
||||
}
|
||||
};
|
||||
325
packages/ui/src/components/menu/search.js
Normal file
325
packages/ui/src/components/menu/search.js
Normal file
@@ -0,0 +1,325 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
import { store } from "../../stores/note-store";
|
||||
import { db } from "../../common/db";
|
||||
import { filter, parse } from "liqe";
|
||||
|
||||
export const mainSearchEngine = async (searchType, value) => {
|
||||
//name is cumbersome
|
||||
// better name? fetchResults
|
||||
const context = store.context;
|
||||
const [lookupType, allData] = await filterItemsToType(searchType, context);
|
||||
if (lookupType !== undefined && allData !== undefined) {
|
||||
let result = await db.lookup[lookupType](allData, value);
|
||||
return { result, allData };
|
||||
} else {
|
||||
return { result: [], allData: [] };
|
||||
}
|
||||
};
|
||||
|
||||
/*
|
||||
there is mainly two types of search:
|
||||
filter search
|
||||
main search
|
||||
filter search is again divided into two: Why not make it one?
|
||||
how to search?
|
||||
db.notes.all === all notes
|
||||
notebooks:all the notes in the notebook
|
||||
topics: all the notes in the topic
|
||||
tags: all notes in the tag
|
||||
dates:all notes between the dates
|
||||
notes: all notes with the word
|
||||
inTitle: all notes with the word in title
|
||||
the search will condense. The scope will decrease with the number of filters
|
||||
*/
|
||||
export const filterSearchEngine = async (definitions) => {
|
||||
//name is cumbersome
|
||||
let notes = [];
|
||||
let searchlabels = [];
|
||||
const organizingNotesFilters = ["notebook", "topic", "tag"];
|
||||
let isOrganizingNotesFilter = false;
|
||||
await db.notes.init();
|
||||
console.log("search", definitions);
|
||||
for (let definition of definitions) {
|
||||
if (organizingNotesFilters.includes(definition.type))
|
||||
isOrganizingNotesFilter = true;
|
||||
}
|
||||
for (let definition of definitions) {
|
||||
switch (definition.type) {
|
||||
case "notebook":
|
||||
//isOrganizingNotesFilter = true; //this boolean should be done seperately
|
||||
for (let topic of definition.topics) {
|
||||
for (let note of topic.notes) {
|
||||
if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "topic":
|
||||
//isOrganizingNotesFilter = true;
|
||||
for (let note of definition.notes) {
|
||||
if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
}
|
||||
break;
|
||||
case "tag":
|
||||
//isOrganizingNotesFilter = true;
|
||||
for (let note of definition.noteIds) {
|
||||
if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
searchlabels.push(definition);
|
||||
}
|
||||
}
|
||||
|
||||
// for (let definition of definitions) { //switch statements or consts
|
||||
// if (definition.type === "notebook") {
|
||||
// isHigherlabelPresent = true;
|
||||
// for (let topic of definition.topics) {
|
||||
// for (let note of topic.notes) {
|
||||
// if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
// }
|
||||
// }
|
||||
// } else if (definition.type === "topic") {
|
||||
// isHigherlabelPresent = true;
|
||||
// for (let note of definition.notes) {
|
||||
// if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
// }
|
||||
// } else if (definition.type === "tag") {
|
||||
// isHigherlabelPresent = true;
|
||||
// for (let note of definition.noteIds) {
|
||||
// if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
// }
|
||||
// } else if (
|
||||
// definition.type === "before" ||
|
||||
// definition.type === "after" ||
|
||||
// definition.type === "during" ||
|
||||
// definition.type === "notes" ||
|
||||
// definition.type === "intitle"
|
||||
// ) {
|
||||
// searchlabels.push(definition);
|
||||
// //notes = await dateSearch(definition.value, definition.type);
|
||||
// }
|
||||
// }
|
||||
|
||||
let result = [];
|
||||
if (searchlabels.length > 0) {
|
||||
for (let label of searchlabels) {
|
||||
if (notes.length > 0) {
|
||||
if (label.type === "notes") {
|
||||
result = await db.lookup["notes"](notes, label.value);
|
||||
} else if (label.type === "intitle") {
|
||||
result = db.lookup["_byTitle"](notes, label.value);
|
||||
} else {
|
||||
result = await dateSearchEngine(label.value, label.type, notes);
|
||||
}
|
||||
} else if (!isOrganizingNotesFilter) {
|
||||
let allNotes = db.notes.all;
|
||||
if (label.type === "notes") {
|
||||
let search = await db.lookup["notes"](allNotes, label.value);
|
||||
result.push(...search);
|
||||
} else if (label.type === "intitle") {
|
||||
let search = await db.lookup["_byTitle"](allNotes, label.value);
|
||||
result.push(...search);
|
||||
} else {
|
||||
result = await dateSearchEngine(label.value, label.type, allNotes);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
return notes;
|
||||
}
|
||||
};
|
||||
|
||||
//definitions will first be sorted in following order: nbks> topics>tags>times>notes>intitle,
|
||||
// const someMethod = async (definition,notes) => {
|
||||
// await db.notes.init();
|
||||
// return {
|
||||
// notebook: () => {
|
||||
// for (let topic of definition.topics) { // noltebooks and topics will be sorted for search in one method
|
||||
// for (let note of topic.notes) {
|
||||
// if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// topic: () => {
|
||||
// for (let note of definition.notes) {
|
||||
// if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
// }
|
||||
// },
|
||||
// tag: () => { //all the notes from tag will be retrived and then mathched with already present notes to sort out relevent notes
|
||||
// for (let note of definition.noteIds) {
|
||||
// if (db.notes.note(note)) notes.push(db.notes.note(note)._note);
|
||||
// }
|
||||
// },
|
||||
// before: () => {//all the notes within dates will be retrived but only those will be sorted out which match with already present notes
|
||||
// let _notes = notes === [] ? db.notes.all : notes;
|
||||
// for (let note of _notes) {
|
||||
// if (note.dateCreated < unixTime) {
|
||||
// result.push(note);
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// after: () => {},
|
||||
// during: () => {}
|
||||
// };
|
||||
// };
|
||||
|
||||
export const dateSearchEngine = async (date, label, notes) => {
|
||||
let unixTime = new Date(date).getTime();
|
||||
let notesArc = notes ? notes : db.notes.all;
|
||||
let result = [];
|
||||
|
||||
switch (label) {
|
||||
case "before":
|
||||
for (let note of notesArc) {
|
||||
if (note.dateCreated < unixTime) {
|
||||
result.push(note);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "after":
|
||||
for (let note of notesArc) {
|
||||
if (note.dateCreated > unixTime) {
|
||||
result.push(note);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case "during":
|
||||
for (let note of notesArc) {
|
||||
let dateCreated = new Date(note.dateCreated);
|
||||
let noteDate = dateFormat(dateCreated).DDMMYY;
|
||||
let selectedUnix = new Date(unixTime);
|
||||
let selectedDate = dateFormat(selectedUnix).DDMMYY;
|
||||
if (noteDate === selectedDate) {
|
||||
result.push(note);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
// if (label === "before") {
|
||||
// for (let note of notesArc) {
|
||||
// if (note.dateCreated < unixTime) {
|
||||
// result.push(note);
|
||||
// }
|
||||
// }
|
||||
// } else if (label === "after") {
|
||||
// for (let note of notesArc) {
|
||||
// if (note.dateCreated > unixTime) {
|
||||
// result.push(note);
|
||||
// }
|
||||
// }
|
||||
// } else if (label === "during") {
|
||||
// for (let note of notesArc) {
|
||||
// let dateCreated = new Date(note.dateCreated);
|
||||
// let noteDate =
|
||||
// dateCreated.getDate() +
|
||||
// "/" +
|
||||
// dateCreated.getMonth() +
|
||||
// "/" +
|
||||
// dateCreated.getFullYear();
|
||||
// let selectedUnix = new Date(unixTime);
|
||||
// let selectedDate =
|
||||
// selectedUnix.getDate() +
|
||||
// "/" +
|
||||
// selectedUnix.getMonth() +
|
||||
// "/" +
|
||||
// selectedUnix.getFullYear();
|
||||
// if (noteDate === selectedDate) {
|
||||
// result.push(note);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
};
|
||||
|
||||
const dateFormat = (date) => {
|
||||
//this should be someplace else
|
||||
return {
|
||||
DDMMYY: date.getDate() + "/" + date.getMonth() + "/" + date.getFullYear()
|
||||
};
|
||||
};
|
||||
|
||||
export async function filterItemsToType(type, context) {
|
||||
switch (type) {
|
||||
case "notes":
|
||||
await db.notes.init();
|
||||
if (!context) return ["notes", db.notes.all];
|
||||
const notes = context.notes;
|
||||
return ["notes", notes];
|
||||
case "notebooks":
|
||||
return ["notebooks", db.notebooks.all];
|
||||
case "topics":
|
||||
const notebooks = db.notebooks.all;
|
||||
if (!notebooks) return ["topics", []];
|
||||
let topics = [];
|
||||
for (let notebook of notebooks) {
|
||||
let notebookTopics = db.notebooks.notebook(notebook.id).topics.all;
|
||||
if (notebookTopics.length > 0) {
|
||||
for (let notebookTopic of notebookTopics) {
|
||||
topics.push(notebookTopic);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ["topics", topics];
|
||||
case "tags":
|
||||
return ["tags", db.tags.all];
|
||||
case "trash":
|
||||
return ["trash", db.trash.all];
|
||||
case "_byTitle":
|
||||
await db.notes.init();
|
||||
if (!context) return ["notes", db.notes.all];
|
||||
let title = context.notes;
|
||||
return ["_byTitle", title];
|
||||
default:
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export function filterItems(query, items) {
|
||||
//naming is wrong
|
||||
//this is fetch suggestions search
|
||||
try {
|
||||
return filter(
|
||||
parse(`text:"${query.toLowerCase()}"`),
|
||||
items.map((item) => {
|
||||
return { item, text: item.query };
|
||||
})
|
||||
).map((v) => {
|
||||
return v.item.query;
|
||||
});
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
export const addToSearchHistory = async (value) => {
|
||||
// const history = await db.searchHistory.getHistory();
|
||||
// value = value.trim();
|
||||
// let isValueAlreadyPresent = false;
|
||||
// history.map((item) => {
|
||||
// if (item.query === value) {
|
||||
// isValueAlreadyPresent = true;
|
||||
// }
|
||||
// });
|
||||
// if (isValueAlreadyPresent) {
|
||||
// return;
|
||||
// }
|
||||
// await db.searchHistory.add(value);
|
||||
};
|
||||
56
packages/ui/src/components/menu/suggestionrow.js
Normal file
56
packages/ui/src/components/menu/suggestionrow.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
This file is part of the Notesnook project (https://notesnook.com/)
|
||||
|
||||
Copyright (C) 2023 Streetwriters (Private) Limited
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import { Button, Text } from "@theme-ui/components";
|
||||
|
||||
export function SuggestionRow(props) {
|
||||
return (
|
||||
<Button
|
||||
id={`suggestionItem_${props.index}`}
|
||||
variant="menuitem"
|
||||
m={0}
|
||||
sx={{
|
||||
display: "flex",
|
||||
":focus": { bg: "hover" },
|
||||
width: "100%",
|
||||
alignItems: "flex-start"
|
||||
}}
|
||||
bg="green"
|
||||
px={2}
|
||||
{...props}
|
||||
>
|
||||
<Text
|
||||
variant="subtitle"
|
||||
fontWeight={props.item.isFilterFocused ? "body" : "bold"}
|
||||
ml={1}
|
||||
sx={{ textOverflow: "ellipsis" }}
|
||||
>
|
||||
{props.item.col1}
|
||||
</Text>
|
||||
<Text
|
||||
variant="subtitle"
|
||||
fontWeight={"body"}
|
||||
ml={1}
|
||||
sx={{ textOverflow: "ellipsis" }}
|
||||
>
|
||||
{props.item.col2}
|
||||
</Text>
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user