1
0
mirror of https://github.com/aquatix/digimarks.git synced 2025-12-06 20:55:10 +01:00

Tables, template reflowing, docstrings, better index page

This commit is contained in:
2025-06-15 22:07:02 +02:00
parent fc0c668ba1
commit 18b40ed485
11 changed files with 357 additions and 216 deletions

View File

@@ -135,6 +135,14 @@ def clean_tags(tags_list: list) -> list:
return tags_res return tags_res
def list_tags_for_bookmarks(bookmarks: list) -> list:
"""Generate a unique list of the tags from the list of bookmarks."""
tags = []
for bookmark in bookmarks:
tags += bookmark.tags_list
return clean_tags(tags)
def file_type(filename: str) -> str: def file_type(filename: str) -> str:
"""Try to determine the file type for the file in `filename`. """Try to determine the file type for the file in `filename`.
@@ -392,7 +400,7 @@ def list_bookmarks(
offset: int = 0, offset: int = 0,
limit: Annotated[int, Query(le=10000)] = 100, limit: Annotated[int, Query(le=10000)] = 100,
) -> list[Bookmark]: ) -> list[Bookmark]:
"""List all bookmarks in the database. By default gives back 100 items.""" """List all bookmarks in the database. By default 100 items are returned."""
bookmarks = session.exec( bookmarks = session.exec(
select(Bookmark) select(Bookmark)
.where(Bookmark.userkey == user_key, Bookmark.status != Visibility.DELETED) .where(Bookmark.userkey == user_key, Bookmark.status != Visibility.DELETED)
@@ -567,10 +575,7 @@ def list_tags_for_user(
) -> 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)).all()
tags = [] return list_tags_for_bookmarks(bookmarks)
for bookmark in bookmarks:
tags += bookmark.tags_list
return clean_tags(tags)
@app.get('/{user_key}', response_class=HTMLResponse) @app.get('/{user_key}', response_class=HTMLResponse)
@@ -579,6 +584,7 @@ def page_user_landing(
request: Request, request: Request,
user_key: str, user_key: str,
): ):
"""HTML page with the main view for the user."""
user = session.exec(select(User).where(User.key == user_key)).first() user = session.exec(select(User).where(User.key == user_key)).first()
if not user: if not user:
raise HTTPException(status_code=404, detail='User not found') raise HTTPException(status_code=404, detail='User not found')
@@ -588,3 +594,42 @@ def page_user_landing(
name='user_index.html', name='user_index.html',
context={'language': language, 'version': DIGIMARKS_VERSION, 'user_key': user_key}, context={'language': language, 'version': DIGIMARKS_VERSION, 'user_key': user_key},
) )
# def tags_page(userkey):
# """Overview of all tags used by user"""
# tags = get_cached_tags(userkey)
# alltags = []
# for tag in tags:
# try:
# publictag = PublicTag.get(PublicTag.userkey == userkey, PublicTag.tag == tag)
# except PublicTag.DoesNotExist:
# publictag = None
#
# total = (
# Bookmark.select()
# .where(Bookmark.userkey == userkey, Bookmark.tags.contains(tag), Bookmark.status == Bookmark.VISIBLE)
# .count()
# )
# alltags.append({'tag': tag, 'publictag': publictag, 'total': total})
# totaltags = len(alltags)
# totalbookmarks = Bookmark.select().where(Bookmark.userkey == userkey, Bookmark.status == Bookmark.VISIBLE).count()
# totalpublic = PublicTag.select().where(PublicTag.userkey == userkey).count()
# totalstarred = Bookmark.select().where(Bookmark.userkey == userkey, Bookmark.starred).count()
# totaldeleted = Bookmark.select().where(Bookmark.userkey == userkey, Bookmark.status == Bookmark.DELETED).count()
# totalnotes = Bookmark.select().where(Bookmark.userkey == userkey, Bookmark.note != '').count()
# totalhttperrorstatus = Bookmark.select().where(Bookmark.userkey == userkey, Bookmark.http_status != 200).count()
# theme = get_theme(userkey)
# return render_template(
# 'tags.html',
# tags=alltags,
# totaltags=totaltags,
# totalpublic=totalpublic,
# totalbookmarks=totalbookmarks,
# totaldeleted=totaldeleted,
# totalstarred=totalstarred,
# totalhttperrorstatus=totalhttperrorstatus,
# totalnotes=totalnotes,
# userkey=userkey,
# theme=theme,
# )

