Files
orion/app/templates/admin/module-info.html
Samir Boulahtit 33072057c2 feat: add module info and configuration pages to admin panel
Add dedicated pages for viewing module details and configuring module
settings. Includes routes, templates, and JS components for module
info page showing features, menu items, dependencies, and self-contained
module paths. Also adds View/Configure navigation buttons to the platform
modules list.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 22:55:12 +01:00

275 lines
17 KiB
HTML

{# app/templates/admin/module-info.html #}
{% extends "admin/base.html" %}
{% from 'shared/macros/alerts.html' import alert_dynamic, error_state, loading_state %}
{% from 'shared/macros/headers.html' import page_header %}
{% block title %}Module Details{% endblock %}
{% block alpine_data %}adminModuleInfo('{{ platform_code }}', '{{ module_code }}'){% endblock %}
{% block content %}
<!-- Header with Back Button -->
<div class="flex items-center justify-between my-6">
<div class="flex items-center">
<a :href="`/admin/platforms/${platformCode}/modules`" class="mr-4 p-2 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors">
<span x-html="$icon('arrow-left', 'w-5 h-5 text-gray-600 dark:text-gray-400')"></span>
</a>
<div>
<div class="flex items-center">
<span x-html="$icon(getModuleIcon(moduleCode), 'w-8 h-8 text-purple-600 dark:text-purple-400 mr-3')"></span>
<h2 class="text-2xl font-semibold text-gray-700 dark:text-gray-200" x-text="module?.name || 'Loading...'"></h2>
<code class="ml-3 text-sm bg-gray-100 dark:bg-gray-700 px-2 py-1 rounded" x-text="moduleCode"></code>
</div>
<p class="text-sm text-gray-600 dark:text-gray-400 mt-1" x-text="module?.description || ''"></p>
</div>
</div>
<div class="flex items-center gap-3">
<!-- Configure Button -->
<a x-show="hasConfig(moduleCode)"
:href="`/admin/platforms/${platformCode}/modules/${moduleCode}/config`"
class="inline-flex items-center px-4 py-2 text-sm font-medium text-white bg-purple-600 rounded-lg hover:bg-purple-700 focus:outline-none focus:ring focus:ring-purple-400">
<span x-html="$icon('cog', 'w-4 h-4 mr-2')"></span>
Configure
</a>
<!-- Status Badge & Toggle -->
<div class="flex items-center gap-3">
<span x-show="module?.is_enabled"
class="px-3 py-1 text-xs font-semibold rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">
Enabled
</span>
<span x-show="!module?.is_enabled && !module?.is_core"
class="px-3 py-1 text-xs font-semibold rounded-full bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400">
Disabled
</span>
<span x-show="module?.is_core"
class="px-3 py-1 text-xs font-semibold rounded-full bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200">
Core
</span>
<!-- Toggle (only for non-core modules) -->
<button
x-show="!module?.is_core"
@click="toggleModule()"
:disabled="saving"
:class="{
'bg-purple-600': module?.is_enabled,
'bg-gray-200 dark:bg-gray-600': !module?.is_enabled
}"
class="relative inline-flex h-6 w-11 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none focus:ring-2 focus:ring-purple-500 focus:ring-offset-2"
role="switch"
:aria-checked="module?.is_enabled"
>
<span
:class="{
'translate-x-5': module?.is_enabled,
'translate-x-0': !module?.is_enabled
}"
class="pointer-events-none inline-block h-5 w-5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out"
></span>
</button>
</div>
</div>
</div>
{{ alert_dynamic(type='success', title='Success', message_var='successMessage', show_condition='successMessage') }}
{{ error_state('Error', show_condition='error') }}
{{ loading_state('Loading module details...') }}
<!-- Main Content -->
<div x-show="!loading && module" class="space-y-6">
<!-- Description Card -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-3">Description</h3>
<p class="text-gray-600 dark:text-gray-400" x-text="module?.description || 'No description available.'"></p>
</div>
<!-- Features -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Features</h3>
<div x-show="module?.features?.length > 0" class="flex flex-wrap gap-2">
<template x-for="feature in module?.features" :key="feature">
<span class="px-3 py-1 text-sm rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300" x-text="feature"></span>
</template>
</div>
<p x-show="!module?.features?.length" class="text-gray-500 dark:text-gray-400 text-sm">No features defined for this module.</p>
</div>
<!-- Menu Items -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Admin Menu Items -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
<span x-html="$icon('office-building', 'w-5 h-5 inline mr-2 text-purple-600 dark:text-purple-400')"></span>
Admin Menu Items
</h3>
<div x-show="module?.admin_menu_items?.length > 0" class="space-y-2">
<template x-for="item in module?.admin_menu_items" :key="item">
<div class="flex items-center p-2 bg-gray-50 dark:bg-gray-700/50 rounded">
<span x-html="$icon('menu-alt-2', 'w-4 h-4 text-gray-500 mr-2')"></span>
<span class="text-sm text-gray-700 dark:text-gray-300" x-text="item"></span>
</div>
</template>
</div>
<p x-show="!module?.admin_menu_items?.length" class="text-gray-500 dark:text-gray-400 text-sm">No admin menu items.</p>
</div>
<!-- Vendor Menu Items -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
<span x-html="$icon('building-storefront', 'w-5 h-5 inline mr-2 text-teal-600 dark:text-teal-400')"></span>
Vendor Menu Items
</h3>
<div x-show="module?.vendor_menu_items?.length > 0" class="space-y-2">
<template x-for="item in module?.vendor_menu_items" :key="item">
<div class="flex items-center p-2 bg-gray-50 dark:bg-gray-700/50 rounded">
<span x-html="$icon('menu-alt-2', 'w-4 h-4 text-gray-500 mr-2')"></span>
<span class="text-sm text-gray-700 dark:text-gray-300" x-text="item"></span>
</div>
</template>
</div>
<p x-show="!module?.vendor_menu_items?.length" class="text-gray-500 dark:text-gray-400 text-sm">No vendor menu items.</p>
</div>
</div>
<!-- Dependencies -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Requires (Dependencies) -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
<span x-html="$icon('link', 'w-5 h-5 inline mr-2 text-amber-600 dark:text-amber-400')"></span>
Dependencies
<span class="text-xs font-normal text-gray-500 dark:text-gray-400 ml-2">(requires)</span>
</h3>
<div x-show="module?.requires?.length > 0" class="flex flex-wrap gap-2">
<template x-for="dep in module?.requires" :key="dep">
<a :href="`/admin/platforms/${platformCode}/modules/${dep}`"
class="px-3 py-1 text-sm rounded-full bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-300 hover:bg-amber-200 dark:hover:bg-amber-900/50 transition-colors"
x-text="dep"></a>
</template>
</div>
<p x-show="!module?.requires?.length" class="text-gray-500 dark:text-gray-400 text-sm">No dependencies.</p>
</div>
<!-- Dependents (Required By) -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
<span x-html="$icon('users', 'w-5 h-5 inline mr-2 text-blue-600 dark:text-blue-400')"></span>
Dependents
<span class="text-xs font-normal text-gray-500 dark:text-gray-400 ml-2">(required by)</span>
</h3>
<div x-show="module?.dependent_modules?.length > 0" class="flex flex-wrap gap-2">
<template x-for="dep in module?.dependent_modules" :key="dep">
<a :href="`/admin/platforms/${platformCode}/modules/${dep}`"
class="px-3 py-1 text-sm rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-300 hover:bg-blue-200 dark:hover:bg-blue-900/50 transition-colors"
x-text="dep"></a>
</template>
</div>
<p x-show="!module?.dependent_modules?.length" class="text-gray-500 dark:text-gray-400 text-sm">No modules depend on this one.</p>
</div>
</div>
<!-- Self-Contained Module Info (if applicable) -->
<div x-show="module?.is_self_contained" class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">
<span x-html="$icon('puzzle', 'w-5 h-5 inline mr-2 text-green-600 dark:text-green-400')"></span>
Self-Contained Module
</h3>
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<!-- Services -->
<div class="flex items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<span x-show="module?.self_contained_info?.services_path" x-html="$icon('check-circle', 'w-5 h-5 text-green-500 mr-3')"></span>
<span x-show="!module?.self_contained_info?.services_path" x-html="$icon('x-circle', 'w-5 h-5 text-gray-400 mr-3')"></span>
<div>
<p class="text-sm font-medium text-gray-700 dark:text-gray-300">Services</p>
<code x-show="module?.self_contained_info?.services_path" class="text-xs text-gray-500 dark:text-gray-400" x-text="module?.self_contained_info?.services_path"></code>
<p x-show="!module?.self_contained_info?.services_path" class="text-xs text-gray-400">Not defined</p>
</div>
</div>
<!-- Models -->
<div class="flex items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<span x-show="module?.self_contained_info?.models_path" x-html="$icon('check-circle', 'w-5 h-5 text-green-500 mr-3')"></span>
<span x-show="!module?.self_contained_info?.models_path" x-html="$icon('x-circle', 'w-5 h-5 text-gray-400 mr-3')"></span>
<div>
<p class="text-sm font-medium text-gray-700 dark:text-gray-300">Models</p>
<code x-show="module?.self_contained_info?.models_path" class="text-xs text-gray-500 dark:text-gray-400" x-text="module?.self_contained_info?.models_path"></code>
<p x-show="!module?.self_contained_info?.models_path" class="text-xs text-gray-400">Not defined</p>
</div>
</div>
<!-- Templates -->
<div class="flex items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<span x-show="module?.self_contained_info?.templates_path" x-html="$icon('check-circle', 'w-5 h-5 text-green-500 mr-3')"></span>
<span x-show="!module?.self_contained_info?.templates_path" x-html="$icon('x-circle', 'w-5 h-5 text-gray-400 mr-3')"></span>
<div>
<p class="text-sm font-medium text-gray-700 dark:text-gray-300">Templates</p>
<code x-show="module?.self_contained_info?.templates_path" class="text-xs text-gray-500 dark:text-gray-400" x-text="module?.self_contained_info?.templates_path"></code>
<p x-show="!module?.self_contained_info?.templates_path" class="text-xs text-gray-400">Not defined</p>
</div>
</div>
<!-- Locales -->
<div class="flex items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<span x-show="module?.self_contained_info?.locales_path" x-html="$icon('check-circle', 'w-5 h-5 text-green-500 mr-3')"></span>
<span x-show="!module?.self_contained_info?.locales_path" x-html="$icon('x-circle', 'w-5 h-5 text-gray-400 mr-3')"></span>
<div>
<p class="text-sm font-medium text-gray-700 dark:text-gray-300">Locales</p>
<code x-show="module?.self_contained_info?.locales_path" class="text-xs text-gray-500 dark:text-gray-400" x-text="module?.self_contained_info?.locales_path"></code>
<p x-show="!module?.self_contained_info?.locales_path" class="text-xs text-gray-400">Not defined</p>
</div>
</div>
<!-- Static Files -->
<div class="flex items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<span x-show="module?.self_contained_info?.static_path" x-html="$icon('check-circle', 'w-5 h-5 text-green-500 mr-3')"></span>
<span x-show="!module?.self_contained_info?.static_path" x-html="$icon('x-circle', 'w-5 h-5 text-gray-400 mr-3')"></span>
<div>
<p class="text-sm font-medium text-gray-700 dark:text-gray-300">Static Files</p>
<code x-show="module?.self_contained_info?.static_path" class="text-xs text-gray-500 dark:text-gray-400" x-text="module?.self_contained_info?.static_path"></code>
<p x-show="!module?.self_contained_info?.static_path" class="text-xs text-gray-400">Not defined</p>
</div>
</div>
<!-- API Routes -->
<div class="flex items-center p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
<span x-show="module?.self_contained_info?.api_path" x-html="$icon('check-circle', 'w-5 h-5 text-green-500 mr-3')"></span>
<span x-show="!module?.self_contained_info?.api_path" x-html="$icon('x-circle', 'w-5 h-5 text-gray-400 mr-3')"></span>
<div>
<p class="text-sm font-medium text-gray-700 dark:text-gray-300">API Routes</p>
<code x-show="module?.self_contained_info?.api_path" class="text-xs text-gray-500 dark:text-gray-400" x-text="module?.self_contained_info?.api_path"></code>
<p x-show="!module?.self_contained_info?.api_path" class="text-xs text-gray-400">Not defined</p>
</div>
</div>
</div>
</div>
<!-- Module Type Info -->
<div class="bg-white dark:bg-gray-800 rounded-lg shadow-md p-6">
<h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Module Information</h3>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="flex justify-between items-center py-2 border-b border-gray-200 dark:border-gray-700">
<span class="text-gray-600 dark:text-gray-400">Module Type</span>
<span x-show="module?.is_core" class="px-2 py-1 text-xs font-medium rounded-full bg-purple-100 text-purple-800 dark:bg-purple-900 dark:text-purple-200">Core</span>
<span x-show="!module?.is_core" class="px-2 py-1 text-xs font-medium rounded-full bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400">Optional</span>
</div>
<div class="flex justify-between items-center py-2 border-b border-gray-200 dark:border-gray-700">
<span class="text-gray-600 dark:text-gray-400">Self-Contained</span>
<span x-show="module?.is_self_contained" class="px-2 py-1 text-xs font-medium rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200">Yes</span>
<span x-show="!module?.is_self_contained" class="px-2 py-1 text-xs font-medium rounded-full bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400">No</span>
</div>
<div class="flex justify-between items-center py-2 border-b border-gray-200 dark:border-gray-700">
<span class="text-gray-600 dark:text-gray-400">Has Configuration</span>
<span x-show="hasConfig(moduleCode)" class="px-2 py-1 text-xs font-medium rounded-full bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200">Yes</span>
<span x-show="!hasConfig(moduleCode)" class="px-2 py-1 text-xs font-medium rounded-full bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400">No</span>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_scripts %}
<script src="{{ url_for('static', path='admin/js/module-info.js') }}"></script>
{% endblock %}