feat: add "Publish Live" button to bypass debug mode per post
Some checks are pending
NordaBiz Tests / Unit & Integration Tests (push) Waiting to run
NordaBiz Tests / E2E Tests (Playwright) (push) Blocked by required conditions
NordaBiz Tests / Smoke Tests (Production) (push) Blocked by required conditions
NordaBiz Tests / Send Failure Notification (push) Blocked by required conditions

- New force_live parameter in publish_post() overrides config.debug_mode
- Red "Publikuj na żywo" button with confirmation dialog
- Visible when company has debug_mode enabled
- Works for new posts, drafts, and re-publishing debug-published posts
- "Publikuj teraz" shows "(debug)" label when in debug mode

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Maciej Pienczyn 2026-02-19 10:28:22 +01:00
parent 5a1f35a668
commit 5950a55416
3 changed files with 44 additions and 13 deletions

View File

@ -163,8 +163,9 @@ def social_publisher_new():
user_id=current_user.id, user_id=current_user.id,
) )
if action == 'publish': if action in ('publish', 'publish_live'):
success, message = social_publisher.publish_post(post.id) force_live = (action == 'publish_live')
success, message = social_publisher.publish_post(post.id, force_live=force_live)
flash(message, 'success' if success else 'danger') flash(message, 'success' if success else 'danger')
else: else:
flash('Post utworzony (szkic).', 'success') flash('Post utworzony (szkic).', 'success')
@ -214,8 +215,9 @@ def social_publisher_edit(post_id):
'success' if result else 'danger') 'success' if result else 'danger')
return redirect(url_for('admin.social_publisher_edit', post_id=post_id)) return redirect(url_for('admin.social_publisher_edit', post_id=post_id))
if action == 'publish': if action in ('publish', 'publish_live'):
success, message = social_publisher.publish_post(post_id) force_live = (action == 'publish_live')
success, message = social_publisher.publish_post(post_id, force_live=force_live)
flash(message, 'success' if success else 'danger') flash(message, 'success' if success else 'danger')
return redirect(url_for('admin.social_publisher_edit', post_id=post_id)) return redirect(url_for('admin.social_publisher_edit', post_id=post_id))

View File

@ -410,9 +410,13 @@ class SocialPublisherService:
return None, None return None, None
def publish_post(self, post_id: int) -> Tuple[bool, str]: def publish_post(self, post_id: int, force_live: bool = False) -> Tuple[bool, str]:
"""Publish a post to Facebook immediately. """Publish a post to Facebook immediately.
Args:
post_id: ID of the post to publish
force_live: If True, publish publicly even if config has debug_mode=True
Returns: Returns:
(success: bool, message: str) (success: bool, message: str)
""" """
@ -421,7 +425,10 @@ class SocialPublisherService:
post = db.query(SocialPost).filter(SocialPost.id == post_id).first() post = db.query(SocialPost).filter(SocialPost.id == post_id).first()
if not post: if not post:
return False, "Post nie znaleziony" return False, "Post nie znaleziony"
if post.status not in ('draft', 'approved', 'scheduled'): allowed = ('draft', 'approved', 'scheduled')
if force_live:
allowed = ('draft', 'approved', 'scheduled', 'published')
if post.status not in allowed:
return False, f"Nie można opublikować posta ze statusem: {post.status}" return False, f"Nie można opublikować posta ze statusem: {post.status}"
# Determine which company's FB page to publish on # Determine which company's FB page to publish on
@ -448,8 +455,8 @@ class SocialPublisherService:
if post.hashtags: if post.hashtags:
message += f"\n\n{post.hashtags}" message += f"\n\n{post.hashtags}"
# Determine if draft mode # Determine if draft mode (force_live overrides debug)
published = not config.debug_mode published = True if force_live else (not config.debug_mode)
# Publish via Facebook Graph API # Publish via Facebook Graph API
from facebook_graph_service import FacebookGraphService from facebook_graph_service import FacebookGraphService
@ -477,7 +484,7 @@ class SocialPublisherService:
post.updated_at = datetime.now() post.updated_at = datetime.now()
db.commit() db.commit()
mode = "DRAFT (debug)" if config.debug_mode else "LIVE" mode = "LIVE (force)" if force_live else ("DRAFT (debug)" if config.debug_mode else "LIVE")
logger.info(f"Published post #{post_id} -> FB {result['id']} ({mode})") logger.info(f"Published post #{post_id} -> FB {result['id']} ({mode})")
return True, f"Post opublikowany ({mode}): {result['id']}" return True, f"Post opublikowany ({mode}): {result['id']}"
else: else:

