Skip to content

Admin Templates

Overview

Admin templates provide the interface for managing Gold Standard Module content, settings, and users. These templates integrate with XOOPS's admin theme while providing a modern, responsive interface for content management.

Admin Template Architecture

flowchart TB
    subgraph "Admin Layout"
        A[Admin Header] --> B[Navigation Menu]
        B --> C[Main Content Area]
        C --> D[Admin Footer]
    end

    subgraph "Template Types"
        E[Dashboard]
        F[List Views]
        G[Form Views]
        H[Settings]
    end

    C --> E
    C --> F
    C --> G
    C --> H

Main Admin Templates

Admin Index/Dashboard (admin/index.tpl)

{* goldstandard_admin_index.tpl *}

<div class="goldstandard-admin-dashboard">
    {* Quick Stats *}
    <section class="dashboard-stats">
        <div class="stat-card">
            <div class="stat-icon stat-icon--articles">
                <svg><!-- article icon --></svg>
            </div>
            <div class="stat-content">
                <span class="stat-value">{$stats.total_articles}</span>
                <span class="stat-label">Total Articles</span>
            </div>
        </div>

        <div class="stat-card">
            <div class="stat-icon stat-icon--published">
                <svg><!-- check icon --></svg>
            </div>
            <div class="stat-content">
                <span class="stat-value">{$stats.published_articles}</span>
                <span class="stat-label">Published</span>
            </div>
        </div>

        <div class="stat-card">
            <div class="stat-icon stat-icon--draft">
                <svg><!-- draft icon --></svg>
            </div>
            <div class="stat-content">
                <span class="stat-value">{$stats.draft_articles}</span>
                <span class="stat-label">Drafts</span>
            </div>
        </div>

        <div class="stat-card">
            <div class="stat-icon stat-icon--views">
                <svg><!-- eye icon --></svg>
            </div>
            <div class="stat-content">
                <span class="stat-value">{$stats.total_views|number_format}</span>
                <span class="stat-label">Total Views</span>
            </div>
        </div>
    </section>

    {* Quick Actions *}
    <section class="quick-actions">
        <h2>Quick Actions</h2>
        <div class="action-buttons">
            <a href="{$admin_url}/article.php?op=new" class="btn btn-primary">
                <svg><!-- plus icon --></svg>
                New Article
            </a>
            <a href="{$admin_url}/category.php?op=new" class="btn btn-secondary">
                <svg><!-- folder icon --></svg>
                New Category
            </a>
            <a href="{$admin_url}/article.php?filter=pending" class="btn btn-warning">
                <svg><!-- clock icon --></svg>
                Review Pending ({$stats.pending_articles})
            </a>
        </div>
    </section>

    <div class="dashboard-grid">
        {* Recent Activity *}
        <section class="dashboard-panel recent-activity">
            <h2>Recent Activity</h2>
            <ul class="activity-list">
                {foreach $recent_activity as $activity}
                <li class="activity-item activity-item--{$activity.type}">
                    <span class="activity-icon">
                        {if $activity.type == 'published'}
                            <svg><!-- publish icon --></svg>
                        {elseif $activity.type == 'created'}
                            <svg><!-- create icon --></svg>
                        {elseif $activity.type == 'updated'}
                            <svg><!-- edit icon --></svg>
                        {/if}
                    </span>
                    <div class="activity-content">
                        <span class="activity-text">
                            <strong>{$activity.user_name|escape}</strong>
                            {$activity.action}
                            <a href="{$activity.item_url}">{$activity.item_title|escape|truncate:40}</a>
                        </span>
                        <span class="activity-time">
                            {$activity.timestamp|date_format:'%b %d, %H:%M'}
                        </span>
                    </div>
                </li>
                {foreachelse}
                <li class="activity-item activity-item--empty">
                    No recent activity
                </li>
                {/foreach}
            </ul>
        </section>

        {* Draft Articles *}
        <section class="dashboard-panel drafts-panel">
            <h2>Your Drafts</h2>
            {if $my_drafts}
            <ul class="draft-list">
                {foreach $my_drafts as $draft}
                <li class="draft-item">
                    <a href="{$admin_url}/article.php?op=edit&id={$draft.id}">
                        {$draft.title|escape|truncate:50}
                    </a>
                    <span class="draft-date">
                        {$draft.updated_at|date_format:'%b %d'}
                    </span>
                </li>
                {/foreach}
            </ul>
            {else}
            <p class="empty-message">No drafts in progress</p>
            {/if}
        </section>

        {* Popular Articles Chart *}
        <section class="dashboard-panel chart-panel">
            <h2>Views This Week</h2>
            <canvas id="viewsChart" data-values='{$chart_data|json_encode}'></canvas>
        </section>
    </div>
