diff --git a/asset-api/index.js b/asset-api/index.js
index 352174a..06d2cec 100644
--- a/asset-api/index.js
+++ b/asset-api/index.js
@@ -7,6 +7,7 @@ import { join } from "node:path";
import mime from "mime";
import { promisify } from "node:util";
import { pipeline } from "node:stream";
+import cors from "@fastify/cors";
const M2M_ALGORITHM = "RSA-SHA512";
const { private: M2M_PRIVATE_KEY, public: M2M_PUBLIC_KEY } = loadM2MKeys();
@@ -25,6 +26,9 @@ const fastify = new Fastify({
});
fastify.register(multipart);
+fastify.register(cors, {
+ origin: true,
+})
fastify.get("/", async () => {
return signString(ASSET_API_LANDING_MESSAGE);
diff --git a/asset-api/package.json b/asset-api/package.json
index a9b30a0..cfb18ed 100644
--- a/asset-api/package.json
+++ b/asset-api/package.json
@@ -4,6 +4,7 @@
"type": "module",
"packageManager": "yarn@4.3.0",
"dependencies": {
+ "@fastify/cors": "^9.0.1",
"@fastify/multipart": "^8.3.0",
"fastify": "^4.28.0",
"mime": "^4.0.3",
diff --git a/asset-api/yarn.lock b/asset-api/yarn.lock
index a59ee5c..f2924c9 100644
--- a/asset-api/yarn.lock
+++ b/asset-api/yarn.lock
@@ -83,6 +83,16 @@ __metadata:
languageName: node
linkType: hard
+"@fastify/cors@npm:^9.0.1":
+ version: 9.0.1
+ resolution: "@fastify/cors@npm:9.0.1"
+ dependencies:
+ fastify-plugin: "npm:^4.0.0"
+ mnemonist: "npm:0.39.6"
+ checksum: 10c0/4db9d3d02edbca741c8ed053819bf3b235ecd70e07c640ed91ba0fc1ee2dc8abedbbffeb79ae1a38ccbf59832e414cad90a554ee44227d0811d5a2d062940611
+ languageName: node
+ linkType: hard
+
"@fastify/deepmerge@npm:^1.0.0":
version: 1.3.0
resolution: "@fastify/deepmerge@npm:1.3.0"
@@ -284,6 +294,7 @@ __metadata:
resolution: "asset-api@workspace:."
dependencies:
"@eslint/js": "npm:^9.5.0"
+ "@fastify/cors": "npm:^9.0.1"
"@fastify/multipart": "npm:^8.3.0"
eslint: "npm:9.x"
fastify: "npm:^4.28.0"
@@ -931,6 +942,15 @@ __metadata:
languageName: node
linkType: hard
+"mnemonist@npm:0.39.6":
+ version: 0.39.6
+ resolution: "mnemonist@npm:0.39.6"
+ dependencies:
+ obliterator: "npm:^2.0.1"
+ checksum: 10c0/a538945ea547976136ee6e16f224c0a50983143619941f6c4d2c82159e36eb6f8ee93d69d3a1267038fc5b16f88e2d43390023de10dfb145fa15c5e2befa1cdf
+ languageName: node
+ linkType: hard
+
"ms@npm:2.1.2":
version: 2.1.2
resolution: "ms@npm:2.1.2"
@@ -945,6 +965,13 @@ __metadata:
languageName: node
linkType: hard
+"obliterator@npm:^2.0.1":
+ version: 2.0.4
+ resolution: "obliterator@npm:2.0.4"
+ checksum: 10c0/ff2c10d4de7d62cd1d588b4d18dfc42f246c9e3a259f60d5716f7f88e5b3a3f79856b3207db96ec9a836a01d0958a21c15afa62a3f4e73a1e0b75f2c2f6bab40
+ languageName: node
+ linkType: hard
+
"on-exit-leak-free@npm:^2.1.0":
version: 2.1.2
resolution: "on-exit-leak-free@npm:2.1.2"
diff --git a/identity-api/package.json b/identity-api/package.json
index d681160..ef5d576 100644
--- a/identity-api/package.json
+++ b/identity-api/package.json
@@ -7,6 +7,7 @@
"type": "module",
"packageManager": "yarn@4.3.0",
"dependencies": {
+ "@fastify/cors": "^9.0.1",
"dotenv": "^16.4.5",
"fastify": "^4.27.0",
"jose": "^5.4.0"
diff --git a/identity-api/src/index.js b/identity-api/src/index.js
index 593e607..780afec 100644
--- a/identity-api/src/index.js
+++ b/identity-api/src/index.js
@@ -3,9 +3,14 @@ import { ASSET_API_ENDPOINT, IDENTITY_API_LANDING_MESSAGE, LISTEN_PORT } from ".
import { contentFromSigned, verifySignature } from "./m2m.js";
import { startAuth } from "./auth.js";
import { randomUUID } from "node:crypto";
+import cors from "@fastify/cors";
let auth = await startAuth();
+app.register(cors, {
+ origin: true,
+})
+
app.get("/", async () => {
return IDENTITY_API_LANDING_MESSAGE;
});
diff --git a/identity-api/yarn.lock b/identity-api/yarn.lock
index 0a3790b..9bf0a0a 100644
--- a/identity-api/yarn.lock
+++ b/identity-api/yarn.lock
@@ -76,6 +76,16 @@ __metadata:
languageName: node
linkType: hard
+"@fastify/cors@npm:^9.0.1":
+ version: 9.0.1
+ resolution: "@fastify/cors@npm:9.0.1"
+ dependencies:
+ fastify-plugin: "npm:^4.0.0"
+ mnemonist: "npm:0.39.6"
+ checksum: 10c0/4db9d3d02edbca741c8ed053819bf3b235ecd70e07c640ed91ba0fc1ee2dc8abedbbffeb79ae1a38ccbf59832e414cad90a554ee44227d0811d5a2d062940611
+ languageName: node
+ linkType: hard
+
"@fastify/error@npm:^3.3.0, @fastify/error@npm:^3.4.0":
version: 3.4.1
resolution: "@fastify/error@npm:3.4.1"
@@ -591,6 +601,13 @@ __metadata:
languageName: node
linkType: hard
+"fastify-plugin@npm:^4.0.0":
+ version: 4.5.1
+ resolution: "fastify-plugin@npm:4.5.1"
+ checksum: 10c0/f58f79cd9d3c88fd7f79a3270276c6339fc57bbe72ef14d20b73779193c404e317ac18e8eae2c5071b3909ebee45d7eb6871da4e65464ac64ed0d9746b4e9b9f
+ languageName: node
+ linkType: hard
+
"fastify@npm:^4.27.0":
version: 4.27.0
resolution: "fastify@npm:4.27.0"
@@ -713,6 +730,7 @@ __metadata:
resolution: "identity-api@workspace:."
dependencies:
"@eslint/js": "npm:^9.5.0"
+ "@fastify/cors": "npm:^9.0.1"
dotenv: "npm:^16.4.5"
eslint: "npm:9.x"
fastify: "npm:^4.27.0"
@@ -900,6 +918,15 @@ __metadata:
languageName: node
linkType: hard
+"mnemonist@npm:0.39.6":
+ version: 0.39.6
+ resolution: "mnemonist@npm:0.39.6"
+ dependencies:
+ obliterator: "npm:^2.0.1"
+ checksum: 10c0/a538945ea547976136ee6e16f224c0a50983143619941f6c4d2c82159e36eb6f8ee93d69d3a1267038fc5b16f88e2d43390023de10dfb145fa15c5e2befa1cdf
+ languageName: node
+ linkType: hard
+
"ms@npm:2.1.2":
version: 2.1.2
resolution: "ms@npm:2.1.2"
@@ -914,6 +941,13 @@ __metadata:
languageName: node
linkType: hard
+"obliterator@npm:^2.0.1":
+ version: 2.0.4
+ resolution: "obliterator@npm:2.0.4"
+ checksum: 10c0/ff2c10d4de7d62cd1d588b4d18dfc42f246c9e3a259f60d5716f7f88e5b3a3f79856b3207db96ec9a836a01d0958a21c15afa62a3f4e73a1e0b75f2c2f6bab40
+ languageName: node
+ linkType: hard
+
"on-exit-leak-free@npm:^2.1.0":
version: 2.1.2
resolution: "on-exit-leak-free@npm:2.1.2"
diff --git a/identity-web/package.json b/identity-web/package.json
index 17ae64c..8ea9ace 100644
--- a/identity-web/package.json
+++ b/identity-web/package.json
@@ -41,6 +41,7 @@
"@fortawesome/free-solid-svg-icons": "^6.5.2",
"@fortawesome/svelte-fontawesome": "^0.2.2",
"felte": "^1.2.14",
+ "fuse.js": "^7.0.0",
"mime": "^4.0.3"
}
}
diff --git a/identity-web/src/lib/components/FeelingsChooser.svelte b/identity-web/src/lib/components/FeelingsChooser.svelte
new file mode 100644
index 0000000..4a513fb
--- /dev/null
+++ b/identity-web/src/lib/components/FeelingsChooser.svelte
@@ -0,0 +1,74 @@
+
+
+
+ {#if displayText}
+
Feelings
+ {/if}
+
+
+
+
+ {#if chosenFeelings.length > 0}
+
+
Chosen:
+ {#each chosenFeelings as feeling (feeling)}
+
+
+
+
+ {/each}
+
+ {:else}
+
No feelings chosen.
+ {#if required}
+
You need to choose at least one feeling.
+ {/if}
+ {/if}
+
+
+
+ {#each feelingsToChoose as feeling (feeling)}
+
+ {/each}
+
+
\ No newline at end of file
diff --git a/identity-web/src/lib/entry.ts b/identity-web/src/lib/entry.ts
index d64b282..cc32dd0 100644
--- a/identity-web/src/lib/entry.ts
+++ b/identity-web/src/lib/entry.ts
@@ -2,6 +2,7 @@ export const TITLED_ENTRIES = ["event", "environment", "memory"];
export const FEELINGS = ["relaxed", "afraid", "angry", "bad", "bored", "confused", "excited", "fine", "happy", "hurt", "in love", "mad", "nervous", "okay", "sad", "scared", "shy", "sleepy", "active", "surprised", "tired", "upset", "worried"];
export type KnownFeeling = "relaxed" | "afraid" | "angry" | "bad" | "bored" | "confused" | "excited" | "fine" | "happy" | "hurt" | "in love" | "mad" | "nervous" | "okay" | "sad" | "scared" | "shy" | "sleepy" | "active" | "surprised" | "tired" | "upset" | "worried";
+export type EntryKind = "song" | "album" | "event" | "memory" | "feeling" | "environment" | "date";
export type IdlessEntry = {
base: SongEntry | AlbumEntry | EventEntry | MemoryEntry | FeelingEntry | EnvironmentEntry | DateEntry,
diff --git a/identity-web/src/routes/dashboard/+page.svelte b/identity-web/src/routes/dashboard/+page.svelte
index c0b81fd..cb3a519 100644
--- a/identity-web/src/routes/dashboard/+page.svelte
+++ b/identity-web/src/routes/dashboard/+page.svelte
@@ -3,27 +3,73 @@
import { account, credentials } from "$lib/stores";
import { onMount } from "svelte";
import Entries from "./Entries.svelte";
- import Overview from "./Overview.svelte"
+ import Overview from "./Overview.svelte";
+ import { FontAwesomeIcon } from "@fortawesome/svelte-fontawesome";
+ import { faFilter } from "@fortawesome/free-solid-svg-icons";
+ import FilterSelector from "./utils/FilterSelector.svelte";
credentials.subscribe((v) => v == null && (setTimeout(() => window.location.pathname = '/auth/login', 200)))
- let throtle = false;
- let currentOffset = 10;
- let step = 5;
- let entries = entryPage($credentials!, 0, currentOffset);
+
+ function createPageHandler({ onLoadingStatusChanged, onEndReached }: { onLoadingStatusChanged: (status: boolean) => any, onEndReached: () => any }) {
+ let loadingPage = false;
+ let rechedEnd = false;
+ let currentOffset = 10;
+ let step = 5;
+
+ return {
+ initialEntries: entryPage($credentials!, 0, currentOffset),
+ nextPage: async () => {
+ if (loadingPage || reachedEnd) {
+ return undefined;
+ }
+
+ loadingPage = true;
+ onLoadingStatusChanged(loadingPage);
+
+ let page = await entryPage($credentials!, currentOffset, step);
+ currentOffset += step;
+
+ loadingPage = false;
+ onLoadingStatusChanged(loadingPage);
+ if (page.length === 0) {
+ reachedEnd = true;
+ onEndReached();
+ }
+
+ return page;
+ }
+ }
+ }
+
let overview = Promise.allSettled([entryPage($credentials!, 0, 3), entryPage($credentials!, 20, 3)])
+ let loadingPage = false;
+ let reachedEnd = false;
+ let filterStatus = false;
+ let { initialEntries: entries, nextPage } = createPageHandler({
+ onLoadingStatusChanged: (status) => loadingPage = status,
+ onEndReached: () => reachedEnd = true,
+ })
+
+ let showFilterSelector = false
+ let chosenFilterFeelings = []
+ let filters = {
+ fromDate: null,
+ toDate: null,
+ kind: null,
+ feelings: null,
+ searchQuery: null,
+ }
+
onMount(() => {
function handleScroll() {
- if (!throtle && window.innerHeight + window.scrollY >= document.body.offsetHeight) {
- throtle = true
+ if (!filterStatus && window.innerHeight + window.scrollY >= document.body.offsetHeight) {
entries.then(async (page) => {
- console.log("new page requested")
- let secondPage = await entryPage($credentials!, currentOffset, step);
- page = [...page, ...secondPage];
-
- currentOffset += step
- throtle = false
- entries = new Promise((resolve) => resolve(page))
+ let secondPage = await nextPage()
+ if (secondPage != null) {
+ page = [...page, ...secondPage];
+ entries = new Promise((resolve) => resolve(page))
+ }
})
}
}
@@ -66,13 +112,41 @@
{/await}
-
-
Memories
-
+ Add an entry
+
Entries
+
+
+ Add an entry
+
+
+ {#if showFilterSelector}
+
chosenFilterFeelings = e.detail} on:updatedFilter={(e) => filters = e.detail} chosenFeelings={chosenFilterFeelings} filters={filters}/>
+ {/if}
+
- refreshEntries()} entries={entries}/>
+ filterStatus = e.detail} on:deleted={() => refreshEntries()} entries={entries} filters={filters}/>
+ {#if loadingPage && !reachedEnd}
+
+
+
Loading entries...
+
+
+
+ {/if}
+
+ {#if reachedEnd}
+
+
+ You've reached the end
+
+
+ {/if}
{/if}
diff --git a/identity-web/src/routes/dashboard/Entries.svelte b/identity-web/src/routes/dashboard/Entries.svelte
index d58a45a..2afc806 100644
--- a/identity-web/src/routes/dashboard/Entries.svelte
+++ b/identity-web/src/routes/dashboard/Entries.svelte
@@ -1,23 +1,97 @@
-{#each entries as entry (entry.id)}
+{#each filteredEntries as entry (entry.id)}
extended = [entry.id, ...extended]}
- on:contracted={() => extended = extended.filter(v => v !== entry.id)}
- on:deleted={(event) => { dispatch('deleted', event.detail) }}
+ on:extended={(e) => extended = [e.detail.id, ...extended]}
+ on:contracted={(e) => extended = extended.filter(v => v !== e.detail.id)}
+ on:deleted={(e) => { dispatch('deleted', e.detail) }}
id={entry.id}
kind={entry.base.kind}
diff --git a/identity-web/src/routes/dashboard/utils/Entry.svelte b/identity-web/src/routes/dashboard/utils/Entry.svelte
index 3649b97..837c904 100644
--- a/identity-web/src/routes/dashboard/utils/Entry.svelte
+++ b/identity-web/src/routes/dashboard/utils/Entry.svelte
@@ -16,7 +16,7 @@
let prevExtended = isExtended
$: if (prevExtended !== isExtended) {
- dispatch(isExtended ? 'extended' : 'contracted')
+ dispatch(isExtended ? 'extended' : 'contracted', { id })
}
async function processDeletion(id: string) {
@@ -44,7 +44,7 @@
-