initialize project documentation and setup instructions
This commit is contained in:
58
templates/403.html
Normal file
58
templates/403.html
Normal file
@@ -0,0 +1,58 @@
|
||||
<!--
|
||||
* © 2025-2026 Skoci Admin
|
||||
* Designed and Developed by Abimanyu
|
||||
* Contact : abimanyuag12@gmail.com
|
||||
* All Rights Reserved
|
||||
-->
|
||||
|
||||
<!DOCTYPE html>
|
||||
{% load static %}
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="403 Error - Access Denied">
|
||||
<link rel="icon" type="image/x-icon" href="{% static 'images/favicon.ico' %}">
|
||||
<title>{{ alt_name_apps }} | 403 - Access Denied</title>
|
||||
<!-- CSS: Framework -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/bootstrap/bootstrap.min.css' %}">
|
||||
<!-- CSS: Icons -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/remixicon/remixicon.css' %}">
|
||||
<!-- CSS: Custom -->
|
||||
<link href="{% static 'css/style.css' %}" rel="stylesheet">
|
||||
{% block style %}<style>html, body { margin: 0; padding: 0; height: 100%; }</style>{% endblock style %}
|
||||
<!-- Icons -->
|
||||
</head>
|
||||
<body>
|
||||
<div class="container d-flex align-items-center justify-content-center min-vh-100">
|
||||
<div class="col-md-8 col-lg-6">
|
||||
<div class="card shadow-lg border-0 text-center">
|
||||
<div class="card-body p-5">
|
||||
<h1 class="display-1 fw-bold text-danger mb-0">403</h1>
|
||||
<h4 class="fw-bold mb-3">Forbidden</h4>
|
||||
<p class="text-muted mb-4 fsmall px-5">
|
||||
You do not have the required permissions to access this page
|
||||
or perform this action.
|
||||
</p>
|
||||
<div class="d-flex justify-content-center gap-2">
|
||||
<button onclick="history.back()" class="btn bz-btn-primary btn-bz-size">← Go Back</button>
|
||||
<a href="/" class="btn bz-btn-outline-primary btn-bz-size">Go to Dashboard</a>
|
||||
</div>
|
||||
<hr class="my-4 opacity-50">
|
||||
<div class="text-center">
|
||||
<p class="fsmall text-muted mb-2">
|
||||
If you believe this is an error, please contact:
|
||||
</p>
|
||||
<a href="mailto:{{ it_support_email }}" class="small text-muted text-decoration-none d-inline-flex align-items-center transition-link">
|
||||
<i class="ri-customer-service-2-line me-2"></i> Contact Support
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-4 fsmall text-muted fw-normal">
|
||||
<div>{{ brand_copyright|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
62
templates/404.html
Normal file
62
templates/404.html
Normal file
@@ -0,0 +1,62 @@
|
||||
<!--
|
||||
* © 2025-2026 Skoci Admin
|
||||
* Designed and Developed by Abimanyu
|
||||
* Contact : abimanyuag12@gmail.com
|
||||
* All Rights Reserved
|
||||
-->
|
||||
|
||||
{% load static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="description" content="404 Error - Page Not Found">
|
||||
<link rel="icon" type="image/x-icon" href="{% static 'images/favicon.ico' %}">
|
||||
<title>{{ alt_name_apps }} | 404 - Page Not Found</title>
|
||||
<!-- CSS: Framework -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/bootstrap/bootstrap.min.css' %}">
|
||||
<!-- CSS: Icons -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/remixicon/remixicon.css' %}">
|
||||
<!-- CSS: Custom -->
|
||||
<link href="{% static 'css/style.css' %}" rel="stylesheet">
|
||||
{% block style %}<style>html, body { margin: 0; padding: 0; height: 100%; }</style>{% endblock style %}
|
||||
</head>
|
||||
<body>
|
||||
<div class="container d-flex align-items-center justify-content-center min-vh-100">
|
||||
<div class="col-md-8 col-lg-6">
|
||||
<div class="card shadow-lg border-0 text-center">
|
||||
<div class="card-body p-5">
|
||||
<h1 class="display-1 fw-bold text-warning mb-0">404</h1>
|
||||
<h4 class="fw-bold mb-3">Page Not Found</h4>
|
||||
<p class="text-muted mb-4 fsmall px-5">
|
||||
Sorry, the page you are looking for does not exist
|
||||
or may have been moved.
|
||||
</p>
|
||||
<div class="d-flex justify-content-center gap-2">
|
||||
<button onclick="history.back()" class="btn bz-btn-primary btn-bz-size">
|
||||
← Go Back
|
||||
</button>
|
||||
|
||||
<a href="/" class="btn bz-btn-outline-primary btn-bz-size">
|
||||
Go to Dashboard
|
||||
</a>
|
||||
</div>
|
||||
<hr class="my-4 opacity-50">
|
||||
<div class="text-center">
|
||||
<p class="fsmall text-muted mb-2">
|
||||
If you believe this is an error, please contact:
|
||||
</p>
|
||||
<a href="mailto:{{ it_support_email }}" class="small text-muted text-decoration-none d-inline-flex align-items-center transition-link">
|
||||
<i class="ri-customer-service-2-line me-2"></i> Contact Support
|
||||
</a>
|
||||
</div>
|
||||
<div class="mt-4 fsmall text-muted fw-normal">
|
||||
<div>{{ brand_copyright|safe }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
105
templates/base.html
Normal file
105
templates/base.html
Normal file
@@ -0,0 +1,105 @@
|
||||
<!--
|
||||
* © 2025-2026 Skoci Admin
|
||||
* Designed and Developed by Abimanyu
|
||||
* Contact : abimanyuag12@gmail.com
|
||||
* All Rights Reserved
|
||||
-->
|
||||
|
||||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="view-transition" content="same-origin">
|
||||
<title>{{ alt_name_apps }} {% if menu %}| {{ menu }}{% endif %}</title>
|
||||
<link rel="icon" type="image/x-icon" href="{% static 'images/favicon.ico' %}">
|
||||
<!-- CSS: Framework -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/bootstrap/bootstrap.min.css' %}">
|
||||
<!-- CSS: Icons -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/bootstrap-icons/bootstrap-icons.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'vendor/remixicon/remixicon.css' %}">
|
||||
<!-- CSS: Plugins -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/datatables/dataTables.bootstrap5.min.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'vendor/datatables/responsive.bootstrap5.min.css' %}">
|
||||
<!-- CSS: Custom -->
|
||||
<link rel="stylesheet" href="{% static 'css/style.css' %}">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="bz-preloader">
|
||||
<div class="bz-spinner"></div>
|
||||
</div>
|
||||
{% include 'layouts/header.html' %}
|
||||
{% include 'layouts/sidebar.html' %}
|
||||
<!-- main-content -->
|
||||
<div class="main-content">
|
||||
<div class="container-fluid py-4">
|
||||
{% if messages %}
|
||||
<div class="row mt-2">
|
||||
{% for message in messages %}
|
||||
<div class="alert bz-alert bz-alert-{% if message.tags == 'error' %}danger{% else %}{{ message.tags }}{% endif %} alert-dismissible fade show" role="alert">
|
||||
<div class="alert-content">
|
||||
<h5 class="fw-bold"><i class="ri-information-fill"></i> {{ message.tags|title }}</h5>
|
||||
<p>{{ message|safe }}</p>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal informasi -->
|
||||
<div class="modal fade" id="helpModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="exampleModalLabel">
|
||||
<i class="bi bi-info-circle"></i> Information
|
||||
</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="mt-3">
|
||||
<p class="px-3">{{ catatan|safe }}</p>
|
||||
<hr class="my-4">
|
||||
<div class="d-flex justify-content-end mb-4">
|
||||
<button type="button" class="btn bz-btn-outline-primary btn-bz-size me-2" data-bs-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="{% static 'vendor/jquery/jquery.min.js' %}"></script>
|
||||
<!-- Bootstrap -->
|
||||
<script src="{% static 'vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
|
||||
<!-- DataTables -->
|
||||
<script src="{% static 'vendor/datatables/jquery.dataTables.min.js' %}"></script>
|
||||
<script src="{% static 'vendor/datatables/dataTables.bootstrap5.min.js' %}"></script>
|
||||
<script src="{% static 'vendor/datatables/dataTables.responsive.min.js' %}"></script>
|
||||
<script src="{% static 'vendor/datatables/responsive.bootstrap5.min.js' %}"></script>
|
||||
<!-- Custom -->
|
||||
<script src="{% static 'js/main.js' %}"></script>
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('.tableDatatables').DataTable({
|
||||
responsive: true,
|
||||
language: {
|
||||
search: "",
|
||||
searchPlaceholder: "Search..."
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock script %}
|
||||
</body>
|
||||
</html>
|
||||
149
templates/layouts/header.html
Normal file
149
templates/layouts/header.html
Normal file
@@ -0,0 +1,149 @@
|
||||
{% load static %}
|
||||
<!-- topbar-right -->
|
||||
<div class="topbar-right">
|
||||
<a href="/" class="text-decoration-none">
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<img src="{% static 'images/logo.png' %}" alt="logo-icon">
|
||||
<div class="d-flex flex-column">
|
||||
<h5 class="small mb-0 fw-bold text-light text-uppercase" style="font-size: .8rem; opacity: .9;">
|
||||
{{ brand }}
|
||||
</h5>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
<button id="toggleSidebarRight" class="btn btn-sm toggle-btn">
|
||||
<i class="ri-arrow-left-s-line chevron"></i>
|
||||
</button>
|
||||
</div>
|
||||
<!-- topbar-main -->
|
||||
<div class="topbar-main">
|
||||
<div class="d-flex align-items-center gap-3" style="height: 79px;">
|
||||
<img class="d-lg-none" src="{% static 'images/logo.png' %}" alt="logo-icon">
|
||||
<button id="mobileToogle" class="btn btn-topbar d-lg-none d-flex align-items-center justify-content-center">
|
||||
<i class="ri-menu-2-line"></i>
|
||||
</button>
|
||||
<div class="vr d-lg-none"></div>
|
||||
<h5 class="fw-bold mb-0 text-uppercase fs-6 d-flex align-items-center">
|
||||
{{ name_apps }}
|
||||
</h5>
|
||||
</div>
|
||||
|
||||
<div class="d-flex align-items-center gap-3">
|
||||
<!-- User Profile -->
|
||||
<button
|
||||
class="btn btn-link text-secondary text-decoration-none d-flex align-items-center gap-3 p-0"
|
||||
type="button"
|
||||
data-bs-toggle="offcanvas"
|
||||
data-bs-target="#profileOffcanvas"
|
||||
aria-controls="profileOffcanvas"
|
||||
>
|
||||
<img src="{% static 'images/profile.png' %}" alt="Profile Avatar" class="image-profile rounded-circle">
|
||||
<div class="d-lg-flex align-items-center gap-1 d-none">
|
||||
<div class="d-flex flex-column align-items-start lh-sm">
|
||||
<div class="fw-bold" style="font-size: 1rem;">{{ user.first_name }} {% if user.last_name %}{{ user.last_name|slice:":1" }}.{% endif %}</div>
|
||||
<div class="text-muted small opacity-75">{% if user.is_superuser %}Superuser{% else %}Admin{% endif %}</div>
|
||||
</div>
|
||||
<!-- <i class="ti ti-chevron-down align-middle"></i> -->
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- topbar-secondary -->
|
||||
<div class="topbar-secondary d-flex align-items-center justify-content-between">
|
||||
<div class="d-flex align-items-center">
|
||||
<a href="javascript:history.back()" class="btn-back d-none d-lg-block">
|
||||
<i class="ri-arrow-left-double-line"></i>
|
||||
</a>
|
||||
<div class="vr mx-3 d-none d-lg-block"></div>
|
||||
<h5 class="fw-medium mb-0 fs-6 text-light">{{ menu }}</h5>
|
||||
</div>
|
||||
<nav>
|
||||
<ul class="nav nav-pills d-none d-lg-flex overflow-auto flex-nowrap align-items-center">
|
||||
{% for menu in context_topbar %}
|
||||
<li class="nav-item" role="presentation">
|
||||
<a href="{{ menu.url }}" class="nav-link {% if menu.url == '#' %}disabled active{% endif %}">{{ menu.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if additional_button and context_topbar %}<div class="vr me-3 align-self-center bg-light" style="height: 18px; opacity: 0.4;"></div>{% endif %}
|
||||
{% if additional_button %}
|
||||
<li class="nav-item">{{ additional_button|safe }}</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% if additional_button and context_topbar %}
|
||||
<div class="dropdown d-lg-none">
|
||||
<button class="btn text-light border-0 p-2" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="ri-menu-line fs-5"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow-sm bz-dropdown-menu">
|
||||
{% for menu in context_topbar %}
|
||||
<li>
|
||||
<a class="dropdown-item {% if menu.url == '#' %}disabled active{% endif %}" href="{{ menu.url }}">{{ menu.title }}</a>
|
||||
</li>
|
||||
{% endfor %}
|
||||
{% if additional_button and context_topbar %}<li class="px-2"><hr class="dropdown-divider my-2 opacity-25 border-light"></li>{% endif %}
|
||||
{% if additional_button %}
|
||||
<li>
|
||||
{{ additional_button|safe }}
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
<!-- Offcanvas Profile Panel -->
|
||||
<div class="offcanvas offcanvas-end" tabindex="-1" id="profileOffcanvas" aria-labelledby="profileOffcanvasLabel">
|
||||
<div class="offcanvas-header border-bottom">
|
||||
<div class="d-flex align-items-center w-100">
|
||||
<div class="flex-grow-1">
|
||||
<p class="offcanvas-title mb-0 fw-bold" id="profileOffcanvasLabel">
|
||||
Your Account
|
||||
</p>
|
||||
<div class="fsmall mb-0">Last sign-in: {{ user.last_login|date:"d/m/Y H:i" }}</div>
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white small" data-bs-dismiss="offcanvas" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="offcanvas-body p-0">
|
||||
<div class="p-4 text-center text-account-dropdown">
|
||||
<div class="position-relative d-inline-block mx-auto">
|
||||
<div class="profile-img-container">
|
||||
<img src="{% static 'images/profile.png' %}" class="img img-thumbnail rounded-circle w-50" alt="Profile Avatar">
|
||||
</div>
|
||||
</div>
|
||||
<div class="fw-bold mt-3 mb-2 opacity-75" style="font-size: 1rem;">{{ user.get_full_name|upper }}</div>
|
||||
<div class="mt-2">
|
||||
<div class="small text-muted opacity-75">
|
||||
<span>{% if user.is_superuser %}Superuser{% else %}Admin{% endif %}</span>
|
||||
</div>
|
||||
<div class="small text-muted opacity-75">
|
||||
{{ user.email }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-3 text-center">
|
||||
<button type="button" class="btn btn-danger btn-bz-size" onclick="location.href='{% url 'logout' %}'">
|
||||
<i class="ri-logout-box-r-line"></i> Sign Out
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Copyright -->
|
||||
<div class="offcanvas-footer p-3 bg-light"> <div class="text-center text-muted small" style="font-size: 0.75rem;">
|
||||
<div class="fw-semibold text-dark mb-1">
|
||||
{{ brand_copyright|safe }}
|
||||
</div>
|
||||
|
||||
<div class="mb-1">
|
||||
{{ repository|safe }}
|
||||
</div>
|
||||
|
||||
<div class="d-inline-flex align-items-center justify-content-center">
|
||||
Built with
|
||||
<img src="{% static 'images/skoci.ico' %}" alt="Icon" width="14" height="14" class="mx-1">
|
||||
<span class="fw-semibold text-dark">Skoci Admin</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
133
templates/layouts/login.html
Normal file
133
templates/layouts/login.html
Normal file
@@ -0,0 +1,133 @@
|
||||
<!--
|
||||
* © 2025-2026 Skoci Admin
|
||||
* Designed and Developed by Abimanyu
|
||||
* Contact : abimanyuag12@gmail.com
|
||||
* All Rights Reserved
|
||||
-->
|
||||
|
||||
{% load static %}
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>{{ alt_name_apps }} | {{ menu|title }}</title>
|
||||
<link rel="icon" type="image/x-icon" href="{% static 'images/favicon.ico' %}">
|
||||
<!-- CSS: Framework -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/bootstrap/bootstrap.min.css' %}">
|
||||
<!-- CSS: Icons -->
|
||||
<link rel="stylesheet" href="{% static 'vendor/remixicon/remixicon.css' %}">
|
||||
<!-- CSS: Custom -->
|
||||
<link href="{% static 'css/style.css' %}" rel="stylesheet">
|
||||
{% block style %}<style>html, body { margin: 0; padding: 0; height: 100%; }</style>{% endblock style %}
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="bz-preloader">
|
||||
<div class="bz-spinner"></div>
|
||||
</div>
|
||||
<div class="split-login-container p-4">
|
||||
<div class="card shadow-lg border-0 login-card-container">
|
||||
<div class="row g-0 h-100" style="min-height: 550px;">
|
||||
<div class="col-md-6 login-logo-section text-center d-none d-md-flex flex-column justify-content-center align-items-center">
|
||||
<div class="p-4 w-100">
|
||||
<img src="{% static 'images/logo-1.png' %}" class="img-fluid mb-4 w-50" alt="Logo">
|
||||
<h5 class="fw-bold mb-1 text-uppercase text-white">{{ name_apps }}</h5>
|
||||
<div class="small text-white-50 mb-4">
|
||||
<span>{{ version }}</span>
|
||||
</div>
|
||||
<div class="text-center mt-5">
|
||||
<div class="small opacity-50 text-white text-uppercase" style="font-size: .6875rem;">
|
||||
{{ brand_copyright|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 login-form-section d-flex align-items-center justify-content-center">
|
||||
<div class="card-body p-4 p-md-5 w-100 position-relative" style="max-width: 450px;">
|
||||
<div class="login-brand-wrapper d-md-none">
|
||||
<div class="login-brand-circle">
|
||||
<img src="{% static 'images/logo-1.png' %}" class="w-75" alt="Logo Icon">
|
||||
</div>
|
||||
<h5 class="fw-bolder mt-2 mb-0 text-uppercase text-dark">{{ name_apps }}</h5>
|
||||
<div class="small opacity-50 mb-3">
|
||||
<span>{{ version }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<h4 class="mb-1 fw-bold text-dark mt-md-0 mt-3 text-center text-md-start">{{ menu }}</h4>
|
||||
<p class="text-muted mb-4 small text-center text-md-start">{% if menu == 'Sign In' %}Access your account{% else %}Join us{% endif %} to continue.</p>
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert bz-alert bz-alert-{% if message.tags == 'error' %}danger{% else %}{{ message.tags }}{% endif %} alert-dismissible fade show mb-3" role="alert">
|
||||
<div class="alert-content">
|
||||
<h5 class="fw-bold"><i class="ri-information-fill"></i> {{ message.tags|title }}</h5>
|
||||
<p class="mb-0">{{ message|safe }}</p>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
<form method="POST" autocomplete="off">
|
||||
{% csrf_token %}
|
||||
<!-- Hidden input untuk redirect setelah login -->
|
||||
<input type="hidden" name="next" value="{{ request.GET.next }}">
|
||||
{% for field in form %}
|
||||
<div class="mb-3 text-start"> <label for="{{ field.id_for_label }}" class="form-label fw-semibold small">{{ field.label }}</label>
|
||||
{% if field.name == "password" %}
|
||||
<div class="input-group">
|
||||
{{ field }}
|
||||
<button class="btn btn-secondary" type="button" id="togglePassword">
|
||||
<i class="ri-eye-off-line"></i>
|
||||
</button>
|
||||
</div>
|
||||
{% else %}
|
||||
{{ field }}
|
||||
{% endif %}
|
||||
{% if field.errors %}
|
||||
<div class="text-danger small mt-1">{{ field.errors }}</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<div class="d-grid mt-4">
|
||||
<button type="submit" class="btn bz-btn-primary shadow-sm py-2">
|
||||
{{ icon }} {{ menu }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
<div class="d-md-none text-center mt-5">
|
||||
<hr class="text-muted opacity-25">
|
||||
<div class="small opacity-50 text-uppercase" style="font-size: .75rem;">
|
||||
{{ brand_copyright|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- jQuery -->
|
||||
<script src="{% static 'vendor/jquery/jquery.min.js' %}"></script>
|
||||
<!-- Bootstrap -->
|
||||
<script src="{% static 'vendor/bootstrap/js/bootstrap.bundle.min.js' %}"></script>
|
||||
<!-- Custom -->
|
||||
<script src="{% static 'js/main.js' %}"></script>
|
||||
|
||||
{% block script %}
|
||||
<script>
|
||||
const togglePassword = document.querySelector('#togglePassword');
|
||||
const password = document.querySelector('input[name="password"]');
|
||||
|
||||
if (togglePassword) {
|
||||
togglePassword.addEventListener('click', function (e) {
|
||||
const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
|
||||
password.setAttribute('type', type);
|
||||
this.querySelector('i').classList.toggle('ri-eye-line');
|
||||
this.querySelector('i').classList.toggle('ri-eye-off-line');
|
||||
});
|
||||
}
|
||||
</script>
|
||||
{% endblock script %}
|
||||
</body>
|
||||
</html>
|
||||
26
templates/layouts/sidebar.html
Normal file
26
templates/layouts/sidebar.html
Normal file
@@ -0,0 +1,26 @@
|
||||
<!-- sidebar-right -->
|
||||
<div class="sidebar-right">
|
||||
<ul class="nav flex-column">
|
||||
<li class="sidebar-title">
|
||||
<span>Overview</span>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{% if '/dashboard/' in request.path %}#{% else %}{% url 'dashboard' %}{% endif %}"
|
||||
class="nav-link {% if '/dashboard/' in request.path %}active{% endif %}" data-tooltip="Dashboard">
|
||||
<i class="ri-apps-fill"></i>
|
||||
<span class="text-wrapper">
|
||||
<span class="text-inner">Dashboard</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{% if '/form/' in request.path %}#{% else %}{% url 'form' %}{% endif %}"
|
||||
class="nav-link {% if '/form/' in request.path %}active{% endif %}" data-tooltip="Form">
|
||||
<i class="ri-apps-fill"></i>
|
||||
<span class="text-wrapper">
|
||||
<span class="text-inner">Form</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
5
templates/pages/dashboard copy.html
Normal file
5
templates/pages/dashboard copy.html
Normal file
@@ -0,0 +1,5 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
<!-- [ Main Content ] start -->
|
||||
{% block content %}
|
||||
{% endblock content %}
|
||||
141
templates/pages/dashboard.html
Normal file
141
templates/pages/dashboard.html
Normal file
@@ -0,0 +1,141 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static custom_filters %}
|
||||
<!-- [ Main Content ] start -->
|
||||
{% block content %}
|
||||
|
||||
{% if card_title %}
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 mb-4">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% if card_title %}
|
||||
<div class="card shadow-lg border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
|
||||
<h6 class="fw-bold mb-0">
|
||||
{{ card_title }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="row g-4 mb-4">
|
||||
{% for field in form %}
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="{{ field.id_for_label }}" class="form-label fw-semibold">
|
||||
{{ field.label }}
|
||||
</label>
|
||||
|
||||
{{ field }}
|
||||
|
||||
{% if field.help_text %}
|
||||
<div class="form-text ms-1">
|
||||
{{ field.help_text }}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{# HANYA tampilkan preview jika ini adalah field image #}
|
||||
{% if field.name == 'image' and enable_preview_image %}
|
||||
<div class="mt-2">
|
||||
{% if item.image %}
|
||||
<img id="preview" src="{{ item.image.url }}" class="img-thumbnail w-25" alt="Preview">
|
||||
{% else %}
|
||||
<img id="preview" src="{% static 'images/placeholder.jpg' %}" class="img-thumbnail w-25" alt="Default">
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<hr class="my-5">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
{% if item %}
|
||||
<button class="btn bz-btn-outline-primary btn-bz-size" onclick="window.history.back();">Cancel</button>
|
||||
{% endif %}
|
||||
<button type="submit" name="action" value="save" class="btn bz-btn-primary btn-bz-size">Submit</button>
|
||||
</div>
|
||||
<div>
|
||||
{{ buttons_action|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if items %}
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 mb-4">
|
||||
<div class="card shadow-lg border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
|
||||
<h6 class="fw-bold mb-0">
|
||||
List View
|
||||
</h6>
|
||||
{{ top_dropdown|safe }}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-bordered tableDatatables w-100">
|
||||
<thead>
|
||||
<tr class="align-middle">
|
||||
<th class="mw-25">No.</th>
|
||||
{% for key, value in fields.items %}
|
||||
<th>{{ value }}</th>
|
||||
{% endfor %}
|
||||
<th style="width:10%">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
{% for field in fields %}
|
||||
{% if field == 'image' %}
|
||||
<td style="width: 150px;">
|
||||
<img id="imagePreview" src="{% if item.image %}{{ item.image.url }}{% else %}{% static 'images/placeholder.jpg' %}{% endif %}" class="img-thumbnail" alt="Preview">
|
||||
</td>
|
||||
{% else %}
|
||||
<td>
|
||||
{{ item|get_field_value:field|safe }}
|
||||
{% if field == 'location' %}
|
||||
{% if item.maps_location %}
|
||||
<div class="mt-1">
|
||||
{# Hilangkan |urlencode jika datanya sudah berupa link utuh #}
|
||||
<a href="{{ item.maps_location }}"
|
||||
target="_blank"
|
||||
class="btn btn-link btn-sm p-0 text-decoration-none"
|
||||
style="font-size: 0.75rem;">
|
||||
View on Maps
|
||||
</a>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% elif field == 'event_name' %}
|
||||
{{ item.copy_link }}
|
||||
{% endif %}
|
||||
</td>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<td>
|
||||
{% if item.buttons_action %}
|
||||
<button type="button" class="btn btn-warning btn-bz-size dropdown-toggle" data-bs-toggle="collapse" data-bs-target="#act-{{ item.id }}">Options </button>
|
||||
<div id="act-{{ item.id }}" class="collapse mt-1">
|
||||
{% for value in item.buttons_action %}
|
||||
{{ value|safe }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% endblock content %}
|
||||
201
templates/pages/form copy.html
Normal file
201
templates/pages/form copy.html
Normal file
@@ -0,0 +1,201 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static custom_filters %}
|
||||
{% block content %}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-12 mb-4">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="tabs-1" role="tabpanel">
|
||||
<div class="card shadow-lg border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
|
||||
<h6 class="fw-bold mb-0">
|
||||
{{ card_title_second }}
|
||||
</h6>
|
||||
</div>
|
||||
{% if form_readonly %}
|
||||
<div class="row g-4">
|
||||
{% for field in form_readonly %}
|
||||
<div class="col-12 col-md-6">
|
||||
<label class="form-label fw-semibold">
|
||||
{{ field.label|title }}
|
||||
</label>
|
||||
<p class="form-control-plaintext border-bottom">
|
||||
{{ field }}
|
||||
</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<hr class="my-5">
|
||||
{% endif %}
|
||||
|
||||
<form method="post" id="main-form" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
<div class="row g-4">
|
||||
{% if reject_reason %}
|
||||
{{ reject_reason }}
|
||||
{% endif %}
|
||||
{% for field in form %}
|
||||
<div class="col-12 col-md-6">
|
||||
{% if field.name == 'file' %}
|
||||
<label for="{{ field.label }}" class="form-label fw-semibold">
|
||||
{{ field.label|title }}
|
||||
</label>
|
||||
<div class="file-input-wrapper">
|
||||
{{ field }}
|
||||
{# <input type="hidden" name="delete_existing_file" id="delete_existing_file" value="false"> #}
|
||||
<label for="id_attachments" class="file-input-label">
|
||||
<i class="bi bi-cloud-arrow-up"></i>
|
||||
<div class="file-input-text">
|
||||
<span>Click or drag to upload files</span>
|
||||
{% if field.help_text %}
|
||||
<div class="form-text">
|
||||
{{ field.help_text }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div id="file_preview_container" class="file-preview" style="{% if form.instance.file %}display: block;{% else %}display: none;{% endif %}">
|
||||
{% if form.instance.file %}
|
||||
<div class="file-item" id="existing-file-{{ form.instance.pk }}">
|
||||
<div class="file-info d-flex align-items-center p-2">
|
||||
<div class="icon-wrapper rounded-circle bg-dark bg-opacity-10 d-flex justify-content-center align-items-center"
|
||||
data-extension="{{ form.instance.file.name|slice:'-3:' }}">
|
||||
<!-- Icon akan di-generate lewat JS -->
|
||||
</div>
|
||||
|
||||
<div class="file-details">
|
||||
<div class="file-name fw-bold">{{ form.instance.file.name|cut:"dms/" }}</div>
|
||||
<div class="file-size text-muted small">
|
||||
{{ form.instance.file.size|filesizeformat }} (Uploaded)
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% comment %}
|
||||
<button type="button" class="file-remove" onclick="showDeleteConfirmation('id_attachments', 'file_preview_container', 0)">
|
||||
<i class="bi bi-x"></i>
|
||||
</button>
|
||||
{% endcomment %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="form-text ms-1">
|
||||
You can attach any relevant supporting documents here.
|
||||
</div>
|
||||
{% else %}
|
||||
<label for="{{ field.label }}" class="form-label fw-semibold">
|
||||
{{ field.label|title }}
|
||||
</label>
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<div class="form-text ms-1">
|
||||
{{ field.help_text }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if field.errors %}
|
||||
<div class="form-text text-danger ms-1">
|
||||
{{ field.errors }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
{{ form.errors }}
|
||||
</div>
|
||||
<hr class="my-5">
|
||||
<div class="d-flex justify-content-end">
|
||||
{{ cancel_btn|safe }}
|
||||
<button class="btn btn-primary btn-new-size" type="submit">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="tabs-2" role="tabpanel">
|
||||
<div class="card shadow-lg border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
|
||||
<h6 class="fw-bold mb-0">
|
||||
{{ tab_2|plural }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-bordered tableDatatables w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No.</th>
|
||||
{% for key, value in fields.items %}
|
||||
<th>{{ value }}</th>
|
||||
{% endfor %}
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
{% for field in fields %}
|
||||
<td>{{ item|get_field_value:field|safe }}</td>
|
||||
{% endfor %}
|
||||
<td>
|
||||
{% if item.buttons_action %}
|
||||
<button type="button" class="btn btn-warning btn-new-size dropdown-toggle" data-bs-toggle="collapse" data-bs-target="#act-{{ item.id }}">Options </button>
|
||||
<div id="act-{{ item.id }}" class="collapse mt-1">
|
||||
{% for value in item.buttons_action %}
|
||||
{{ value|safe }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% else %}--{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.select2-multiple').select2({
|
||||
theme: 'bootstrap-5',
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
{% if document_ajax %}
|
||||
ajax: {
|
||||
url: "{{ document_ajax }}",
|
||||
data: params => ({ term: params.term }),
|
||||
processResults: data => ({ results: data.results }),
|
||||
cache: true, // Jika user mengetik kata yang sama, tidak akan request ke server lagi, hasil lama langsung dipakai.
|
||||
}
|
||||
{% endif %}
|
||||
});
|
||||
|
||||
$('.select2-tags').select2({
|
||||
theme: 'bootstrap-5',
|
||||
tags: true,
|
||||
// tokenSeparators: [',', ' '],
|
||||
allowClear: true,
|
||||
width: '100%',
|
||||
{% if tag_ajax %}
|
||||
ajax: {
|
||||
url: "{{ tag_ajax }}",
|
||||
data: params => ({ term: params.term }),
|
||||
processResults: data => ({ results: data.results }),
|
||||
cache: true, // Jika user mengetik kata yang sama, tidak akan request ke server lagi, hasil lama langsung dipakai.
|
||||
}
|
||||
{% endif %}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% endblock scripts %}
|
||||
|
||||
{% endblock content %}
|
||||
119
templates/pages/form.html
Normal file
119
templates/pages/form.html
Normal file
@@ -0,0 +1,119 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static custom_filters %}
|
||||
<!-- [ Main Content ] start -->
|
||||
{% block content %}
|
||||
|
||||
{% if card_form %}
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 mb-4">
|
||||
<form method="post" enctype="multipart/form-data">
|
||||
{% csrf_token %}
|
||||
{% if card_form %}
|
||||
<div class="card shadow-lg border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
|
||||
<h6 class="fw-bold mb-0">
|
||||
{{ card_form }}
|
||||
</h6>
|
||||
</div>
|
||||
<div class="row g-4 mb-4">
|
||||
{% for field in form %}
|
||||
<div class="col-12 col-md-6">
|
||||
<label for="{{ field.id_for_label }}" class="form-label fw-semibold">
|
||||
{{ field.label }}
|
||||
</label>
|
||||
{{ field }}
|
||||
{% if field.help_text %}
|
||||
<div class="form-text ms-1">
|
||||
{{ field.help_text }}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
<hr class="my-5">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div>
|
||||
{% if item %}
|
||||
<button class="btn bz-btn-outline-primary btn-bz-size" onclick="window.history.back();">Cancel</button>
|
||||
{% endif %}
|
||||
<button type="submit" name="action" value="save" class="btn bz-btn-primary btn-bz-size">Submit</button>
|
||||
</div>
|
||||
<div>
|
||||
{{ buttons_action|safe }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if card_list %}
|
||||
<div class="row mt-3">
|
||||
<div class="col-12 mb-4">
|
||||
<div class="card shadow-lg border-0">
|
||||
<div class="card-body p-5">
|
||||
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-4">
|
||||
<h6 class="fw-bold mb-0">
|
||||
{{ card_list }}
|
||||
</h6>
|
||||
{# Jika ada dropdown #}
|
||||
{% comment %}{{ top_card_dropdown|safe }}{% endcomment %}
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover table-bordered tableDatatables w-100">
|
||||
<thead>
|
||||
<tr class="align-middle">
|
||||
<th class="mw-25">No.</th>
|
||||
{# Menggunakan Objek Form #}
|
||||
{% for field in form %}
|
||||
<th>{{ field.label }}</th>
|
||||
{% endfor %}
|
||||
{# Menggunakan Mapping Label #}
|
||||
{% for key, value in fields.items %}
|
||||
<th>{{ value }}</th>
|
||||
{% endfor %}
|
||||
<th style="width:10%">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
{% for item in items %}
|
||||
<tr>
|
||||
<td>{{ forloop.counter }}</td>
|
||||
{# Menggunakan Objek Form #}
|
||||
{% for field in form %}
|
||||
<td>
|
||||
{{ item|get_field_value:field.name|safe }}
|
||||
</td>
|
||||
{% endfor %}
|
||||
{# Menggunakan Mapping Label #}
|
||||
{% for field in fields %}
|
||||
<td>{{ item|get_field_value:field|safe }}{{ field }}</td>
|
||||
{% endfor %}
|
||||
<td>
|
||||
{% if item.buttons_action %}
|
||||
<button type="button" class="btn btn-warning btn-bz-size dropdown-toggle" data-bs-toggle="collapse" data-bs-target="#act-{{ item.id }}">Options </button>
|
||||
<div id="act-{{ item.id }}" class="collapse mt-1">
|
||||
{% for value in item.buttons_action %}
|
||||
{{ value|safe }}
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% endblock content %}
|
||||
Reference in New Issue
Block a user