Files
docupulse/templates/main/instances.html
2025-06-26 15:24:40 +02:00

833 lines
46 KiB
HTML

{% extends "common/base.html" %}
{% from "components/header.html" import header %}
{% block title %}Instances - DocuPulse{% endblock %}
{% block extra_css %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/instances.css') }}?v={{ 'css/instances.css'|asset_version }}">
{% endblock %}
{% block content %}
{{ header(
title="Instance Management",
description="Manage and monitor your DocuPulse instances",
icon="fa-server",
buttons=[
{
'text': 'Launch New Instance',
'url': '#',
'onclick': 'showAddInstanceModal()',
'icon': 'fa-rocket',
'class': 'btn-primary'
},
{
'text': 'Link Existing Instance',
'url': '#',
'onclick': 'showAddExistingInstanceModal()',
'icon': 'fa-link',
'class': 'btn-secondary'
}
]
) }}
<!-- Latest Version Information -->
<div class="container-fluid mb-4">
<div class="row">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body">
<div class="row align-items-center">
<div class="col-md-8">
<h5 class="card-title mb-2">
<i class="fas fa-code-branch me-2" style="color: var(--primary-color);"></i>
Latest Available Version
</h5>
<div class="d-flex align-items-center">
<div class="me-4">
<span class="badge bg-success fs-6" id="latestVersionBadge">
<i class="fas fa-spinner fa-spin me-1"></i> Loading...
</span>
</div>
<div>
<small class="text-muted">
<i class="fas fa-clock me-1"></i>
Last checked: <span id="lastChecked" class="text-muted">Loading...</span>
</small>
</div>
</div>
</div>
<div class="col-md-4 text-end">
<button class="btn btn-outline-primary btn-sm" onclick="refreshLatestVersion()">
<i class="fas fa-sync-alt me-1"></i> Refresh
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Quick Links to Infrastructure Tools -->
<div class="container-fluid mb-4">
<div class="row">
<div class="col-12">
<div class="card border-0 shadow-sm">
<div class="card-body">
<h5 class="card-title mb-3">
<i class="fas fa-tools me-2" style="color: var(--primary-color);"></i>
Infrastructure Tools
</h5>
<div class="row g-3 infrastructure-tools">
<div class="col-md-2">
<a href="{{ portainer_settings.url if portainer_settings and portainer_settings.url else '#' }}"
target="_blank"
class="btn btn-outline-primary w-100 h-100 d-flex flex-column align-items-center justify-content-center p-3"
{% if not portainer_settings or not portainer_settings.url %}disabled style="pointer-events: none;"{% endif %}
aria-label="Open Portainer Container Management">
<i class="fab fa-docker fa-2x mb-2"></i>
<span class="fw-bold">Portainer</span>
<small class="text-muted">Container Management</small>
</a>
</div>
<div class="col-md-2">
<a href="{{ nginx_settings.url if nginx_settings and nginx_settings.url else '#' }}"
target="_blank"
class="btn btn-outline-success w-100 h-100 d-flex flex-column align-items-center justify-content-center p-3"
{% if not nginx_settings or not nginx_settings.url %}disabled style="pointer-events: none;"{% endif %}
aria-label="Open NGINX Proxy Manager">
<i class="fas fa-globe fa-2x mb-2"></i>
<span class="fw-bold">NGINX Proxy</span>
<small class="text-muted">Reverse Proxy & SSL</small>
</a>
</div>
<div class="col-md-2">
<a href="{{ git_settings.url if git_settings and git_settings.url else '#' }}"
target="_blank"
class="btn btn-outline-info w-100 h-100 d-flex flex-column align-items-center justify-content-center p-3"
{% if not git_settings or not git_settings.url %}disabled style="pointer-events: none;"{% endif %}
aria-label="Open Gitea Code Repository">
<i class="fab fa-git-alt fa-2x mb-2"></i>
<span class="fw-bold">Gitea</span>
<small class="text-muted">Code Repository</small>
</a>
</div>
<div class="col-md-2">
<a href="https://dash.cloudflare.com"
target="_blank"
class="btn btn-outline-warning w-100 h-100 d-flex flex-column align-items-center justify-content-center p-3"
aria-label="Open Cloudflare Dashboard">
<i class="fas fa-cloud fa-2x mb-2"></i>
<span class="fw-bold">Cloudflare</span>
<small class="text-muted">DNS & CDN</small>
</a>
</div>
<div class="col-md-2">
<a href="https://dashboard.stripe.com"
target="_blank"
class="btn btn-outline-purple w-100 h-100 d-flex flex-column align-items-center justify-content-center p-3"
aria-label="Open Stripe Dashboard">
<i class="fab fa-stripe fa-2x mb-2"></i>
<span class="fw-bold">Stripe</span>
<small class="text-muted">Payment & Billing</small>
</a>
</div>
</div>
{% if not portainer_settings or not portainer_settings.url or not nginx_settings or not nginx_settings.url or not git_settings or not git_settings.url %}
<div class="mt-3">
<div class="alert alert-warning mb-0">
<i class="fas fa-exclamation-triangle me-2"></i>
<strong>Note:</strong> Some infrastructure tools are not configured.
<a href="/settings#connections" class="alert-link">Configure them in Settings</a> to enable quick access.
</div>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="table-responsive">
<table class="table table-hover">
<thead>
<tr>
<th>PORT</th>
<th>Company</th>
<th>Rooms</th>
<th>Conversations</th>
<th>Data</th>
<th>Payment Plan</th>
<th>Main URL</th>
<th>Status</th>
<th>Version</th>
<th>Portainer Stack</th>
<th>Connection Token</th>
<th>Actions</th>
</tr>
</thead>
<tbody>
{% for instance in instances %}
<tr>
<td>{{ instance.name }}</td>
<td>{{ instance.company }}</td>
<td>{{ instance.rooms_count }}</td>
<td>{{ instance.conversations_count }}</td>
<td>{{ "%.1f"|format(instance.data_size) }} GB</td>
<td id="payment-plan-{{ instance.id }}">{{ instance.payment_plan }}</td>
<td>
<a href="{{ instance.main_url }}"
target="_blank"
class="text-decoration-none"
style="color: var(--primary-color);">
{{ instance.main_url }}
<i class="fas fa-external-link-alt ms-1"></i>
</a>
</td>
<td>
<span class="badge bg-{{ 'success' if instance.status == 'active' else 'danger' }}"
data-bs-toggle="tooltip"
data-instance-id="{{ instance.id }}"
data-token="{{ instance.connection_token }}"
title="{{ instance.status_details }}">
{{ instance.status|title }}
</span>
</td>
<td>
{% if instance.deployed_version %}
<span class="badge bg-info version-badge" data-bs-toggle="tooltip"
title="Deployed: {{ instance.deployed_version }}{% if instance.version_checked_at %}<br>Checked: {{ instance.version_checked_at.strftime('%Y-%m-%d %H:%M') }}{% endif %}">
{{ instance.deployed_version[:8] if instance.deployed_version != 'unknown' else 'unknown' }}
</span>
{% else %}
<span class="badge bg-secondary version-badge">unknown</span>
{% endif %}
</td>
<td>
{% if instance.portainer_stack_name %}
<span class="badge bg-primary" data-bs-toggle="tooltip"
title="Stack ID: {{ instance.portainer_stack_id or 'N/A' }}">
{{ instance.portainer_stack_name }}
</span>
{% else %}
<span class="badge bg-secondary">Not set</span>
{% endif %}
</td>
<td>
{% if instance.connection_token %}
<span class="badge bg-success" data-bs-toggle="tooltip" title="Instance is authenticated">
Authenticated
</span>
{% else %}
<span class="badge bg-warning" data-bs-toggle="tooltip" title="Click to authenticate instance">
<a href="#" class="text-dark text-decoration-none" onclick="showAuthModal('{{ instance.main_url }}', {{ instance.id }})">
Generate Token
</a>
</span>
{% endif %}
</td>
<td>
<div class="btn-group">
<button class="btn btn-sm btn-outline-info" onclick="window.location.href='/instances/{{ instance.id }}/detail'">
<i class="fas fa-info-circle"></i>
</button>
<button class="btn btn-sm btn-outline-warning" onclick="showUpdateInstanceModal({{ instance.id }}, '{{ instance.portainer_stack_name }}', '{{ instance.main_url }}')" title="Update Instance">
<i class="fas fa-arrow-up"></i>
</button>
<button class="btn btn-sm btn-outline-danger" type="button" onclick="showDeleteInstanceModal({{ instance.id }})">
<i class="fas fa-trash"></i>
</button>
</div>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Add Instance Modal -->
<div class="modal fade" id="addInstanceModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Launch New Instance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="addInstanceForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div class="text-center mb-4">
<i class="fas fa-rocket fa-3x mb-3" style="color: var(--primary-color);"></i>
<h4>Ready to Launch?</h4>
<p class="text-muted">We'll guide you through the process of launching a new DocuPulse instance.</p>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="nextStepLaunchInstance()">
Next <i class="fas fa-arrow-right ms-1"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Launch Steps Modal -->
<div class="modal fade" id="launchStepsModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Launch New Instance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<!-- Hidden fields for pricing tier selection -->
<input type="hidden" id="selectedPricingTierId" value="">
<input type="hidden" id="selectedPricingTierName" value="">
<!-- Steps Navigation -->
<div class="d-flex justify-content-between mb-4">
<div class="step-item active" data-step="1">
<div class="step-circle">1</div>
<div class="step-label">Connections</div>
</div>
<div class="step-item" data-step="2">
<div class="step-circle">2</div>
<div class="step-label">Repository</div>
</div>
<div class="step-item" data-step="3">
<div class="step-circle">3</div>
<div class="step-label">Company</div>
</div>
<div class="step-item" data-step="4">
<div class="step-circle">4</div>
<div class="step-label">Variables</div>
</div>
<div class="step-item" data-step="5">
<div class="step-circle">5</div>
<div class="step-label">White Label</div>
</div>
<div class="step-item" data-step="6">
<div class="step-circle">6</div>
<div class="step-label">Pricing Tier</div>
</div>
<div class="step-item" data-step="7">
<div class="step-circle">7</div>
<div class="step-label">Launch</div>
</div>
</div>
<!-- Step Content -->
<div class="step-content">
<!-- Step 1 -->
<div class="step-pane active" id="step1">
<!-- Portainer Connection -->
<div class="connection-check mb-4">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-server me-2"></i>
<h5 class="mb-0">Portainer Connection</h5>
<div class="ms-auto">
<span class="connection-status" id="portainerStatus">
<i class="fas fa-spinner fa-spin"></i> Checking...
</span>
</div>
</div>
<div class="connection-details" id="portainerDetails">
<small class="text-muted">Verifying connection to Portainer...</small>
</div>
</div>
<!-- NGINX Connection -->
<div class="connection-check">
<div class="d-flex align-items-center mb-2">
<i class="fas fa-network-wired me-2"></i>
<h5 class="mb-0">NGINX Proxy Manager Connection</h5>
<div class="ms-auto">
<span class="connection-status" id="nginxStatus">
<i class="fas fa-spinner fa-spin"></i> Checking...
</span>
</div>
</div>
<div class="connection-details" id="nginxDetails">
<small class="text-muted">Verifying connection to NGINX Proxy Manager...</small>
</div>
</div>
<!-- Retry Button -->
<div class="text-center mt-4">
<button class="btn btn-sm"
onclick="retryConnection('nginx')"
style="background-color: var(--primary-color); color: white;">
<i class="fas fa-sync-alt me-1"></i> Retry
</button>
</div>
</div>
<!-- Step 2 -->
<div class="step-pane" id="step2">
<div class="step-content" id="step2">
<div class="card">
<div class="card-body">
<div class="mb-3">
<label class="form-label">Repository</label>
<select class="form-select" id="giteaRepoSelect">
<option value="">Loading repositories...</option>
</select>
<div class="form-text">Select the repository containing your application code</div>
</div>
<div class="mb-3">
<label class="form-label">Branch</label>
<select class="form-select" id="giteaBranchSelect" disabled>
<option value="">Select a repository first</option>
</select>
<div class="form-text">Select the branch to deploy</div>
</div>
</div>
</div>
</div>
</div>
<!-- Step 3 -->
<div class="step-pane" id="step3">
<div class="step-content">
<div class="card">
<div class="card-body">
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Company Name <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="companyName" required>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Industry</label>
<input type="text" class="form-control" id="industry">
</div>
</div>
<div class="mb-3">
<label class="form-label">Street Address <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="streetAddress" required>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">City <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="city" required>
</div>
<div class="col-md-3 mb-3">
<label class="form-label">State</label>
<input type="text" class="form-control" id="state">
</div>
<div class="col-md-3 mb-3">
<label class="form-label">ZIP Code <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="zipCode" required>
</div>
</div>
<div class="mb-3">
<label class="form-label">Country <span class="text-danger">*</span></label>
<input type="text" class="form-control" id="country" required>
</div>
<div class="row">
<div class="col-md-4 mb-3">
<label class="form-label">Website</label>
<input type="url" class="form-control" id="website">
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Email <span class="text-danger">*</span></label>
<input type="email" class="form-control" id="email" required>
</div>
<div class="col-md-4 mb-3">
<label class="form-label">Phone <span class="text-danger">*</span></label>
<input type="tel" class="form-control" id="phone" required>
</div>
</div>
<div class="mb-3">
<label class="form-label">Company Description</label>
<textarea class="form-control" id="companyDescription" rows="4"></textarea>
</div>
</div>
</div>
</div>
</div>
<!-- Step 4 -->
<div class="step-pane" id="step4">
<h5 class="mb-4">Port Configuration</h5>
<div class="mb-3">
<label for="port" class="form-label">Internal Port Number <span class="text-danger">*</span></label>
<input type="number" class="form-control" id="port" required min="1024" max="65535">
<div class="form-text">Ports below 1024 are reserved for system use. Ports are automatically assigned by the system but you can change it if you want.</div>
</div>
<div class="mb-3">
<label class="form-label">Web Addresses <span class="text-danger">*</span></label>
<div id="webAddressesContainer">
<div class="input-group mb-2">
<span class="input-group-text">https://</span>
<input type="text" class="form-control web-address" required placeholder="your-domain.com">
<button type="button" class="btn btn-outline-danger remove-address" onclick="removeWebAddress(this)" style="display: none;">
<i class="fas fa-times"></i>
</button>
</div>
</div>
<button type="button" class="btn btn-outline-primary btn-sm" onclick="addWebAddress()">
<i class="fas fa-plus"></i> Add Another Address
</button>
<div class="form-text">Enter the domain names where your instance will be accessible</div>
</div>
</div>
<!-- Step 5: White Label -->
<div class="step-pane" id="step5">
<div class="step-content">
<div class="card">
<div class="card-body">
<h5 class="card-title mb-4">White Label Configuration</h5>
<div class="row">
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Primary Color</label>
<div class="input-group">
<input type="color" class="form-control form-control-color" id="primaryColor" value="#16767B" title="Choose primary color">
<input type="text" class="form-control" id="primaryColorRGB" value="22,118,123" readonly>
</div>
<div class="form-text">Default: RGB(22,118,123)</div>
</div>
</div>
<div class="col-md-6">
<div class="mb-3">
<label class="form-label">Secondary Color</label>
<div class="input-group">
<input type="color" class="form-control form-control-color" id="secondaryColor" value="#741B5F" title="Choose secondary color">
<input type="text" class="form-control" id="secondaryColorRGB" value="116,27,95" readonly>
</div>
<div class="form-text">Default: RGB(116,27,95)</div>
</div>
</div>
</div>
<div class="mt-4">
<h6>Preview</h6>
<div id="previewContainer">
<div class="preview-box p-3 rounded mb-2" id="primaryPreview" style="background-color: #16767B; color: white;">
Primary Color Sample
</div>
<div class="preview-box p-3 rounded" id="secondaryPreview" style="background-color: #741B5F; color: white;">
Secondary Color Sample
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Step 6: Pricing Tier Selection -->
<div class="step-pane" id="step6">
<div class="step-content">
<div class="card">
<div class="card-body">
<h5 class="card-title mb-4">Select Pricing Tier</h5>
<p class="text-muted mb-4">Choose the pricing tier that best fits your needs. This will determine the resource limits for your instance.</p>
<div id="pricingTiersContainer" class="row">
<!-- Pricing tiers will be loaded here -->
<div class="col-12 text-center">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading pricing tiers...</span>
</div>
<p class="mt-2">Loading available pricing tiers...</p>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Step 7 -->
<div class="step-pane" id="step7">
<div class="text-center">
<i class="fas fa-rocket fa-4x mb-4" style="color: var(--primary-color);"></i>
<h4>Ready to Launch!</h4>
<p class="text-muted mb-4">Review your instance configuration before launching</p>
<div class="card mb-4">
<div class="card-body">
<h5 class="card-title mb-3">Instance Configuration</h5>
<div class="row">
<div class="col-md-6">
<p><strong>Repository:</strong> <span id="reviewRepo"></span></p>
<p><strong>Branch:</strong> <span id="reviewBranch"></span></p>
<p><strong>Company:</strong> <span id="reviewCompany"></span></p>
<p><strong>Pricing Tier:</strong> <span id="reviewPricingTier"></span></p>
</div>
<div class="col-md-6">
<p><strong>Port:</strong> <span id="reviewPort"></span></p>
<p><strong>Web Addresses:</strong> <span id="reviewWebAddresses"></span></p>
</div>
</div>
</div>
</div>
<button type="button" class="btn btn-primary btn-lg" onclick="launchInstance()">
<i class="fas fa-rocket me-2"></i> Launch Instance
</button>
</div>
</div>
</div>
</div>
<div class="modal-footer d-flex justify-content-end" id="launchStepsFooter">
<button type="button" class="btn btn-secondary" onclick="previousStep()">
<i class="fas fa-arrow-left me-1"></i> Previous
</button>
<button type="button" class="btn btn-primary" onclick="nextStep()">
Next <i class="fas fa-arrow-right ms-1"></i>
</button>
</div>
</div>
</div>
</div>
<!-- Edit Instance Modal -->
<div class="modal fade" id="editInstanceModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Edit Instance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="editInstanceForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" id="edit_instance_id">
<div class="mb-3">
<label for="edit_name" class="form-label">Instance Name</label>
<input type="text" class="form-control" id="edit_name" name="name" required>
</div>
<div class="mb-3">
<label for="edit_main_url" class="form-label">Main URL</label>
<input type="url" class="form-control" id="edit_main_url" name="main_url" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="submitEditInstance()">Save Changes</button>
</div>
</div>
</div>
</div>
<!-- Add Existing Instance Modal -->
<div class="modal fade" id="addExistingInstanceModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Existing Instance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="addExistingInstanceForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<div class="mb-3">
<label for="existing_url" class="form-label">Instance URL</label>
<input type="url" class="form-control" id="existing_url" name="url" required onchange="updateInstanceFields()">
</div>
<div class="mb-3">
<label for="existing_name" class="form-label">Instance Name</label>
<input type="text" class="form-control" id="existing_name" name="name" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="submitAddExistingInstance()">Add Instance</button>
</div>
</div>
</div>
</div>
<!-- Auth Modal -->
<div class="modal fade" id="authModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Authenticate Instance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="authForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" id="instance_url" name="instance_url">
<input type="hidden" id="instance_id" name="instance_id">
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control" id="password" name="password" required>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-primary" onclick="authenticateInstance()">Authenticate</button>
</div>
</div>
</div>
</div>
<!-- Delete Instance Modal -->
<div class="modal fade" id="deleteInstanceModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Delete Instance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<div class="text-center mb-4">
<i class="fas fa-exclamation-triangle fa-3x text-warning mb-3"></i>
<h4>Are you sure?</h4>
<p class="text-muted">This action cannot be undone. The instance and all its data will be permanently deleted.</p>
</div>
<div class="alert alert-warning">
<h6><i class="fas fa-info-circle me-2"></i>What will be deleted:</h6>
<ul class="mb-0">
<li>Instance configuration</li>
<li>Portainer Docker stack and all containers</li>
<li>All associated Docker volumes and data</li>
<li>NGINX proxy host configuration</li>
<li>All rooms and conversations</li>
<li>User data and files</li>
<li>Database records</li>
</ul>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="confirmDelete" required>
<label class="form-check-label" for="confirmDelete">
I understand that this action is irreversible and I want to delete this instance
</label>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-danger" id="confirmDeleteBtn" disabled onclick="confirmDeleteInstance()">
<i class="fas fa-trash me-1"></i>Delete Instance
</button>
</div>
</div>
</div>
</div>
<!-- Update Instance Modal -->
<div class="modal fade" id="updateInstanceModal" tabindex="-1">
<div class="modal-dialog modal-dialog-centered modal-lg">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Update Instance</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<form id="updateInstanceForm">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" id="update_instance_id">
<input type="hidden" id="update_stack_name">
<input type="hidden" id="update_instance_url">
<div class="text-center mb-4">
<i class="fas fa-arrow-up fa-3x mb-3" style="color: var(--primary-color);"></i>
<h4>Update Instance</h4>
<p class="text-muted">Update your instance with the latest version from the repository.</p>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label class="form-label">Repository</label>
<select class="form-select" id="updateRepoSelect">
<option value="">Loading repositories...</option>
</select>
<div class="form-text">Select the repository containing your application code</div>
</div>
<div class="col-md-6 mb-3">
<label class="form-label">Branch</label>
<select class="form-select" id="updateBranchSelect" disabled>
<option value="">Select a repository first</option>
</select>
<div class="form-text">Select the branch to deploy</div>
</div>
</div>
<div class="alert alert-info">
<h6><i class="fas fa-info-circle me-2"></i>Update Process:</h6>
<ul class="mb-0">
<li>Download the latest code from the selected repository and branch</li>
<li>Build a new Docker image with the updated code</li>
<li>Deploy the updated stack to replace the current instance</li>
<li>Preserve all existing data and configuration</li>
<li>Maintain the same port and domain configuration</li>
</ul>
</div>
<div class="alert alert-warning">
<h6><i class="fas fa-exclamation-triangle me-2"></i>Important Notes:</h6>
<ul class="mb-0">
<li>The instance will be temporarily unavailable during the update process</li>
<li>All existing data, rooms, and conversations will be preserved</li>
<li>The update process may take several minutes to complete</li>
<li>You will be redirected to a progress page to monitor the update</li>
</ul>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="button" class="btn btn-warning" onclick="startInstanceUpdate()">
<i class="fas fa-arrow-up me-1"></i>Start Update
</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block extra_js %}
<script>
// Pass settings data to JavaScript
window.portainerSettings = {
url: "{{ portainer_settings.url if portainer_settings and portainer_settings.url else '' }}",
api_key: "{{ portainer_settings.api_key if portainer_settings and portainer_settings.api_key else '' }}"
};
window.nginxSettings = {
url: "{{ nginx_settings.url if nginx_settings and nginx_settings.url else '' }}",
username: "{{ nginx_settings.username if nginx_settings and nginx_settings.username else '' }}",
password: "{{ nginx_settings.password if nginx_settings and nginx_settings.password else '' }}"
};
window.gitSettings = {
url: "{{ git_settings.url if git_settings and git_settings.url else '' }}",
token: "{{ git_settings.token if git_settings and git_settings.token else '' }}",
repo: "{{ git_settings.repo if git_settings and git_settings.repo else '' }}"
};
window.cloudflareSettings = {
api_token: "{{ cloudflare_settings.api_token if cloudflare_settings and cloudflare_settings.api_token else '' }}",
zone_id: "{{ cloudflare_settings.zone_id if cloudflare_settings and cloudflare_settings.zone_id else '' }}"
};
</script>
<script src="{{ url_for('static', filename='js/instances.js') }}?v={{ 'js/instance_detail.js'|asset_version }}"></script>
{% endblock %}