Browse Source

quiet logging and increase contrast

change jumble link for magazine link to an alexandria link
redo the fallback banner
bug-fixes
gitcitadel
Silberengel 2 weeks ago
parent
commit
4767acd28d
  1. 6
      Dockerfile
  2. 78
      assets/controllers/magazine_hierarchy_editor_controller.js
  3. 3
      assets/controllers/progress_bar_controller.js
  4. 102
      assets/styles/app.css
  5. 7
      assets/styles/article.css
  6. 2
      assets/styles/form.css
  7. 9
      assets/styles/layout.css
  8. 15
      assets/styles/magazine-editor.css
  9. 2
      assets/styles/nostr-previews.css
  10. 3
      config/packages/monolog.yaml
  11. 3
      config/unfold.yaml
  12. 2
      src/Service/CacheService.php
  13. 2
      src/Service/NostrRelayFanoutTransport.php
  14. 14
      src/Service/NostrRelayQuery.php
  15. 4
      templates/components/Header.html.twig
  16. 19
      templates/pages/magazine_edit.html.twig

6
Dockerfile

@ -107,13 +107,15 @@ RUN set -eux; \ @@ -107,13 +107,15 @@ RUN set -eux; \
composer dump-autoload --classmap-authoritative --no-dev; \
composer dump-env prod; \
rm -f .env; \
composer run-script --no-dev post-install-cmd; \
php bin/console asset-map:compile --no-debug; \
# Strip deployment secrets from the compiled .env.local.php so they cannot be read from the
# image layers. The listed keys must be injected as real environment variables at runtime;
# Symfony will raise a clear error rather than silently using the public .env.dist defaults.
# Done LAST: cache:clear and asset-map:compile both boot the Symfony kernel and need the env
# vars resolved; stripping before them causes "Environment variable not found" errors.
# MAINTENANCE: if a new secret is added to .env.dist, add it here too so it is not
# compiled into the image. Use array_diff_key so the strip is explicit and order-independent;
# missing keys are safely ignored (they were never compiled in and therefore never a risk).
php -r '$strip=array_flip(["APP_SECRET","DATABASE_URL","MYSQL_USER","MYSQL_PASSWORD","MYSQL_ROOT_PASSWORD"]); $e=array_diff_key(include(".env.local.php"),$strip); file_put_contents(".env.local.php","<?php return ".var_export($e,true).";".PHP_EOL);' ; \
composer run-script --no-dev post-install-cmd; \
php bin/console asset-map:compile --no-debug; \
chmod +x bin/console; sync;

78
assets/controllers/magazine_hierarchy_editor_controller.js

