~fabrixxm/activist

bfe933d94cfe525675b9fbb88a34b0e17dbbe9f9 — fabrixxm a month ago 3d96f93 + 0ecc8ce
Merge branch 'wip'
M activist/background.py => activist/background.py +2 -2
@@ 13,7 13,7 @@ from .config import settings
logger = logging.getLogger(__name__)


class UrecoverableBacgroundTaskException(Exception):
class UrecoverableBackgroundTaskException(Exception):
    "Raising this exception from a task cause task to fail directly without retry"
    pass



@@ 103,7 103,7 @@ class TaskType:
            self._set_state("failed")
            return
        
        if isinstance(e, UrecoverableBacgroundTaskException):
        if isinstance(e, UrecoverableBackgroundTaskException):
            logger.info("task failed and requested to be dequeued")
            self._set_state("failed")
            return

M activist/db/sqlbuilder.py => activist/db/sqlbuilder.py +7 -0
@@ 123,6 123,13 @@ class Query(QueryBase):
        for k, v in kwargs.items():
            self.tables.append(_Table(name=k, alias=v))

    def avec(self, **kwargs) -> Self:
        for k,v in kwargs.items():
            self.data['WITH'].append(f"k as ({v})")
            if isinstance(v, QueryBase):
                self.parameters += v.parameters
        return self

    def select(self, *args, **kwargs) -> Self:
        """
            SELECT

M activist/static/style.css => activist/static/style.css +54 -17
@@ 85,7 85,9 @@ dl>dd {
    text-wrap: nowrap;
}

p:last-child { margin-bottom: 0;}
p:last-child {
    margin-bottom: 0;
}

@media screen and (min-width: 600px) {
    dl.kv {


@@ 129,7 131,7 @@ p:last-child { margin-bottom: 0;}

/* search bar */
.searchbar {
	width: 100%;
    width: 100%;
}

.searchbar .input-group-btn {


@@ 178,10 180,10 @@ footer.navbar.mobile>.navbar-section>.btn:not(:first-child) {


.object-action-bar {
	display: flex;
	flex-direction: revert;
    display: flex;
    flex-direction: revert;
    align-items: center;
	gap: 0.5rem;
    gap: 0.5rem;
}

.object-activities-summary {


@@ 256,27 258,61 @@ body.article article>header>h1::after {
    overflow-y: auto;
}


/** grid - images in post */
.img-grid {
    display: grid;
    grid-template-columns: auto auto;
    grid-auto-rows: 200px;
    grid-gap: 0.2rem;
}

.img-grid-1 {
    grid-template-columns: auto;
    grid-template-rows: 400px;
}

.img-grid-2 {
    grid-template-columns: auto auto;
    grid-template-rows: 400px;
}

.img-grid-odd .img-area-2 {
    grid-row: 1 / span 2;
    grid-column: 2;
}

.img-grid>img {
    display: block;
    object-fit: cover;
    width: 100%;
    height: 100%;
    border-radius: 10px;
}


/** photos page */

.card.photo {
    position: relative;
    overflow: hidden;
}

/* keep .card.photo square https://stackoverflow.com/a/28985475 */
.card.photo::before {
	content: "";
	display: block;
	padding-top: 100%;
    content: "";
    display: block;
    padding-top: 100%;
}

.card.photo > .card-image {
	position: absolute;
	height: 100%;
	width: 100%;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
.card.photo>.card-image {
    position: absolute;
    height: 100%;
    width: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}

.card.photo>.card-header {


@@ 301,7 337,8 @@ body.article article>header>h1::after {
    align-items: start;
    padding-bottom: 0.5rem;
}
.card-body > .smaller-tile:last-child {

.card-body>.smaller-tile:last-child {
    padding-bottom: 0;
}


M activist/tasks.py => activist/tasks.py +2 -2
@@ 6,7 6,7 @@ import json
import logging
import datetime
from typing import Optional
from .background import background, UrecoverableBacgroundTaskException
from .background import background, UrecoverableBackgroundTaskException
from .consts import AS_PUBLIC, ACTORS
from .config import settings
from . import activitypub


@@ 25,7 25,7 @@ def publish(obj_id:str):
    logger.debug("publish post %r", obj_id)
    asobj = db.Object.get(obj_id)
    if asobj is None:
        raise UrecoverableBacgroundTaskException(f"Publish Task. Object not found '{obj_id}'")
        raise UrecoverableBackgroundTaskException(f"Publish Task. Object not found '{obj_id}'")
    obj = asobj.data
    recipients = []
    for prop in [ "to", "bto", "cc", "bcc", "audience" ]:

M activist/templates/f/object.tpl.j2 => activist/templates/f/object.tpl.j2 +32 -27
@@ 8,23 8,24 @@
{% set actor = obj.attributedTo %}
<div class="card">
    <div class="object-activities-summary text-tiny text-gray">
    {% if obj.inReplyTo_id %}
        <i class="icon i-message-circle-reply"></i> 
        in reply to <a href="{{ url_for('thread', uri=obj.inReplyTo_id|urlsafe )}}">{{ obj.inReplyTo.attributedTo.data|firstof('name', 'preferredUsername') }}</a><br>
    {% endif %}
    {% set firstactivity = obj.get_first_activity() %}
    {% if firstactivity %}
        <i class="{{ class(
            'icon', {
            'i-star': firstactivity.type == 'Like',
            'i-star-off': firstactivity.type == 'Dislike',
            'i-rotate-ccw-square': firstactivity.type == 'Announce',
        }) }}"></i>
        {{ firstactivity.type|pastaction(Announce = 'reshared') }} by <a href="{{ firstactivity.actor_id }}">{{ firstactivity.actor.data|firstof('name', 'preferredUsername') }}</a>
    {% endif %}

        {% if obj.inReplyTo_id %}
            <i class="icon i-message-circle-reply"></i> 
            in reply to <a href="{{ url_for('thread', uri=obj.inReplyTo_id|urlsafe )}}">{{ obj.inReplyTo.attributedTo.data|firstof('name', 'preferredUsername') }}</a><br>
        {% endif %}
        {% set firstactivity = obj.get_first_activity() %}
        {% if firstactivity %}
            <i class="{{ class(
                'icon', {
                'i-star': firstactivity.type == 'Like',
                'i-star-off': firstactivity.type == 'Dislike',
                'i-rotate-ccw-square': firstactivity.type == 'Announce',
            }) }}"></i>
            {{ firstactivity.type|pastaction(Announce = 'reshared') }} by <a href="{{ firstactivity.actor_id }}">{{ firstactivity.actor.data|firstof('name', 'preferredUsername') }}</a>
        {% endif %}
    </div>

    {% include "f/header.tpl.j2" %}

    {% if obj.data.name %}
    <div class="card-header">
        <div class="card-title h5">


@@ 33,15 34,20 @@
        </div>
    </div>
    {% endif %}

    <div class="card-body">
        {{ obj.data.content }}

        {% set attachments = obj.data.attachment %}
        {% for a in attachments  %}
            {# TODO: check type and mediaType #}
            <img src="{{ a.url }}" class="img-responsive">
        {% endfor %}
    </div>
		{% set attachments = obj.data.attachment %}
		{% set acount = attachments|count %}
		{% set isodd = acount % 2 %}
		<div class="img-grid img-grid-{{acount}} img-grid-{{ 'odd' if isodd else 'even' }}">
		{% for a in attachments  %}
			{# TODO: check type and mediaType #}
			<img src="{{ a.url }}" class="img-responsive img-area-{{ loop.index }}">
		{% endfor %}
		</div>
	</div>

    {% if obj.data.url and obj.data.mediaType and obj.data.mediaType.startswith("image/") %}
    <div class="card-image">


@@ 55,12 61,11 @@

    {% set qreplies = obj.replies() %}
    {% if replies and qreplies.count() > 0 %}
    <div class="card-body">
    {% for obj in qreplies.fetch()  %}
        {% include "f/object-small.tpl.j2" %}
    {% endfor %}
    </div>
        <div class="card-body">
        {% for obj in qreplies.fetch()  %}
            {% include "f/object-small.tpl.j2" %}
        {% endfor %}
        </div>
    {% endif %}

</div>