Browse Source

added paginated users table

development
Rohan Sircar 4 years ago
parent
commit
e569420ca5
  1. 3
      package.json
  2. 16
      src/main/frontend/admin/main.ts
  3. 35
      src/main/frontend/admin/pages/user/ViewUsers.ts
  4. 12
      src/main/frontend/common/ajax/Messages.ts
  5. 15
      src/main/frontend/common/ajax/Users.ts
  6. 6
      src/main/frontend/common/dto/AdminUserDTO.ts
  7. 6
      src/main/frontend/common/routes/Admin.ts
  8. 16
      src/main/frontend/common/util/Util.ts
  9. 42
      src/main/resources/static/css/admin-custom.css
  10. 8
      src/main/resources/static/css/admin-table.css
  11. 1
      src/main/resources/static/css/dataTables.bootstrap4.min.css
  12. 180
      src/main/resources/templates/admin/users.html
  13. 51
      src/main/resources/templates/fragments/admin.html
  14. 7
      yarn.lock

3
package.json

@ -1,6 +1,7 @@
{
"dependencies": {
"@types/bootbox": "^5.2.0",
"@types/datatables.net": "^1.10.19",
"@types/dompurify": "^2.0.0",
"@types/jquery": "^3.3.31",
"@types/markdown-it": "^0.0.9",
@ -58,4 +59,4 @@
"watch": "watchify src/main/frontend/chat/main.ts -p [ tsify --target ES6 --noImplicitAny ] --debug -o src/main/resources/static/js/bundle.js",
"watch-admin": "watchify src/main/frontend/admin/main.ts -p [ tsify --target ES6 --noImplicitAny ] --debug -o src/main/resources/static/js/adminBundle.js"
}
}
}

16
src/main/frontend/admin/main.ts

@ -4,18 +4,24 @@ import log from "loglevel";
import { AlertifyNotificationService } from "../common/service/AlertifyNotificationService";
import { stats } from "./pages/Home";
import { Credentials } from "../common/global/Credentials";
import { getOtherUsers } from "../common/ajax/Users";
import { viewUsers } from "./pages/user/ViewUsers";
log.setLevel("TRACE");
const es = EncryptionServiceFactory.getEncryptionService();
const ns = new AlertifyNotificationService();
const authToken = Credentials.authToken
const authToken = Credentials.authToken;
$("#changePassphraseForm").on("submit", (event) => {
event.preventDefault();
changePassphrase(es, ns, authToken);
});
const pathMatcher = (path: string) => window.location.pathname == path
const pathMatcher = (path: string) => window.location.pathname == path;
if(pathMatcher("/admin")) {
stats()
}
if (pathMatcher("/admin")) {
stats();
}
if (pathMatcher("/admin/users")) {
// $("#usersTableBody").html("");
viewUsers(authToken);
}

35
src/main/frontend/admin/pages/user/ViewUsers.ts

@ -0,0 +1,35 @@
import moment from "moment";
import { capitalize } from "../../../common/util/Util";
export async function viewUsers(authToken: string) {
// const users = await getOtherUsers(authToken);
const usersTable = $("#usersTable").DataTable({
ajax: {
url: "/api/admin/get/users",
headers: {
"X-AUTH-TOKEN": authToken,
},
dataSrc: "",
},
columns: [
{ data: "id" },
{ data: "userName" },
{
data: "role",
render: (data: string) => {
return capitalize(data.replace("_", " ").toLowerCase());
},
},
{
data: "joinDate",
render: (data: string, type) => {
return type === "sort"
? data
: moment.utc(data).format("DD/MM/YY").toString();
},
},
],
lengthMenu: [2, 10, 25, 50, 75, 100],
});
}

12
src/main/frontend/common/ajax/Messages.ts