@ -39,29 +39,30 @@ export default class MagazineHierarchyEditorController extends Controller { @@ -39,29 +39,30 @@ export default class MagazineHierarchyEditorController extends Controller {
* never reaches the panel (e.g. `stopPropagation` from another listener) or fieldset/legend
* hit-testing is odd.
*/
// Bind once: re-binding on every reconnect wraps the already-bound function, and the bound
// reference must be stable so removeEventListener in disconnect() can match it.
this._onDocClickCapture ??= this._onDocClickCapture.bind(this);
this._onPanelFocusOut ??= this._onPanelFocusOut.bind(this);
this._onDragStart ??= this._onDragStart.bind(this);
this._onDragOver ??= this._onDragOver.bind(this);
this._onDrop ??= this._onDrop.bind(this);
this._onDragEnd ??= this._onDragEnd.bind(this);
document.addEventListener('click', this._onDocClickCapture, true);
this.element.addEventListener('focusout', this._onPanelFocusOut);
this.element.addEventListener('dragstart', this._onDragStart);
this.element.addEventListener('dragover', this._onDragOver);
this.element.addEventListener('drop', this._onDrop);
this.element.addEventListener('dragend', this._onDragEnd);
// Bind once using *different* property names than the method names.
// ??= would short-circuit for same-name properties because the prototype method is
// already non-null, leaving the handler unbound (this === DOM element at call time).
this._boundDocClickCapture ??= this._onDocClickCapture.bind(this);
this._boundPanelFocusOut ??= this._onPanelFocusOut.bind(this);
this._boundDragStart ??= this._onDragStart.bind(this);
this._boundDragOver ??= this._onDragOver.bind(this);
this._boundDrop ??= this._onDrop.bind(this);
this._boundDragEnd ??= this._onDragEnd.bind(this);
document.addEventListener('click', this._boundDocClickCapture, true);
this.element.addEventListener('focusout', this._boundPanelFocusOut);
this.element.addEventListener('dragstart', this._boundDragStart);
this.element.addEventListener('dragover', this._boundDragOver);
this.element.addEventListener('drop', this._boundDrop);
this.element.addEventListener('dragend', this._boundDragEnd);
}
disconnect() {
document.removeEventListener('click', this._onDocClickCapture, true);
this.element.removeEventListener('focusout', this._onPanelFocusOut);
this.element.removeEventListener('dragstart', this._onDragStart);
this.element.removeEventListener('dragover', this._onDragOver);
this.element.removeEventListener('drop', this._onDrop);
this.element.removeEventListener('dragend', this._onDragEnd);
document.removeEventListener('click', this._boundDocClickCapture, true);
this.element.removeEventListener('focusout', this._boundPanelFocusOut);
this.element.removeEventListener('dragstart', this._boundDragStart);
this.element.removeEventListener('dragover', this._boundDragOver);
this.element.removeEventListener('drop', this._boundDrop);
this.element.removeEventListener('dragend', this._boundDragEnd);
}
/**
@ -85,6 +86,9 @@ export default class MagazineHierarchyEditorController extends Controller { @@ -85,6 +86,9 @@ export default class MagazineHierarchyEditorController extends Controller {
return;
}
const t = ev.target;
// Publish: handled here via document-capture; the button must NOT also carry a
// data-action binding or _publish() would fire twice per click.
if (t.closest('[data-mag-editor-cmd="publish"]')) {
void this._publish();
return;
@ -93,34 +97,24 @@ export default class MagazineHierarchyEditorController extends Controller { @@ -93,34 +97,24 @@ export default class MagazineHierarchyEditorController extends Controller {
this.addTopLevelCategory();
return;
}
const addSubCmd = t.closest('[data-mag-editor-cmd="add-subcategory"]');
if (addSubCmd instanceof HTMLElement) {
this.addSubcategory(ev, addSubCmd);
return;
}
const rmCatCmd = t.closest('[data-mag-editor-cmd="remove-category"]');
if (rmCatCmd instanceof HTMLElement) {
this.removeCategory(ev, rmCatCmd);
return;
}
const addArticle = t.closest('[data-mag-a-add]');
if (addArticle instanceof HTMLElement) {
this.addALine(ev, addArticle);
const addSubBtn = t.closest('[data-mag-editor-cmd="add-subcategory"]');
if (addSubBtn instanceof HTMLElement) {
this.addSubcategory(ev, addSubBtn);
return;
}
const rmArticle = t.closest('.magazine-editor__a-remove-icon');
if (rmArticle instanceof HTMLElement) {
this.removeALine(ev, rmArticle);
const rmCatBtn = t.closest('[data-mag-editor-cmd="remove-category"]');
if (rmCatBtn instanceof HTMLElement) {
this.removeCategory(ev, rmCatBtn);
return;
}
const sub = t.closest('.magazine-editor__add-sub');
if (sub instanceof HTMLElement) {
this.addSubcategory(ev, sub);
const addArticleBtn = t.closest('[data-mag-a-add]');
if (addArticleBtn instanceof HTMLElement) {
this.addALine(ev, addArticleBtn);
return;
}
const rmCat = t.closest('.magazine-editor__remove-node');
if (rmCat instanceof HTMLElement) {
this.removeCategory(ev, rmCat);
const rmArticleBtn = t.closest('.magazine-editor__a-remove-icon');
if (rmArticleBtn instanceof HTMLElement) {
this.removeALine(ev, rmArticleBtn);
return;
}
}

3
assets/controllers/progress_bar_controller.js

@ -84,6 +84,9 @@ export default class extends Controller { @@ -84,6 +84,9 @@ export default class extends Controller {
this.barTarget.style.transition = 'width 0.18s ease-out';
this.barTarget.style.width = '100%';
window.setTimeout(() => {
if (!this.hasBarTarget) {
return;
}
this.barTarget.style.transition = 'none';
this.barTarget.style.width = '0';
this.barTarget.style.removeProperty('transition');

102
assets/styles/app.css

@ -102,17 +102,37 @@ strong:not(>h2), .strong { @@ -102,17 +102,37 @@ strong:not(>h2), .strong {
a {
color: var(--color-secondary);
text-decoration: none;
/* WCAG 1.4.1: links must have a non-colour cue (underline) so they are identifiable
without relying on colour alone. UI-chrome zones (nav, buttons, cards, badges)
suppress it below. */
text-decoration: underline;
text-underline-offset: 0.18em;
}
a:hover {
color: var(--color-link-hover);
text-decoration: underline;
}
/* Cards: the whole card is the interactive element; suppress underline on heading/image links. */
.card a,
.card a:hover {
text-decoration: none;
color: var(--color-text);
cursor: pointer;
}
/* Buttons used as links. */
.btn,
a.btn,
button a {
text-decoration: none;
}
/* Tags, badges — clearly interactive chips. */
a.tag,
.tags a,
.user-badge,
.user-badge:hover {
text-decoration: none;
}
.card a:hover h2 {
@ -1089,9 +1109,9 @@ svg.icon { @@ -1089,9 +1109,9 @@ svg.icon {
padding: 0.12em 0 0.08em;
}
#site-header .header__logo-circle {
width: 40px;
height: 40px;
#site-header .header__logo-banner {
width: 100px;
height: 38px;
}
.hamburger {
@ -1104,37 +1124,26 @@ svg.icon { @@ -1104,37 +1124,26 @@ svg.icon {
}
}
/* Fixed square + overflow clips to a true circle. Logo img is out-of-flow so
global img { height: auto } cannot shrink the bitmap; object-fit fills the disc.
Slight scale crops typical padding baked into square marketing PNGs. */
.header__logo-circle {
display: inline-block;
position: relative;
width: 60px;
height: 60px;
/* Horizontal banner logo: portrait painting cropped to a wide strip that shows the
subject's face/upper body. object-position 50% 14% targets the face at the top
of the portrait; adjust the Y value if the crop drifts on a different painting. */
.header__logo-banner {
display: block;
flex-shrink: 0;
border-radius: 50%;
overflow: hidden;
box-shadow: 0 0 0 1px var(--color-border);
vertical-align: middle;
}
#site-header .header__logo-circle {
width: 48px;
/* Width drives the banner proportions; height clips into the portrait. */
width: 140px;
height: 48px;
object-fit: cover;
object-position: 50% 14%;
border-radius: 5px;
box-shadow: 0 0 0 1px var(--color-border);
/* Prevent global img { height: auto } from overriding the fixed height. */
max-width: none;
}
.header__logo-circle > img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
max-width: none;
object-fit: cover;
object-position: center;
display: block;
transform: scale(1.18);
transform-origin: center center;
#site-header .header__logo-banner {
width: 120px;
height: 44px;
}
.header__logo a:hover {
@ -1192,7 +1201,9 @@ footer p { @@ -1192,7 +1201,9 @@ footer p {
}
footer a {
color: var(--color-text-contrast);
/* --color-text-contrast is nearly invisible on the footer background; use the
dedicated footer-link token which has 4.5:1 contrast in both schemes. */
color: var(--color-footer-link);
}
/* Tags container */
@ -1335,12 +1346,13 @@ a.tag:focus-visible { @@ -1335,12 +1346,13 @@ a.tag:focus-visible {
}
.author-profile__section-type {
font-size: 0.72rem;
font-size: 0.78rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text);
opacity: 0.75;
/* Use --color-text-mid directly rather than --color-text at opacity: 0.75, which
falls below 3:1 on dark backgrounds; text-mid has 7:1 in both schemes. */
color: var(--color-text-mid);
line-height: 1.35;
padding-top: 0.15em;
}
@ -1386,12 +1398,11 @@ a.tag:focus-visible { @@ -1386,12 +1398,11 @@ a.tag:focus-visible {
}
.author-profile__identity-type {
font-size: 0.72rem;
font-size: 0.78rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text);
opacity: 0.75;
color: var(--color-text-mid);
}
.author-profile__meta-value,
@ -1459,12 +1470,11 @@ a.tag:focus-visible { @@ -1459,12 +1470,11 @@ a.tag:focus-visible {
}
.author-profile__payment-type {
font-size: 0.72rem;
font-size: 0.78rem;
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.04em;
color: var(--color-text);
opacity: 0.75;
color: var(--color-text-mid);
}
.author-profile__jumble {
@ -1722,9 +1732,9 @@ a:focus-visible { @@ -1722,9 +1732,9 @@ a:focus-visible {
font-size: clamp(0.88rem, 4.4vw, 1.12rem);
}
#site-header .header__logo-circle {
width: 36px;
height: 36px;
#site-header .header__logo-banner {
width: 88px;
height: 34px;
}
}

7
assets/styles/article.css

@ -139,9 +139,9 @@ @@ -139,9 +139,9 @@
margin: 2rem 0;
padding-top: 0.5rem;
border-top: 1px solid var(--color-border);
font-size: 0.88rem;
font-size: 1rem;
font-weight: 400;
color: color-mix(in srgb, var(--color-text-mid) 58%, var(--color-bg) 42%);
color: var(--color-text-mid);
font-family: var(--font-family), sans-serif;
}
@ -204,6 +204,7 @@ @@ -204,6 +204,7 @@
margin-left: -30px;
line-height: 1.2;
color: var(--color-secondary);
text-decoration: none;
}
.heading-permalink:hover {
@ -297,7 +298,7 @@ @@ -297,7 +298,7 @@
border-left: 2px solid color-mix(in srgb, var(--color-border) 50%, transparent);
background: color-mix(in srgb, var(--color-bg-light) 55%, transparent);
border-radius: 0 3px 3px 0;
font-size: 0.82em;
font-size: 0.9em;
line-height: 1.45;
color: var(--color-text-mid);
}

2
assets/styles/form.css

@ -29,7 +29,7 @@ input:focus, textarea:focus { @@ -29,7 +29,7 @@ input:focus, textarea:focus {
}
.help-text {
font-size: 0.8rem;
font-size: 0.875rem;
color: var(--color-text);
font-weight: lighter;
}

9
assets/styles/layout.css

@ -696,7 +696,7 @@ aside { @@ -696,7 +696,7 @@ aside {
border-radius: 0;
background: transparent;
line-height: 1.45;
font-size: 0.78rem;
font-size: 0.875rem;
transition: color 0.18s ease, background 0.18s ease;
}
@ -744,7 +744,7 @@ aside { @@ -744,7 +744,7 @@ aside {
/* Match article `bodyHtml` semantics; keep aside scale (`.user-highlight__body` is larger in-article). */
.home-aside-highlights__quote--html.user-highlight__body {
margin: 0 0 0.3rem;
font-size: 0.78rem;
font-size: 0.875rem;
line-height: 1.45;
color: inherit;
}
@ -758,7 +758,7 @@ aside { @@ -758,7 +758,7 @@ aside {
.home-aside-highlights__meta {
display: block;
font-size: 0.78rem;
font-size: 0.875rem;
font-style: normal;
font-weight: 500;
font-family: var(--font-family), system-ui, sans-serif;
@ -1067,9 +1067,8 @@ footer { @@ -1067,9 +1067,8 @@ footer {
.site-footer__syndication-hint {
margin: 0 0 0.75rem;
font-size: 0.9rem;
font-size: 1rem;
color: var(--color-text);
opacity: 0.9;
max-width: 40rem;
}

15
assets/styles/magazine-editor.css

@ -238,23 +238,21 @@ @@ -238,23 +238,21 @@
min-width: 0;
}
/* Drag handle is a <span> (not a <button>) so it does not absorb the pointer-down
that starts the parent row's HTML5 drag. cursor: grab must be set explicitly here
because .magazine-editor__panel button { cursor: pointer } no longer applies. */
.magazine-editor__a-drag-handle {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0.1rem 0.15rem;
margin: 0;
background: none;
border: none;
color: var(--color-text-mid, rgba(160, 160, 160, 0.55));
cursor: grab;
touch-action: none;
user-select: none;
line-height: 0;
font-size: 0;
text-transform: none;
font-weight: normal;
border-radius: 2px;
box-shadow: none;
}
.magazine-editor__a-drag-handle:active {
@ -265,11 +263,6 @@ @@ -265,11 +263,6 @@
color: var(--color-text, inherit);
}
.magazine-editor__a-drag-handle:focus-visible {
outline: 2px solid var(--color-focus, currentColor);
outline-offset: 2px;
}
.magazine-editor__a-drag-handle svg {
display: block;
}

2
assets/styles/nostr-previews.css

@ -70,7 +70,7 @@ @@ -70,7 +70,7 @@
}
.nostr-preview .card-text {
font-size: 0.9rem;
font-size: 1rem;
color: var(--color-text);
}

3
config/packages/monolog.yaml

@ -77,6 +77,9 @@ when@prod: @@ -77,6 +77,9 @@ when@prod:
console:
type: console
process_psr_3_messages: false
# warning+ already goes to stderr as JSON; set this to error so the console
# handler does not duplicate those lines in human-readable form.
level: error
channels: [ "!event", "!doctrine", "!deprecation" ]
deprecation:
type: stream

3
config/unfold.yaml

@ -65,3 +65,6 @@ parameters: @@ -65,3 +65,6 @@ parameters:
- title: "Decent Newsroom"
url: "https://decentnewsroom.com/mag/newsroom-magazine-on-imwald-by-laeserin"
description: "Decentralized magazine platform. View the magazine on Decent Newsroom."
- title: "Alexandria"
url: "https://next-alexandria.gitcitadel.eu/publication/naddr/naddr1qvzqqqr4tqpzphtxf40yq9jr82xdd8cqtts5szqyx5tcndvaukhsvfmduetr85ceqqnkuethwdex7mmd94kkzemp0f5kuefddahz66tdwaskcepdvfuj6mrpv4ek2unfdcycjhwp"
description: "View the magazine on Alexandria."

2
src/Service/CacheService.php

@ -169,7 +169,7 @@ final class CacheService implements HighlightAuthorMetadataProvider, ResetInterf @@ -169,7 +169,7 @@ final class CacheService implements HighlightAuthorMetadataProvider, ResetInterf
$this->requestBundlesByHex[$hex] = $this->bundleFromKind0EventRow($rowsAfterRelay[$key], $npub);
continue;
}
$this->logger->warning('Profile metadata fetch failed; using npub placeholder.', [
$this->logger->info('Profile metadata fetch failed; using npub placeholder.', [
'npub' => $npub,
]);
$this->requestBundlesByHex[$hex] = $this->placeholderMetadataBundle($npub);

2
src/Service/NostrRelayFanoutTransport.php

@ -144,7 +144,7 @@ final readonly class NostrRelayFanoutTransport @@ -144,7 +144,7 @@ final readonly class NostrRelayFanoutTransport
}
if (microtime(true) >= $deadlineAt) {
foreach ($pending as $wss => $p) {
$this->logger->warning('nostr.article_discussion.relay_worker_soft_timeout', [
$this->logger->info('nostr.article_discussion.relay_worker_soft_timeout', [
'relay' => $wss,
'soft_deadline_sec' => self::DISCUSSION_PARALLEL_SOFT_DEADLINE_SEC,
]);

14
src/Service/NostrRelayQuery.php

@ -101,7 +101,10 @@ final readonly class NostrRelayQuery @@ -101,7 +101,10 @@ final readonly class NostrRelayQuery
foreach ($relayRes as $item) {
try {
if (!\is_object($item)) {
$this->logger->warning(sprintf(
// Non-object relay responses (connection drops, bad HTTP status, etc.)
// are expected for dead or misconfigured relays; INFO keeps them out of
// the warning stream without losing them from the log file.
$this->logger->info(sprintf(
'Invalid response item from %s',
self::relayLogLabel($relayUrl)
), [
@ -123,7 +126,9 @@ final readonly class NostrRelayQuery @@ -123,7 +126,9 @@ final readonly class NostrRelayQuery
}
break;
case 'AUTH':
$this->logger->warning(sprintf(
// AUTH challenges are expected from paid/restricted relays; we do not
// support NIP-42 signing, so this is a no-op but not an error.
$this->logger->info(sprintf(
'Relay %s requires authentication',
self::relayLogLabel($relayUrl)
), [
@ -133,8 +138,11 @@ final readonly class NostrRelayQuery @@ -133,8 +138,11 @@ final readonly class NostrRelayQuery
break;
case 'ERROR':
case 'NOTICE':
// Relay-level ERROR/NOTICE messages (rate limits, dropped connections,
// etc.) are external signals; INFO keeps them observable without
// polluting the warning tier.
$msg = (string) ($item->message ?? 'No message');
$this->logger->warning(sprintf(
$this->logger->info(sprintf(
'[%s] %s: %s',
self::relayLogLabel($relayUrl),
$item->type,

4
templates/components/Header.html.twig

@ -2,9 +2,7 @@ @@ -2,9 +2,7 @@
<div class="header__logo">
<a href="/" class="header__brand">
<h1 class="brand">
<span class="header__logo-circle">
<img src="{{ asset('icons/favicon-96x96.png') }}" alt="{{ website_short_name }}" class="logo" />
</span>
<img src="{{ asset('laeserin_logo.png') }}" alt="{{ website_short_name }}" class="header__logo-banner" />
<span class="brand__title">{{ website_name }}</span>
</h1>
</a>

19
templates/pages/magazine_edit.html.twig

@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
min-width: 0;
box-sizing: border-box;
}
.card.magazine-editor [data-mag-a-row] > button.magazine-editor__a-drag-handle {
.card.magazine-editor [data-mag-a-row] > .magazine-editor__a-drag-handle {
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
@ -36,14 +36,10 @@ @@ -36,14 +36,10 @@
border: none !important;
color: var(--color-text-mid, rgba(160,160,160,0.55)) !important;
cursor: grab !important;
text-transform: none !important;
font-weight: normal !important;
font-size: 0 !important;
line-height: 0 !important;
box-shadow: none !important;
border-radius: 2px !important;
font-size: 0 !important;
}
.card.magazine-editor [data-mag-a-row] > button.magazine-editor__a-drag-handle svg {
.card.magazine-editor [data-mag-a-row] > .magazine-editor__a-drag-handle svg {
display: block;
}
.card.magazine-editor [data-mag-a-row] > button.magazine-editor__a-remove-icon {
@ -110,13 +106,13 @@ @@ -110,13 +106,13 @@
<template data-magazine-hierarchy-editor-target="aRowTemplate">
<div class="magazine-editor__a-row" data-mag-a-row draggable="true">
<button type="button" class="magazine-editor__a-drag-handle" aria-label="Drag to reorder" tabindex="-1">
<span class="magazine-editor__a-drag-handle" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16" width="10" height="16" fill="currentColor" aria-hidden="true">
<circle cx="3" cy="3" r="1.2"/><circle cx="7" cy="3" r="1.2"/>
<circle cx="3" cy="8" r="1.2"/><circle cx="7" cy="8" r="1.2"/>
<circle cx="3" cy="13" r="1.2"/><circle cx="7" cy="13" r="1.2"/>
</svg>
</button>
</span>
<div class="magazine-editor__a-line-field">
<input type="text" class="magazine-editor__input magazine-editor__input--mono magazine-editor__a-line-input" data-mag-a-line value="" spellcheck="false" autocomplete="off">
</div>
@ -260,13 +256,13 @@ @@ -260,13 +256,13 @@
<div class="magazine-editor__a-list" data-mag-a-list>
{% for coord in node.a_coordinates %}
<div class="magazine-editor__a-row" data-mag-a-row draggable="true">
<button type="button" class="magazine-editor__a-drag-handle" aria-label="Drag to reorder" tabindex="-1">
<span class="magazine-editor__a-drag-handle" aria-hidden="true">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 10 16" width="10" height="16" fill="currentColor" aria-hidden="true">
<circle cx="3" cy="3" r="1.2"/><circle cx="7" cy="3" r="1.2"/>
<circle cx="3" cy="8" r="1.2"/><circle cx="7" cy="8" r="1.2"/>
<circle cx="3" cy="13" r="1.2"/><circle cx="7" cy="13" r="1.2"/>
</svg>
</button>
</span>
<div class="magazine-editor__a-line-field">
<input type="text" class="magazine-editor__input magazine-editor__input--mono magazine-editor__a-line-input" data-mag-a-line value="{{ coord|e('html_attr') }}" spellcheck="false" autocomplete="off">
</div>
@ -301,7 +297,6 @@ @@ -301,7 +297,6 @@
class="btn btn-primary"
data-magazine-hierarchy-editor-target="publishBtn"
data-mag-editor-cmd="publish"
data-action="click->magazine-hierarchy-editor#publish"
>
Sign and publish all changed events
</button>

Loading…
Cancel
Save