BTHLABS-66: Prepping for public release: Take four

Apple gonna Apple... ;)
This commit is contained in:
2025-11-25 12:54:52 +01:00
parent 23f8296659
commit cca49f2292
13 changed files with 246 additions and 10 deletions

View File

@@ -27,7 +27,7 @@ COPY --chown=$APP_USER_UID:$APP_USER_GID packages/common/ /srv/packages/common/
COPY --chown=$APP_USER_UID:$APP_USER_GID packages/soa/ /srv/packages/soa/
RUN poetry install --only main,deployment && \
minify -i --css-precision 0 --js-precision 0 --js-version 2022 hotpocket_backend/apps/ui/static/ui/css/hotpocket-backend*.css hotpocket_backend/apps/ui/static/ui/js/hotpocket*.js && \
minify -i --css-precision 0 --js-precision 0 --js-version 2022 hotpocket_backend/apps/ui/static/ui/css/hotpocket-backend*.css hotpocket_backend/apps/ui/static/ui/js/hotpocket-backend*.js && \
./manage.py collectstatic --settings hotpocket_backend.settings.deployment.build --noinput && \
find hotpocket_backend/static/ -name "*.map*" -delete && \
rm -f hotpocket_backend/settings/deployment/build.py && \

View File

@@ -1,2 +1,3 @@
from .access_token import AccessToken # noqa: F401
from .account import AccountAdmin # noqa: F401
from .auth_key import AuthKey # noqa: F401

View File

@@ -2,16 +2,41 @@
from __future__ import annotations
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from hotpocket_backend.apps.accounts.models import AccessToken
class AccessTokenAdmin(admin.ModelAdmin):
list_display = ('pk', 'account_uuid', 'origin', 'created_at', 'is_active')
list_display = (
'pk', 'account_uuid', 'origin', 'created_at', 'render_is_active',
)
search_fields = ('pk', 'account_uuid', 'key', 'origin')
readonly_fields = (
'pk',
'account_uuid',
'key',
'origin',
'meta',
'created_at',
'deleted_at',
)
ordering = ['-created_at']
def has_change_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
@admin.display(
description=_('Is Active?'), boolean=True, ordering='-deleted_at',
)
def render_is_active(self, obj: AccessToken | None = None) -> bool | None:
if obj is None:
return None
return obj.is_active
admin.site.register(AccessToken, AccessTokenAdmin)

View File

@@ -3,15 +3,26 @@ from __future__ import annotations
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.utils.translation import gettext_lazy as _
from hotpocket_backend.apps.accounts.models import Account
class AccountAdmin(UserAdmin):
list_display = (*UserAdmin.list_display, 'is_active')
list_display = (*UserAdmin.list_display, 'render_is_active')
ordering = ['username']
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
@admin.display(
description=_('Is Active?'), boolean=True, ordering='-is_active',
)
def render_is_active(self, obj: Account | None = None) -> bool | None:
if obj is None:
return None
return obj.is_active
admin.site.register(Account, AccountAdmin)

View File

@@ -0,0 +1,41 @@
# -*- coding: utf-8 -*-
from __future__ import annotations
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from hotpocket_backend.apps.accounts.models import AuthKey
class AuthKeyAdmin(admin.ModelAdmin):
list_display = (
'pk', 'account_uuid', 'key', 'created_at', 'consumed_at', 'render_is_active',
)
search_fields = ('pk', 'account_uuid', 'key')
readonly_fields = (
'pk',
'account_uuid',
'key',
'consumed_at',
'created_at',
'deleted_at',
)
ordering = ['-created_at']
def has_change_permission(self, request, obj=None):
return False
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
@admin.display(
description=_('Is Active?'), boolean=True, ordering='-deleted_at',
)
def render_is_active(self, obj: AuthKey | None = None) -> bool | None:
if obj is None:
return None
return obj.is_active
admin.site.register(AuthKey, AuthKeyAdmin)

View File

@@ -1 +1,2 @@
from . import association # noqa: F401
from . import save # noqa: F401

View File

@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*-
from __future__ import annotations
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from hotpocket_backend.apps.saves.models import Association
class AssociationAdmin(admin.ModelAdmin):
list_display = (
'pk', 'account_uuid', 'target', 'created_at', 'render_is_active',
)
search_fields = ('pk', 'account_uuid')
fields = (
'pk',
'account_uuid',
'archived_at',
'starred_at',
'target_meta',
'target_title',
'target_description',
'created_at',
'deleted_at',
)
readonly_fields = (
'pk',
'account_uuid',
'target_meta',
'target',
'archived_at',
'starred_at',
'created_at',
'deleted_at',
)
ordering = ['-created_at']
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
@admin.display(
description=_('Is Active?'), boolean=True, ordering='-deleted_at',
)
def render_is_active(self, obj: Association | None = None) -> bool | None:
if obj is None:
return None
return obj.is_active
admin.site.register(Association, AssociationAdmin)