</div>

Article List (admin/article_list.tpl)

{* goldstandard_admin_article_list.tpl *}

<div class="goldstandard-admin-list">
    {* Page Header *}
    <header class="page-header">
        <h1>Articles</h1>
        <a href="{$admin_url}/article.php?op=new" class="btn btn-primary">
            Add New Article
        </a>
    </header>

    {* Filters & Search *}
    <div class="list-toolbar">
        <form action="" method="get" class="filter-form">
            {* Search *}
            <div class="search-box">
                <input type="search"
                       name="search"
                       value="{$search|escape}"
                       placeholder="Search articles...">
                <button type="submit" class="btn-search">
                    <svg><!-- search icon --></svg>
                </button>
            </div>

            {* Status Filter *}
            <select name="status" class="filter-select">
                <option value="">All Statuses</option>
                <option value="published" {if $filter_status == 'published'}selected{/if}>
                    Published
                </option>
                <option value="draft" {if $filter_status == 'draft'}selected{/if}>
                    Draft
                </option>
                <option value="pending" {if $filter_status == 'pending'}selected{/if}>
                    Pending Review
                </option>
                <option value="archived" {if $filter_status == 'archived'}selected{/if}>
                    Archived
                </option>
            </select>

            {* Category Filter *}
            <select name="category" class="filter-select">
                <option value="">All Categories</option>
                {foreach $categories as $cat}
                <option value="{$cat.id}" {if $filter_category == $cat.id}selected{/if}>
                    {$cat.name|escape}
                </option>
                {/foreach}
            </select>

            <button type="submit" class="btn btn-secondary">Filter</button>
            {if $search || $filter_status || $filter_category}
            <a href="{$admin_url}/article.php" class="btn btn-link">Clear</a>
            {/if}
        </form>

        {* Bulk Actions *}
        <div class="bulk-actions">
            <select name="bulk_action" id="bulk-action" class="filter-select">
                <option value="">Bulk Actions</option>
                <option value="publish">Publish</option>
                <option value="unpublish">Unpublish</option>
                <option value="archive">Archive</option>
                <option value="delete">Delete</option>
            </select>
            <button type="button" id="apply-bulk" class="btn btn-secondary">Apply</button>
        </div>
    </div>

    {* Article Table *}
    <div class="table-responsive">
        <table class="admin-table" id="articles-table">
            <thead>
                <tr>
                    <th class="col-check">
                        <input type="checkbox" id="select-all" aria-label="Select all">
                    </th>
                    <th class="col-title">
                        <a href="?sort=title&order={if $sort == 'title' && $order == 'asc'}desc{else}asc{/if}">
                            Title
                            {if $sort == 'title'}
                                <span class="sort-indicator">{if $order == 'asc'}&uarr;{else}&darr;{/if}</span>
                            {/if}
                        </a>
                    </th>
                    <th class="col-author">Author</th>
                    <th class="col-category">Category</th>
                    <th class="col-status">Status</th>
                    <th class="col-date">
                        <a href="?sort=date&order={if $sort == 'date' && $order == 'desc'}asc{else}desc{/if}">
                            Date
                            {if $sort == 'date'}
                                <span class="sort-indicator">{if $order == 'asc'}&uarr;{else}&darr;{/if}</span>
                            {/if}
                        </a>
                    </th>
                    <th class="col-views">Views</th>
                    <th class="col-actions">Actions</th>
                </tr>
            </thead>
            <tbody>
                {foreach $articles as $article}
                <tr class="article-row{if $article.status == 'draft'} row-draft{/if}">
                    <td class="col-check">
                        <input type="checkbox"
                               name="article_ids[]"
                               value="{$article.id}"
                               aria-label="Select article">
                    </td>
                    <td class="col-title">
                        <a href="{$admin_url}/article.php?op=edit&id={$article.id}"
                           class="article-title">
                            {$article.title|escape|truncate:60}
                        </a>
                        {if $article.featured}
                        <span class="badge badge-featured">Featured</span>
                        {/if}
                    </td>
                    <td class="col-author">
                        <span class="author-name">{$article.author_name|escape}</span>
                    </td>
                    <td class="col-category">
                        {if $article.categories}
                            {$article.categories[0].name|escape}
                            {if count($article.categories) > 1}
                                <span class="more-categories">+{count($article.categories) - 1}</span>
                            {/if}
                        {else}
                            <span class="no-category">—</span>
                        {/if}
                    </td>
                    <td class="col-status">
                        <span class="status-badge status-{$article.status}">
                            {$article.status|capitalize}
                        </span>
                    </td>
                    <td class="col-date">
                        {if $article.published_at}
                            {$article.published_at|date_format:'%Y-%m-%d'}
                        {else}
                            <span class="date-none">Not published</span>
                        {/if}
                    </td>
                    <td class="col-views">
                        {$article.view_count|number_format}
                    </td>
                    <td class="col-actions">
                        <div class="action-menu">
                            <a href="{$article.url}" target="_blank" title="View">
                                <svg><!-- eye icon --></svg>
                            </a>
                            <a href="{$admin_url}/article.php?op=edit&id={$article.id}" title="Edit">
                                <svg><!-- edit icon --></svg>
                            </a>
                            <a href="{$admin_url}/article.php?op=delete&id={$article.id}"
                               class="action-delete"
                               title="Delete"
                               onclick="return confirm('Delete this article?')">
                                <svg><!-- trash icon --></svg>
                            </a>
                        </div>
                    </td>
                </tr>
                {foreachelse}
                <tr>
                    <td colspan="8" class="no-results">
                        <p>No articles found.</p>
                        <a href="{$admin_url}/article.php?op=new" class="btn btn-primary">
                            Create your first article
                        </a>
                    </td>
                </tr>
                {/foreach}
            </tbody>
        </table>
    </div>

    {* Pagination *}
    {if $total_pages > 1}
    <div class="table-footer">
        <span class="showing-info">
            Showing {$start_item} - {$end_item} of {$total_items}
        </span>
        {include file='db:goldstandard_partials_pagination.tpl'
            current_page=$current_page
            total_pages=$total_pages
            base_url="{$admin_url}/article.php?{$query_string}"}
    </div>
    {/if}
