| 1 |
{% extends "base.html" %} |
| 2 |
|
| 3 |
{% block title %}Custom page: {{ heading }} - Makenotwork{% endblock %} |
| 4 |
|
| 5 |
{% block head %} |
| 6 |
<style> |
| 7 |
.cp-editor { max-width: 1200px; margin: 0 auto; padding: 1rem; } |
| 8 |
.cp-editor-head { display: flex; justify-content: space-between; align-items: baseline; gap: 1rem; flex-wrap: wrap; } |
| 9 |
.cp-editor-actions { display: flex; gap: 1rem; } |
| 10 |
.cp-intro { color: var(--muted, #666); margin: .25rem 0 1rem; } |
| 11 |
.cp-editor-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; align-items: start; } |
| 12 |
.cp-editor-form { display: flex; flex-direction: column; gap: .35rem; } |
| 13 |
.cp-code { width: 100%; min-height: 220px; font-family: var(--font-mono, ui-monospace, monospace); font-size: .85rem; line-height: 1.4; resize: vertical; } |
| 14 |
.cp-editor-buttons { display: flex; align-items: center; gap: 1rem; margin-top: .5rem; } |
| 15 |
.cp-preview-pane { border: 1px solid var(--detail, #ccc); border-radius: 4px; overflow: hidden; } |
| 16 |
.cp-preview-bar { font-size: .8rem; padding: .3rem .6rem; background: var(--light-background, #f2f2f2); border-bottom: 1px solid var(--detail, #ccc); } |
| 17 |
.cp-preview { width: 100%; height: 520px; border: 0; background: #fff; display: block; } |
| 18 |
.cp-blocked { margin-top: 1.25rem; } |
| 19 |
.cp-blocked-title { font-weight: 600; margin-bottom: .5rem; } |
| 20 |
.cp-blocked-empty { color: var(--muted, #666); } |
| 21 |
.cp-blocked-list { list-style: none; padding: 0; margin: 0; } |
| 22 |
.cp-blocked-list li { padding: .4rem 0; border-bottom: 1px solid var(--detail, #eee); font-size: .85rem; display: flex; gap: .5rem; flex-wrap: wrap; align-items: baseline; } |
| 23 |
.cp-blocked-kind { font-weight: 600; } |
| 24 |
.cp-blocked-loc { color: var(--muted, #666); } |
| 25 |
.cp-blocked-val { background: var(--light-background, #f2f2f2); padding: 0 .25rem; } |
| 26 |
.cp-status.cp-ok { color: var(--success, #2a7); } |
| 27 |
.cp-status.cp-err { color: var(--warning, #b00); } |
| 28 |
.cp-reset { margin-top: 1.5rem; } |
| 29 |
.cp-locked-banner { margin: .5rem 0 1rem; padding: .75rem 1rem; border: 1px solid var(--warning, #b00); border-radius: 4px; background: var(--light-background, #fbeaea); } |
| 30 |
@media (max-width: 800px) { .cp-editor-grid { grid-template-columns: 1fr; } } |
| 31 |
</style> |
| 32 |
{% endblock %} |
| 33 |
|
| 34 |
{% block content %} |
| 35 |
<div class="cp-editor"> |
| 36 |
<header class="cp-editor-head"> |
| 37 |
<h1>Custom page: {{ heading }}</h1> |
| 38 |
<nav class="cp-editor-actions"> |
| 39 |
<a href="{{ live_url }}" target="_blank" rel="noopener">View live</a> |
| 40 |
<a href="/docs/custom-pages" target="_blank" rel="noopener">Guide</a> |
| 41 |
</nav> |
| 42 |
</header> |
| 43 |
<p class="cp-intro"> |
| 44 |
Write your own HTML and CSS. No JavaScript, and every link must point to |
| 45 |
makenot.work. Anything off-platform is listed below and stripped on save. |
| 46 |
</p> |
| 47 |
|
| 48 |
{% if locked %} |
| 49 |
<div class="cp-locked-banner"> |
| 50 |
Your custom pages are locked by moderation. Editing is disabled and your |
| 51 |
pages currently show the platform default. Contact info@makenot.work. |
| 52 |
</div> |
| 53 |
{% endif %} |
| 54 |
|
| 55 |
<div class="cp-editor-grid"> |
| 56 |
<form class="cp-editor-form" hx-post="{{ base_path }}" hx-target="#cp-status" hx-swap="innerHTML"> |
| 57 |
{% if let Some(token) = csrf_token %}<input type="hidden" name="_csrf" value="{{ token }}">{% endif %} |
| 58 |
|
| 59 |
<label for="cp-html">HTML</label> |
| 60 |
<textarea id="cp-html" name="custom_html" class="cp-code" spellcheck="false" |
| 61 |
{% if locked %}disabled{% endif %} |
| 62 |
hx-post="{{ base_path }}/draft" hx-trigger="keyup changed delay:1s" |
| 63 |
hx-include="closest form" hx-target="#cp-blocked" hx-swap="outerHTML">{{ html_value }}</textarea> |
| 64 |
|
| 65 |
<label for="cp-css">CSS</label> |
| 66 |
<textarea id="cp-css" name="custom_css" class="cp-code" spellcheck="false" |
| 67 |
{% if locked %}disabled{% endif %} |
| 68 |
hx-post="{{ base_path }}/draft" hx-trigger="keyup changed delay:1s" |
| 69 |
hx-include="closest form" hx-target="#cp-blocked" hx-swap="outerHTML">{{ css_value }}</textarea> |
| 70 |
|
| 71 |
<div class="cp-editor-buttons"> |
| 72 |
<button type="submit" class="btn-primary"{% if locked %} disabled{% endif %}>Save and publish</button> |
| 73 |
<span id="cp-status" class="cp-status"></span> |
| 74 |
</div> |
| 75 |
</form> |
| 76 |
|
| 77 |
<div class="cp-preview-pane"> |
| 78 |
<div class="cp-preview-bar">Preview (updates as you type)</div> |
| 79 |
<iframe id="cp-preview" class="cp-preview" title="Live preview" src="{{ preview_url }}"></iframe> |
| 80 |
</div> |
| 81 |
</div> |
| 82 |
|
| 83 |
<section class="cp-blocked-section"> |
| 84 |
<h2 class="subsection-title">Blocked references</h2> |
| 85 |
{% include "partials/custom_page_blocked.html" %} |
| 86 |
</section> |
| 87 |
|
| 88 |
<form class="cp-reset" method="post" action="{{ base_path }}/reset" |
| 89 |
onsubmit="return confirm('Reset this page to the platform default? This clears your custom HTML and CSS.');"> |
| 90 |
{% if let Some(token) = csrf_token %}<input type="hidden" name="_csrf" value="{{ token }}">{% endif %} |
| 91 |
<button type="submit" class="btn-danger">Reset to default</button> |
| 92 |
</form> |
| 93 |
</div> |
| 94 |
{% endblock %} |
| 95 |
|