mirror of
https://github.com/aquatix/digimarks.git
synced 2025-12-06 22:05:09 +01:00
Only fetch new bookmarks and tags when cache is not up-to-date
This commit is contained in:
@@ -19,7 +19,7 @@ from fastapi.staticfiles import StaticFiles
|
|||||||
from fastapi.templating import Jinja2Templates
|
from fastapi.templating import Jinja2Templates
|
||||||
from pydantic import AnyUrl, DirectoryPath, FilePath
|
from pydantic import AnyUrl, DirectoryPath, FilePath
|
||||||
from pydantic_settings import BaseSettings
|
from pydantic_settings import BaseSettings
|
||||||
from sqlmodel import AutoString, Field, Session, SQLModel, create_engine, select
|
from sqlmodel import AutoString, Field, Session, SQLModel, create_engine, desc, select
|
||||||
|
|
||||||
DIGIMARKS_USER_AGENT = 'digimarks/2.0.0-dev'
|
DIGIMARKS_USER_AGENT = 'digimarks/2.0.0-dev'
|
||||||
DIGIMARKS_VERSION = '2.0.0a1'
|
DIGIMARKS_VERSION = '2.0.0a1'
|
||||||
@@ -381,7 +381,11 @@ def get_bookmark(
|
|||||||
url_hash: str,
|
url_hash: str,
|
||||||
) -> Bookmark:
|
) -> Bookmark:
|
||||||
"""Show bookmark details."""
|
"""Show bookmark details."""
|
||||||
bookmark = session.exec(select(Bookmark).where(Bookmark.userkey == user_key, Bookmark.url_hash == url_hash)).first()
|
bookmark = session.exec(
|
||||||
|
select(Bookmark).where(
|
||||||
|
Bookmark.userkey == user_key, Bookmark.url_hash == url_hash, Bookmark.status != Visibility.DELETED
|
||||||
|
)
|
||||||
|
).first()
|
||||||
# bookmark = session.get(Bookmark, {'url_hash': url_hash, 'userkey': user_key})
|
# bookmark = session.get(Bookmark, {'url_hash': url_hash, 'userkey': user_key})
|
||||||
return bookmark
|
return bookmark
|
||||||
|
|
||||||
@@ -450,13 +454,42 @@ def delete_bookmark(
|
|||||||
return {'ok': True}
|
return {'ok': True}
|
||||||
|
|
||||||
|
|
||||||
|
@app.get('/api/v1/{user_key}/latest_changes/')
|
||||||
|
def bookmarks_changed_since(
|
||||||
|
session: SessionDep,
|
||||||
|
user_key: str,
|
||||||
|
):
|
||||||
|
"""Last update on server, so the (browser) client knows whether to fetch an update."""
|
||||||
|
latest_modified_bookmark = session.exec(
|
||||||
|
select(Bookmark)
|
||||||
|
.where(Bookmark.userkey == user_key, Bookmark.status != Visibility.DELETED)
|
||||||
|
.order_by(desc(Bookmark.modified_date))
|
||||||
|
).first()
|
||||||
|
latest_created_bookmark = session.exec(
|
||||||
|
select(Bookmark)
|
||||||
|
.where(Bookmark.userkey == user_key, Bookmark.status != Visibility.DELETED)
|
||||||
|
.order_by(desc(Bookmark.created_date))
|
||||||
|
).first()
|
||||||
|
|
||||||
|
latest_modification = max(latest_modified_bookmark.modified_date, latest_created_bookmark.created_date)
|
||||||
|
|
||||||
|
return {
|
||||||
|
'current_time': datetime.now(UTC),
|
||||||
|
'latest_change': latest_modified_bookmark.modified_date,
|
||||||
|
'latest_created': latest_created_bookmark.created_date,
|
||||||
|
'latest_modification': latest_modification,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@app.get('/api/v1/{user_key}/tags/')
|
@app.get('/api/v1/{user_key}/tags/')
|
||||||
def list_tags_for_user(
|
def list_tags_for_user(
|
||||||
session: SessionDep,
|
session: SessionDep,
|
||||||
user_key: str,
|
user_key: str,
|
||||||
) -> list[str]:
|
) -> list[str]:
|
||||||
"""List all tags in use by the user."""
|
"""List all tags in use by the user."""
|
||||||
bookmarks = session.exec(select(Bookmark).where(Bookmark.userkey == user_key)).all()
|
bookmarks = session.exec(
|
||||||
|
select(Bookmark).where(Bookmark.userkey == user_key, Bookmark.status != Visibility.DELETED)
|
||||||
|
).all()
|
||||||
tags = []
|
tags = []
|
||||||
for bookmark in bookmarks:
|
for bookmark in bookmarks:
|
||||||
tags += bookmark.tags_list
|
tags += bookmark.tags_list
|
||||||
|
|||||||
@@ -9,12 +9,18 @@ document.addEventListener('alpine:init', () => {
|
|||||||
bookmarks: [],
|
bookmarks: [],
|
||||||
tags: [],
|
tags: [],
|
||||||
|
|
||||||
tryout: 'hey',
|
/* Loading indicator */
|
||||||
|
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|
||||||
|
/* Search filter */
|
||||||
search: '',
|
search: '',
|
||||||
|
|
||||||
|
/* Sort on ~ */
|
||||||
|
sort_title_asc: Alpine.$persist(false).as('sort_title_asc'),
|
||||||
|
sort_title_desc: Alpine.$persist(false).as('sort_title_desc'),
|
||||||
|
sort_created_asc: Alpine.$persist(false).as('sort_created_asc'),
|
||||||
|
sort_created_desc: Alpine.$persist(false).as('sort_created_desc'),
|
||||||
|
|
||||||
async init() {
|
async init() {
|
||||||
/** Initialise the application after loading */
|
/** Initialise the application after loading */
|
||||||
// if (this.userKey in this.cache) {
|
// if (this.userKey in this.cache) {
|
||||||
@@ -28,28 +34,47 @@ document.addEventListener('alpine:init', () => {
|
|||||||
}, 1000);
|
}, 1000);
|
||||||
},
|
},
|
||||||
async loadCache() {
|
async loadCache() {
|
||||||
console.log('Loading bookmarks from cache for user "' + this.userKey + '"');
|
if (this.userKey in this.cache) {
|
||||||
this.bookmarks = this.cache[this.userKey]['bookmarks'] || [];
|
console.log('Loading bookmarks from cache for user "' + this.userKey + '"');
|
||||||
|
this.bookmarks = this.cache[this.userKey]['bookmarks'] || [];
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async getBookmarks() {
|
async getBookmarks() {
|
||||||
/** Get the bookmarks from the backend */
|
/** Get the bookmarks from the backend */
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
|
if (!(this.userKey in this.cache)) {
|
||||||
|
/* There is no cache for this userKey yet, create on */
|
||||||
|
console.log('Creating cache for user "' + this.userKey + '"');
|
||||||
|
this.cache[this.userKey] = {'bookmarks': [], 'latest_changes': {}};
|
||||||
|
}
|
||||||
|
|
||||||
|
let latest_status_response = await fetch('/api/v1/' + this.userKey + '/latest_changes/');
|
||||||
|
let latest_status_result = await latest_status_response.json();
|
||||||
|
let should_fetch = false;
|
||||||
|
let latest_modification_in_cache = this.cache[this.userKey].latest_changes.latest_modification || "0000-00-00";
|
||||||
|
should_fetch = latest_status_result.latest_modification > latest_modification_in_cache;
|
||||||
|
this.cache[this.userKey].latest_changes = latest_status_result;
|
||||||
|
|
||||||
|
if (!should_fetch) {
|
||||||
|
console.log('Cache is up-to-date');
|
||||||
|
this.loading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.log('Fetching latest bookmarks from backend for user "' + this.userKey + '"...');
|
console.log('Fetching latest bookmarks from backend for user "' + this.userKey + '"...');
|
||||||
let response = await fetch('/api/v1/' + this.userKey + '/bookmarks/?limit=10000');
|
let response = await fetch('/api/v1/' + this.userKey + '/bookmarks/?limit=10000');
|
||||||
let result = await response.json();
|
let result = await response.json();
|
||||||
console.log(result);
|
|
||||||
this.bookmarks = result;
|
this.bookmarks = result;
|
||||||
if (!(this.userKey in this.cache)) {
|
|
||||||
/* There is no cache for this userKey yet, create on */
|
|
||||||
console.log('caching');
|
|
||||||
this.cache[this.userKey] = {'bookmarks': []};
|
|
||||||
}
|
|
||||||
/* Cache the bookmarks to Local Storage */
|
/* Cache the bookmarks to Local Storage */
|
||||||
this.cache[this.userKey]['bookmarks'] = result;
|
this.cache[this.userKey]['bookmarks'] = result;
|
||||||
|
|
||||||
|
let tags_response = await fetch('/api/v1/' + this.userKey + '/tags/');
|
||||||
|
let tags_result = await tags_response.json();
|
||||||
|
this.cache[this.userKey]['tags'] = tags_result;
|
||||||
|
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
},
|
},
|
||||||
get filteredItems() {
|
get filteredBookmarks() {
|
||||||
// return this.cache[this.userKey]['bookmarks'].filter(
|
// return this.cache[this.userKey]['bookmarks'].filter(
|
||||||
// i => i.title.includes(this.search)
|
// i => i.title.includes(this.search)
|
||||||
// )
|
// )
|
||||||
@@ -58,6 +83,11 @@ document.addEventListener('alpine:init', () => {
|
|||||||
i => i.title.match(new RegExp(this.search, "i"))
|
i => i.title.match(new RegExp(this.search, "i"))
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
get filteredTags() {
|
||||||
|
return this.cache[this.userKey].tags.filter(
|
||||||
|
i => i.match(new RegExp(this.search, "i"))
|
||||||
|
)
|
||||||
|
},
|
||||||
async sortAlphabetically(order = 'asc') {
|
async sortAlphabetically(order = 'asc') {
|
||||||
if (order === 'desc') {
|
if (order === 'desc') {
|
||||||
this.bookmarks.sort((a, b) => b.title.localeCompare(a.title));
|
this.bookmarks.sort((a, b) => b.title.localeCompare(a.title));
|
||||||
|
|||||||
@@ -31,10 +31,17 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul x-cloak>
|
<ul x-cloak>
|
||||||
<template x-for="bookmark in $store.digimarks.filteredItems" :key="bookmark.id">
|
<template x-for="bookmark in $store.digimarks.filteredBookmarks" :key="bookmark.id">
|
||||||
<li><a x-text="bookmark.title" x-bind:href="bookmark.url" target="_blank"></a></li>
|
<li><a x-text="bookmark.title" x-bind:href="bookmark.url" target="_blank"></a></li>
|
||||||
</template>
|
</template>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
<h2>tags</h2>
|
||||||
|
<ul x-cloak>
|
||||||
|
<template x-for="tag in $store.digimarks.filteredTags" :key="tag">
|
||||||
|
<li x-text="tag"></li>
|
||||||
|
</template>
|
||||||
|
</ul>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|||||||
Reference in New Issue
Block a user