HEX
Server: LiteSpeed
System: Linux php-prod-1.spaceapp.ru 5.15.0-157-generic #167-Ubuntu SMP Wed Sep 17 21:35:53 UTC 2025 x86_64
User: xnsbb3110 (1041)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: //proc/self/root/usr/local/CyberCP/packages/templates/packages/listPackages.html
{% extends "baseTemplate/index.html" %}
{% load i18n %}
{% block title %}{% trans "List Packages - CyberPanel" %}{% endblock %}

{% block header_scripts %}
<style>
    /* Modern page styles matching new design */
    .page-wrapper {
        background: transparent;
        padding: 20px;
    }
    
    .page-container {
        max-width: 1400px;
        margin: 0 auto;
    }
    
    .page-header {
        margin-bottom: 30px;
    }
    
    .page-title {
        font-size: 28px;
        font-weight: 700;
        color: var(--text-primary);
        margin-bottom: 8px;
    }
    
    .page-subtitle {
        font-size: 14px;
        color: var(--text-secondary);
    }
    
    /* Card styles */
    .content-card {
        background: var(--surface-primary);
        border-radius: 12px;
        padding: 30px;
        box-shadow: 0 2px 8px var(--shadow-light);
        border: 1px solid var(--border-primary);
        margin-bottom: 25px;
    }
    
    .card-title {
        font-size: 18px;
        font-weight: 700;
        color: var(--text-primary);
        margin-bottom: 25px;
        display: flex;
        align-items: center;
        gap: 10px;
    }
    
    .card-title::before {
        content: '';
        width: 4px;
        height: 24px;
        background: var(--accent-primary);
        border-radius: 2px;
    }
    
    /* Table styles */
    .modern-table {
        width: 100%;
        background: var(--surface-primary);
        border-radius: 10px;
        overflow: hidden;
        box-shadow: 0 1px 3px var(--shadow-xs);
        border: 1px solid var(--border-primary);
    }
    
    .modern-table thead {
        background: var(--surface-secondary);
    }
    
    .modern-table th {
        padding: 16px 20px;
        font-size: 13px;
        font-weight: 600;
        color: var(--text-muted);
        text-transform: uppercase;
        letter-spacing: 0.5px;
        border-bottom: 1px solid var(--border-primary);
        text-align: left;
    }
    
    .modern-table td {
        padding: 16px 20px;
        font-size: 14px;
        color: var(--text-primary);
        border-bottom: 1px solid var(--border-light);
    }
    
    .modern-table tbody tr:last-child td {
        border-bottom: none;
    }
    
    .modern-table tbody tr:hover {
        background: var(--surface-hover);
    }
    
    /* Resource badges */
    .resource-badge {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 4px 10px;
        background: var(--surface-secondary);
        border: 1px solid var(--border-primary);
        border-radius: 6px;
        font-size: 13px;
        font-weight: 600;
    }
    
    .resource-badge.unlimited {
        background: var(--success-light);
        border-color: var(--success-border);
        color: var(--success-dark);
    }
    
    /* Status badges */
    .status-badge {
        display: inline-flex;
        align-items: center;
        gap: 6px;
        padding: 6px 12px;
        border-radius: 6px;
        font-size: 12px;
        font-weight: 600;
    }
    
    .status-badge.enabled {
        background: var(--success-light);
        color: var(--success-dark);
    }
    
    .status-badge.disabled {
        background: var(--warning-light);
        color: var(--warning-dark);
    }
    
    /* Action buttons */
    .action-buttons {
        display: flex;
        gap: 8px;
    }
    
    .btn-action {
        padding: 6px 14px;
        border-radius: 6px;
        font-size: 13px;
        font-weight: 600;
        text-decoration: none;
        transition: all 0.2s ease;
        cursor: pointer;
        border: none;
        display: inline-flex;
        align-items: center;
        gap: 6px;
    }
    
    .btn-edit {
        background: var(--surface-secondary);
        color: var(--accent-primary);
    }
    
    .btn-edit:hover {
        background: var(--accent-primary);
        color: var(--text-inverse);
        transform: translateY(-1px);
    }
    
    .btn-delete {
        background: var(--error-light);
        color: var(--error-primary);
    }
    
    .btn-delete:hover {
        background: var(--error-primary);
        color: var(--text-inverse);
        transform: translateY(-1px);
    }
    
    /* Modal styles */
    .modal-content {
        border-radius: 12px;
        border: none;
        box-shadow: 0 8px 32px var(--shadow-medium);
    }
    
    .modal-header {
        background: var(--surface-secondary);
        border-bottom: 1px solid var(--border-primary);
        border-radius: 12px 12px 0 0;
        padding: 20px 25px;
    }
    
    .modal-title {
        font-size: 18px;
        font-weight: 700;
        color: var(--text-primary);
        display: flex;
        align-items: center;
        gap: 10px;
    }
    
    .modal-body {
        padding: 25px;
    }
    
    .modal-footer {
        background: var(--surface-secondary);
        border-top: 1px solid var(--border-primary);
        border-radius: 0 0 12px 12px;
        padding: 15px 25px;
        display: flex;
        justify-content: flex-end;
        gap: 10px;
    }
    
    /* Form styles in modal */
    .form-section {
        margin-bottom: 25px;
    }
    
    .form-section-title {
        font-size: 14px;
        font-weight: 700;
        color: var(--text-primary);
        margin-bottom: 15px;
        display: flex;
        align-items: center;
        gap: 8px;
    }
    
    .form-section-title i {
        color: var(--accent-primary);
    }
    
    .form-group {
        margin-bottom: 20px;
    }
    
    .form-label {
        display: block;
        font-size: 13px;
        font-weight: 600;
        color: var(--text-muted);
        margin-bottom: 8px;
        text-transform: uppercase;
        letter-spacing: 0.5px;
    }
    
    .form-control {
        width: 100%;
        padding: 10px 14px;
        border: 1px solid var(--border-primary);
        border-radius: 8px;
        font-size: 14px;
        color: var(--text-primary);
        background: var(--surface-primary);
        transition: all 0.2s ease;
    }
    
    .form-control:hover {
        border-color: var(--accent-primary);
    }
    
    .form-control:focus {
        outline: none;
        border-color: var(--accent-primary);
        box-shadow: 0 0 0 3px var(--accent-focus);
    }
    
    .form-control[readonly] {
        background: var(--surface-secondary);
        cursor: not-allowed;
    }
    
    /* Input group */
    .input-group {
        display: flex;
        align-items: center;
        gap: 0;
    }
    
    .input-group .form-control {
        border-radius: 8px 0 0 8px;
    }
    
    .input-suffix {
        background: var(--surface-secondary);
        border: 1px solid var(--border-primary);
        border-left: none;
        padding: 10px 16px;
        border-radius: 0 8px 8px 0;
        font-size: 13px;
        color: var(--text-muted);
        font-weight: 600;
        white-space: nowrap;
    }
    
    /* Help text */
    .help-text {
        font-size: 12px;
        color: var(--text-secondary);
        margin-top: 6px;
    }
    
    /* Checkbox styles */
    .checkbox-wrapper {
        display: flex;
        align-items: start;
        gap: 10px;
        padding: 12px 16px;
        background: var(--surface-secondary);
        border: 1px solid var(--border-primary);
        border-radius: 8px;
        transition: all 0.2s ease;
        cursor: pointer;
        margin-bottom: 12px;
    }
    
    .checkbox-wrapper:hover {
        border-color: var(--accent-primary);
        background: var(--accent-lighter);
    }
    
    .checkbox-wrapper input[type="checkbox"] {
        width: 18px;
        height: 18px;
        border-radius: 4px;
        cursor: pointer;
        accent-color: var(--accent-primary);
        margin-top: 2px;
    }
    
    .checkbox-content {
        flex: 1;
    }
    
    .checkbox-label {
        font-size: 14px;
        color: var(--text-primary);
        font-weight: 600;
        cursor: pointer;
        user-select: none;
        display: block;
        margin-bottom: 4px;
    }
    
    .checkbox-desc {
        font-size: 12px;
        color: var(--text-secondary);
        line-height: 1.5;
    }
    
    /* Button styles */
    .btn {
        display: inline-flex;
        align-items: center;
        gap: 8px;
        padding: 10px 20px;
        border: none;
        border-radius: 8px;
        font-size: 14px;
        font-weight: 600;
        cursor: pointer;
        transition: all 0.2s ease;
        text-decoration: none;
    }
    
    .btn-primary {
        background: var(--accent-primary);
        color: var(--text-inverse);
    }
    
    .btn-primary:hover {
        background: var(--accent-dark);
        box-shadow: 0 4px 12px var(--accent-shadow);
        transform: translateY(-1px);
    }
    
    .btn-secondary {
        background: var(--surface-secondary);
        color: var(--accent-primary);
        border: 1px solid var(--border-primary);
    }
    
    .btn-secondary:hover {
        background: var(--accent-light);
        border-color: var(--accent-primary);
    }
    
    /* Loading spinner */
    .loading-spinner {
        display: inline-block;
        width: 16px;
        height: 16px;
        border: 2px solid var(--border-light);
        border-top: 2px solid var(--accent-primary);
        border-radius: 50%;
        animation: spin 1s linear infinite;
        margin-left: 10px;
    }
    
    @keyframes spin {
        0% { transform: rotate(0deg); }
        100% { transform: rotate(360deg); }
    }
    
    @media (max-width: 768px) {
        .modern-table {
            display: block;
            overflow-x: auto;
            white-space: nowrap;
        }
        
        .action-buttons {
            flex-direction: column;
        }
    }
