diff --git a/.gitignore b/.gitignore index c0739ce4ef0b8293ec8d34f428377bf9fcf5af8d..7e6811adf6066c047eb2fca79f1f49238d300bc2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,6 +15,7 @@ media /static/ media/ .coverage +virtualenv # If your build process includes running collectstatic, then you probably don't need or want to include staticfiles/ # in your Git repository. Update and uncomment the following line accordingly. diff --git a/administration/templates/administration/base_administrasi.html b/administration/templates/administration/base_administrasi.html index 4e8acf203c9f51e8a259f7a65a475bc57450ab56..e92e0277c2ab9096266b43ea3670c0fb41e39ec0 100644 --- a/administration/templates/administration/base_administrasi.html +++ b/administration/templates/administration/base_administrasi.html @@ -68,7 +68,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> diff --git a/administration/templates/administration/base_administrasi2.html b/administration/templates/administration/base_administrasi2.html index cf48a013a723adf31ceaea1039ed8c1e76aae3da..a731025ecefb52cbc43d5499d45074907923029c 100644 --- a/administration/templates/administration/base_administrasi2.html +++ b/administration/templates/administration/base_administrasi2.html @@ -4,6 +4,7 @@ <html lang="en"> <!-- Static assets --> <head> + <title>Digipus</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> @@ -67,7 +68,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> diff --git a/administration/templates/administration/data_statistik.html b/administration/templates/administration/data_statistik.html index 2aad8e549f34095ff42972a7c2c5ad91691fa478..17df72575d35c2a457fe0ae1500c4af991e0abdd 100644 --- a/administration/templates/administration/data_statistik.html +++ b/administration/templates/administration/data_statistik.html @@ -28,7 +28,7 @@ <div class="h5 mb-0 font-weight-bold text-gray-800">{{chart_data.total.0}}</div> </div> <div class="col-auto"> - <i class="fas fa-eye" aria-hidden="true"></i> + <em class="fas fa-eye" aria-hidden="true"></em> </div> </div> </div> @@ -45,7 +45,7 @@ <div class="h5 mb-0 font-weight-bold text-gray-800">{{chart_data.total.1}}</div> </div> <div class="col-auto"> - <i class="fas fa-download" aria-hidden="true"></i> + <em class="fas fa-download" aria-hidden="true"></em> </div> </div> </div> @@ -62,7 +62,7 @@ <div class="h5 mb-0 font-weight-bold text-gray-800">{{chart_data.total.2}}</div> </div> <div class="col-auto"> - <i class="fas fa-thumbs-up" aria-hidden="true"></i> + <em class="fas fa-thumbs-up" aria-hidden="true"></em> </div> </div> </div> @@ -79,7 +79,7 @@ <div class="h5 mb-0 font-weight-bold text-gray-800">{{chart_data.total.3}}</div> </div> <div class="col-auto"> - <i class="fas fa-comments fa-2x text-gray-300"></i> + <em class="fas fa-comments fa-2x text-gray-300"></em> </div> </div> </div> @@ -100,7 +100,7 @@ <!-- <div class="dropdown no-arrow"> <a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> - <i class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></i> + <em class="fas fa-ellipsis-v fa-sm fa-fw text-gray-400"></em> </a> <div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink"> diff --git a/administration/templates/detail_admin.html b/administration/templates/detail_admin.html index 2f86f7006c304af25c06382f4433ed408ffabf14..5105c7706cce8755a67c0c411a24579ef161d9db 100644 --- a/administration/templates/detail_admin.html +++ b/administration/templates/detail_admin.html @@ -19,31 +19,46 @@ <h4>{{ user.email }}</h4> <h4>{{ user.biography }}</h4> <div class="profile-margin"></div> - <table> - <tr> - <td class="profile-data">Instansi</td> - <td>{{ user.instansi }}</td> - </tr> - - <td class="profile-data">LinkedIn</td> - <td><a href="https://linkedin.com">{{ user.linkedin }}</a></td> - </tr> - - <tr> - <td class="profile-data">Facebook</td> - <td><a href="https://facebook.com">{{ user.facebook }}</a></td> - </tr> - - <tr> - <td class="profile-data">Twitter</td> - <td><a href="https://twitter.com">{{ user.twitter }}</a></td> - </tr> - - <tr> - <td class="profile-data">Instagram</td> - <td><a href="https://instagram.com">{{ user.instagram }}</a></td> - </tr> - </table> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + instansi + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + {{user.instansi}} + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + LinkedIn + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://linkedin.com">{{ user.linkedin }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Facebook + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://facebook.com">{{ user.facebook }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Twitter + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://twitter.com">{{ user.twitter }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Instagram + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://instagram.com">{{ user.instagram }}</a> + </div> + </div> <a class="btn btn-primary btn-admin" href="/administration/kelola-admin/">Kembali ke Kelola Admin</a> </div> </div> diff --git a/administration/templates/detail_kontri_admin.html b/administration/templates/detail_kontri_admin.html index fb425130b9478304df78d175dcc1dccec0946072..ef4ff27d8bb210b497fc24fa18160e3ae3273d81 100644 --- a/administration/templates/detail_kontri_admin.html +++ b/administration/templates/detail_kontri_admin.html @@ -18,31 +18,46 @@ <h4>{{ user.email }}</h4> <h4>{{ user.biography }}</h4> <div class="profile-margin"></div> - <table> - <tr> - <td class="profile-data">Instansi</td> - <td>{{ user.instansi }}</td> - </tr> - - <td class="profile-data">LinkedIn</td> - <td><a href="https://linkedin.com">{{ user.linkedin }}</a></td> - </tr> - - <tr> - <td class="profile-data">Facebook</td> - <td><a href="https://facebook.com">{{ user.facebook }}</a></td> - </tr> - - <tr> - <td class="profile-data">Twitter</td> - <td><a href="https://twitter.com">{{ user.twitter }}</a></td> - </tr> - - <tr> - <td class="profile-data">Instagram</td> - <td><a href="https://instagram.com">{{ user.instagram }}</a></td> - </tr> - </table> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + instansi + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + {{user.instansi}} + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + LinkedIn + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://linkedin.com">{{ user.linkedin }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Facebook + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://facebook.com">{{ user.facebook }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Twitter + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://twitter.com">{{ user.twitter }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Instagram + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://instagram.com">{{ user.instagram }}</a> + </div> + </div> <a class="btn btn-primary btn-admin" href="/administration/kelola-kontributor/">Kembali ke Kelola Kontributor</a> </div> </div> diff --git a/administration/templates/detail_verif.html b/administration/templates/detail_verif.html index 18b1751c9bec8649249ece282e2e92f14117303d..a5755d3980c9120fdf5c6eec648162d29205b6df 100644 --- a/administration/templates/detail_verif.html +++ b/administration/templates/detail_verif.html @@ -8,7 +8,7 @@ Pratinjau Materi <!-- Sidebar Toggle (Topbar) --> <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3"> - <i class="fa fa-bars"></i> + <em class="fa fa-bars"></em> </button> <div class="sidebar-brand-text mx-3">Pratinjau Materi</div> @@ -53,7 +53,7 @@ Pratinjau Materi <div class="info-wrapper"> <div class="info" id="1"> <dt class="col col-4"> - <p class="info-name">Verifikatur</p> + <p class="info-name"><strong>Verifikatur</strong></p> </dt> <dd> <p class="info-content">{{verification_report.user.name}}</p> @@ -61,7 +61,7 @@ Pratinjau Materi </div> <div class="info" id="1"> <dt class="col col-4"> - <p class="info-name">Waktu Verifikasi</p> + <p class="info-name"><strong>Waktu Verifikasi</strong></p> </dt> <dd> <p class="info-content">{{verification_report.timestamp}}</p> @@ -69,7 +69,7 @@ Pratinjau Materi </div> <div class="info" id="1"> <dt class="col col-4"> - <p class="info-name">Status Materi</p> + <p class="info-name"><strong>Status Materi</strong></p> </dt> <dd> <p class="info-content">{{verification_report.status}}</p> diff --git a/administration/templates/kelola_admin.html b/administration/templates/kelola_admin.html index 1af6884bf2e244ff5cc323b2f94dfce561f236b9..dd020c9771ca6b73161182317499809216bf6e16 100644 --- a/administration/templates/kelola_admin.html +++ b/administration/templates/kelola_admin.html @@ -15,7 +15,7 @@ <div class="card-header py-3"> <div class="d-flex"> <div class="mr-auto p-2"> - <h6 class="m-0 font-weight-bold text-primary">Tabel Daftar Admin</h6> + <h6 id="table-description" class="m-0 font-weight-bold text-primary">Tabel Daftar Admin</h6> </div> <div class="p-2"> <a href="/administration/kelola-admin/tambah/" class="accept-button button-decoration button-header">Buat Akun Baru</a> @@ -24,7 +24,7 @@ </div> <div class="card-body"> <div class="table-responsive"> - <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0"> + <table aria-describedby="table-description" class="table table-bordered" id="dataTable"> <thead> <tr> <th scope="col">Nama</th> diff --git a/administration/templates/kelola_kontributor.html b/administration/templates/kelola_kontributor.html index 0fdfe526aeb6b32b9e3c57643beb2472a965a75f..21b94fc5bc769c604ed0e78dddcc854b05f8dc8b 100644 --- a/administration/templates/kelola_kontributor.html +++ b/administration/templates/kelola_kontributor.html @@ -13,25 +13,25 @@ <!-- DataTales Example --> <div class="card shadow mb-4"> <div class="card-header py-3"> - <h6 class="m-0 font-weight-bold text-primary">Tabel Daftar Kontributor</h6> + <h6 id="table-description" class="m-0 font-weight-bold text-primary">Tabel Daftar Kontributor</h6> </div> <div class="card-body"> <div class="table-responsive"> - <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0"> + <table aria-describedby="table-description" class="table table-bordered" id="dataTable" width="100%" cellspacing="0"> <thead> <tr> - <th>Nama</th> - <th>NIK</th> - <th>Instansi</th> - <th>Detail</th> + <th scope="col">Nama</th> + <th scope="col">NIK</th> + <th scope="col">Instansi</th> + <th scope="col">Detail</th> </tr> </thead> <tfoot> <tr> - <th>Nama</th> - <th>NIK</th> - <th>Instansi</th> - <th>Detail</th> + <th scope="col">Nama</th> + <th scope="col">NIK</th> + <th scope="col">Instansi</th> + <th scope="col">Detail</th> </tr> </tr> </tfoot> diff --git a/administration/templates/laporan_materi.html b/administration/templates/laporan_materi.html index 5b92f17dce51124d0ff32ba034ac282131d2954e..33e489890c0eaa9979f3fd06567f559e8df7ebdb 100644 --- a/administration/templates/laporan_materi.html +++ b/administration/templates/laporan_materi.html @@ -76,11 +76,11 @@ </div> <div class="card shadow mb-4"> <div class="card-header py-3"> - <h6 class="m-0 font-weight-bold text-primary" id="titleTabelPending">Materi yang Diblokir</h6> + <h6 id="table-description" class="m-0 font-weight-bold text-primary" id="titleTabelPending">Materi yang Diblokir</h6> </div> <div class="card-body"> <div class="table-responsive"> - <table class="table table-bordered" id="dataTablePending" aria-describedby="titleTabelPending"> + <table aria-describedby="table-description" class="table table-bordered" id="dataTablePending" aria-describedby="titleTabelPending"> {% if not materi_diblokir %} Tidak ada materi yang diblokir {% else %} diff --git a/administration/templates/registrasi_admin.html b/administration/templates/registrasi_admin.html index 7d3a0151bb82231d953cbcbc96034ec44a3a8710..8da8fc6f3271dd7dd02a0e2374c1cfb3b4d50499 100644 --- a/administration/templates/registrasi_admin.html +++ b/administration/templates/registrasi_admin.html @@ -103,7 +103,7 @@ <!-- Sidebar Toggle (Topbar) --> <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3"> - <i class="fa fa-bars"></i> + <em class="fa fa-bars"></em> </button> <div class="sidebar-brand-text mx-3">Diskominfo Kota Depok</div> @@ -257,7 +257,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> <!-- Bootstrap core JavaScript--> diff --git a/administration/templates/setting_verifikasi.html b/administration/templates/setting_verifikasi.html index f21254ef032ac3fdae82641d1827a99e6c5403fd..aa5fbdf0f5462035f49f610aca5144a48c29d88c 100644 --- a/administration/templates/setting_verifikasi.html +++ b/administration/templates/setting_verifikasi.html @@ -112,7 +112,7 @@ <!-- Sidebar Toggle (Topbar) --> <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3"> - <i class="fa fa-bars"></i> + <em class="fa fa-bars"></em> </button> <div class="sidebar-brand-text mx-3">Diskominfo Kota Depok</div> @@ -172,7 +172,7 @@ <label>Deskripsi :</label>{{ form.description }}<br> <br> <div class="row"> - <button class="primary_btn save" style="border-radius:20px;" type="submit"><i class="far fa-save"></i> + <button class="primary_btn save" style="border-radius:20px;" type="submit"><em class="far fa-save"></em> Simpan</button> </div> </form> @@ -182,24 +182,24 @@ <!-- DataTales Example --> <div class="card shadow mb-4"> <div class="card-header py-3"> - <h6 class="m-0 font-weight-bold text-primary">Point Verifikasi Materi</h6> + <h6 id="table-description" class="m-0 font-weight-bold text-primary">Point Verifikasi Materi</h6> </div> <div class="card-body"> <div class="table-responsive"> - <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0"> + <table aria-describedby="table-description" class="table table-bordered" id="dataTable" width="100%" cellspacing="0"> <thead> <tr> - <th>Judul Verifikasi</th> - <th>Deskripsi</th> - <th></th> + <th scope="col">Judul Verifikasi</th> + <th scope="col">Deskripsi</th> + <th scope="col"></th> </tr> </thead> <tbody> {% for item in verification_settings %} <tr> - <th>{{item.title}}</th> - <th>{{item.description}}</th> - <th> </th> + <th scope="col">{{item.title}}</th> + <th scope="col">{{item.description}}</th> + <th scope="col"> </th> </tr> {% endfor %} </tbody> @@ -232,7 +232,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> <!-- <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" diff --git a/administration/templates/settings.html b/administration/templates/settings.html index 6381a4e088abdaa87f41c4d531d01183de455015..3f43715589699c8aa4ee113e4989679e8f5b29cd 100644 --- a/administration/templates/settings.html +++ b/administration/templates/settings.html @@ -281,9 +281,9 @@ <tbody> {% for item in items %} <tr> - <th>{{item.title}} {{item.name}}</th> - <th>{{item.description}}</th> - <th class="verif-buttons"> + <th scope="col">{{item.title}} {{item.name}}</th> + <th scope="col">{{item.description}}</th> + <th scope="col" class="verif-buttons"> {% if item.name is None %} <a href="/administration/setting/verification/{{ item.id }}/edit" @@ -377,9 +377,9 @@ <tbody> {% for item in items_archived %} <tr> - <th>{{item.title}} {{item.name}}</th> - <th>{{item.description}}</th> - <th>{{item.archived_by.name}}</th> + <th scope="col">{{item.title}} {{item.name}}</th> + <th scope="col">{{item.description}}</th> + <th scope="col">{{item.archived_by.name}}</th> </tr> {% endfor %} </tbody> diff --git a/app/templates/app/base_admin.html b/app/templates/app/base_admin.html index d8b93163621bbb7494764c66f0216ff1217ef447..73465184f28526320515eb1de9dda37b81dc887b 100644 --- a/app/templates/app/base_admin.html +++ b/app/templates/app/base_admin.html @@ -4,7 +4,7 @@ <html lang="en"> <head> - + <title>Digipus</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> @@ -75,7 +75,7 @@ <nav class="navbar navbar-expand navbar-light bg-white topbar mb-4 static-top shadow"> <!-- Sidebar Toggle (Topbar) --> <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3"> - <i class="fa fa-bars"></i> + <em class="fa fa-bars"></em> </button> <div class="sidebar-brand-text mx-3">Diskominfo Kota Depok</div> <!-- Topbar Navbar --> @@ -139,7 +139,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> <!-- Bootstrap core JavaScript--> diff --git a/app/templates/app/base_dashboard.html b/app/templates/app/base_dashboard.html index 0d5b034e451e352d040882b9d41e5dce595088c6..b8281931e7b8fae10fe76dd0477fee586206fcb2 100644 --- a/app/templates/app/base_dashboard.html +++ b/app/templates/app/base_dashboard.html @@ -4,6 +4,7 @@ <html lang="en"> <head> + <title>Digipus</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> @@ -64,7 +65,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> </body> diff --git a/app/templates/app/base_profile.html b/app/templates/app/base_profile.html index e21cb34dcfe7c051f68daedbb888b84c7ea22b49..6dc27646954f8d5b97e55725285ec708edfe6233 100644 --- a/app/templates/app/base_profile.html +++ b/app/templates/app/base_profile.html @@ -4,7 +4,7 @@ <html lang="en"> <head> - + <title>Digipus</title> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> @@ -66,7 +66,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> </body> diff --git a/app/templates/app/detail_materi.html b/app/templates/app/detail_materi.html index e15f5f9fa4cda0a0c915adec2200c784710696fb..191fe2d5609640b111399aadae506fb5b5a4cda8 100644 --- a/app/templates/app/detail_materi.html +++ b/app/templates/app/detail_materi.html @@ -260,6 +260,7 @@ </div> {% if materi_data.status == "APPROVE" %} <div id="komentar" class="container-fluid comments-wrapper p-0"> + {% if is_authenticated %} <div class="add-comments col col-8 bg-white shadow-sm rounded p-3 mb-3"> <form method="POST"> {% csrf_token %} @@ -272,6 +273,9 @@ </div> </form> </div> + {% else %} + <h3>Login terlebih dahulu untuk berkomentar</h3> + {% endif %} {% for comment in comment_data %} <div class="col col-8 comment shadow-sm p-3 mb-1 bg-white rounded"> <div class="d-flex bd-highlight mb-3 align-items-center user"> @@ -284,7 +288,7 @@ {% else %} <span style="background-color: #{{comment.profile}}" class="profile p-1 bd-highligh"></span> {% endif %} - <p class="p-1 bd-highligh m-0"><b>{{comment.user.name}}</b></p> + <p class="p-1 bd-highligh m-0"><strong>{{comment.user.name}}</strong></p> <p class="p-1 bd-highligh m-0">•</p> <p class="timestamp p-1 bd-highligh m-0 text-muted"> {{ comment.timestamp|naturaltime }} diff --git a/app/templates/app/includes/navbar_katalog_materi.html b/app/templates/app/includes/navbar_katalog_materi.html index 14db671ecb64fadb5319600b914023baa852bdad..c747e1cfb734c93be052b0c037b007144fc5112e 100644 --- a/app/templates/app/includes/navbar_katalog_materi.html +++ b/app/templates/app/includes/navbar_katalog_materi.html @@ -1,4 +1,48 @@ - <nav class="navbar navbar-dark static-top shadow katalog-navbar"> <!-- Sidebar Toggle (Topbar) --> - <div class="sidebar-brand-text">Digipus</div> + <nav class="navbar navbar-expand-lg navbar-light static-top shadow katalog-navbar"> <!-- Sidebar Toggle (Topbar) --> + <div class="sidebar-brand-text navbar-brand">Digipus</div> + <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarContent" aria-controls="navbarContent" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + + <div class="collapse navbar-collapse" id="navbarContent"> + <ul class="navbar-nav ml-auto"> + <li class="nav-item active"> + <a class="nav-link" href="/">Home<span class="sr-only">(current)</span></a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/forum">Forum</a> + </li> + {% if not request.user.is_authenticated %} + <li class="nav-item"> + <a class="nav-link" href="/registrasi">Registrasi</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/login">Login Kontributor</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/login_admin">Login Admin</a> + </li> + {% else %} + <li class="nav-item"> + <a class="nav-link" href="/dashboard">Dasbor</a> + </li> + {% if request.user.is_admin %} + <li class="nav-item"> + <a class="nav-link" href="/administration">Administrasi</a> + </li> + <li class="nav-item"> + <a class="nav-link" href="/profil-admin">Profil</a> + </li> + {% else %} + <li class="nav-item"> + <a class="nav-link" href="/profil">Profil</a> + </li> + {% endif %} + <li class="nav-item"> + <a class="nav-link" href="/logout">Logout</a> + </li> + {% endif %} + </ul> + </div> </nav> \ No newline at end of file diff --git a/app/templates/app/includes/navigation.html b/app/templates/app/includes/navigation.html index 73360a92eab1c0560b32aa5e508c9a10ed194575..37988b70b41417630adc6d1376da77a8ee73f9d6 100644 --- a/app/templates/app/includes/navigation.html +++ b/app/templates/app/includes/navigation.html @@ -2,7 +2,7 @@ <!-- Sidebar Toggle (Topbar) --> <button id="sidebarToggleTop" class="btn btn-link d-md-none rounded-circle mr-3"> - <i class="fa fa-bars"></i> + <em class="fa fa-bars"></em> </button> <div class="sidebar-brand-text mx-3">Diskominfo Kota Depok</div> diff --git a/app/templates/app/katalog_materi.html b/app/templates/app/katalog_materi.html index b788a696bc8c1747f2a2bb1c0921a222bb8e1536..34051b5b01acc4892b0f15d9d751844c1cb17b78 100644 --- a/app/templates/app/katalog_materi.html +++ b/app/templates/app/katalog_materi.html @@ -49,10 +49,10 @@ <body style="background-color: #f8f8f8;"> - {% include 'app/includes/navbar_katalog_materi.html' %} <!-- Page Content --> <div class="container"> + {% include 'app/includes/navbar_katalog_materi.html' %} <header class="jumbotron my-4"> <div class="container"> <div class="row header"> @@ -94,11 +94,13 @@ <div id="collapseOne" class="collapse" aria-labelledby="headingOne" data-parent="#accordionExample"> <div class="card-body"> - {% for itemKategori in kategori_list %} - <li> - <a href="?kategori={{itemKategori.pk}}">{{itemKategori.name}}</a> - </li> - {% endfor %} + <ul> + {% for itemKategori in kategori_list %} + <li> + <a href="?kategori={{itemKategori.pk}}">{{itemKategori.name}}</a> + </li> + {% endfor %} + </ul> </div> </div> </div> @@ -115,24 +117,29 @@ <div id="collapseTwo" class="collapse" aria-labelledby="headingTwo" data-parent="#accordionExample"> <div class="card-body"> - <li> - <a href="?sort=terbaru">terbaru</a> - </li> - <li> - <a href="?sort=terlama">terlama</a> - </li> - <li> - <a href="?sort=terpopuler">terpopuler</a> - </li> - <li> - <a href="?sort=judul">judul</a> - </li> - <li> - <a href="?sort=penulis">penulis</a> - </li> - <li> - <a href="?sort=pengunggah">pengunggah</a> - </li> + <ul> + <li> + <a href="?sort=terbaru">terbaru</a> + </li> + <li> + <a href="?sort=terlama">terlama</a> + </li> + <li> + <a href="?sort=terpopuler">terpopuler</a> + </li> + <li> + <a href="?sort=judul">judul</a> + </li> + <li> + <a href="?sort=penulis">penulis</a> + </li> + <li> + <a href="?sort=pengunggah">pengunggah</a> + </li> + <li> + <a href="?sort=jumlah_unduh">jumlah unduh</a> + </li> + </ul> </div> </div> </div> diff --git a/app/templates/comments.html b/app/templates/comments.html index 96f4a9c097f101ebab3d74c877ad6d92c2566ba8..6a1180d2a5f6b61643dd13a45577ddf206b00af3 100644 --- a/app/templates/comments.html +++ b/app/templates/comments.html @@ -48,7 +48,7 @@ <span style="background-color: #{{comment.profile}}" class="profile p-1 bd-highlight"></span> {% endif %} <p class="p-1 bd-highligh m-0"> - <b>{{comment.user.name}}</b> + <strong>{{comment.user.name}}</strong> </p> <p class="p-1 bd-highligh m-0">•</p> <p class="timestamp p-1 bd-highligh m-0"> diff --git a/app/templates/dashboard.html b/app/templates/dashboard.html index 95ec1ee58a534f65270862f791cd32f71eaecce2..076ad12d1cc465adb079a69e16e3e5e5feff1d11 100644 --- a/app/templates/dashboard.html +++ b/app/templates/dashboard.html @@ -3,7 +3,7 @@ {% block title %} <title>Riwayat Unggah | Digipus</title> -{% endblock %} +{% endblock %} {% block content %} <!-- Page Heading --> @@ -13,25 +13,25 @@ <!-- DataTales Example --> <div class="card shadow mb-4"> <div class="card-header py-3"> - <h6 class="m-0 font-weight-bold text-primary">Tabel Riwayat Unggah</h6> + <h6 id="table-description" class="m-0 font-weight-bold text-primary">Tabel Riwayat Unggah</h6> </div> <div class="card-body"> <div class="table-responsive"> - <table class="table table-bordered" id="dataTable" width="100%" cellspacing="0"> + <table aria-describedby="table-description" class="table table-bordered" id="dataTable"> <thead> <tr> - <th>Judul Materi</th> - <th>Pembuat Materi</th> - <th>Status</th> - <th>Detail</th> + <th scope="col">Judul Materi</th> + <th scope="col">Pembuat Materi</th> + <th scope="col">Status</th> + <th scope="col">Detail</th> </tr> </thead> <tfoot> <tr> - <th>Judul Materi</th> - <th>Pembuat Materi</th> - <th>Status</th> - <th>Detail</th> + <th scope="col">Judul Materi</th> + <th scope="col">Pembuat Materi</th> + <th scope="col">Status</th> + <th scope="col">Detail</th> </tr> </tfoot> <tbody> @@ -43,10 +43,12 @@ <td class="verif-buttons"> <span> <a href="/materi/{{materi.id}}/" class="accept-button button-decoration" - style="background-color:#4e73df">Detail</a> + style="background-color:#4e73df">Detail</a> {% if materi.get_status_display == "Ditolak" or materi.get_status_display == "Perbaikan" %} <a href="/revisi/materi/{{materi.id}}/" class="reject-button button-decoration">Revisi</a> {% endif %} + <a type="button" href="/materi/{{materi.id}}/delete" class="reject-button button-decoration" + style="background-color:red">Hapus</a> </span> </td> </tr> diff --git a/app/templates/profil-admin.html b/app/templates/profil-admin.html index 58ad43884d115f874cf1abba499d67572341b5fa..a2a566f12071edfd2907fe1ff2b3c5380f051ef6 100644 --- a/app/templates/profil-admin.html +++ b/app/templates/profil-admin.html @@ -18,31 +18,46 @@ <h4>{{ user.email }}</h4> <h4>{{ user.biography }}</h4> <div class="profile-margin"></div> - <table> - <tr> - <td class="profile-data">Instansi</td> - <td>{{ user.instansi }}</td> - </tr> - - <td class="profile-data">LinkedIn</td> - <td><a href="https://linkedin.com">{{ user.linkedin }}</a></td> - </tr> - - <tr> - <td class="profile-data">Facebook</td> - <td><a href="https://facebook.com">{{ user.facebook }}</a></td> - </tr> - - <tr> - <td class="profile-data">Twitter</td> - <td><a href="https://twitter.com">{{ user.twitter }}</a></td> - </tr> - - <tr> - <td class="profile-data">Instagram</td> - <td><a href="https://instagram.com">{{ user.instagram }}</a></td> - </tr> - </table> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + instansi + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + {{user.instansi}} + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + LinkedIn + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://linkedin.com">{{ user.linkedin }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Facebook + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://facebook.com">{{ user.facebook }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Twitter + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://twitter.com">{{ user.twitter }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Instagram + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://instagram.com">{{ user.instagram }}</a> + </div> + </div> </div> </div> {% endblock %} \ No newline at end of file diff --git a/app/templates/profil.html b/app/templates/profil.html index 13ad5403e9873c1a8efaf626397e322c35bdea06..3145ab41746a6ff532e8fe8ef2fc7dcee333370d 100644 --- a/app/templates/profil.html +++ b/app/templates/profil.html @@ -22,31 +22,46 @@ <h4>{{ user.email }}</h4> <h4>{{ user.biography }}</h4> <div class="profile-margin"></div> - <table> - <tr> - <td class="profile-data">Instansi</td> - <td>{{ user.instansi }}</td> - </tr> - - <td class="profile-data">LinkedIn</td> - <td><a href="https://linkedin.com">{{ user.linkedin }}</a></td> - </tr> - - <tr> - <td class="profile-data">Facebook</td> - <td><a href="https://facebook.com">{{ user.facebook }}</a></td> - </tr> - - <tr> - <td class="profile-data">Twitter</td> - <td><a href="https://twitter.com">{{ user.twitter }}</a></td> - </tr> - - <tr> - <td class="profile-data">Instagram</td> - <td><a href="https://instagram.com">{{ user.instagram }}</a></td> - </tr> - </table> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + instansi + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + {{user.instansi}} + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + LinkedIn + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://linkedin.com">{{ user.linkedin }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Facebook + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://facebook.com">{{ user.facebook }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Twitter + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://twitter.com">{{ user.twitter }}</a> + </div> + </div> + <div class="row"> + <div class="col-md-6 my-auto" style="font-size: 2rem;"> + Instagram + </div> + <div class="col-md-6 my-auto" style="font-size: 1.2rem;"> + <a href="https://instagram.com">{{ user.instagram }}</a> + </div> + </div> </div> </div> {% endblock %} \ No newline at end of file diff --git a/app/templates/sukses_admin.html b/app/templates/sukses_admin.html index 313d93ce805937c12d3728278727de36237fe194..40692fdb1abd598551b99f2a644c22352e9f63d1 100644 --- a/app/templates/sukses_admin.html +++ b/app/templates/sukses_admin.html @@ -73,7 +73,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> <!-- Bootstrap core JavaScript--> diff --git a/app/templates/sukses_kontri.html b/app/templates/sukses_kontri.html index af4ee3bf90ee2b19102a8717da5b519c5bcab9ba..0aaf4a33bbe8bbe7cb3560ae4ed7ffca5a7178fe 100644 --- a/app/templates/sukses_kontri.html +++ b/app/templates/sukses_kontri.html @@ -79,7 +79,7 @@ <!-- Scroll to Top Button--> <a class="scroll-to-top rounded" href="#page-top"> - <i class="fas fa-angle-up"></i> + <em class="fas fa-angle-up"></em> </a> <!-- Bootstrap core JavaScript--> diff --git a/app/tests.py b/app/tests.py index cdaec1cdee20aef52d6399a7eebea560b4f49b9a..f8e17b82dd0e4554e9d69b9d1f398498c1a8ebf8 100644 --- a/app/tests.py +++ b/app/tests.py @@ -1,6 +1,7 @@ import json, tempfile, os, mock import pandas as pd from io import StringIO +import time from bs4 import BeautifulSoup from datetime import datetime @@ -12,7 +13,8 @@ from django.core.files import File from django.core.exceptions import PermissionDenied, ValidationError from django.core.files.uploadedfile import SimpleUploadedFile from django.core.management import call_command -from django.urls import resolve, reverse +from django.test import Client, TestCase, TransactionTestCase +from django.urls import resolve from django.db.utils import IntegrityError from django.test import Client, RequestFactory, TestCase, TransactionTestCase from pytz import timezone @@ -51,6 +53,7 @@ from .views import ( KatalogPerKontributorView, UploadMateriView, UploadMateriExcelView, + PasswordChangeView, ) from app.forms import SuntingProfilForm from app.utils.fileManagementUtil import get_random_filename, remove_image_exifdata @@ -136,6 +139,45 @@ class DaftarKatalogTest(TestCase): self.assertSequenceEqual(search_result, expected_search_result) +class DaftarKatalogSortingByJumlahUnduhTest(TestCase): + def setUp(self): + self.client = Client() + + self.contributor_credential = { + "email": "kontributor@gov.id", + "password": "passwordtest" + } + + self.contributor_credential_2 = { + "email": "kontributor2@gov.id", + "password": "passwordtest" + } + + self.contributor = get_user_model().objects.create_user( + **self.contributor_credential, name="Kontributor 1", is_contributor=True) + self.contributor2 = get_user_model().objects.create_user( + **self.contributor_credential_2, name="Kontributor 2", is_contributor=True) + + self.cover = SimpleUploadedFile( + "Cherprang_Areekul40_nJM9dGt.jpg", b"Test file") + self.content = SimpleUploadedFile("Bahan_PA_RKK.pdf", b"Test file") + + Materi(title="Materi 1", author="Agas", uploader=self.contributor, + publisher="Kelas SC", descriptions="Deskripsi Materi 1", + status="APPROVE", cover=self.cover, content=self.content).save() + time.sleep(1) + Materi(title="Materi 2", author="Agas", uploader=self.contributor, + publisher="Kelas SC", descriptions="Deskripsi Materi 2", + status="APPROVE", cover=self.cover, content=self.content).save() + + self.last_uploaded_material = Materi.objects.last() + + material_unduh_url = f"/materi/{self.last_uploaded_material.id}/unduh" + self.client.get(material_unduh_url) + + def test_sorting_by_jumlah_unduh(self): + response = self.client.get("/?sort=jumlah_unduh") + self.assertRegex(str(response.content), rf'.*Materi 2.*Materi 1.*') class DaftarKatalogPerKontributorTest(TestCase): def setUp(self): @@ -323,10 +365,17 @@ class DetailMateriTest(TestCase): self.assertContains(response, "Anonymous") def test_detail_materi_contains_form_comment(self): + self.client.login(**self.contributor_credential) response = self.client.get(self.url) self.assertContains(response, "Beri komentar...") + def test_detail_materi_not_contains_form_comment(self): + response = self.client.get(self.url) + self.assertNotContains(response, "Beri komentar...") + self.assertContains(response, "Login terlebih dahulu untuk berkomentar") + def test_delete_comments_by_admin(self): + self.client.login(**self.contributor_credential) url = self.url self.client.post(url, {"comment": "This is new comment by Anonymous"}) deleteURL = ( @@ -432,7 +481,6 @@ class DetailMateriTest(TestCase): self.assertEqual(last_url, "/materi/%d/" % self.materi1.id) self.assertEqual(status_code, 302) - class PostsViewTest(TestCase): @classmethod def generate_posts_data(cls, user): @@ -877,6 +925,25 @@ class DashboardKontributorViewTest(TestCase): self.assertIn(ERROR_403_MESSAGE, html) +class DeleteMateriTest(TestCase): + def setUp(self): + self.client = Client() + self.content = SimpleUploadedFile( + "content.txt", b"Test") + self.cover = SimpleUploadedFile( + "flower.jpg", b"Test file") + self.contributor = User.objects.create_contributor(email="kontributor@gov.id", + password="kontributor") + Materi(title="Materi 1", author="Agas", uploader=self.contributor, + publisher="Kelas SC", descriptions="Deskripsi Materi 1", + status="APPROVE", cover=self.cover, content=self.content).save() + self.materi1 = Materi.objects.first() + self.url = "/materi/" + str(self.materi1.id) + "/delete" + + def test_url_delete_materi_is_success(self): + response = self.client.get(self.url) + self.assertEqual(response.status_code, 302) + class ProfilAdminTest(TestCase): def setUp(self): self.client = Client() diff --git a/app/urls.py b/app/urls.py index 3f0cc7dfdb02eb480b55a178cb0a7a5baa5f8df5..47d53b6738c06219dee17eec1f717d0426f6a92e 100644 --- a/app/urls.py +++ b/app/urls.py @@ -14,6 +14,7 @@ urlpatterns = [ path("materi/like/", views.toggle_like, name="PostLikeToggle"), path("delete/<int:pk_materi>/<int:pk_comment>", views.delete_comment, name="delete-comment"), + path("materi/<int:pk>/delete", views.delete_materi, name="detele-materi"), path("materi/<int:pk>/unduh", views.download_materi, name="download-materi"), path("materi/<int:pk>/view", views.view_materi, name="view-materi"), path("dashboard/", DashboardKontributorView.as_view(), name="dashboard"), diff --git a/app/views.py b/app/views.py index ed1c3561489beed91a5c63a41aa1a70c96db6cf4..5a547c4ee15400ef5f4f7e07f9d3b582a148780e 100644 --- a/app/views.py +++ b/app/views.py @@ -7,7 +7,8 @@ from django.contrib import messages from django.contrib.auth.models import AnonymousUser from django.core.exceptions import PermissionDenied, ValidationError from django.db.models import Q, Count -from django.http import Http404, HttpResponse, HttpResponseRedirect, JsonResponse +from django.http import (Http404, HttpResponse, HttpResponseRedirect, + JsonResponse) from django.urls import reverse from django.shortcuts import get_object_or_404, redirect from django.template import loader @@ -32,14 +33,10 @@ from authentication.models import User import django import pandas as pd from io import BytesIO +from django.contrib import messages from pydrive.auth import GoogleAuth from pydrive.drive import GoogleDrive from pydrive.auth import AuthenticationRejected -from django.contrib.auth.views import PasswordChangeForm -from django.urls import reverse_lazy -from django.contrib.auth.views import PasswordChangeView -from django.shortcuts import render - def permission_denied(request, exception, template_name="error_403.html"): return defaults.permission_denied(request, exception, template_name) @@ -82,18 +79,20 @@ class DaftarKatalog(TemplateView): getSort = request.GET.get("sort") if getSort: url = url + "&sort={0}".format(getSort) - if getSort == "judul": - lstMateri = lstMateri.order_by("title") - elif getSort == "penulis": - lstMateri = lstMateri.order_by("author") - elif getSort == "pengunggah": - lstMateri = lstMateri.order_by("uploader") - elif getSort == "terbaru": - lstMateri = lstMateri.order_by("-date_created") - elif getSort == "terlama": - lstMateri = lstMateri.order_by("date_created") - elif getSort == "terpopuler": - lstMateri = lstMateri.annotate(count=Count("like__id")).order_by("-count") + if(getSort == "judul"): + lstMateri = lstMateri.order_by('title') + elif(getSort == "penulis"): + lstMateri = lstMateri.order_by('author') + elif(getSort == "pengunggah"): + lstMateri = lstMateri.order_by('uploader') + elif(getSort == "terbaru"): + lstMateri = lstMateri.order_by('-date_created') + elif(getSort == "terlama"): + lstMateri = lstMateri.order_by('date_created') + elif(getSort == "terpopuler"): + lstMateri = lstMateri.annotate(count=Count('like__id')).order_by('-count') + elif(getSort == "jumlah_unduh"): + lstMateri = lstMateri.annotate(count=Count('unduh__id')).order_by('-count') context["materi_list"] = lstMateri paginator = Paginator(context["materi_list"], 15) @@ -161,7 +160,9 @@ class DetailMateri(TemplateView): if self.request.user.is_authenticated: materi_rating = Rating.objects.filter(materi=materi, user=self.request.user).first() if materi_rating is not None: - context["materi_rating_score"] = materi_rating.score + context['materi_rating_score'] = materi_rating.score + + context['is_authenticated'] = self.request.user.is_authenticated return context @@ -193,10 +194,11 @@ class DetailMateri(TemplateView): materi = get_object_or_404(Materi, pk=kwargs["pk"]) user_obj = request.user if request.user.is_authenticated else None - comment = Comment.objects.create( - comment=commentText, username=self.get_user_name(request), materi=materi, user=user_obj - ) - comment.save() + if user_obj: + comment = Comment.objects.create( + comment=commentText, username=self.get_user_name(request), materi=materi, user=user_obj + ) + comment.save() return HttpResponseRedirect(request.path) @@ -350,6 +352,11 @@ def view_materi(request, pk): raise Http404("File tidak dapat ditemukan.") +def delete_materi(request, pk): + materi = get_object_or_404(Materi, pk=pk) + materi.delete() + return HttpResponseRedirect("/dashboard/") + class UploadMateriView(TemplateView): template_name = "unggah.html" context = {} @@ -852,17 +859,16 @@ def save_to_gdrive(request, pk): path = materi.content.path file_path = os.path.join(settings.MEDIA_ROOT, path) if os.path.exists(file_path): - with open(file_path, "rb") as fh: - upload_to_gdrive(file_path, materi.title) + upload_to_gdrive(file_path, materi.title) else: raise Http404("File tidak dapat ditemukan.") - return HttpResponseRedirect(reverse("detail-materi", kwargs={"pk": pk})) - + return HttpResponseRedirect(reverse('detail-materi', kwargs={'pk': pk})) + class PasswordChangeView(PasswordChangeView): from_class = PasswordChangeForm success_url = reverse_lazy('password_success') def password_success(request): - return render(request, 'password_success.html', {}) + return render(request, 'password_success.html', {}) \ No newline at end of file diff --git a/authentication/templates/login.html b/authentication/templates/login.html index 0dfae589ed5969411d1930b21e24b16e1fc0267b..68859550dc8a8c72519d2ab9f4a7a6a3ec0e80c1 100644 --- a/authentication/templates/login.html +++ b/authentication/templates/login.html @@ -69,7 +69,7 @@ </div> - + <div class="g-recaptcha" data-sitekey={{captcha_site_key}}></div> <div class="container-login100-form-btn"> <button class="login100-form-btn" type="submit"> Login @@ -100,6 +100,8 @@ <script src="../static/../static/vendor/countdowntime/countdowntime.js"></script> <!--===============================================================================================--> <script src="../static/js/login.js"></script> + <!--===============================================================================================--> + <script src='https://www.google.com/recaptcha/api.js'></script> </body> diff --git a/authentication/templates/login_admin.html b/authentication/templates/login_admin.html index ca2cad7d4f40dea55792e3d7eac14320972b4b61..fca44f4cf9d0bd8344d9cbca7dae0e8189a75cd1 100644 --- a/authentication/templates/login_admin.html +++ b/authentication/templates/login_admin.html @@ -54,7 +54,7 @@ <div class="work_info"> <form class="login100-form validate-form" method="POST"> {% csrf_token %} - + <input type="hidden" name="source" value="admin" /> <div class="login100-form-title p-b-43"> Halo, Admin </div> @@ -84,7 +84,7 @@ </div> </div> - + <div class="g-recaptcha" data-sitekey="6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"></div> <div class="container-login100-form-btn"> <button class="login100-form-btn" type="submit"> Login @@ -116,6 +116,9 @@ <script src="../static/../static/vendor/countdowntime/countdowntime.js"></script> <!--===============================================================================================--> <script src="../static/js/login.js"></script> + <!--===============================================================================================--> + <script src='https://www.google.com/recaptcha/api.js'></script> + </body> diff --git a/authentication/tests.py b/authentication/tests.py index 85d09f60d9b428681a141669ae2267cf842a18f5..66be76191b4e0e79803b115c0a735d722b0090ec 100644 --- a/authentication/tests.py +++ b/authentication/tests.py @@ -80,7 +80,7 @@ class LoginPageContributorTest(TestCase): self.view = Login self.template_name = "login.html" self.login_credential = { - "email": "kontributor@gov.id", "pass": "kontributor"} + "email": "kontributor@gov.id", "pass": "kontributor", "g-recaptcha-response" : "testcaptcha"} self.error_message = { "empty_email_or_password": "Email atau Password anda kosong.", "wrong_email_or_password": "Email atau Password anda salah.", @@ -114,11 +114,11 @@ class LoginPageContributorTest(TestCase): self.assertContains(response, "Kata Sandi") def test_kontributor_login_missing_email_or_password(self): - response = self.client.post(self.url, {"email": "kontributor@gov.id"}) + response = self.client.post(self.url, {"email": "kontributor@gov.id", "g-recaptcha-response" : "testcaptcha"}) self.assertIn("error_message", response.context_data) self.assertIn(self.error_message["empty_email_or_password"], response.context_data["error_message"]) - response = self.client.post(self.url, {"pass": "kontributor"}) + response = self.client.post(self.url, {"pass": "kontributor", "g-recaptcha-response" : "testcaptcha"}) self.assertIn("error_message", response.context_data) self.assertIn(self.error_message["empty_email_or_password"], response.context_data["error_message"]) @@ -126,19 +126,19 @@ class LoginPageContributorTest(TestCase): def test_kontributor_login_wrong_email_or_password(self): # Wrong password response = self.client.post( - self.url, {"email": "kontributor@gov.id", "pass": "kontributor1"}) + self.url, {"email": "kontributor@gov.id", "pass": "kontributor1", "g-recaptcha-response" : "testcaptcha"}) self.assertIn("error_message", response.context_data) self.assertIn(self.error_message["wrong_email_or_password"], response.context_data["error_message"]) # Wrong email response = self.client.post( - self.url, {"email": "kontributor1@gov.id", "pass": "kontributor"}) + self.url, {"email": "kontributor1@gov.id", "pass": "kontributor", "g-recaptcha-response" : "testcaptcha"}) self.assertIn("error_message", response.context_data) self.assertIn(self.error_message["wrong_email_or_password"], response.context_data["error_message"]) # Wrong email and password response = self.client.post( - self.url, {"email": "kontributor1@gov.id", "pass": "kontributor1"}) + self.url, {"email": "kontributor1@gov.id", "pass": "kontributor1", "g-recaptcha-response" : "testcaptcha"}) self.assertIn("error_message", response.context_data) self.assertIn(self.error_message["wrong_email_or_password"], response.context_data["error_message"]) diff --git a/authentication/views.py b/authentication/views.py index 8e50ca975d598bb7b506a76150576191abbc6e71..03408cbaf9d5204e6bf89900b327cc6f1e564691 100644 --- a/authentication/views.py +++ b/authentication/views.py @@ -1,7 +1,10 @@ from django.contrib.auth import authenticate, login from django.http import HttpResponseRedirect, QueryDict from django.views.generic import TemplateView - +from django.conf import settings +from django.contrib import messages +import urllib +import json class Login(TemplateView): @@ -27,30 +30,46 @@ class Login(TemplateView): def get(self, request, *args, **kwargs): context = self.get_context_data(**kwargs) + context['captcha_site_key'] = settings.GOOGLE_RECAPTCHA_SITE_KEY return self.render_to_response(context=context) def post(self, request, *args, **kwargs): email = request.POST.get("email", None) password = request.POST.get("pass", None) + context = self.get_context_data(*args, **kwargs) if email is None or password is None: context = self.get_context_data(*args, **kwargs) context["error_message"] = "Email atau Password anda kosong." return self.render_to_response(context=context) - else: - user = authenticate(email=email, password=password) - if user is not None: - login(request, user) - redirect_to = "/" - querystring = QueryDict(request.META['QUERY_STRING']) - if request.user.is_admin: - redirect_to = "/sukses-admin/" - elif request.user.is_contributor: - redirect_to = "/sukses-kontributor/" - if 'next' in querystring: - redirect_to = querystring['next'] - return HttpResponseRedirect(redirect_to) + else: + recaptcha_response = request.POST.get('g-recaptcha-response') + url = 'https://www.google.com/recaptcha/api/siteverify' + values = { + 'secret': settings.GOOGLE_RECAPTCHA_SECRET_KEY, + 'response': recaptcha_response + } + data = urllib.parse.urlencode(values).encode() + req = urllib.request.Request(url, data=data) + response = urllib.request.urlopen(req) + result = json.loads(response.read().decode()) + + if result['success']: + user = authenticate(email=email, password=password) + if user is not None: + login(request, user) + redirect_to = "/" + querystring = QueryDict(request.META['QUERY_STRING']) + if request.user.is_admin: + redirect_to = "/sukses-admin/" + elif request.user.is_contributor: + redirect_to = "/sukses-kontributor/" + if 'next' in querystring: + redirect_to = querystring['next'] + return HttpResponseRedirect(redirect_to) + else: + context["error_message"] = "Email atau Password anda salah." + return self.render_to_response(context=context) else: - context = self.get_context_data(*args, **kwargs) - context["error_message"] = "Email atau Password anda salah." - return self.render_to_response(context=context) + messages.error(request, 'Invalid reCAPTCHA. Please try again.') + return self.render_to_response(context=context) diff --git a/digipus/__pycache__/settings.cpython-36.pyc b/digipus/__pycache__/settings.cpython-36.pyc index 20df0c90cc3f2c037c813b0bcfe76a67c759ad9f..16b556f3a066bf9fc7adc203f67e352d4013fbe6 100644 Binary files a/digipus/__pycache__/settings.cpython-36.pyc and b/digipus/__pycache__/settings.cpython-36.pyc differ diff --git a/digipus/settings.py b/digipus/settings.py index a1c930660339988f60d34dad5d86c7f561ce7473..d5f32c78246e7d4b8caaedcbef66ba9dca186448 100644 --- a/digipus/settings.py +++ b/digipus/settings.py @@ -14,6 +14,7 @@ import os import dj_database_url from decouple import config +from django.contrib.messages import constants as messages # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -145,6 +146,16 @@ USE_L10N = True USE_TZ = True +MESSAGE_TAGS = { + messages.DEBUG: 'alert-info', + messages.INFO: 'alert-info', + messages.SUCCESS: 'alert-success', + messages.WARNING: 'alert-warning', + messages.ERROR: 'alert-danger', +} + +GOOGLE_RECAPTCHA_SECRET_KEY = config('GOOGLE_RECHAPTCHA', default= "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe") +GOOGLE_RECAPTCHA_SITE_KEY = config('CLIENT_RECHAPTCHA', default= "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI") # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.0/howto/static-files/