30
loading...
This website collects cookies to deliver better user experience
MultiFieldPanel
implementation (code below), note that it has a custom template and classes and that is pretty much it.
class MultiFieldPanel(BaseCompositeEditHandler):
template = "wagtailadmin/edit_handlers/multi_field_panel.html"
def classes(self):
classes = super().classes()
classes.append("multi-field")
return classes
edit_handers.py
and then a custom class that extends MultiFieldPanel
.ZenModeMultiFieldPanel
and override one attribite template
and one method classes
.templates/edit_handlers/zen_mode_multi_field_panel.html
that will include the existing "wagtailadmin/edit_handlers/multi_field_panel.html"
template.'hidden'
.classes
method, we will append one class 'zen-mode-panel'
to make it easier to target the styles to these Panels.Page
model and wrap one or more fields within this ZenModeMultiFieldPanel
, for example:
ZenModeMultiFieldPanel(
[FieldPanel("introduction", classname="full"), StreamFieldPanel("body")],
heading="Content",
),
from wagtail.admin.edit_handlers import MultiFieldPanel
class ZenModeMultiFieldPanel(MultiFieldPanel):
template = "myapp/edit_handlers/zen_mode_multi_field_panel.html"
def classes(self):
classes = super().classes()
classes.append("zen-mode-panel")
return classes
{% load wagtailadmin_tags %}
<button
class="zen-mode activate button button-small button-secondary button--icon"
>
Zen {% icon name="collapse-up" wrapped=1 %}
</button>
<button
class="zen-mode exit button button-small button-secondary button--icon hidden"
>
Exit {% icon name="collapse-down" wrapped=1 %}
</button>
{% include "wagtailadmin/edit_handlers/multi_field_panel.html" %}
Panel
in the browser and see the button + classes on the panel container.static
files are set up in Django, if this is not already in place you will need to read the docs about Managing static files.wagtail_hooks.py
file if you do not already have one within your main app.static
folder static/css/zen-mode-multi-field-panel.css
and put a basic CSS selector to position the buttons and to test the CSS is being imported.wagtail_hooks.py
file, use the insert_global_admin_css
hook to load the static CSS file.static
folder static/js/zen-mode-multi-field-panel.js
and put a basic JS initiation file with a selector logging out each Zen MultiFieldPanel
based on the classes set in the .zen-mode-panel
class.wagtail_hooks.py
file, use the insert_global_admin_js
hook to load the static JS file.insert_editor_css
& insert_editor_js
, however this means that this custom Panel will not work as desired when using it in other places (such as Snippet or ModelAdmin editing) throughout the admin..object.multi-field.zen-mode-panel .button.zen-mode {
position: absolute;
right: 4rem;
z-index: 100;
top: 0.5rem;
}
.object.multi-field.zen-mode-panel .button.zen-mode.hidden {
display: none;
}
window.addEventListener("DOMContentLoaded", () => {
document.querySelectorAll(".zen-mode-panel").forEach((panel) => {
console.log("found panel!", { panel });
});
});
from django.utils.html import format_html
from django.templatetags.static import static
from wagtail.core import hooks
@hooks.register("insert_global_admin_css")
def global_admin_zen_mode_multi_field_panel_css():
return format_html(
'<link rel="stylesheet" href="{}">',
static("css/zen-mode-multi-field-panel.css"),
)
@hooks.register("insert_global_admin_js")
def global_adminzen_mode_multi_field_panel__js():
return format_html(
'<script src="{}"></script>',
static("js/zen-mode-multi-field-panel.js"),
)
document.querySelectorAll(".zen-mode-panel").forEach(...
to find ALL of the zen-mode-panel (this means we can support multiple of these throughout the editor if needed).panel
we will find that panel's activate and exit buttons and set them to a variable activateButton
and exitButton
.requestFullscreen
exists on the panel
element, if it does not we add the class 'hidden'
to the activateButton
and return so that the button is hidden and no fulscreen activation actions can take place.activateButton
's onClick
event that will requestFullscreen
on the panel
, it also needs to call event.preventDefault()
so that the form does not submit.exitButton
's onClick
event that will exitFullscreen
on the document
(important, not the panel). It also needs to call event.preventDefault()
so that the form does not submit.fullscreen-active
to the panel container and also switch the visibility of the activate/exit button.onfullscreenchange
on the panel
is that it simplifies the overall logic, avoids content from getting out of sync and means the built-in browser handling of esc
press will work without issues.window.addEventListener("DOMContentLoaded", () => {
const FULLSCREEN_ACTIVE = "fullscreen-active";
const HIDDEN = "hidden";
document.querySelectorAll(".zen-mode-panel").forEach((panel) => {
const activateButton = panel.querySelector(".zen-mode.activate");
const exitButton = panel.querySelector(".zen-mode.exit");
// ---- Hide button & return early if fullscreen is not supported ---- //
if (!panel.requestFullscreen) {
return activateButton.classList.toggle(HIDDEN);
}
// ---- Add button event listeners ---- //
activateButton.onclick = (event) => {
event.preventDefault(); // ensure the button does not submit the form
panel.requestFullscreen();
};
exitButton.onclick = (event) => {
event.preventDefault(); // ensure the button does not submit the form
document.exitFullscreen();
};
// ---- Add fullscreen event listener ---- //
panel.onfullscreenchange = (event) => {
panel.classList.toggle(FULLSCREEN_ACTIVE);
activateButton.classList.toggle(HIDDEN);
exitButton.classList.toggle(HIDDEN);
};
});
});
fullscreen-active
and a background-color
.StreamFields
). We set a max-width
none so content goes to full width, a max-height
and overflow-scroll
so that content scrolls and then some padding..object.multi-field.zen-mode-panel .button.zen-mode {
position: absolute;
right: 4rem;
z-index: 100;
top: 0.5rem;
}
.object.multi-field.zen-mode-panel .button.zen-mode.hidden {
display: none;
}
.object.multi-field.zen-mode-panel.fullscreen-active {
background-color: white;
}
.object.multi-field.zen-mode-panel.fullscreen-active fieldset {
/* ensure that scrolling within content still works */
max-width: none;
max-height: calc(100vh - 6rem);
overflow: scroll;
padding-right: 1rem;
padding-bottom: 2rem;
}
ZenModeMultiFieldPanel
is available.