mirror of
https://github.com/artegoser/AnoPaper.git
synced 2024-11-25 21:36:21 +03:00
feat: Note search, locale time string
This commit is contained in:
parent
482031b1f6
commit
a34ae82215
9 changed files with 118 additions and 33 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -15,6 +15,7 @@
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"fuse.js": "^6.6.2",
|
||||||
"js-sha3": "^0.8.0",
|
"js-sha3": "^0.8.0",
|
||||||
"openai": "^3.2.1",
|
"openai": "^3.2.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
@ -2299,6 +2300,14 @@
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||||
},
|
},
|
||||||
|
"node_modules/fuse.js": {
|
||||||
|
"version": "6.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz",
|
||||||
|
"integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/gensync": {
|
"node_modules/gensync": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.2",
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
|
@ -7231,6 +7240,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||||
},
|
},
|
||||||
|
"fuse.js": {
|
||||||
|
"version": "6.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz",
|
||||||
|
"integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA=="
|
||||||
|
},
|
||||||
"gensync": {
|
"gensync": {
|
||||||
"version": "1.0.0-beta.2",
|
"version": "1.0.0-beta.2",
|
||||||
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
"fuse.js": "^6.6.2",
|
||||||
"js-sha3": "^0.8.0",
|
"js-sha3": "^0.8.0",
|
||||||
"openai": "^3.2.1",
|
"openai": "^3.2.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
|
|
|
@ -97,4 +97,5 @@ export {
|
||||||
SettingsTextInput,
|
SettingsTextInput,
|
||||||
SettingsSelectInput,
|
SettingsSelectInput,
|
||||||
SettingsSection,
|
SettingsSection,
|
||||||
|
setSetting,
|
||||||
};
|
};
|
||||||
|
|
|
@ -4,11 +4,16 @@ function printDate(time) {
|
||||||
return i < 10 ? "0" + i : "" + i;
|
return i < 10 ? "0" + i : "" + i;
|
||||||
}
|
}
|
||||||
|
|
||||||
let dateStr = `${padStr(time.getHours())}:${padStr(
|
let dateStr =
|
||||||
time.getMinutes()
|
settings.language === "ru" || settings.language === "ru-RU"
|
||||||
)}:${padStr(time.getSeconds())} ${padStr(time.getDate())}.${padStr(
|
? `${padStr(time.getHours())}:${padStr(time.getMinutes())}:${padStr(
|
||||||
|
time.getSeconds()
|
||||||
|
)} ${padStr(time.getDate())}.${padStr(1 + time.getMonth())}.${padStr(
|
||||||
|
time.getFullYear()
|
||||||
|
)}`
|
||||||
|
: `${time.toLocaleTimeString("en-US")} ${padStr(
|
||||||
1 + time.getMonth()
|
1 + time.getMonth()
|
||||||
)}.${padStr(time.getFullYear())}`;
|
)}/${padStr(time.getDate())}/${padStr(time.getFullYear())}`;
|
||||||
|
|
||||||
return dateStr;
|
return dateStr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,8 @@ let en = {
|
||||||
BroadcastSync: "Getting notes, settings from another device",
|
BroadcastSync: "Getting notes, settings from another device",
|
||||||
SyncAll: "Send data to all devices",
|
SyncAll: "Send data to all devices",
|
||||||
Sync: "Sync",
|
Sync: "Sync",
|
||||||
|
Search: "Search",
|
||||||
|
NoNotesFound: "No notes found",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default en;
|
export default en;
|
||||||
|
|
|
@ -51,6 +51,8 @@ let ru = {
|
||||||
BroadcastSync: "Получение заметок, настроек с другого устройства",
|
BroadcastSync: "Получение заметок, настроек с другого устройства",
|
||||||
SyncAll: "Отправить данные",
|
SyncAll: "Отправить данные",
|
||||||
Sync: "Синхронизация",
|
Sync: "Синхронизация",
|
||||||
|
Search: "Поиск",
|
||||||
|
NoNotesFound: "Заметок не найдено",
|
||||||
};
|
};
|
||||||
|
|
||||||
export default ru;
|
export default ru;
|
||||||
|
|
|
@ -1,26 +1,60 @@
|
||||||
import { ButtonWithIcon } from "../components/button";
|
import { ButtonWithIcon } from "../components/button";
|
||||||
import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
|
import { ChevronDoubleRightIcon } from "@heroicons/react/24/outline";
|
||||||
import { printDate } from "../components/utils";
|
import { printDate } from "../components/utils";
|
||||||
|
import Fuse from "fuse.js";
|
||||||
|
import { inputStyle } from "../components/styles";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { setSetting } from "../components/settingsInputs";
|
||||||
|
|
||||||
function Notes() {
|
function Notes() {
|
||||||
let notes = Object.entries(localStorage.getObj("Notes"))
|
if (!settings.newNotes) {
|
||||||
|
let notesObj = localStorage.getObj("Notes");
|
||||||
|
let notes = Object.entries(notesObj);
|
||||||
|
for (let [id, note] of notes) {
|
||||||
|
note.id = id;
|
||||||
|
note.textTime = printDate(note.time);
|
||||||
|
notesObj[id] = note;
|
||||||
|
}
|
||||||
|
localStorage.setObj("Notes", notesObj);
|
||||||
|
setSetting("newNotes", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
let n = Object.values(localStorage.getObj("Notes"));
|
||||||
|
|
||||||
|
let fuse = new Fuse(n, {
|
||||||
|
keys: ["name", "text", "textTime", "tags"],
|
||||||
|
});
|
||||||
|
|
||||||
|
let [search, setSearch] = useState("");
|
||||||
|
|
||||||
|
let found = search === "" ? n : fuse.search(search);
|
||||||
|
|
||||||
|
if (search !== "") {
|
||||||
|
found = found
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return b[1].time - a[1].time;
|
return b.refIndex - a.refIndex;
|
||||||
})
|
})
|
||||||
.map((val) => {
|
.map(({ item }) => item);
|
||||||
|
} else {
|
||||||
|
found = found.sort((a, b) => {
|
||||||
|
return b.time - a.time;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let notes = found.map((item) => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="grid grid-cols-1 lg:grid-cols-2 border border-blue-300 rounded-lg m-2 p-2 justify-items-start"
|
className="grid grid-cols-1 lg:grid-cols-2 border border-blue-300 rounded-lg m-2 p-2 justify-items-start"
|
||||||
key={val[0]}
|
key={item.id}
|
||||||
>
|
>
|
||||||
<div className="font-medium leading-tight text-4xl mt-0 mb-2">
|
<div className="font-medium leading-tight text-4xl mt-0 mb-2">
|
||||||
{val[1].name}
|
{item.name}
|
||||||
</div>
|
</div>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 justify-self-center lg:justify-self-end">
|
<div className="grid grid-cols-1 lg:grid-cols-2 justify-self-center lg:justify-self-end">
|
||||||
<div className="text-center">{printDate(val[1].time)}</div>
|
<div className="text-center">{printDate(item.time)}</div>
|
||||||
<div className="">
|
<div className="">
|
||||||
<ButtonWithIcon
|
<ButtonWithIcon
|
||||||
href={`/notes/${val[0]}`}
|
href={`/notes/${item.id}`}
|
||||||
reverse={true}
|
reverse={true}
|
||||||
icon={ChevronDoubleRightIcon}
|
icon={ChevronDoubleRightIcon}
|
||||||
text={locals.Open}
|
text={locals.Open}
|
||||||
|
@ -31,13 +65,32 @@ function Notes() {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (notes.length === 0)
|
if (n.length === 0) {
|
||||||
return (
|
return (
|
||||||
<div className="md">
|
<div className="md">
|
||||||
<h3>{locals.NoNotesYet}</h3>
|
<h3>{locals.NoNotesYet}</h3>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
return notes;
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="">
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
className={`mb-2 md:w-1/6 w-full ${inputStyle}`}
|
||||||
|
placeholder={locals.Search}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSearch(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{notes}
|
||||||
|
{found.length === 0 && (
|
||||||
|
<div className="md">
|
||||||
|
<h3>{locals.NoNotesFound}</h3>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Notes;
|
export default Notes;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Navigate } from "react-router-dom";
|
import { Navigate } from "react-router-dom";
|
||||||
|
import { printDate } from "../components/utils";
|
||||||
|
|
||||||
function uuidv4() {
|
function uuidv4() {
|
||||||
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, (c) =>
|
||||||
|
@ -19,10 +20,14 @@ function Save() {
|
||||||
|
|
||||||
let notesObj = localStorage.getObj("Notes");
|
let notesObj = localStorage.getObj("Notes");
|
||||||
|
|
||||||
|
let time = Date.now();
|
||||||
|
|
||||||
notesObj[id] = {
|
notesObj[id] = {
|
||||||
|
id,
|
||||||
name,
|
name,
|
||||||
text,
|
text,
|
||||||
time: Date.now(),
|
time,
|
||||||
|
textTime: printDate(time),
|
||||||
pubTime,
|
pubTime,
|
||||||
pub: !!pubTime,
|
pub: !!pubTime,
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,6 +3,7 @@ import {
|
||||||
SettingsTextInput,
|
SettingsTextInput,
|
||||||
SettingsSelectInput,
|
SettingsSelectInput,
|
||||||
SettingsSection,
|
SettingsSection,
|
||||||
|
setSetting,
|
||||||
} from "../components/settingsInputs";
|
} from "../components/settingsInputs";
|
||||||
import { reRenderPage } from "../components/utils";
|
import { reRenderPage } from "../components/utils";
|
||||||
import Locales from "../localisation/main";
|
import Locales from "../localisation/main";
|
||||||
|
@ -125,6 +126,7 @@ function Settings() {
|
||||||
Locales[navigator.userLanguage] ||
|
Locales[navigator.userLanguage] ||
|
||||||
Locales.en;
|
Locales.en;
|
||||||
|
|
||||||
|
setSetting("newNotes", false);
|
||||||
reRenderPage();
|
reRenderPage();
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
Loading…
Add table
Reference in a new issue