</div>

Article Form (admin/article_form.tpl)

{* goldstandard_admin_article_form.tpl *}

<div class="goldstandard-admin-form">
    <form action="{$form_action}" method="post" enctype="multipart/form-data" id="article-form">
        {$xoops_token}

        <header class="form-header">
            <h1>{if $article.id}Edit Article{else}New Article{/if}</h1>
            <div class="form-actions">
                <button type="submit" name="save_draft" class="btn btn-secondary">
                    Save Draft
                </button>
                <button type="submit" name="publish" class="btn btn-primary">
                    {if $article.status == 'published'}Update{else}Publish{/if}
                </button>
            </div>
        </header>

        <div class="form-layout">
            {* Main Content Column *}
            <div class="form-main">
                {* Title *}
                <div class="form-group">
                    <label for="title">Title</label>
                    <input type="text"
                           id="title"
                           name="title"
                           value="{$article.title|escape}"
                           class="form-control form-control-lg"
                           required
                           placeholder="Enter article title">
                </div>

                {* Slug *}
                <div class="form-group">
                    <label for="slug">
                        URL Slug
                        <span class="hint">(auto-generated from title)</span>
                    </label>
                    <div class="input-group">
                        <span class="input-prefix">{$module_url}/</span>
                        <input type="text"
                               id="slug"
                               name="slug"
                               value="{$article.slug|escape}"
                               class="form-control"
                               pattern="[a-z0-9-]+"
                               placeholder="article-url-slug">
                    </div>
                </div>

                {* Content Editor *}
                <div class="form-group">
                    <label for="content">Content</label>
                    <textarea id="content"
                              name="content"
                              class="form-control editor"
                              rows="20">{$article.content|escape}</textarea>
                </div>

                {* Excerpt *}
                <div class="form-group">
                    <label for="excerpt">
                        Excerpt
                        <span class="hint">(optional - auto-generated if empty)</span>
                    </label>
                    <textarea id="excerpt"
                              name="excerpt"
                              class="form-control"
                              rows="3"
                              maxlength="500">{$article.excerpt|escape}</textarea>
                    <span class="char-count">
                        <span id="excerpt-count">{$article.excerpt|count_characters}</span>/500
                    </span>
                </div>
            </div>

            {* Sidebar *}
            <aside class="form-sidebar">
                {* Status *}
                <div class="sidebar-panel">
                    <h3>Status</h3>
                    <div class="form-group">
                        <select name="status" id="status" class="form-control">
                            <option value="draft" {if $article.status == 'draft'}selected{/if}>
                                Draft
                            </option>
                            <option value="pending" {if $article.status == 'pending'}selected{/if}>
                                Pending Review
                            </option>
                            <option value="published" {if $article.status == 'published'}selected{/if}>
                                Published
                            </option>
                            <option value="archived" {if $article.status == 'archived'}selected{/if}>
                                Archived
                            </option>
                        </select>
                    </div>

                    {if $article.status == 'published'}
                    <div class="form-group">
                        <label>Published</label>
                        <p class="form-static">
                            {$article.published_at|date_format:'%B %d, %Y at %H:%M'}
                        </p>
                    </div>
                    {/if}

                    <div class="form-group">
                        <label>
                            <input type="checkbox"
                                   name="featured"
                                   value="1"
                                   {if $article.featured}checked{/if}>
                            Featured Article
                        </label>
                    </div>
                </div>

                {* Categories *}
                <div class="sidebar-panel">
                    <h3>Categories</h3>
                    <div class="category-checklist">
                        {foreach $categories as $category}
                        <label class="checkbox-label" style="padding-left: {$category.depth * 20}px">
                            <input type="checkbox"
                                   name="category_ids[]"
                                   value="{$category.id}"
                                   {if in_array($category.id, $article.category_ids)}checked{/if}>
                            {$category.name|escape}
                        </label>
                        {/foreach}
                    </div>
                    <a href="{$admin_url}/category.php?op=new" class="add-new-link">
                        + Add New Category
                    </a>
                </div>

                {* Featured Image *}
                <div class="sidebar-panel">
                    <h3>Featured Image</h3>
                    <div class="image-upload" id="featured-image-upload">
                        {if $article.featured_image}
                        <div class="image-preview">
                            <img src="{$article.featured_image}" alt="Featured image">
                            <button type="button" class="btn-remove-image">
                                <svg><!-- x icon --></svg>
                            </button>
                        </div>
                        <input type="hidden" name="featured_image" value="{$article.featured_image}">
                        {else}
                        <div class="upload-placeholder">
                            <svg><!-- upload icon --></svg>
                            <span>Click or drag to upload</span>
                        </div>
                        {/if}
                        <input type="file"
                               name="featured_image_file"
                               accept="image/*"
                               class="file-input">
                    </div>
                    <div class="form-group">
                        <label for="featured_image_alt">Alt Text</label>
                        <input type="text"
                               id="featured_image_alt"
                               name="featured_image_alt"
                               value="{$article.featured_image_alt|escape}"
                               class="form-control">
                    </div>
                </div>

                {* Tags *}
                <div class="sidebar-panel">
                    <h3>Tags</h3>
                    <div class="tag-input-container">
                        <input type="text"
                               id="tag-input"
                               class="form-control"
                               placeholder="Add tags...">
                        <div class="tag-list" id="tag-list">
                            {foreach $article.tags as $tag}
                            <span class="tag">
                                {$tag.name|escape}
                                <button type="button" class="tag-remove">&times;</button>
                                <input type="hidden" name="tags[]" value="{$tag.name|escape}">
                            </span>
                            {/foreach}
                        </div>
                    </div>
                    <p class="hint">Separate tags with Enter</p>
                </div>

                {* SEO Settings *}
                <div class="sidebar-panel collapsible">
                    <h3>
                        SEO Settings
                        <button type="button" class="btn-collapse">
                            <svg><!-- chevron icon --></svg>
                        </button>
                    </h3>
                    <div class="panel-content">
                        <div class="form-group">
                            <label for="meta_title">Meta Title</label>
                            <input type="text"
                                   id="meta_title"
                                   name="meta_title"
                                   value="{$article.meta_title|escape}"
                                   class="form-control"
                                   maxlength="60">
                            <span class="char-count">{$article.meta_title|count_characters}/60</span>
                        </div>
                        <div class="form-group">
                            <label for="meta_description">Meta Description</label>
                            <textarea id="meta_description"
                                      name="meta_description"
                                      class="form-control"
                                      rows="3"
                                      maxlength="160">{$article.meta_description|escape}</textarea>
                            <span class="char-count">{$article.meta_description|count_characters}/160</span>
                        </div>
                    </div>
                </div>
            </aside>
        </div>

        {* Hidden Fields *}
        <input type="hidden" name="id" value="{$article.id}">
        <input type="hidden" name="op" value="{if $article.id}update{else}create{/if}">
    </form>
