Initial commit: Cloud Control Panel
This commit is contained in:
193
resources/views/dashboard.php
Executable file
193
resources/views/dashboard.php
Executable file
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
/** @var Din9xtrCloud\ViewModels\Dashboard\DashboardViewModel $viewModel */
|
||||
?>
|
||||
<div class="dashboard-container">
|
||||
|
||||
|
||||
<!-- Основная статистика хранения -->
|
||||
<section class="storage-overview">
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">Storage Overview</h2>
|
||||
<div class="storage-summary">
|
||||
<span class="summary-text">Total: <strong><?= $viewModel->stats['storage']['total'] ?></strong></span>
|
||||
<span class="summary-text">Used: <strong><?= $viewModel->stats['storage']['used'] ?></strong></span>
|
||||
<span class="summary-text">Free: <strong><?= $viewModel->stats['storage']['free'] ?></strong></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Прогресс-бар общего использования -->
|
||||
<div class="main-progress-container">
|
||||
<div class="progress-header">
|
||||
<span class="progress-label">Overall Usage</span>
|
||||
<span class="progress-percent"><?= $viewModel->stats['storage']['percent'] ?>%</span>
|
||||
</div>
|
||||
<div class="main-progress-bar">
|
||||
<div class="main-progress-fill" style="width: <?= $viewModel->stats['storage']['percent'] ?>%"></div>
|
||||
</div>
|
||||
<div class="progress-details">
|
||||
<span class="detail-item">Used: <?= $viewModel->stats['storage']['used'] ?></span>
|
||||
<span class="detail-item">Available: <?= $viewModel->stats['storage']['free'] ?></span>
|
||||
<span class="detail-item">Total: <?= $viewModel->stats['storage']['total'] ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Детальная статистика по типам файлов -->
|
||||
<section class="stats-grid">
|
||||
<?php foreach ($viewModel->stats['storage']['folders'] as $folder): ?>
|
||||
<a href="/folders/<?= urlencode($folder['name']) ?>" class="stat-card">
|
||||
<div class="stat-icon" style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);">
|
||||
<span>📁</span>
|
||||
</div>
|
||||
|
||||
<div class="stat-content">
|
||||
<h3 class="stat-title"><?= htmlspecialchars($folder['name']) ?></h3>
|
||||
|
||||
<div class="stat-value"><?= $folder['size'] ?></div>
|
||||
|
||||
<div class="stat-progress">
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill" style="width: <?= $folder['percent'] ?>%"></div>
|
||||
</div>
|
||||
<span class="progress-text"><?= $folder['percent'] ?>% of total</span>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<?php endforeach; ?>
|
||||
</section>
|
||||
|
||||
|
||||
<!-- Быстрые действия -->
|
||||
<section class="quick-actions">
|
||||
<h2 class="actions-title">Storage Management</h2>
|
||||
<div class="actions-grid">
|
||||
<button class="action-btn" id="upload-file-btn">
|
||||
<span class="action-icon">📤</span>
|
||||
<span class="action-text">Upload Files</span>
|
||||
</button>
|
||||
<button class="action-btn" id="create-folder-btn">
|
||||
<span class="action-icon">📁</span>
|
||||
<span class="action-text">Create Folder</span>
|
||||
</button>
|
||||
<!-- <button class="action-btn">-->
|
||||
<!-- <span class="action-icon">🧹</span>-->
|
||||
<!-- <span class="action-text">Clean Storage</span>-->
|
||||
<!-- </button>-->
|
||||
<!-- <button class="action-btn">-->
|
||||
<!-- <span class="action-icon">📊</span>-->
|
||||
<!-- <span class="action-text">Generate Report</span>-->
|
||||
<!-- </button>-->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Предупреждения и уведомления -->
|
||||
<!-- <section class="alerts-container">-->
|
||||
<!-- <div class="section-header">-->
|
||||
<!-- <h2 class="section-title">Storage Alerts</h2>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="alerts-list">-->
|
||||
<!-- <div class="alert-item warning">-->
|
||||
<!-- <div class="alert-icon">⚠️</div>-->
|
||||
<!-- <div class="alert-content">-->
|
||||
<!-- <h4>Storage nearing capacity</h4>-->
|
||||
<!-- <p>You've used 65% of your available storage. Consider upgrading your plan.</p>-->
|
||||
<!-- </div>-->
|
||||
<!-- <button class="alert-action">Review</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="alert-item info">-->
|
||||
<!-- <div class="alert-icon">ℹ️</div>-->
|
||||
<!-- <div class="alert-content">-->
|
||||
<!-- <h4>Backup scheduled</h4>-->
|
||||
<!-- <p>Next backup: Today at 2:00 AM</p>-->
|
||||
<!-- </div>-->
|
||||
<!-- <button class="alert-action">Settings</button>-->
|
||||
<!-- </div>-->
|
||||
<!-- </section>-->
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Модальное окно - скрыто по умолчанию -->
|
||||
<div class="modal-overlay" id="create-folder-modal">
|
||||
<div class="modal">
|
||||
<h3>Create new folder</h3>
|
||||
|
||||
<form method="POST" action="/storage/folders">
|
||||
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($viewModel->csrf) ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Folder name</label>
|
||||
<label>
|
||||
<input
|
||||
type="text"
|
||||
name="name"
|
||||
required
|
||||
pattern="[a-zA-Z\u0400-\u04FF0-9_\- ]+"
|
||||
>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn btn-secondary" id="cancel-create-folder">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary">
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-overlay" id="upload-file-modal">
|
||||
<div class="modal">
|
||||
<h3>Upload File</h3>
|
||||
|
||||
<form method="POST" action="/storage/files" enctype="multipart/form-data">
|
||||
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($viewModel->csrf) ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Select folder</label>
|
||||
<label>
|
||||
<select name="folder" required class="folder-select">
|
||||
<option value="" disabled selected>Choose folder...</option>
|
||||
<?php foreach ($viewModel->stats['storage']['folders'] as $folder): ?>
|
||||
<option value="<?= htmlspecialchars($folder['name']) ?>">
|
||||
<?= htmlspecialchars($folder['name']) ?>
|
||||
</option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Choose file</label>
|
||||
<input type="file" name="file" required accept="*/*" class="file-input">
|
||||
<div class="file-preview" style="display:none; margin-top:10px;">
|
||||
<img src="" alt="Preview" style="max-width:100px; max-height:100px; display:none;">
|
||||
<div class="file-info"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="upload-progress" style="display:none;">
|
||||
<div class="progress-bar" style="height:6px; background:#e2e8f0; border-radius:3px;">
|
||||
<div class="progress-fill"
|
||||
style="height:100%; background:#667eea; width:0; border-radius:3px;"></div>
|
||||
</div>
|
||||
<div class="progress-text" style="font-size:0.9rem; color:#718096; margin-top:5px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn btn-secondary" id="cancel-upload-file">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" id="submit-upload">
|
||||
Upload
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/js/tus.js"></script>
|
||||
<script src="/js/shared.js"></script>
|
||||
<script src="/js/dashboard.js"></script>
|
||||
21
resources/views/error.php
Executable file
21
resources/views/error.php
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/** @var Din9xtrCloud\ViewModels\Errors\ErrorViewModel $viewModel */
|
||||
?>
|
||||
|
||||
<div class="error-container">
|
||||
<div class="error-code"><?= htmlspecialchars($viewModel->errorCode) ?></div>
|
||||
|
||||
<p class="error-message">
|
||||
<?= nl2br(htmlspecialchars($viewModel->message)) ?>
|
||||
</p>
|
||||
|
||||
|
||||
<div class="action-buttons">
|
||||
<a href="javascript:history.back()" class="btn btn-secondary">
|
||||
Go Back
|
||||
</a>
|
||||
<a href="/" class="btn btn-primary">
|
||||
Go to Homepage
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
163
resources/views/folder.php
Normal file
163
resources/views/folder.php
Normal file
@@ -0,0 +1,163 @@
|
||||
<?php
|
||||
/** @var Din9xtrCloud\ViewModels\Folder\FolderViewModel $viewModel */
|
||||
?>
|
||||
<div class="folder-container">
|
||||
|
||||
<!-- Действия с файлами -->
|
||||
<section class="file-actions-section">
|
||||
<h2 class="section-title">Files</h2>
|
||||
<div class="action-buttons">
|
||||
<button class="btn btn-primary" id="upload-file-folder">
|
||||
<span class="btn-icon">📤</span>Upload File
|
||||
</button>
|
||||
<form method="GET" action="/storage/files/download/multiple" class="multiple-download-form"
|
||||
style="display: none;">
|
||||
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($viewModel->csrf) ?>">
|
||||
<input type="hidden" name="folder" value="<?= htmlspecialchars($viewModel->title) ?>">
|
||||
<input type="hidden" name="file_names" id="multiple-download-names" value="">
|
||||
<button type="submit" class="btn btn-success" id="download-multiple-btn">
|
||||
<span class="btn-icon">⬇️</span>Download Selected
|
||||
</button>
|
||||
</form>
|
||||
<form method="POST" action="/storage/files/delete/multiple" class="multiple-delete-form"
|
||||
style="display: none;">
|
||||
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($viewModel->csrf) ?>">
|
||||
<input type="hidden" name="folder" value="<?= htmlspecialchars($viewModel->title) ?>">
|
||||
<input type="hidden" name="file_names" id="multiple-file-names" value="">
|
||||
<button type="submit" class="btn btn-danger" id="delete-multiple-btn">
|
||||
<span class="btn-icon">🗑️</span>Delete Selected
|
||||
</button>
|
||||
</form>
|
||||
<div class="selection-controls">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="select-all-checkbox">
|
||||
<span class="checkmark"></span>
|
||||
Select All
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Список файлов -->
|
||||
<section class="files-section">
|
||||
<?php if (empty($viewModel->files)): ?>
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon">📁</div>
|
||||
<h3>No files in this folder</h3>
|
||||
<p>Upload your first file to get started</p>
|
||||
<button class="btn btn-primary" id="upload-first-file">
|
||||
<span class="btn-icon">📤</span>Upload File
|
||||
</button>
|
||||
</div>
|
||||
<?php else: ?>
|
||||
<div class="files-grid">
|
||||
<?php foreach ($viewModel->files as $file): ?>
|
||||
<div class="file-card" data-file-name="<?= htmlspecialchars($file['name']) ?>">
|
||||
<div class="file-card-header">
|
||||
<label class="file-checkbox">
|
||||
<input type="checkbox" class="file-select-checkbox"
|
||||
value="<?= htmlspecialchars($file['name']) ?>">
|
||||
</label>
|
||||
<div class="file-icon">
|
||||
<?php
|
||||
$extension = pathinfo($file['name'], PATHINFO_EXTENSION);
|
||||
$icon = match (strtolower($extension)) {
|
||||
'jpg', 'jpeg', 'png', 'gif', 'webp', 'svg' => '🖼️',
|
||||
'pdf' => '📕',
|
||||
'doc', 'docx' => '📄',
|
||||
'xls', 'xlsx' => '📊',
|
||||
'zip', 'rar', '7z', 'tar', 'gz' => '📦',
|
||||
'mp3', 'wav', 'ogg' => '🎵',
|
||||
'mp4', 'avi', 'mkv', 'mov' => '🎬',
|
||||
default => '📄'
|
||||
};
|
||||
echo $icon;
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file-info">
|
||||
<h4 class="file-name" title="<?= htmlspecialchars($file['name']) ?>">
|
||||
<?= htmlspecialchars($file['name']) ?>
|
||||
</h4>
|
||||
|
||||
<div class="file-details">
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Size:</span>
|
||||
<span class="detail-value"><?= $file['size'] ?></span>
|
||||
</div>
|
||||
<div class="detail-item">
|
||||
<span class="detail-label">Modified:</span>
|
||||
<span class="detail-value"><?= $file['modified'] ?></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="file-card-actions">
|
||||
<a href="/storage/files/download?file=<?= urlencode($file['name']) ?>&folder=<?= urlencode($viewModel->title) ?>"
|
||||
class="file-action-btn download-btn"
|
||||
title="Download">
|
||||
<span class="action-icon">🤏</span>
|
||||
</a>
|
||||
<form method="POST" action="/storage/files/delete"
|
||||
class="delete-form"
|
||||
onsubmit="return confirm('Are you sure you want to delete <?= htmlspecialchars($file['name']) ?>?')">
|
||||
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($viewModel->csrf) ?>">
|
||||
<input type="hidden" name="file_name" value="<?= htmlspecialchars($file['name']) ?>">
|
||||
<input type="hidden" name="folder"
|
||||
value="<?= htmlspecialchars($viewModel->title) ?>">
|
||||
<button type="submit" class="file-action-btn delete-btn" title="Delete">
|
||||
<span class="action-icon">🗑️</span>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<!-- Модальное окно загрузки файла -->
|
||||
<div class="modal-overlay" id="upload-file-modal-folder">
|
||||
<div class="modal">
|
||||
<h3>Upload File to <?= htmlspecialchars($viewModel->folderName) ?></h3>
|
||||
|
||||
<form method="POST" action="/storage/files" enctype="multipart/form-data" id="upload-form-folder">
|
||||
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($viewModel->csrf) ?>">
|
||||
<input type="hidden" name="folder" value="<?= htmlspecialchars($viewModel->title) ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Choose file</label>
|
||||
<input type="file" name="file" required accept="*/*" class="file-input" id="file-input-folder">
|
||||
<div class="file-preview" style="display:none; margin-top:10px;">
|
||||
<img src="" alt="Preview" style="max-width:100px; max-height:100px; display:none;">
|
||||
<div class="file-info"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="upload-progress" style="display:none;">
|
||||
<div class="progress-bar" style="height:6px; background:#e2e8f0; border-radius:3px;">
|
||||
<div class="progress-fill"
|
||||
style="height:100%; background:#667eea; width:0; border-radius:3px;"></div>
|
||||
</div>
|
||||
<div class="progress-text" style="font-size:0.9rem; color:#718096; margin-top:5px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-actions">
|
||||
<button type="button" class="btn btn-secondary" id="cancel-upload-file-folder">
|
||||
Cancel
|
||||
</button>
|
||||
<button type="submit" class="btn btn-primary" id="submit-upload-folder">
|
||||
Upload
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="/js/tus.js"></script>
|
||||
<script src="/js/shared.js"></script>
|
||||
<script src="/js/folder.js"></script>
|
||||
26
resources/views/headers/dashboard.php
Normal file
26
resources/views/headers/dashboard.php
Normal file
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
/** @var Din9xtrCloud\ViewModels\Dashboard\DashboardViewModel $page */
|
||||
?>
|
||||
<header class="dashboard-header">
|
||||
<div class="welcome-section">
|
||||
<h1 class="welcome-title">Welcome to your cloud storage
|
||||
<?= htmlspecialchars($page->username) ?> 👋</h1>
|
||||
<p class="welcome-subtitle">Manage your cloud storage efficiently</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<form action="/" method="GET" style="display: inline;">
|
||||
|
||||
<button class="btn btn-primary" id="refresh-dashboard">
|
||||
<span class="btn-icon">💨</span>Refresh
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<form action="/logout" method="POST" style="display: inline;">
|
||||
<button type="submit" class="btn btn-secondary" id="logout-btn">
|
||||
<span class="btn-icon">🚪</span> Logout
|
||||
</button>
|
||||
<input type="hidden" name="_csrf"
|
||||
value="<?= htmlspecialchars($page->csrf) ?>">
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
32
resources/views/headers/folder.php
Normal file
32
resources/views/headers/folder.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php /** @var Din9xtrCloud\ViewModels\Folder\FolderViewModel $page */
|
||||
?>
|
||||
<header class="folder-header">
|
||||
<div class="folder-info">
|
||||
<h1 class="folder-title">
|
||||
<span class="folder-icon">📁</span>
|
||||
<?= htmlspecialchars($page->title) ?>
|
||||
</h1>
|
||||
<div class="folder-stats">
|
||||
<span class="stat-item"><?= count($page->files) ?> files</span>
|
||||
<span class="stat-separator">•</span>
|
||||
<span class="stat-item"><?= $page->totalSize ?></span>
|
||||
<span class="stat-separator">•</span>
|
||||
<span class="stat-item">Last updated: <?= $page->lastModified ?></span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="folder-actions">
|
||||
<?php if ($page->title !== 'documents' && $page->title !== 'media'): ?>
|
||||
<form method="POST" action="/storage/folders/<?= urlencode($page->title) ?>/delete" style="display:inline;">
|
||||
<input type="hidden" name="_csrf" value="<?= htmlspecialchars($page->csrf) ?>">
|
||||
<button type="submit" class="btn btn-danger"
|
||||
onclick="return confirm('Delete folder <?= htmlspecialchars($page->title) ?>?');">
|
||||
<span class="btn-icon">🗑️</span>Delete Folder
|
||||
</button>
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<a href="/" class="btn btn-secondary">
|
||||
<span class="btn-icon">👈</span>Back to Dashboard
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
53
resources/views/layouts/app.php
Executable file
53
resources/views/layouts/app.php
Executable file
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
use Din9xtrCloud\ViewModels\LayoutViewModel;
|
||||
|
||||
/** @var LayoutViewModel $viewModel */
|
||||
$page = $viewModel->page;
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title><?= htmlspecialchars($page->title() ?? 'Cloud App') ?></title>
|
||||
<link rel="stylesheet" href=/assets/cloud.css>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
||||
<?php if ($page->layoutConfig->header === 'default'): ?>
|
||||
<header>
|
||||
<nav class="navbar">
|
||||
<span class="navbar-brand">Cloud Control Panel</span>
|
||||
<a href="/" class="back-link">👈 Back</a>
|
||||
|
||||
</nav>
|
||||
</header>
|
||||
<?php else: ?>
|
||||
<?php
|
||||
$headerFile = __DIR__ . '/../headers/' . $page->layoutConfig->header . '.php';
|
||||
if (file_exists($headerFile)):
|
||||
include $headerFile;
|
||||
?>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<main class="container">
|
||||
<?= $viewModel->content ?>
|
||||
|
||||
</main>
|
||||
<?php if ($page->layoutConfig->showFooter): ?>
|
||||
|
||||
<footer>
|
||||
<p>© <?= date('Y') ?> Cloud Control Panel.
|
||||
<a href="/license" style="color: #667eea; text-decoration: none; transition: color 0.3s ease;"
|
||||
onmouseover="this.style.color='#764ba2'; this.style.textDecoration='underline'"
|
||||
onmouseout="this.style.color='#667eea'; this.style.textDecoration='none'">
|
||||
MIT License
|
||||
</a>
|
||||
</p>
|
||||
</footer>
|
||||
<?php endif; ?>
|
||||
</body>
|
||||
</html>
|
||||
498
resources/views/license.php
Normal file
498
resources/views/license.php
Normal file
@@ -0,0 +1,498 @@
|
||||
<?php
|
||||
/** @var Din9xtrCloud\ViewModels\LicenseViewModel $viewModel */
|
||||
?>
|
||||
<style>
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background: linear-gradient(135deg, #f5f7fa 0%, #e4edf5 100%);
|
||||
color: #2d3748;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
header {
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
color: #4a5568;
|
||||
padding: 1rem 2rem;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-weight: 700;
|
||||
font-size: 1.5rem;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.2);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.05);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 1000;
|
||||
border-radius: 0 0 20px 20px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.navbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.navbar-brand {
|
||||
color: transparent;
|
||||
background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
font-size: 1.75rem;
|
||||
font-weight: 800;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.back-link {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
font-weight: 600;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.back-link:hover {
|
||||
color: #764ba2;
|
||||
transform: translateX(-3px);
|
||||
}
|
||||
|
||||
main {
|
||||
width: 100%;
|
||||
max-width: 1000px;
|
||||
margin: 100px auto 60px;
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(10px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.license-container {
|
||||
background: rgba(255, 255, 255, 0.98);
|
||||
border-radius: 24px;
|
||||
padding: 3rem;
|
||||
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.08),
|
||||
0 8px 24px rgba(0, 0, 0, 0.05),
|
||||
inset 0 1px 0 rgba(255, 255, 255, 0.8);
|
||||
backdrop-filter: blur(20px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
.license-header {
|
||||
text-align: center;
|
||||
margin-bottom: 3rem;
|
||||
padding-bottom: 2rem;
|
||||
border-bottom: 2px solid rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.license-title {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
-webkit-background-clip: text;
|
||||
background-clip: text;
|
||||
color: transparent;
|
||||
font-size: 2.5rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.license-subtitle {
|
||||
color: #718096;
|
||||
font-size: 1.1rem;
|
||||
line-height: 1.6;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.quick-summary {
|
||||
background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%);
|
||||
border-radius: 16px;
|
||||
padding: 2.5rem;
|
||||
margin-bottom: 3rem;
|
||||
border-left: 4px solid #667eea;
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
color: #2d3748;
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
margin-bottom: 1.5rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
.summary-title::before {
|
||||
content: '📋';
|
||||
font-size: 1.8rem;
|
||||
}
|
||||
|
||||
.summary-content {
|
||||
color: #4a5568;
|
||||
line-height: 1.7;
|
||||
font-size: 1.05rem;
|
||||
}
|
||||
|
||||
.permissions-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||
gap: 2rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.permission-card {
|
||||
background: #f7fafc;
|
||||
border-radius: 16px;
|
||||
padding: 2rem;
|
||||
transition: all 0.3s ease;
|
||||
border: 2px solid transparent;
|
||||
}
|
||||
|
||||
.permission-card:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.permission-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
.permission-icon {
|
||||
font-size: 2rem;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.permission-title {
|
||||
font-size: 1.3rem;
|
||||
font-weight: 700;
|
||||
color: #2d3748;
|
||||
}
|
||||
|
||||
.permission-list {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.permission-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 0.75rem;
|
||||
margin-bottom: 1rem;
|
||||
color: #4a5568;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.permission-item::before {
|
||||
font-size: 1.2rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.can-list .permission-item::before {
|
||||
content: '✅';
|
||||
color: #48bb78;
|
||||
}
|
||||
|
||||
.must-list .permission-item::before {
|
||||
content: '✍️';
|
||||
color: #667eea;
|
||||
}
|
||||
|
||||
.cannot-list .permission-item::before {
|
||||
content: '❌';
|
||||
color: #fc8181;
|
||||
}
|
||||
|
||||
.full-license {
|
||||
background: #f7fafc;
|
||||
border-radius: 16px;
|
||||
padding: 2.5rem;
|
||||
margin-top: 3rem;
|
||||
}
|
||||
|
||||
.full-license-header {
|
||||
text-align: center;
|
||||
margin-bottom: 2rem;
|
||||
}
|
||||
|
||||
.full-license-title {
|
||||
color: #2d3748;
|
||||
font-size: 1.8rem;
|
||||
font-weight: 800;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.full-license-subtitle {
|
||||
color: #718096;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.license-text {
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 2rem;
|
||||
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Fira Code', monospace;
|
||||
font-size: 0.95rem;
|
||||
line-height: 1.8;
|
||||
color: #4a5568;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #e2e8f0;
|
||||
}
|
||||
|
||||
footer {
|
||||
text-align: center;
|
||||
padding: 2rem;
|
||||
font-size: 0.9rem;
|
||||
color: #718096;
|
||||
width: 100%;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color: #667eea;
|
||||
text-decoration: none;
|
||||
transition: color 0.3s ease;
|
||||
}
|
||||
|
||||
footer a:hover {
|
||||
color: #764ba2;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%);
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
header {
|
||||
background: rgba(30, 41, 59, 0.95);
|
||||
color: #cbd5e1;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.license-container {
|
||||
background: rgba(30, 41, 59, 0.95);
|
||||
border: 1px solid rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.quick-summary {
|
||||
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%);
|
||||
border-left-color: #818cf8;
|
||||
}
|
||||
|
||||
.summary-title {
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.summary-content {
|
||||
color: #cbd5e1;
|
||||
}
|
||||
|
||||
.permission-card {
|
||||
background: rgba(30, 41, 59, 0.7);
|
||||
}
|
||||
|
||||
.permission-title {
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.permission-item {
|
||||
color: #cbd5e1;
|
||||
}
|
||||
|
||||
.full-license {
|
||||
background: rgba(30, 41, 59, 0.7);
|
||||
}
|
||||
|
||||
.full-license-title {
|
||||
color: #f1f5f9;
|
||||
}
|
||||
|
||||
.license-text {
|
||||
background: rgba(15, 23, 42, 0.9);
|
||||
color: #cbd5e1;
|
||||
border-color: #475569;
|
||||
}
|
||||
|
||||
.back-link {
|
||||
color: #818cf8;
|
||||
}
|
||||
|
||||
.back-link:hover {
|
||||
color: #c084fc;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.license-container {
|
||||
padding: 2rem;
|
||||
}
|
||||
|
||||
.license-title {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
.permissions-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.quick-summary {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.license-text {
|
||||
padding: 1.5rem;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.license-container {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.license-title {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
.permission-card {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<div class="license-container">
|
||||
<div class="license-header">
|
||||
<h1 class="license-title">MIT License</h1>
|
||||
<p class="license-subtitle">
|
||||
Behind every piece of software lies the dedication, expertise, and passion of talented individuals.
|
||||
We champion a license that embodies the spirit of freedom and openness.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="quick-summary">
|
||||
<h2 class="summary-title">Quick Summary</h2>
|
||||
<p class="summary-content">
|
||||
At our core, we value the vibrant community of individuals who make each line of code possible.
|
||||
With pride, we champion a license that is renowned as one of the most liberal in the industry,
|
||||
empowering users to unleash their creativity, explore new possibilities, and shape their digital
|
||||
experiences.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="permissions-grid">
|
||||
<!-- Can -->
|
||||
<div class="permission-card">
|
||||
<div class="permission-header">
|
||||
<div class="permission-icon"
|
||||
style="background: linear-gradient(135deg, #48bb7815 0%, #38a16915 100%); color: #48bb78;">
|
||||
✅
|
||||
</div>
|
||||
<h3 class="permission-title">Can</h3>
|
||||
</div>
|
||||
<ul class="permission-list can-list">
|
||||
<li class="permission-item">You may use the work commercially.</li>
|
||||
<li class="permission-item">You may make changes to the work.</li>
|
||||
<li class="permission-item">You may distribute the compiled code and/or source.</li>
|
||||
<li class="permission-item">You may incorporate the work into something that has a more restrictive
|
||||
license.
|
||||
</li>
|
||||
<li class="permission-item">You may use the work for private use.</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Must -->
|
||||
<div class="permission-card">
|
||||
<div class="permission-header">
|
||||
<div class="permission-icon"
|
||||
style="background: linear-gradient(135deg, #667eea15 0%, #764ba215 100%); color: #667eea;">
|
||||
✍️
|
||||
</div>
|
||||
<h3 class="permission-title">Must</h3>
|
||||
</div>
|
||||
<ul class="permission-list must-list">
|
||||
<li class="permission-item">You must include the copyright notice in all copies or substantial uses
|
||||
of the work.
|
||||
</li>
|
||||
<li class="permission-item">You must include the license notice in all copies or substantial uses of
|
||||
the work.
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<!-- Cannot -->
|
||||
<div class="permission-card">
|
||||
<div class="permission-header">
|
||||
<div class="permission-icon"
|
||||
style="background: linear-gradient(135deg, #fc818115 0%, #f5656515 100%); color: #fc8181;">
|
||||
❌
|
||||
</div>
|
||||
<h3 class="permission-title">Cannot</h3>
|
||||
</div>
|
||||
<ul class="permission-list cannot-list">
|
||||
<li class="permission-item">The work is provided "as is". You may not hold the author liable.</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="full-license">
|
||||
<div class="full-license-header">
|
||||
<h2 class="full-license-title">MIT License</h2>
|
||||
<p class="full-license-subtitle">Full License Text</p>
|
||||
</div>
|
||||
<div class="license-text">
|
||||
Copyright © Grudinin Andrew (din9xtr)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
|
||||
associated documentation files (the "Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial
|
||||
portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
||||
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
||||
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
21
resources/views/login.php
Executable file
21
resources/views/login.php
Executable file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
/** @var Din9xtrCloud\ViewModels\Login\LoginViewModel $viewModel */
|
||||
|
||||
?>
|
||||
<div class="login-card">
|
||||
<h1><?= htmlspecialchars($viewModel->title ?? 'Login') ?></h1>
|
||||
<?php if (!empty($viewModel->error)) : ?>
|
||||
<p class="error"><?= htmlspecialchars($viewModel->error) ?></p>
|
||||
<?php endif; ?>
|
||||
<form method="POST" action="/login" class="login-form">
|
||||
<label>
|
||||
<input type="text" name="username" required placeholder="Enter username">
|
||||
</label>
|
||||
<label>
|
||||
<input type="password" name="password" required placeholder="Enter password">
|
||||
</label>
|
||||
<button type="submit">Sign In</button>
|
||||
<input type="hidden" name="_csrf"
|
||||
value="<?= htmlspecialchars($viewModel->csrf) ?>">
|
||||
</form>
|
||||
</div>
|
||||
Reference in New Issue
Block a user