{% extends "baseTemplate/index.html" %} {% load static %} {% comment %} /plugins/detail/ — one plugin. Rendered server side: the row, what it actually bound, whether the files still hash to what was installed, and its log. Everything on this page is escaped by Django's autoescaping; a plugin's author-controlled name, description and log messages are never marked safe. {% endcomment %} {% block title %}{% if missing %}Plugin not found{% else %}{{ plugin.name }}{% endif %}{% endblock %} {% block styles %} {% include "pluginHolder/_styles.html" %} {% endblock %} {% block content %} {% if missing %}

Plugin not found

No plugin named {{ slug }} is installed.

Back to plugins
{% else %}
{{ pluginJSON|json_script:"cpPluginRow" }}

{{ plugin.name }}

{{ plugin.slug }} · version {{ plugin.version }} {% if plugin.author %} · by {{ plugin.author }}{% endif %} {% if plugin.homepage %} · homepage {% endif %}

{% include "pluginHolder/_warning.html" %}
{% if plugin.loadError %} {% endif %} {% if not compatible %} {% endif %} {% if checksumState.readable and plugin.checksum and not checksumState.matches %} {% elif not checksumState.readable %} {% endif %}

State

Enabled
{% if plugin.enabled %}Yes{% else %}No{% endif %}
Loaded in this process
{% if plugin.isLoaded %}Yes{% else %}No{% endif %}
Compatibility
{{ plugin.compatibilityLabel }}
Source
{{ plugin.get_source_display }}
Installed
{{ plugin.installedAt }} {% if plugin.installedBy %}by {{ plugin.installedBy.userName }}{% endif %}
Last loaded
{{ plugin.lastLoadedAt|default:"never" }}
Directory
{{ pluginPath }}
Checksum at install
{{ plugin.checksum|default:"—" }}
Checksum now
{{ checksumState.current|default:"—" }}

Disabling detaches every hook immediately. The module stays in memory until the panel restarts — Python cannot truly unload one — but nothing will call it.

Hooks

What this plugin is bound to right now, next to what its manifest declared. A declared hook with nothing bound means register() did not attach it.

{% if liveHooks %} {% for entry in liveHooks %}
{{ entry.name }}
    {% for bound in entry.entries %}
  • {{ bound.callable }} at priority {{ bound.priority }} {% if bound.failures %} · {{ bound.failures }} failure(s) this run {% endif %}
  • {% endfor %}
{% endfor %} {% else %}

Nothing is bound in this process.

{% endif %}

Declared in the manifest

{% for hook in plugin.declaredHooks %} {{ hook }} {% empty %} No hooks declared. {% endfor %} {% if plugin.declaredPermissions %}

Permissions the author asked for

{% for perm in plugin.declaredPermissions %} {{ perm }} {% endfor %}

These are documentation, not enforcement. A plugin runs with the panel's own access regardless of what it declares here.

{% endif %} {% if plugin.description %}

Description

{{ plugin.description }}

{% endif %}

Plugin log

Every exception a hook raised, contained so the panel operation could finish. Newest first, last {{ logs|length }} entr{{ logs|length|pluralize:"y,ies" }}.

{% if logs %}
{% for entry in logs %}
[{{ entry.ts }}] {{ entry.level|upper }}: {{ entry.message }}
{% endfor %}
{% else %}

Nothing logged yet.

{% endif %}
{% endif %} {% endblock %} {% block scripts %} {% endblock %}