</div>

Settings Template (admin/settings.tpl)

{* goldstandard_admin_settings.tpl *}

<div class="goldstandard-admin-settings">
    <header class="page-header">
        <h1>Module Settings</h1>
    </header>

    <form action="{$form_action}" method="post" id="settings-form">
        {$xoops_token}

        {* Settings Navigation Tabs *}
        <div class="settings-tabs">
            <nav class="tab-nav" aria-label="Settings sections">
                <button type="button" class="tab-btn active" data-tab="general">
                    General
                </button>
                <button type="button" class="tab-btn" data-tab="content">
                    Content
                </button>
                <button type="button" class="tab-btn" data-tab="display">
                    Display
                </button>
                <button type="button" class="tab-btn" data-tab="seo">
                    SEO
                </button>
                <button type="button" class="tab-btn" data-tab="notifications">
                    Notifications
                </button>
                <button type="button" class="tab-btn" data-tab="api">
                    API
                </button>
            </nav>

            {* General Settings *}
            <div class="tab-panel active" id="panel-general">
                <h2>General Settings</h2>

                <div class="form-group">
                    <label for="module_title">Module Title</label>
                    <input type="text"
                           id="module_title"
                           name="config[module_title]"
                           value="{$config.module_title|escape}"
                           class="form-control">
                    <p class="help-text">Displayed in page titles and navigation</p>
                </div>

                <div class="form-group">
                    <label for="articles_per_page">Articles Per Page</label>
                    <input type="number"
                           id="articles_per_page"
                           name="config[articles_per_page]"
                           value="{$config.articles_per_page}"
                           class="form-control"
                           min="5"
                           max="100">
                </div>

                <div class="form-group">
                    <label for="date_format">Date Format</label>
                    <select id="date_format" name="config[date_format]" class="form-control">
                        <option value="%B %d, %Y" {if $config.date_format == '%B %d, %Y'}selected{/if}>
                            January 15, 2026
                        </option>
                        <option value="%d/%m/%Y" {if $config.date_format == '%d/%m/%Y'}selected{/if}>
                            15/01/2026
                        </option>
                        <option value="%Y-%m-%d" {if $config.date_format == '%Y-%m-%d'}selected{/if}>
                            2026-01-15
                        </option>
                    </select>
                </div>

                <div class="form-group">
                    <label>
                        <input type="checkbox"
                               name="config[enable_comments]"
                               value="1"
                               {if $config.enable_comments}checked{/if}>
                        Enable Comments
                    </label>
                </div>
            </div>

            {* Content Settings *}
            <div class="tab-panel" id="panel-content">
                <h2>Content Settings</h2>

                <div class="form-group">
                    <label for="allowed_html">Allowed HTML Tags</label>
                    <input type="text"
                           id="allowed_html"
                           name="config[allowed_html]"
                           value="{$config.allowed_html|escape}"
                           class="form-control">
                    <p class="help-text">Comma-separated list: p,a,strong,em,ul,ol,li</p>
                </div>

                <div class="form-group">
                    <label for="excerpt_length">Excerpt Length (words)</label>
                    <input type="number"
                           id="excerpt_length"
                           name="config[excerpt_length]"
                           value="{$config.excerpt_length}"
                           class="form-control"
                           min="20"
                           max="500">
                </div>

                <div class="form-group">
                    <label for="max_image_size">Max Image Size (MB)</label>
                    <input type="number"
                           id="max_image_size"
                           name="config[max_image_size]"
                           value="{$config.max_image_size}"
                           class="form-control"
                           min="1"
                           max="50">
                </div>
            </div>

            {* Additional panels... *}
        </div>

        <div class="form-actions">
            <button type="submit" class="btn btn-primary">Save Settings</button>
            <button type="reset" class="btn btn-secondary">Reset</button>
        </div>
    </form>