</style>
{% endblock %}

{% block content %}
{% load static %}
{% get_current_language as LANGUAGE_CODE %}

<div class="page-wrapper" ng-controller="listPackageTables">
    <div class="page-container">
        <div class="page-header">
            <h1 class="page-title">{% trans "List Packages" %}</h1>
            <p class="page-subtitle">{% trans "Manage your hosting packages - edit resource limits or delete packages" %}</p>
        </div>

        <div class="content-card">
            <h2 class="card-title">
                {% trans "Hosting Packages" %}
                <span ng-hide="cyberpanelLoading" class="loading-spinner"></span>
            </h2>
            
            <div class="table-responsive">
                <table class="modern-table">
                    <thead>
                        <tr>
                            <th>{% trans "Package Name" %}</th>
                            <th>{% trans "Disk Space" %}</th>
                            <th>{% trans "Bandwidth" %}</th>
                            <th>{% trans "Domains" %}</th>
                            <th>{% trans "Emails" %}</th>
                            <th>{% trans "Databases" %}</th>
                            <th>{% trans "FTP Accounts" %}</th>
                            <th>{% trans "FQDN Status" %}</th>
                            <th>{% trans "Actions" %}</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr ng-repeat="record in records track by $index">
                            <td>
                                <strong>{$ record.package $}</strong>
                            </td>
                            <td>
                                <span class="resource-badge" ng-class="{'unlimited': record.diskSpace == 0}">
                                    <span ng-if="record.diskSpace == 0">{% trans "Unlimited" %}</span>
                                    <span ng-if="record.diskSpace != 0">{$ record.diskSpace $} MB</span>
                                </span>
                            </td>
                            <td>
                                <span class="resource-badge" ng-class="{'unlimited': record.bandwidth == 0}">
                                    <span ng-if="record.bandwidth == 0">{% trans "Unlimited" %}</span>
                                    <span ng-if="record.bandwidth != 0">{$ record.bandwidth $} MB</span>
                                </span>
                            </td>
                            <td>
                                <span class="resource-badge" ng-class="{'unlimited': record.allowedDomains == 0}">
                                    <span ng-if="record.allowedDomains == 0">{% trans "Unlimited" %}</span>
                                    <span ng-if="record.allowedDomains != 0">{$ record.allowedDomains $}</span>
                                </span>
                            </td>
                            <td>{$ record.emailAccounts $}</td>
                            <td>{$ record.dataBases $}</td>
                            <td>{$ record.ftpAccounts $}</td>
                            <td>
                                <span class="status-badge" ng-class="{'enabled': record.allowFullDomain, 'disabled': !record.allowFullDomain}">
                                    <i class="fas fa-circle" style="font-size: 8px;"></i>
                                    <span ng-if="record.allowFullDomain">{% trans "Enabled" %}</span>
                                    <span ng-if="!record.allowFullDomain">{% trans "Disabled" %}</span>
                                </span>
                            </td>
                            <td>
                                <div class="action-buttons">
                                    <button class="btn-action btn-edit" 
                                            ng-click="editInitial(record.package, record.diskSpace, record.bandwidth, record.emailAccounts, record.dataBases, record.ftpAccounts, record.allowedDomains, record.allowFullDomain, record.enforceDiskLimits)"
                                            data-toggle="modal" 
                                            data-target="#editPackageModal">
                                        <i class="fas fa-edit"></i>
                                        {% trans "Edit" %}
                                    </button>
                                    <button class="btn-action btn-delete" 
                                            ng-click="confirmDelete(record.package)">
                                        <i class="fas fa-trash"></i>
                                        {% trans "Delete" %}
                                    </button>
                                </div>
                            </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Edit Package Modal - Inside Controller -->
    <div id="editPackageModal" class="modal fade" role="dialog">
        <div class="modal-dialog modal-lg">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal">&times;</button>
                    <h4 class="modal-title">
                        {% trans "Edit Package" %}
                        <span ng-hide="cyberpanelLoading" class="loading-spinner"></span>
                    </h4>
                </div>
                <div class="modal-body">
                    <form name="editPackageForm">
                        <div class="form-group">
                            <label class="form-label">{% trans "Package Name" %}</label>
                            <input type="text" class="form-control" ng-model="name" readonly>
                        </div>
                        
                        <div class="form-section">
                            <div class="form-section-title">
                                <i class="fas fa-globe"></i>
                                {% trans "Web Resources" %}
                            </div>
                            
                            <div class="form-group">
                                <label class="form-label">{% trans "Domains" %}</label>
                                <input type="number" class="form-control" ng-model="allowedDomains" required>
                                <div class="help-text">{% trans "Number of domains allowed (0 = Unlimited)" %}</div>
                            </div>
                            
                            <div class="form-group">
                                <label class="form-label">{% trans "Disk Space" %}</label>
                                <div class="input-group">
                                    <input type="number" class="form-control" ng-model="diskSpace" required>
                                    <span class="input-suffix">MB</span>
                                </div>
                                <div class="help-text">{% trans "Disk space in MB (0 = Unlimited)" %}</div>
                            </div>
                            
                            <div class="form-group">
                                <label class="form-label">{% trans "Bandwidth" %}</label>
                                <div class="input-group">
                                    <input type="number" class="form-control" ng-model="bandwidth" required>
                                    <span class="input-suffix">MB</span>
                                </div>
                                <div class="help-text">{% trans "Monthly bandwidth in MB (0 = Unlimited)" %}</div>
                            </div>
                        </div>
                        
                        <div class="form-section">
                            <div class="form-section-title">
                                <i class="fas fa-server"></i>
                                {% trans "Services & Features" %}
                            </div>
                            
                            <div class="form-group">
                                <label class="form-label">{% trans "Email Accounts" %}</label>
                                <input type="number" class="form-control" ng-model="emails" required>
                            </div>
                            
                            <div class="form-group">
                                <label class="form-label">{% trans "Databases" %}</label>
                                <input type="number" class="form-control" ng-model="dataBases" required>
                            </div>
                            
                            <div class="form-group">
                                <label class="form-label">{% trans "FTP Accounts" %}</label>
                                <input type="number" class="form-control" ng-model="ftpAccounts" required>
                            </div>
                        </div>
                        
                        <div class="form-section">
                            <div class="form-section-title">
                                <i class="fas fa-cog"></i>
                                {% trans "Additional Features" %}
                            </div>
                            
                            <div class="checkbox-wrapper">
                                <input ng-model="allowFullDomain" type="checkbox" id="editAllowFullDomain">
                                <div class="checkbox-content">
                                    <label for="editAllowFullDomain" class="checkbox-label">
                                        {% trans "Allow Fully Qualified Domains" %}
                                    </label>
                                    <div class="checkbox-desc">
                                        {% trans "Allow creation of fully qualified domain names as child-domains" %}
                                    </div>
                                </div>
                            </div>
                            
                            <div class="checkbox-wrapper">
                                <input ng-model="enforceDiskLimits" type="checkbox" id="editEnforceDiskLimits">
                                <div class="checkbox-content">
                                    <label for="editEnforceDiskLimits" class="checkbox-label">
                                        {% trans "Enforce Disk Limits" %}
                                    </label>
                                    <div class="checkbox-desc">
                                        {% trans "Strictly enforce disk space limits for websites using this package" %}
                                    </div>
                                </div>
                            </div>
                        </div>
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-dismiss="modal">
                        {% trans "Cancel" %}
                    </button>
                    <button type="button" class="btn btn-primary" ng-click="saveChanges()" data-dismiss="modal">
                        <i class="fas fa-save"></i>
                        {% trans "Save Changes" %}
                    </button>
                </div>
            </div>
        </div>
    </div>

    <!-- Delete Package Modal -->
    <div id="deletePackageModal" class="modal fade" role="dialog">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal">&times;</button>
                    <h4 class="modal-title">
                        {% trans "Delete Package" %}
                    </h4>
                </div>
                <div class="modal-body">
                    <div class="alert alert-danger">
                        <i class="fas fa-exclamation-triangle"></i>
                        <strong>{% trans "Warning!" %}</strong> {% trans "Are you sure you want to delete this package?" %}
                    </div>
                    <p>{% trans "Package to delete:" %} <strong>{$ packageToDelete $}</strong></p>
                    <p class="text-muted">{% trans "This action cannot be undone." %}</p>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-dismiss="modal">
                        {% trans "Cancel" %}
                    </button>
                    <button type="button" class="btn btn-danger" ng-click="deletePackageFinal(packageToDelete)" data-dismiss="modal">
                        <i class="fas fa-trash"></i>
                        {% trans "Delete Package" %}
                    </button>
                </div>
            </div>
        </div>
    </div>
</div>

{% endblock %}