Added stats to admin UI #11
This commit is contained in:
parent
77bff3924c
commit
05ba6fbacc
@ -2,11 +2,20 @@ import { changePassphrase } from "./pages/user/ChangePassphrase";
|
||||
import { EncryptionServiceFactory } from "../common/service/EncryptionServiceFactory";
|
||||
import log from "loglevel";
|
||||
import { AlertifyNotificationService } from "../common/service/AlertifyNotificationService";
|
||||
import { stats } from "./pages/Home";
|
||||
import { Credentials } from "../common/global/Credentials";
|
||||
|
||||
log.setLevel("TRACE");
|
||||
const es = EncryptionServiceFactory.getEncryptionService();
|
||||
const ns = new AlertifyNotificationService();
|
||||
const authToken = Credentials.authToken
|
||||
$("#changePassphraseForm").on("submit", (event) => {
|
||||
event.preventDefault();
|
||||
changePassphrase(es, ns);
|
||||
changePassphrase(es, ns, authToken);
|
||||
});
|
||||
|
||||
const pathMatcher = (path: string) => window.location.pathname == path
|
||||
|
||||
if(pathMatcher("/admin")) {
|
||||
stats()
|
||||
}
|
21
src/main/frontend/admin/pages/Home.ts
Normal file
21
src/main/frontend/admin/pages/Home.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { getStats } from "../../common/ajax/Messages";
|
||||
|
||||
import { Credentials } from "../../common/global/Credentials";
|
||||
import log from "loglevel";
|
||||
|
||||
export async function stats(): Promise<void> {
|
||||
const stats = await getStats(Credentials.authToken);
|
||||
$("#totalMessages").each((i, el) => {
|
||||
el.textContent = stats.totalMessages.toString();
|
||||
});
|
||||
$("#totalUsers").each((i, el) => {
|
||||
el.textContent = stats.totalUsers.toString();
|
||||
});
|
||||
$("#totalOnlineUsers").each((i, el) => {
|
||||
el.textContent = stats.totalOnlineUsers.toString();
|
||||
});
|
||||
$("#numMessagesToday").each((i, el) => {
|
||||
el.textContent = stats.numMessagesToday.toString();
|
||||
});
|
||||
log.debug(stats);
|
||||
}
|
@ -7,15 +7,16 @@ import { Credentials } from "../../../common/global/Credentials";
|
||||
import { MessageCipher } from "../../../common/entity/MessageCipher";
|
||||
import log from "loglevel";
|
||||
import { NotificationService } from "../../../common/service/NotificationService";
|
||||
import { isPassphraseValid } from "../../../common/util/passphrase";
|
||||
import { isPassphraseValid } from "../../../common/util/Passphrase";
|
||||
import {
|
||||
getAllMessages,
|
||||
sendReencryptedMessages,
|
||||
} from "../../../common/ajax/messages";
|
||||
} from "../../../common/ajax/Messages";
|
||||
|
||||
export async function changePassphrase(
|
||||
es: EncryptionService,
|
||||
ns: NotificationService
|
||||
ns: NotificationService,
|
||||
authToken: string
|
||||
): Promise<void> {
|
||||
// $("#changePassphraseForm").val();
|
||||
|
||||
@ -26,7 +27,7 @@ export async function changePassphrase(
|
||||
const passphraseOld: string = $("#passphraseOld").val() as string;
|
||||
const passphraseNew: string = $("#passphraseNew").val() as string;
|
||||
|
||||
const valid = await isPassphraseValid(passphraseOld, user, es);
|
||||
const valid = await isPassphraseValid(passphraseOld, user, es, authToken);
|
||||
|
||||
if (!valid) {
|
||||
log.error("Please check your passphrase");
|
||||
|
@ -4,27 +4,21 @@ import { ReencryptionDTO } from "../dto/ReencryptionDTO";
|
||||
import { ChatMessageDTO } from "../dto/ChatMessageDTO";
|
||||
import { JsonAPI } from "../../chat/singleton/JsonAPI";
|
||||
import * as log from "loglevel";
|
||||
import { StatsDTO } from "../dto/StatsDTO";
|
||||
import { createApiHeaders } from "./util";
|
||||
|
||||
export async function getAllMessages(user: string, authToken: string) {
|
||||
let headers = new Headers();
|
||||
// headers.append('Accept','application/json')
|
||||
// headers.append('Content-Type', 'application/json');
|
||||
headers.append("X-AUTH-TOKEN", authToken);
|
||||
let response = await fetch(`${Routes.Admin.getAllMessagesURL}${user}`, {
|
||||
method: "GET",
|
||||
headers: headers,
|
||||
headers: createApiHeaders(authToken),
|
||||
});
|
||||
return response.json() as Promise<ReencryptionDTO[]>;
|
||||
}
|
||||
|
||||
async function getAllRegularUsers(authToken: string) {
|
||||
let headers = new Headers();
|
||||
// headers.append('Accept','application/json')
|
||||
// headers.append('Content-Type', 'application/json');
|
||||
headers.append("X-AUTH-TOKEN", authToken);
|
||||
let response = await fetch(`${Routes.Admin.getAllRegularUsersURL}`, {
|
||||
method: "GET",
|
||||
headers: headers,
|
||||
headers: createApiHeaders(authToken),
|
||||
});
|
||||
let data = (await response.json()) as string[];
|
||||
return data;
|
||||
@ -49,19 +43,14 @@ export async function sendReencryptedMessages(
|
||||
|
||||
export async function getOneMessage(
|
||||
toUser: string,
|
||||
page: number
|
||||
page: number,
|
||||
authToken: string
|
||||
): Promise<ChatMessageDTO[]> {
|
||||
const headers = new Headers();
|
||||
if (JsonAPI.authToken == null) {
|
||||
log.error("authToken null");
|
||||
return [];
|
||||
}
|
||||
headers.append("X-AUTH-TOKEN", JsonAPI.authToken);
|
||||
const url = Sprintf(JsonAPI.CHAT_MESSAGE_PAGE_GET, toUser, page, 1);
|
||||
log.debug(url);
|
||||
const response = await fetch(url, {
|
||||
method: "GET",
|
||||
headers: headers,
|
||||
headers: createApiHeaders(authToken),
|
||||
});
|
||||
log.debug(response.clone());
|
||||
// if (fetchErrorHandler(response.clone(), this._notificationService)) {
|
||||
@ -80,3 +69,11 @@ export async function getOneMessage(
|
||||
const data2 = func(data);
|
||||
return data2;
|
||||
}
|
||||
|
||||
export async function getStats(authToken: string) {
|
||||
const response = await fetch("/api/stats/", {
|
||||
headers: createApiHeaders(authToken),
|
||||
method: "GET",
|
||||
})
|
||||
return (await response.json()) as StatsDTO;
|
||||
}
|
9
src/main/frontend/common/ajax/util.ts
Normal file
9
src/main/frontend/common/ajax/util.ts
Normal file
@ -0,0 +1,9 @@
|
||||
|
||||
export function createApiHeaders(authToken: string): Headers {
|
||||
const headers = new Headers();
|
||||
// headers.append("Content-Type", "application/json");
|
||||
headers.append("X-AUTH-TOKEN", authToken);
|
||||
return headers;
|
||||
}
|
||||
|
||||
|
6
src/main/frontend/common/dto/StatsDTO.ts
Normal file
6
src/main/frontend/common/dto/StatsDTO.ts
Normal file
@ -0,0 +1,6 @@
|
||||
export interface StatsDTO {
|
||||
totalMessages: number;
|
||||
totalOnlineUsers: number;
|
||||
totalUsers: number;
|
||||
numMessagesToday: number;
|
||||
}
|
3
src/main/frontend/common/routes/Stats.ts
Normal file
3
src/main/frontend/common/routes/Stats.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export namespace Stats {
|
||||
export const rootStats = "/api/stats/"
|
||||
}
|
@ -1,14 +1,15 @@
|
||||
import { EncryptionService } from "../service/EncryptionService";
|
||||
import { ChatMessageDTO } from "../dto/ChatMessageDTO";
|
||||
import * as log from "loglevel";
|
||||
import { getOneMessage } from "../ajax/messages";
|
||||
import { getOneMessage } from "../ajax/Messages";
|
||||
|
||||
export async function isPassphraseValid(
|
||||
passphrase: string,
|
||||
userName: string,
|
||||
es: EncryptionService
|
||||
es: EncryptionService,
|
||||
authToken: string
|
||||
): Promise<boolean> {
|
||||
const messages: ChatMessageDTO[] = await getOneMessage(userName, 0);
|
||||
const messages: ChatMessageDTO[] = await getOneMessage(userName, 0, authToken);
|
||||
if (messages.length === 0) return true;
|
||||
try {
|
||||
es.decrypt(passphrase, messages[0].messageCipher);
|
@ -8,14 +8,9 @@
|
||||
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
|
||||
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js"
|
||||
data-template-prefix="../" defer="defer" th:if="false"></script>
|
||||
<!-- <script th:src="@{/js/admin.js}" src="../../static/js/admin.js" defer="defer"></script> -->
|
||||
<script th:src="@{/js/adminBundle.js}" src="../../static/js/adminBundle.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"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.js"></script>
|
||||
|
||||
<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">
|
||||
<th:block th:include="fragments/admin :: headFragment"></th:block>
|
||||
|
||||
</head>
|
||||
<!-- TODO
|
||||
Make user admin / remove user from admin
|
||||
|
@ -6,14 +6,10 @@
|
||||
<title id="pageTitle">Admin Home</title>
|
||||
</div>
|
||||
<script src="https://code.jquery.com/jquery-2.1.4.min.js" th:if="false"></script>
|
||||
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" data-template-prefix="../" defer="defer" th:if="false"></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"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.8.0/Chart.js"></script>
|
||||
|
||||
<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">
|
||||
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js"
|
||||
data-template-prefix="../" defer="defer" th:if="false"></script>
|
||||
|
||||
<th:block th:include="fragments/admin :: headFragment"></th:block>
|
||||
</head>
|
||||
<!-- TODO
|
||||
Make user admin / remove user from admin
|
||||
@ -21,13 +17,13 @@
|
||||
Delete Messages
|
||||
-->
|
||||
|
||||
<!-- <div th:include="fragments/admin :: admin-sidebar"></div> -->
|
||||
<!-- <div th:include="fragments/admin :: admin-sideb ar"></div> -->
|
||||
|
||||
<body id="page-top">
|
||||
|
||||
<!-- Page Wrapper -->
|
||||
<div id="wrapper">
|
||||
|
||||
|
||||
|
||||
<th:block th:include="fragments/admin :: sidebar-fragment"></th:block>
|
||||
|
||||
@ -36,7 +32,7 @@
|
||||
|
||||
<!-- Main Content -->
|
||||
<div id="content">
|
||||
|
||||
|
||||
<div th:include="fragments/admin :: topbar-fragment"></div>
|
||||
|
||||
<!-- Begin Page Content -->
|
||||
@ -45,7 +41,8 @@
|
||||
<!-- Page Heading -->
|
||||
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||
<h1 class="h3 mb-0 text-light">Dashboard</h1>
|
||||
<a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i class="fas fa-download fa-sm text-white-50"></i> Generate Report</a>
|
||||
<a href="#" class="d-none d-sm-inline-block btn btn-sm btn-primary shadow-sm"><i
|
||||
class="fas fa-download fa-sm text-white-50"></i> Generate Report</a>
|
||||
</div>
|
||||
|
||||
<!-- Content Row -->
|
||||
@ -53,15 +50,18 @@
|
||||
|
||||
<!-- Earnings (Monthly) Card Example -->
|
||||
<div class="col-xl-3 col-md-6 mb-4">
|
||||
<div class="card text-light border border-dark bg-dark border-left-primary-dark shadow h-100 py-2">
|
||||
<div
|
||||
class="card text-light border border-dark bg-dark border-left-primary-dark shadow h-100 py-2">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-primary-dark text-uppercase mb-1">Earnings (Monthly)</div>
|
||||
<div class="h5 mb-0 font-weight-bold ">$40,000</div>
|
||||
<div
|
||||
class="text-xs font-weight-bold text-primary-dark text-uppercase mb-1">
|
||||
Total Users</div>
|
||||
<div class="h5 mb-0 font-weight-bold " id="totalUsers">0</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="fas fa-calendar fa-2x text-gray-300"></i>
|
||||
<i class="fas fa-users fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -70,15 +70,17 @@
|
||||
|
||||
<!-- Earnings (Monthly) Card Example -->
|
||||
<div class="col-xl-3 col-md-6 mb-4">
|
||||
<div class="card text-light border border-dark bg-dark border-left-success shadow h-100 py-2">
|
||||
<div
|
||||
class="card text-light border border-dark bg-dark border-left-success shadow h-100 py-2">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">Earnings (Annual)</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-light">$215,000</div>
|
||||
<div class="text-xs font-weight-bold text-success text-uppercase mb-1">
|
||||
Total Messages</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-light" id="totalMessages">0</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="fas fa-dollar-sign fa-2x text-gray-300"></i>
|
||||
<i class="fas fa-comments fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -91,20 +93,23 @@
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Tasks</div>
|
||||
<div class="text-xs font-weight-bold text-info text-uppercase mb-1">Users Online
|
||||
</div>
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col-auto">
|
||||
<div class="h5 mb-0 mr-3 font-weight-bold text-white">50%</div>
|
||||
<div class="h5 mb-0 mr-3 font-weight-bold text-white" id="totalOnlineUsers">0</div>
|
||||
</div>
|
||||
<div class="col">
|
||||
<!-- <div class="col">
|
||||
<div class="progress progress-sm mr-2">
|
||||
<div class="progress-bar bg-info" role="progressbar" style="width: 50%" aria-valuenow="50" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div class="progress-bar bg-info" role="progressbar"
|
||||
style="width: 50%" aria-valuenow="50" aria-valuemin="0"
|
||||
aria-valuemax="100"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="fas fa-clipboard-list fa-2x text-gray-300"></i>
|
||||
<i class="fas fa-user fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -113,15 +118,17 @@
|
||||
|
||||
<!-- Pending Requests Card Example -->
|
||||
<div class="col-xl-3 col-md-6 mb-4">
|
||||
<div class="card text-light border border-dark bg-dark border-left-warning shadow h-100 py-2">
|
||||
<div
|
||||
class="card text-light border border-dark bg-dark border-left-warning shadow h-100 py-2">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col mr-2">
|
||||
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">Pending Requests</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-white">18</div>
|
||||
<div class="text-xs font-weight-bold text-warning text-uppercase mb-1">
|
||||
Messages Today</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-white">0</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="fas fa-comments fa-2x text-gray-300"></i>
|
||||
<i class="fas fa-comment fa-2x text-gray-300"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -137,13 +144,16 @@
|
||||
<div class="col-xl-8 col-lg-7">
|
||||
<div class="card bg-dark border border-dark text-white shadow mb-4">
|
||||
<!-- Card Header - Dropdown -->
|
||||
<div class="card-header bg-secondary border border-secondary py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<div
|
||||
class="card-header bg-secondary border border-secondary py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold text-white">Earnings Overview</h6>
|
||||
<div class="dropdown no-arrow">
|
||||
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<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-white"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
|
||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
||||
aria-labelledby="dropdownMenuLink">
|
||||
<div class="dropdown-header">Dropdown Header:</div>
|
||||
<a class="dropdown-item" href="#">Action</a>
|
||||
<a class="dropdown-item" href="#">Another action</a>
|
||||
@ -165,13 +175,16 @@
|
||||
<div class="col-xl-4 col-lg-5">
|
||||
<div class="card bg-dark border border-dark text-white shadow mb-4">
|
||||
<!-- Card Header - Dropdown -->
|
||||
<div class="card-header bg-secondary border border-secondary py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<div
|
||||
class="card-header bg-secondary border border-secondary py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold text-white">Revenue Sources</h6>
|
||||
<div class="dropdown no-arrow">
|
||||
<a class="dropdown-toggle" href="#" role="button" id="dropdownMenuLink" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<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-white"></i>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in" aria-labelledby="dropdownMenuLink">
|
||||
<div class="dropdown-menu dropdown-menu-right shadow animated--fade-in"
|
||||
aria-labelledby="dropdownMenuLink">
|
||||
<div class="dropdown-header">Dropdown Header:</div>
|
||||
<a class="dropdown-item" href="#">Action</a>
|
||||
<a class="dropdown-item" href="#">Another action</a>
|
||||
@ -187,14 +200,14 @@
|
||||
</div>
|
||||
<div class="mt-4 text-center small">
|
||||
<span class="mr-2">
|
||||
<i class="fas fa-circle text-primary"></i> Direct
|
||||
</span>
|
||||
<i class="fas fa-circle text-primary"></i> Direct
|
||||
</span>
|
||||
<span class="mr-2">
|
||||
<i class="fas fa-circle text-success"></i> Social
|
||||
</span>
|
||||
<i class="fas fa-circle text-success"></i> Social
|
||||
</span>
|
||||
<span class="mr-2">
|
||||
<i class="fas fa-circle text-info"></i> Referral
|
||||
</span>
|
||||
<i class="fas fa-circle text-info"></i> Referral
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -213,25 +226,35 @@
|
||||
<h6 class="m-0 font-weight-bold text-white">Projects</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<h4 class="small font-weight-bold">Server Migration <span class="float-right">20%</span></h4>
|
||||
<h4 class="small font-weight-bold">Server Migration <span
|
||||
class="float-right">20%</span></h4>
|
||||
<div class="progress mb-4">
|
||||
<div class="progress-bar bg-danger" role="progressbar" style="width: 20%" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div class="progress-bar bg-danger" role="progressbar" style="width: 20%"
|
||||
aria-valuenow="20" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<h4 class="small font-weight-bold">Sales Tracking <span class="float-right">40%</span></h4>
|
||||
<h4 class="small font-weight-bold">Sales Tracking <span
|
||||
class="float-right">40%</span></h4>
|
||||
<div class="progress mb-4">
|
||||
<div class="progress-bar bg-warning" role="progressbar" style="width: 40%" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div class="progress-bar bg-warning" role="progressbar" style="width: 40%"
|
||||
aria-valuenow="40" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<h4 class="small font-weight-bold">Customer Database <span class="float-right">60%</span></h4>
|
||||
<h4 class="small font-weight-bold">Customer Database <span
|
||||
class="float-right">60%</span></h4>
|
||||
<div class="progress mb-4">
|
||||
<div class="progress-bar" role="progressbar" style="width: 60%" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div class="progress-bar" role="progressbar" style="width: 60%"
|
||||
aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<h4 class="small font-weight-bold">Payout Details <span class="float-right">80%</span></h4>
|
||||
<h4 class="small font-weight-bold">Payout Details <span
|
||||
class="float-right">80%</span></h4>
|
||||
<div class="progress mb-4">
|
||||
<div class="progress-bar bg-info" role="progressbar" style="width: 80%" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div class="progress-bar bg-info" role="progressbar" style="width: 80%"
|
||||
aria-valuenow="80" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
<h4 class="small font-weight-bold">Account Setup <span class="float-right">Complete!</span></h4>
|
||||
<h4 class="small font-weight-bold">Account Setup <span
|
||||
class="float-right">Complete!</span></h4>
|
||||
<div class="progress">
|
||||
<div class="progress-bar bg-success" role="progressbar" style="width: 100%" aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
<div class="progress-bar bg-success" role="progressbar" style="width: 100%"
|
||||
aria-valuenow="100" aria-valuemin="0" aria-valuemax="100"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -299,11 +322,17 @@
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="text-center">
|
||||
<img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;" th:src="@{/img/undraw_posting_photo.svg}" src="../../static/img/undraw_posting_photo.svg" alt="">
|
||||
<img class="img-fluid px-3 px-sm-4 mt-3 mb-4" style="width: 25rem;"
|
||||
th:src="@{/img/undraw_posting_photo.svg}"
|
||||
src="../../static/img/undraw_posting_photo.svg" alt="">
|
||||
</div>
|
||||
<p>Add some quality, svg illustrations to your project courtesy of <a target="_blank" rel="nofollow" href="https://undraw.co/">unDraw</a>, a constantly updated collection of beautiful svg images that you can use completely
|
||||
<p>Add some quality, svg illustrations to your project courtesy of <a
|
||||
target="_blank" rel="nofollow" href="https://undraw.co/">unDraw</a>, a
|
||||
constantly updated collection of beautiful svg images that you can use
|
||||
completely
|
||||
free and without attribution!</p>
|
||||
<a target="_blank" rel="nofollow" href="https://undraw.co/">Browse Illustrations on unDraw →</a>
|
||||
<a target="_blank" rel="nofollow" href="https://undraw.co/">Browse Illustrations on
|
||||
unDraw →</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -313,8 +342,11 @@
|
||||
<h6 class="m-0 font-weight-bold text-white">Development Approach</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce CSS bloat and poor page performance. Custom CSS classes are used to create custom components and custom utility classes.</p>
|
||||
<p class="mb-0">Before working with this theme, you should become familiar with the Bootstrap framework, especially the utility classes.</p>
|
||||
<p>SB Admin 2 makes extensive use of Bootstrap 4 utility classes in order to reduce
|
||||
CSS bloat and poor page performance. Custom CSS classes are used to create
|
||||
custom components and custom utility classes.</p>
|
||||
<p class="mb-0">Before working with this theme, you should become familiar with the
|
||||
Bootstrap framework, especially the utility classes.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -336,7 +368,9 @@
|
||||
<!-- 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>
|
||||
<div th:if="false">
|
||||
<th:block th:include="admin :: modal"></th:block>
|
||||
</div>
|
||||
|
||||
<!-- Page level custom scripts -->
|
||||
<script th:src="@{/js/demo/chart-area-demo.js}" src="../../static/js/demo/chart-area-demo.js"></script>
|
||||
|
@ -13,6 +13,19 @@
|
||||
<script src="http://blackpeppersoftware.github.io/thymeleaf-fragment.js/thymeleaf-fragment.js" defer="defer" th:if="false"></script>
|
||||
<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>
|
||||
|
||||
<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">
|
||||
</th:block>
|
||||
|
||||
|
||||
|
||||
<link href="../../static/css/sb-admin-2.css" rel="stylesheet" th:if="false">
|
||||
<link href="../../static/css/admin-custom.css" rel="stylesheet" th:if="false">
|
||||
</head>
|
||||
|
@ -81,7 +81,7 @@
|
||||
<a href="user/home.html" sec:authorize="isFullyAuthenticated()" th:href="@{/user}" class="nav-link">User Area</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a th:href="chat" href="chat.html" class="nav-link">Chat</a>
|
||||
<a th:href="@{/chat}" href="chat.html" class="nav-link">Chat</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a th:href="login" sec:authorize="!isFullyAuthenticated()" href="login.html" class="nav-link">Login</a>
|
||||
|
Loading…
Reference in New Issue
Block a user