View File

@@ -11,6 +11,26 @@ class SaveAdmin(admin.ModelAdmin):
list_display = (
'pk', 'key', 'account_uuid', 'created_at', 'render_is_active',
)
search_fields = ('pk', 'account_uuid', 'url')
fields = (
'pk',
'account_uuid',
'key',
'url',
'title',
'description',
'last_processed_at',
'is_netloc_banned',
'created_at',
'deleted_at',
)
readonly_fields = (
'pk',
'account_uuid',
'key',
'created_at',
'deleted_at',
)
ordering = ['-created_at']
def has_delete_permission(self, request, obj=None):

View File

@@ -45,7 +45,6 @@
return null;
}
onLoad = (event) => {
console.log('HotPocketApp.onLoad()', event);
for (let pluginSpec of this.plugins) {
if (pluginSpec[1].onLoad) {
pluginSpec[1].onLoad(event);

View File

@@ -130,6 +130,56 @@
{% translate 'Log out' %}
</a>
</li>
<li class="nav-item px-3 d-flex justify-content-center">
{% spaceless %}
<a
class="btn btn-outline-info btn-sm"
href="https://apps.apple.com/pl/app/hotpocket-by-bthlabs/id6752321380"
rel="noopener noreferrer"
target="_blank"
title="{% translate 'Safari and Share extension for iOS and macOS' %}"
>
<i class="bi bi-apple"></i>
</a>
<a
class="btn btn-outline-info btn-sm ms-1"
href="https://chromewebstore.google.com/detail/save-to-hotpocket/mkmoejhhgnadmijpgkkioicjmikkkjbd"
rel="noopener noreferrer"
target="_blank"
title="{% translate 'Chrome extension' %}"
>
<i class="bi bi-browser-chrome"></i>
</a>
<a
class="btn btn-outline-info btn-sm ms-1"
href="https://addons.mozilla.org/en-GB/firefox/addon/save-to-hotpocket/"
rel="noopener noreferrer"
target="_blank"
title="{% translate 'Firefox extension' %}"
>
<i class="bi bi-browser-firefox"></i>
</a>
<a
class="btn btn-outline-info btn-sm ms-1"
data-bs-toggle="modal"
data-bs-target="#modalPWA"
href="#"
title="{% translate 'Android PWA' %}"
>
<i class="bi bi-android2"></i>
</a>
<div class="vr my-1 ms-1 opacity-75"></div>
<a
class="btn btn-outline-info btn-sm ms-1"
href="https://git.bthlabs.pl/tomekwojcik/hotpocket"
rel="noopener noreferrer"
target="_blank"
title="{% translate 'Source code repository' %}"
>
<i class="bi bi-git"></i>
</a>
{% endspaceless %}
</li>
{% else %}
<li class="nav-item">
<a class="nav-link" href="{% url 'ui.accounts.login' %}">
@@ -142,6 +192,38 @@
{% include "ui/ui/partials/uname.html" %}
</div>
</div>
{% if not request.user.is_anonymous %}
<div class="modal modal-fade" id="modalPWA" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5" id="modalPWALabel">
{% translate 'HotPocket on Android and others' %}
</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p class="mb-1">
{% blocktranslate %}
HotPocket doesn't natively support Android and other systems. However, it's a Progressive Web Application. You can install it from your browser and it'll register itself as share target.
{% endblocktranslate %}
</p>
<p class="mb-0">
{% blocktranslate %}
This is currently supported on Android and Windows 11 (when installed using Edge).
{% endblocktranslate %}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">
{% translate 'Cool' %}
</button>
</div>
</div>
</div>
</div>
{% endif %}
{% endblock %}
{% block scripts %}

View File

@@ -27,9 +27,6 @@ def page_not_found(request: HttpRequest,
exception: Exception,
template_name: str = ERROR_404_TEMPLATE_NAME,
) -> HttpResponseNotFound:
if exception:
LOGGER.error('Exception: %s', exception, exc_info=exception)
return HttpResponseNotFound(render_to_string(
'ui/errors/page_not_found.html',
context={},

File diff suppressed because one or more lines are too long