@ -8,7 +8,7 @@ import { StatsDTO } from "../dto/StatsDTO";
import { createApiHeaders } from "./util";
export async function getAllMessages(user: string, authToken: string) {
let response = await fetch(`${Routes.Admin.getAllMessagesURL}${user}`, {
let response = await fetch(`${Routes.Admin.getAllMessages}${user}`, {
method: "GET",
headers: createApiHeaders(authToken),
});
@ -16,7 +16,7 @@ export async function getAllMessages(user: string, authToken: string) {
}
async function getAllRegularUsers(authToken: string) {
let response = await fetch(`${Routes.Admin.getAllRegularUsersURL}`, {
let response = await fetch(`${Routes.Admin.getOtherUsers}`, {
method: "GET",
headers: createApiHeaders(authToken),
});
@ -34,7 +34,7 @@ export async function sendReencryptedMessages(
// headers.append('Accept','application/json')
headers.append("Content-Type", "application/json");
headers.append("X-AUTH-TOKEN", authToken);
fetch(Routes.Admin.reencryptURL, {
fetch(Routes.Admin.reencrypt, {
method: "POST",
headers: headers,
body: JSON.stringify(rencryptionDTOs),
@ -74,6 +74,6 @@ export async function getStats(authToken: string) {
const response = await fetch("/api/stats/", {
headers: createApiHeaders(authToken),
method: "GET",
})
return (await response.json()) as StatsDTO;
}
});
return (await response.json()) as StatsDTO;
}

15
src/main/frontend/common/ajax/Users.ts

@ -0,0 +1,15 @@
import { Routes } from "../routes/Routes";
import { createApiHeaders } from "./util";
import { AdminUserDTO } from "../dto/AdminUserDTO";
export async function getOtherUsers(
authToken: string
): Promise<AdminUserDTO[]> {
const response = await fetch(Routes.Admin.getOtherUsers, {
method: "GET",
headers: createApiHeaders(authToken),
});
let data = (await response.json()) as AdminUserDTO[];
return data;
}

6
src/main/frontend/common/dto/AdminUserDTO.ts

@ -0,0 +1,6 @@
export interface AdminUserDTO {
id: number;
userName: string;
role: string;
joinDate: string;
}

6
src/main/frontend/common/routes/Admin.ts

@ -1,5 +1,5 @@
export namespace Admin {
export const getAllMessagesURL = `/api/admin/get/messages/`; //hostAddress set in thymeleaf backend
export const reencryptURL = `/api/admin/post/re-encrypt`;
export const getAllRegularUsersURL = `/api/admin/get/users`;
export const getAllMessages = `/api/admin/get/messages/`; //hostAddress set in thymeleaf backend
export const reencrypt = `/api/admin/post/re-encrypt`;
export const getOtherUsers = `/api/admin/get/users`;
}

16
src/main/frontend/common/util/Util.ts

@ -0,0 +1,16 @@
/**
* Capitalizes first letters of words in string.
* @param {string} str String to be modified
* @param {boolean=false} lower Whether all other letters should be lowercased
* @return {string}
* @usage
* capitalize('fix this string'); // -> 'Fix This String'
* capitalize('javaSCrIPT'); // -> 'JavaSCrIPT'
* capitalize('javaSCrIPT', true); // -> 'Javascript'
*/
export function capitalize(str: string, lower = false): string {
return (lower ? str.toLowerCase() : str).replace(
/(?:^|\s|["'([{])+\S/g,
(match) => match.toUpperCase()
);
}

42
src/main/resources/static/css/admin-custom.css

@ -1,33 +1,33 @@
.text-primary-dark {
/* color: #67b2fd; */
color: #7accff;
/* color: #67b2fd; */
color: #7accff;
}
.border-left-primary-dark {
border-left: 0.25rem solid #7accff !important;
border-left: 0.25rem solid #7accff !important;
}
.sidebar .nav-item .collapse .collapse-inner .collapse-item,
.sidebar .nav-item .collapsing .collapse-inner .collapse-item {
padding: 0.5rem 1rem;
margin: 0 0.5rem;
display: block;
color: #fff;
text-decoration: none;
border-radius: 0.35rem;
white-space: nowrap;
padding: 0.5rem 1rem;
margin: 0 0.5rem;
display: block;
color: #fff;
text-decoration: none;
border-radius: 0.35rem;
white-space: nowrap;
}
.sidebar-dark .nav-item .nav-link i {
color: rgba(255, 255, 255, 0.7);
color: rgba(255, 255, 255, 0.7);
}
.sidebar-dark .nav-item .nav-link {
color: rgba(255, 255, 255, 0.95);
color: rgba(255, 255, 255, 0.95);
}
.sidebar-dark .nav-item .nav-link[data-toggle="collapse"]::after {
color: rgba(255, 255, 255, 0.8);
color: rgba(255, 255, 255, 0.8);
}
.sidebar .nav-item .collapse .collapse-inner .collapse-item:hover,
@ -40,7 +40,7 @@
} */
.text-info {
color: #5bd6e8 !important;
color: #5bd6e8 !important;
}
/* :root {
@ -48,14 +48,18 @@
} */
.sidebar-dark hr.sidebar-divider {
border-top: 1px solid rgba(255, 255, 255, 0.5);
border-top: 1px solid rgba(255, 255, 255, 0.5);
}
body {
background: #333;
color: #fff;
background: #333;
color: #fff;
}
#wrapper #content-wrapper {
background-color: #333;
}
background-color: #333;
}
table.table-bordered.dataTable {
border-right-width: 1px;
}

8
src/main/resources/static/css/admin-table.css

@ -0,0 +1,8 @@
label,
#usersTable_info,
.dataTables_paginate,
.paginate_button,
#usersTable_next,
#usersTable_previous {
color: white !important;
}

1
src/main/resources/static/css/dataTables.bootstrap4.min.css
File diff suppressed because it is too large
View File

180
src/main/resources/templates/admin/users.html

@ -12,9 +12,9 @@
<th:block th:include="fragments/admin :: headFragment"></th:block>
<style>
.sidebar {
/* .sidebar {
height: 100%;
}
} */
</style>
</head>
<!-- TODO
@ -49,7 +49,7 @@
<!-- Content Row -->
<div class="row">
<div class="col-lg-10 offset-lg-1">
<div class="col">
<!-- Approach -->
<div class="card bg-dark border border-dark text-white shadow mb-4">
@ -57,156 +57,56 @@
<h6 class="m-0 font-weight-bold text-white">Users</h6>
</div>
<div class="card-body">
<table data-toggle="table" class="text-white">
<thead>
<tr>
<th>User ID</th>
<th>User Name</th>
<th>Role</th>
<th>Registration Date</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Item 1</td>
<td>$1</td>
<td></td>
<td><button class="btn btn-info"><i
class="fas fa-ellipsis-h"></i></button></td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
<tr>
<td>2</td>
<td>Item 2</td>
<td>$2</td>
</tr>
</tbody>
</table>
<div class="table-responsive">
<table data-toggle="table" class="table table-bordered text-white" width="100%"
cellspacing="0" id="usersTable">
<thead>
<tr>
<th>User ID</th>
<th>User Name</th>
<th>Role</th>
<th>Registration Date</th>
<!-- <th>Action</th> -->
</tr>
</thead>
<tbody id="usersTableBody">
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- /.container-fluid -->
</div>
<!-- /.container-fluid -->
<!-- End of Main Content -->
</div>
<!-- End of Main Content -->
<div th:include="fragments/admin :: footer"></div>
<div th:include="fragments/admin :: footer"></div>
</div>
<!-- End of Content Wrapper -->
</div>
<!-- End of Content Wrapper -->
<!-- End of Page Wrapper -->
</div>
<!-- End of Page Wrapper -->
<th:block th:include="fragments/admin :: modal"></th:block>
<div th:if="false">
<th:block th:include="admin :: modal"></th:block>
</div>
<th:block th:include="fragments/admin :: modal"></th:block>
<div th:if="false">
<th:block th:include="admin :: modal"></th:block>
</div>
<template id="users-table-template">
<tr>
<td>{{id}}</td>
<td>{{userName}}</td>
<td>{{role}}</td>
<td>{{joinDate}}</td>
<td></td>
</tr>
</template>
<template id="users-table-template">
<tr>
<td>{{id}}</td>
<td>{{userName}}</td>
<td>{{role}}</td>
<td>{{joinDate}}</td>
<td><button class="btn btn-info"><i class="fas fa-ellipsis-h"></i></button></td>
</tr>
</template>
</body>

51
src/main/resources/templates/fragments/admin.html

@ -17,33 +17,62 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css"
th:if="false">
<th:block th:fragment="headFragment">
<script th:src="@{/js/adminBundle.js}" src="../../static/js/adminBundle.js" defer="defer"></script>
<script th:src="@{/js/admin.js}" src="../../static/js/admin.js" defer="defer"></script>
<script th:src="@{/js/sb-admin-2.js}" src="../../static/js/sb-admin-2.js" defer="defer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.js" defer></script>
<script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous" defer></script>
<th:block th:fragment="headFragment">
<!-- <script src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous" defer></script> -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"
integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"
defer></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"
integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"
defer></script>
<script src="https://unpkg.com/bootstrap-table@1.17.1/dist/bootstrap-table.min.js" defer></script>
<!-- <script src="https://unpkg.com/bootstrap-table@1.17.1/dist/bootstrap-table.min.js" defer></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/jquery.dataTables.min.js"
integrity="sha512-BkpSL20WETFylMrcirBahHfSnY++H2O1W+UnEEO4yNIl+jI2+zowyoGJpbtk6bx97fBXf++WJHSSK2MV4ghPcg=="
crossorigin="anonymous"></script> -->
<!-- <script src="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/js/dataTables.bootstrap.min.js"
integrity="sha512-F0E+jKGaUC90odiinxkfeS3zm9uUT1/lpusNtgXboaMdA3QFMUez0pBmAeXGXtGxoGZg3bLmrkSkbK1quua4/Q=="
crossorigin="anonymous"></script> -->
<!-- <link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/css/dataTables.bootstrap4.min.css"
integrity="sha512-PT0RvABaDhDQugEbpNMwgYBCnGCiTZMh9yOzUsJHDgl/dMhD9yjHAwoumnUk3JydV3QTcIkNDuN40CJxik5+WQ=="
crossorigin="anonymous" /> -->
<script th:src="@{/js/adminBundle.js}" src="../../static/js/adminBundle.js" defer="defer"></script>
<!-- <script th:src="@{/js/admin.js}" src="../../static/js/admin.js" defer="defer"></script> -->
<script th:src="@{/js/sb-admin-2.js}" src="../../static/js/sb-admin-2.js" defer="defer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.js" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.js" defer></script>
<link href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" rel="stylesheet">
<link href="http://fonts.googleapis.com/css?family=Roboto:400,700,300" rel="stylesheet" type="text/css">
<link th:href="@{/css/sb-admin-2.css}" href="../../static/css/sb-admin-2.css" rel="stylesheet">
<link th:href="@{/css/admin-custom.css}" href="../../static/css/admin-custom.css" rel="stylesheet">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css"
integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
<link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.17.1/dist/bootstrap-table.min.css">
<!-- <link rel="stylesheet" href="https://unpkg.com/bootstrap-table@1.17.1/dist/bootstrap-table.min.css"> -->
<!-- <link rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/datatables/1.10.21/css/jquery.dataTables.min.css"
integrity="sha512-1k7mWiTNoyx2XtmI96o+hdjP8nn0f3Z2N4oF/9ZZRgijyV4omsKOXEnqL1gKQNPy2MTSP9rIEWGcH/CInulptA=="
crossorigin="anonymous" /> -->
<!-- <link rel="stylesheet" th:href="@{/css/admin-table.css}" href="../../../resources/static/css/admin-table.css"> -->
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.21/datatables.min.css" />
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.21/datatables.min.js"></script>
<link rel="stylesheet" th:href="@{/css/dataTables.bootstrap4.min.css}"
href="../../../resources/static/css/dataTables.bootstrap4.min.css">
<link th:href="@{/css/admin-custom.css}" href="../../static/css/admin-custom.css" rel="stylesheet">
</th:block>

7
yarn.lock

@ -9,6 +9,13 @@
dependencies:
"@types/jquery" "*"
"@types/datatables.net@^1.10.19":
version "1.10.19"
resolved "https://registry.yarnpkg.com/@types/datatables.net/-/datatables.net-1.10.19.tgz#17c5f94433f761086131c6c8dc055a0e1099d1f9"
integrity sha512-WuzgytEmsIpVYZbkce+EvK1UqBI7/cwcC/WgYeAtXdq2zi+yWzJwMT5Yb6irAiOi52DBjeAEeRt3bYzFYvHWCQ==
dependencies:
"@types/jquery" "*"
"@types/dompurify@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@types/dompurify/-/dompurify-2.0.0.tgz#9616caa5bf2569aea2e4889d4f929d968c081b40"

Loading…
Cancel
Save