View File

@@ -1,7 +1,7 @@
/** /**
* digimarks styling * digimarks styling
* *
* Overrides on the digui styling * Overrides on and additions to the digui styling
*/ */
/* Star, error, note etc */ /* Star, error, note etc */
@@ -12,4 +12,14 @@
.star { .star {
color: #ffeb3b; color: #ffeb3b;
}
.thumbnail {
/*width: 80px;*/
width: 66;
}
.thumbnail img {
/*width: 72px;*/
width: 60px;
} }

View File

@@ -200,7 +200,7 @@ h1 {
font-size: 2em; font-size: 2em;
} }
a, a:hover, a:visited, a:active { a, a:hover, a:visited, a:active, a.button, a.button:hover, a.button:active, a.button:visited {
text-decoration: none; text-decoration: none;
} }
@@ -230,9 +230,7 @@ ol li::marker, ul li::marker {
/* Buttons */ /* Buttons */
button, input, select, textarea { button, .button, input, select, textarea {
border: var(--border-width) solid var(--border-color);
border-radius: var(--border-radius);
box-sizing: border-box; box-sizing: border-box;
color: var(--text-color-secondary); color: var(--text-color-secondary);
background-color: var(--button-color); background-color: var(--button-color);
@@ -241,7 +239,6 @@ button, input, select, textarea {
font-size: 13px; font-size: 13px;
/*line-height: 29px;*/ /*line-height: 29px;*/
/*padding: 0 10px 0 11px;*/ /*padding: 0 10px 0 11px;*/
padding: .5rem .5rem;
position: relative; position: relative;
text-align: left; text-align: left;
text-decoration: none; text-decoration: none;
@@ -251,14 +248,20 @@ button, input, select, textarea {
vertical-align: middle; vertical-align: middle;
} }
button:hover { button, .button, input, select, textarea, table {
border: var(--border-width) solid var(--border-color);
border-radius: var(--border-radius);
padding: .5rem .5rem;
}
button:hover, .button:hover {
/*background-color: #f7fafa;*/ /*background-color: #f7fafa;*/
/*background-color: #d57803;*/ /*background-color: #d57803;*/
background-color: var(--color-highlight); background-color: var(--color-highlight);
filter: brightness(80%); filter: brightness(80%);
} }
button:focus { button:focus, .button:focus {
/*border-color: #008296;*/ /*border-color: #008296;*/
/*box-shadow: rgba(213, 217, 217, .5) 0 2px 5px 0;*/ /*box-shadow: rgba(213, 217, 217, .5) 0 2px 5px 0;*/
outline: 0; outline: 0;
@@ -292,6 +295,16 @@ button:focus {
filter: brightness(80%); filter: brightness(80%);
} }
/* Table */
th {
text-align: left;
}
th, td {
padding: 0 0.3rem;
}
/* Cards */ /* Cards */
.cards { .cards {
@@ -311,14 +324,18 @@ button:focus {
[data-theme='nebula'] .card, [data-theme='nebula'] .card,
[data-theme='nebula'] button, [data-theme='nebula'] button,
[data-theme='nebula'] .button,
[data-theme='nebula'] input, [data-theme='nebula'] input,
[data-theme='nebula'] select, [data-theme='nebula'] select,
[data-theme='nebula'] textarea, [data-theme='nebula'] textarea,
[data-theme='nebula'] table,
[data-theme='nebula-dark'] .card, [data-theme='nebula-dark'] .card,
[data-theme='nebula-dark'] button, [data-theme='nebula-dark'] button,
[data-theme='nebula-dark'] .button,
[data-theme='nebula-dark'] input, [data-theme='nebula-dark'] input,
[data-theme='nebula-dark'] select, [data-theme='nebula-dark'] select,
[data-theme='nebula-dark'] textarea { [data-theme='nebula-dark'] textarea,
[data-theme='nebula-dark'] table {
box-shadow: var(--shadow-color) 0 2px 5px 0; box-shadow: var(--shadow-color) 0 2px 5px 0;
} }

View File

@@ -1,6 +1,6 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}404: Page not found{% endblock %} {% block title %}404: Page not found{% endblock %}
{% block pageheader %}404: Page not found{% endblock %} {% block page_header %}404: Page not found{% endblock %}
{% block pagecontent %} {% block page_content %}
The page you requested was not found. The page you requested was not found.
{% endblock %} {% endblock %}

View File

@@ -18,7 +18,7 @@
<script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script> <script defer src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js"></script>
</head> </head>
<body> <body>
{% block pagecontent %} {% block page_content %}
<div id="container" x-data=""> <div id="container" x-data="">

View File

@@ -1,113 +1,127 @@
{% extends "base.html" %} {% extends "base.html" %}
{% if not action %} {% if not action %}
{% set action = 'Bookmarks' %} {% set action = 'Bookmarks' %}
{% endif %} {% endif %}
{% block title %}{{ action }}{% endblock %} {% block title %}{{ action }}{% endblock %}
{% block pageheader %}{{ action }}{% endblock %} {% block page_header %}{{ action }}{% endblock %}
{% block pagecontent %} {% block page_content %}
{% if tag and not publictag %} {% if tag and not publictag %}
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<a href="{{ url_for('addpublictag', userkey=userkey, tag=tag) }}">Create public page <i class="material-icons right">tag</i></a> <a href="{{ url_for('addpublictag', userkey=userkey, tag=tag) }}">Create public page <i
</div> class="material-icons right">tag</i></a>
</div> </div>
{% endif %} </div>
{% endif %}
{% if tag and publictag %} {% if tag and publictag %}
<div class="row"> <div class="row">
<div class="col s12"><a href="{{ url_for('publictag_page', tagkey=publictag.tagkey) }}">Public link</a></div> <div class="col s12"><a href="{{ url_for('publictag_page', tagkey=publictag.tagkey) }}">Public link</a>
</div> </div>
{% endif %} </div>
{% endif %}
{% if message %} {% if message %}
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<div class="card-panel {{ theme.MESSAGE_BACKGROUND }}"> <div class="card-panel {{ theme.MESSAGE_BACKGROUND }}">
<span class="{{ theme.MESSAGE_TEXT }}"> <span class="{{ theme.MESSAGE_TEXT }}">
{{ message|safe }} {{ message|safe }}
</span> </span>
</div>
</div>
</div> </div>
{% endif %}
<div class="row">
<form action="{{ url_for('bookmarks_page', userkey=userkey) }}" name="filterForm" method="POST"
autocomplete="off">
<div class="input-field col l9 m9 s8">
<input placeholder="search text" type="text" name="filter_text" id="filter_text" class="autocomplete"
value="{{ filter_text }}" autocomplete="false"/>
</div>
<div class="input-field col l3 m3 s4">
<p class="right-align">
<button class="btn waves-effect waves-light" type="submit" name="submitBtn" title="Find"><i
class="material-icons">search</i></button>
{% if show_as and show_as == 'list' %}
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod=filtermethod, sortmethod=sortmethod, show_as=None) }}"
class="waves-effect waves-light btn" title="Show as cards"><i class="material-icons">apps</i></a>
{% else %}
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod=filtermethod, sortmethod=sortmethod, show_as='list') }}"
class="waves-effect waves-light btn" title="Show as list"><i
class="material-icons">reorder</i></a>
{% endif %}
</p>
</div>
</form>
</div> </div>
</div>
{% endif %}
<div class="row"> {% if tags %}
<form action="{{ url_for('bookmarks_page', userkey=userkey) }}" name="filterForm" method="POST" autocomplete="off"> <div class="row">
<div class="input-field col l9 m9 s8"> <div class="col s12">
<input placeholder="search text" type="text" name="filter_text" id="filter_text" class="autocomplete" value="{{ filter_text }}" autocomplete="false" /> <ul class="collapsible" data-collapsible="expandable">
<li>
<div class="collapsible-header"><i class="material-icons">label</i>Filter on
star/problem/comment/tag
</div>
<div class="collapsible-body" style="padding: 10px;">
<div class="chip">
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='starred') }}"><i
class="tiny material-icons {{ theme.STAR }}">star</i></a>
</div>
<div class="chip">
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='broken') }}"><i
class="tiny material-icons {{ theme.PROBLEM }}">report_problem</i></a>
</div>
<div class="chip">
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='note') }}"><i
class="tiny material-icons {{ theme.COMMENT }}">comment</i></a>
</div>
{% for tag in tags %}
<div class="chip">
<a href="{{ url_for('tag_page', userkey=userkey, tag=tag) }}">{{ tag }}</a>
</div>
{% endfor %}
</li>
</ul>
</div>
</div> </div>
{% endif %}
<div class="input-field col l3 m3 s4"> {% if show_as and show_as == 'list' %}
<p class="right-align"><button class="btn waves-effect waves-light" type="submit" name="submitBtn" title="Find"><i class="material-icons">search</i></button> {% include 'list.html' %}
{% if show_as and show_as == 'list' %} {% else %}
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod=filtermethod, sortmethod=sortmethod, show_as=None) }}" class="waves-effect waves-light btn" title="Show as cards"><i class="material-icons">apps</i></a> {% include 'cards.html' %}
{% else %} {% endif %}
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod=filtermethod, sortmethod=sortmethod, show_as='list') }}" class="waves-effect waves-light btn" title="Show as list"><i class="material-icons">reorder</i></a>
{% endif %}
</p>
</div>
</form>
</div>
{% if tags %} <div class="fixed-action-btn" style="bottom: 20px; right: 20px;">
<div class="row"> <a class="btn-floating btn-large {{ theme.FAB }}" href="{{ url_for('addbookmark', userkey=userkey) }}">
<div class="col s12"> <i class="large material-icons">add</i>
<ul class="collapsible" data-collapsible="expandable"> </a>
<li>
<div class="collapsible-header"><i class="material-icons">label</i>Filter on star/problem/comment/tag</div>
<div class="collapsible-body" style="padding: 10px;">
<div class="chip">
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='starred') }}"><i class="tiny material-icons {{ theme.STAR }}">star</i></a>
</div>
<div class="chip">
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='broken') }}"><i class="tiny material-icons {{ theme.PROBLEM }}">report_problem</i></a>
</div>
<div class="chip">
<a href="{{ url_for('bookmarks_page', userkey=userkey, filtermethod='note') }}"><i class="tiny material-icons {{ theme.COMMENT }}">comment</i></a>
</div>
{% for tag in tags %}
<div class="chip">
<a href="{{ url_for('tag_page', userkey=userkey, tag=tag) }}">{{ tag }}</a>
</div>
{% endfor %}
</li>
</ul>
</div> </div>
</div>
{% endif %}
{% if show_as and show_as == 'list' %}
{% include 'list.html' %}
{% else %}
{% include 'cards.html' %}
{% endif %}
<div class="fixed-action-btn" style="bottom: 20px; right: 20px;">
<a class="btn-floating btn-large {{ theme.FAB }}" href="{{ url_for('addbookmark', userkey=userkey) }}">
<i class="large material-icons">add</i>
</a>
</div>
{% endblock %} {% endblock %}
{% block extrajs %} {% block extrajs %}
<script> <script>
function submitFilter() { function submitFilter() {
document.filterForm.submit(); document.filterForm.submit();
} }
/* Search filter autocomplete */
var options = { /* Search filter autocomplete */
onAutocomplete: submitFilter, var options = {
minLength: 3, onAutocomplete: submitFilter,
limit: 10, minLength: 3,
data: { limit: 10,
}, data: {},
} }
var elem = document.querySelector('.autocomplete'); var elem = document.querySelector('.autocomplete');
var instance = M.Autocomplete.init(elem, options); var instance = M.Autocomplete.init(elem, options);
/* TODO: fetch from API /* TODO: fetch from API
instance.updateData({ instance.updateData({
}); });
*/ */
</script> </script>
<script src="{{ url_for('bookmarks_js', userkey=userkey) }}" ></script> <script src="{{ url_for('bookmarks_js', userkey=userkey) }}"></script>
{% endblock %} {% endblock %}