View File

@ -362,21 +362,43 @@
<div class="btn-group"> <div class="btn-group">
<a href="{{ url_for('admin.social_publisher_list') }}" class="btn btn-secondary">Anuluj</a> <a href="{{ url_for('admin.social_publisher_list') }}" class="btn btn-secondary">Anuluj</a>
{% set is_debug = configured_companies and configured_companies|selectattr('debug_mode')|list|length > 0 %}
{% if post %} {% if post %}
<button type="submit" name="action" value="save" class="btn btn-primary">Zapisz zmiany</button> <button type="submit" name="action" value="save" class="btn btn-primary">Zapisz zmiany</button>
{% if post.status == 'draft' %} {% if post.status == 'draft' %}
<button type="submit" name="action" value="approve" class="btn btn-info" style="background: #0ea5e9; color: white; border: none;">Zatwierdź</button> <button type="submit" name="action" value="approve" class="btn btn-info" style="background: #0ea5e9; color: white; border: none;">Zatwierdz</button>
{% endif %} {% endif %}
{% if post.status in ['draft', 'approved'] %} {% if post.status in ['draft', 'approved'] %}
<button type="submit" name="action" value="publish" class="btn btn-success">Publikuj teraz</button> <button type="submit" name="action" value="publish" class="btn btn-success">Publikuj teraz{% if is_debug %} (debug){% endif %}</button>
{% if is_debug %}
<button type="submit" name="action" value="publish_live" class="btn btn-success"
style="background: #dc2626; border: none;"
onclick="return confirm('Post zostanie opublikowany PUBLICZNIE i bedzie widoczny dla wszystkich. Kontynuowac?');">
Publikuj na zywo
</button>
{% endif %}
{% endif %}
{% if post.status == 'published' and is_debug %}
<button type="submit" name="action" value="publish_live" class="btn btn-success"
style="background: #dc2626; border: none;"
onclick="return confirm('Post zostanie ponownie opublikowany PUBLICZNIE. Kontynuowac?');">
Opublikuj publicznie
</button>
{% endif %} {% endif %}
{% if post.status != 'published' %} {% if post.status != 'published' %}
<button type="submit" name="action" value="delete" class="btn btn-error" <button type="submit" name="action" value="delete" class="btn btn-error"
onclick="return confirm('Czy na pewno chcesz usunąć ten post?');">Usuń</button> onclick="return confirm('Czy na pewno chcesz usunac ten post?');">Usun</button>
{% endif %} {% endif %}
{% else %} {% else %}
<button type="submit" name="action" value="draft" class="btn btn-secondary">Zapisz szkic</button> <button type="submit" name="action" value="draft" class="btn btn-secondary">Zapisz szkic</button>
<button type="submit" name="action" value="publish" class="btn btn-success">Publikuj teraz</button> <button type="submit" name="action" value="publish" class="btn btn-success">Publikuj teraz{% if is_debug %} (debug){% endif %}</button>
{% if is_debug %}
<button type="submit" name="action" value="publish_live" class="btn btn-success"
style="background: #dc2626; border: none;"
onclick="return confirm('Post zostanie opublikowany PUBLICZNIE i bedzie widoczny dla wszystkich. Kontynuowac?');">
Publikuj na zywo
</button>
{% endif %}
{% endif %} {% endif %}
</div> </div>
</form> </form>