</div>

Admin JavaScript Integration

{* Include at bottom of admin templates *}
<script>
document.addEventListener('DOMContentLoaded', function() {
    // Bulk actions
    document.getElementById('apply-bulk')?.addEventListener('click', function() {
        const action = document.getElementById('bulk-action').value;
        if (!action) return;

        const checked = document.querySelectorAll('input[name="article_ids[]"]:checked');
        if (checked.length === 0) {
            alert('Please select at least one article');
            return;
        }

        if (action === 'delete' && !confirm('Delete selected articles?')) {
            return;
        }

        // Submit form with bulk action
        const form = document.createElement('form');
        form.method = 'POST';
        form.action = '{$admin_url}/article.php?op=bulk';

        // Add action
        const actionInput = document.createElement('input');
        actionInput.name = 'action';
        actionInput.value = action;
        form.appendChild(actionInput);

        // Add IDs
        checked.forEach(cb => {
            const input = document.createElement('input');
            input.name = 'ids[]';
            input.value = cb.value;
            form.appendChild(input);
        });

        document.body.appendChild(form);
        form.submit();
    });

    // Select all checkbox
    document.getElementById('select-all')?.addEventListener('change', function() {
        const checkboxes = document.querySelectorAll('input[name="article_ids[]"]');
        checkboxes.forEach(cb => cb.checked = this.checked);
    });
});
</script>