View File

@@ -1,11 +0,0 @@
var elem = document.querySelector('.autocomplete');
var instance = M.Autocomplete.getInstance(elem);
instance.updateData({
{% for bookmark in bookmarks %}
{% if bookmark.favicon %}
"{{ bookmark.title | replace('"', '\\"') | replace('\n', '') | replace('\r', '') }}": "{{ url_for('static', filename='favicons/' + bookmark.favicon) }}",
{% else %}
"{{ bookmark.title | replace('"', '\\"') | replace('\n', '') | replace('\r', '') }}": null,
{% endif %}
{% endfor %}
});

View File

@@ -1,17 +1,30 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}digimarks{% endblock %} {% block title %}digimarks{% endblock %}
{% block pageheader %}digimarks{% endblock %} {% block page_header %}digimarks{% endblock %}
{% block pagecontent %} {% block page_content %}
<p>Please visit your personal url, or <a href="https://github.com/aquatix/digimarks">see the digimarks project page</a>.</p> <article>
<div class="row"> <header>
<div class="col s12"> <nav class="menu">
<div class="card-panel orange lighten-2"> <ul>
<span class="black-text"> <li><h1>digimarks</h1></li>
If you forgot/lost your personal url, contact your digimarks administrator.{# On startup, the personal codes are printed to the standard output (so should be findable in a log). Of course, bookmarks.db contains the user information too.#} <li>
</span> <a class="button" href="https://github.com/aquatix/digimarks">digimarks project page</a>
</div> </li>
</div> </ul>
</div> </nav>
</header>
<main>
<h1>Welcome to digimarks, your online bookmarking and notes tool</h1>
<p>Please visit your personal url, or <a href="https://github.com/aquatix/digimarks">see the digimarks
project page</a>.</p>
<p>If you forgot/lost your personal url, contact your digimarks
administrator.{# On startup, the personal codes are printed to the standard output (so should be findable in a log). Of course, bookmarks.db contains the user information too.#}
</p>
</main>
</article>
{% endblock %} {% endblock %}

View File

@@ -1,29 +1,30 @@
{% extends "base.html" %} {% extends "base.html" %}
{% if not action %} {% if not action %}
{% set action = 'Bookmarks' %} {% set action = 'Bookmarks' %}
{% endif %} {% endif %}
{% block title %}{{ action }}{% endblock %} {% block title %}{{ action }}{% endblock %}
{% block pageheader %}{{ action }}{% endblock %} {% block page_header %}{{ action }}{% endblock %}
{% block pagecontent %} {% block page_content %}
{% if message %} {% if message %}
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<div class="card-panel orange lighten-2"> <div class="card-panel orange lighten-2">
<span class="white-text"> <span class="white-text">
{{ message }} {{ message }}
</span> </span>
</div>
</div>
</div>
{% endif %}
<div class="row">
<div class="col s12">
<a href="{{ url_for('publictag_feed', tagkey=tagkey) }}"><i class="material-icons tiny">rss_feed</i>
feed</a>
</div> </div>
</div> </div>
</div>
{% endif %}
<div class="row"> {% include 'cards.html' %}
<div class="col s12">
<a href="{{ url_for('publictag_feed', tagkey=tagkey) }}"><i class="material-icons tiny">rss_feed</i> feed</a>
</div>
</div>
{% include 'cards.html' %}
{% endblock %} {% endblock %}

View File

@@ -1,65 +1,68 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Tags{% endblock %} {% block title %}Tags{% endblock %}
{% block pageheader %}Tags{% endblock %} {% block page_header %}Tags{% endblock %}
{% block pagecontent %} {% block page_content %}
<div class="row"> <div class="row">
<div class="col s12"> <div class="col s12">
<table class="centered"> <table class="centered">
<thead> <thead>
<tr> <tr>
<th><i class="material-icons" title="Unique labels">label</i></th> <th><i class="material-icons" title="Unique labels">label</i></th>
<th><i class="material-icons green-text" title="Public tag pages">present_to_all</i></th> <th><i class="material-icons green-text" title="Public tag pages">present_to_all</i></th>
<th><i class="material-icons" title="Total bookmarks">turned_in</i></th> <th><i class="material-icons" title="Total bookmarks">turned_in</i></th>
<th><i class="material-icons" title="Bookmarks with notes">comment</i></th> <th><i class="material-icons" title="Bookmarks with notes">comment</i></th>
<th><i class="material-icons yellow-text" title="Starred bookmarks">star</i></th> <th><i class="material-icons yellow-text" title="Starred bookmarks">star</i></th>
<th><i class="material-icons orange-text" title="HTTP status is not 200 OK">warning</i></th> <th><i class="material-icons orange-text" title="HTTP status is not 200 OK">warning</i></th>
<th><i class="material-icons red-text" title="Deleted bookmarks">delete</i></th> <th><i class="material-icons red-text" title="Deleted bookmarks">delete</i></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr> <tr>
<td>{{ totaltags }}</td> <td>{{ totaltags }}</td>
<td>{{ totalpublic }}</td> <td>{{ totalpublic }}</td>
<td>{{ totalbookmarks }}</td> <td>{{ totalbookmarks }}</td>
<td>{{ totalnotes }}</td> <td>{{ totalnotes }}</td>
<td>{{ totalstarred }}</td> <td>{{ totalstarred }}</td>
<td>{{ totalhttperrorstatus }}</td> <td>{{ totalhttperrorstatus }}</td>
<td>{{ totaldeleted }}</td> <td>{{ totaldeleted }}</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<br /><br /> <br/><br/>
<table> <table>
<thead> <thead>
<tr> <tr>
<th>Tag</th> <th>Tag</th>
<th>Public link</th> <th>Public link</th>
<th>Number of bookmarks</th> <th>Number of bookmarks</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{% for tag in tags %} {% for tag in tags %}
<tr> <tr>
<td> <td>
<a href="{{ url_for('tag_page', userkey=userkey, tag=tag['tag']) }}">{{ tag['tag'] }}</a> <a href="{{ url_for('tag_page', userkey=userkey, tag=tag['tag']) }}">{{ tag['tag'] }}</a>
</td> </td>
<td> <td>
{% if tag['publictag'] %} {% if tag['publictag'] %}
<a href="{{ url_for('publictag_page', tagkey=tag['publictag'].tagkey) }}">Public link</a> (<a href="{{ url_for('removepublictag', tag=tag['tag'], tagkey=tag['publictag'].tagkey, userkey=userkey) }}">Delete</a> <i class="tiny material-icons red-text">warning</i>) <a href="{{ url_for('publictag_page', tagkey=tag['publictag'].tagkey) }}">Public
{% else %} link</a> (
<a href="{{ url_for('addpublictag', userkey=userkey, tag=tag['tag']) }}">Create</a> <a href="{{ url_for('removepublictag', tag=tag['tag'], tagkey=tag['publictag'].tagkey, userkey=userkey) }}">Delete</a>
{% endif %} <i class="tiny material-icons red-text">warning</i>)
</td> {% else %}
<td> <a href="{{ url_for('addpublictag', userkey=userkey, tag=tag['tag']) }}">Create</a>
{{ tag['total'] }} {% endif %}
</td> </td>
</tr> <td>
{% endfor %} {{ tag['total'] }}
</tbody> </td>
</table> </tr>
{% endfor %}
</tbody>
</table>
</div>
</div> </div>
</div>
{% endblock %} {% endblock %}

View File

@@ -1,7 +1,7 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}Bookmarks{% endblock %} {% block title %}Bookmarks{% endblock %}
{% block pageheader %}Bookmarks{% endblock %} {% block page_header %}Bookmarks{% endblock %}
{% block pagecontent %} {% block page_content %}
<article <article
x-init="$store.digimarks.userKey = '{{ user_key }}'; $store.digimarks.loadCache(); $store.digimarks.getBookmarks()" x-init="$store.digimarks.userKey = '{{ user_key }}'; $store.digimarks.loadCache(); $store.digimarks.getBookmarks()"
x-data=""> x-data="">
@@ -16,7 +16,7 @@
</button> </button>
</li> </li>
<li> <li>
<button @click="$store.digimarks.startAddingBookmark">add bookmark</button> <button @click="$store.digimarks.startAddingBookmark()">add bookmark</button>
</li> </li>
<li> <li>
<button @click="$store.digimarks.loopToNextTheme()" class="theme-toggle">theme</button> <button @click="$store.digimarks.loopToNextTheme()" class="theme-toggle">theme</button>
@@ -50,12 +50,48 @@
</button> </button>
</p> </p>
<table x-cloak x-show="$store.digimarks.show_bookmarks_list">
<thead>
<tr>
<th colspan="2">&nbsp;</th>
<th>Title</th>
<th>Note</th>
<th>Tags</th>
</tr>
</thead>
<tbody>
<template x-for="bookmark in $store.digimarks.filteredBookmarks" :key="bookmark.id">
<tr>
<td class="thumbnail">
<div class="card-thumb" x-show="bookmark.favicon"><img
x-bind:src="'/content/favicons/' + bookmark.favicon"></div>
</td>
<td>
<div x-show="bookmark.starred" class="star"><i class="fa-fw fa-solid fa-star"></i>
</div>
<div x-show="bookmark.http_status !== 200 && bookmark.http_status !== 304"
class="error"><i
class="fa-fw fa-solid fa-triangle-exclamation"></i>
</div>
</td>
<td><a x-text="bookmark.title" x-bind:href="bookmark.url" target="_blank"></a></td>
<td x-text="bookmark.note"></td>
<td>
<template x-for="tag in bookmark.tag_list">
<span x-text="tag" class="chip"></span>
</template>
</td>
</tr>
</template>
</tbody>
</table>
{#
<ul x-cloak x-show="$store.digimarks.show_bookmarks_list"> <ul x-cloak x-show="$store.digimarks.show_bookmarks_list">
<template x-for="bookmark in $store.digimarks.filteredBookmarks" :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>
#}
<section x-cloak x-show="$store.digimarks.show_bookmarks_cards" class="cards"> <section x-cloak x-show="$store.digimarks.show_bookmarks_cards" class="cards">
<template x-for="bookmark in $store.digimarks.filteredBookmarks" :key="bookmark.id"> <template x-for="bookmark in $store.digimarks.filteredBookmarks" :key="bookmark.id">
<div class="card"> <div class="card">
@@ -65,7 +101,7 @@
<div class="statuses"> <div class="statuses">
<div x-show="bookmark.starred" class="star"><i class="fa-fw fa-solid fa-star"></i> <div x-show="bookmark.starred" class="star"><i class="fa-fw fa-solid fa-star"></i>
</div> </div>
<div x-show="bookmark.http_status != 200 && bookmark.http_status != 304" <div x-show="bookmark.http_status !== 200 && bookmark.http_status !== 304"
class="error"><i class="error"><i
class="fa-fw fa-solid fa-triangle-exclamation"></i> class="fa-fw fa-solid fa-triangle-exclamation"></i>
</div> </div>
@@ -91,11 +127,24 @@
x-transition.opacity> x-transition.opacity>
<h1>Tags</h1> <h1>Tags</h1>
<ul> <table>
<thead>
<tr>
<th>Tag</th>
<th>Public link</th>
<th>Number of bookmarks</th>
</tr>
</thead>
<tbody>
<template x-for="tag in $store.digimarks.filteredTags" :key="tag"> <template x-for="tag in $store.digimarks.filteredTags" :key="tag">
<li x-text="tag"></li> <tr>
<td x-text="tag"></td>
<td></td>
<td></td>
</tr>
</template> </template>
</ul> </tbody>
</table>
</section> </section>
<section x-cloak x-show="$store.digimarks.bookmark_to_edit" x-transition.opacity> <section x-cloak x-show="$store.digimarks.bookmark_to_edit" x-transition.opacity>