Friends page, Profile page, Settings, Images
This commit is contained in:
parent
c19bba5930
commit
064ded5fe5
@ -147,6 +147,15 @@ public class APIController {
|
||||
return ResponseEntity.badRequest().build();
|
||||
}
|
||||
|
||||
@PostMapping("/api/v1/friends/remove/")
|
||||
public ResponseEntity<String> removeFriend( @RequestParam("friend_id") Long friend_id ) {
|
||||
if( userService.findById(friend_id) == null ) return ResponseEntity.badRequest().build();
|
||||
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
|
||||
Long userId = userService.findByUsername(((org.springframework.security.core.userdetails.User) auth.getPrincipal()).getUsername()).getId();
|
||||
friendService.removeFriend(userId, friend_id);
|
||||
return ResponseEntity.ok().build();
|
||||
}
|
||||
|
||||
@PostMapping("/async/notify/get/")
|
||||
@ResponseBody
|
||||
public DeferredResult<LongPollResult> getNotify(@RequestParam("last_chat_id") Long last_chat_id,
|
||||
|
@ -1,14 +1,21 @@
|
||||
package com.alterdekim.game.controller;
|
||||
|
||||
import com.alterdekim.game.dto.FriendPageResult;
|
||||
import com.alterdekim.game.dto.UserDTO;
|
||||
import com.alterdekim.game.entities.Invite;
|
||||
import com.alterdekim.game.entities.User;
|
||||
import com.alterdekim.game.service.InviteService;
|
||||
import com.alterdekim.game.service.InviteServiceImpl;
|
||||
import com.alterdekim.game.service.UserService;
|
||||
import com.alterdekim.game.service.UserServiceImpl;
|
||||
import com.alterdekim.game.util.AuthenticationUtil;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import jakarta.validation.Valid;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@ -23,27 +30,22 @@ public class AuthController {
|
||||
|
||||
private final String base_title = " | Nosedive";
|
||||
|
||||
private final UserService userService;
|
||||
private final InviteService inviteService;
|
||||
@Autowired
|
||||
private UserServiceImpl userService;
|
||||
|
||||
public AuthController(UserService userService, InviteService inviteService) {
|
||||
this.inviteService = inviteService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@GetMapping("/game")
|
||||
public String gamePage(Model model) {
|
||||
return "game";
|
||||
}
|
||||
@Autowired
|
||||
private InviteServiceImpl inviteService;
|
||||
|
||||
@GetMapping("/login")
|
||||
public String loginPage(Model model) {
|
||||
AuthenticationUtil.authProfile(model, userService);
|
||||
model.addAttribute("title", "Login" + base_title);
|
||||
return "login";
|
||||
}
|
||||
|
||||
@GetMapping("/signup")
|
||||
public String showRegistrationForm(Model model) {
|
||||
AuthenticationUtil.authProfile(model, userService);
|
||||
UserDTO userDto = new UserDTO();
|
||||
model.addAttribute("user", userDto);
|
||||
return "signup";
|
||||
|
@ -1,8 +1,11 @@
|
||||
package com.alterdekim.game.controller;
|
||||
|
||||
import com.alterdekim.game.dto.AuthApiObject;
|
||||
import com.alterdekim.game.dto.FriendPageResult;
|
||||
import com.alterdekim.game.entities.User;
|
||||
import com.alterdekim.game.service.FriendServiceImpl;
|
||||
import com.alterdekim.game.service.UserServiceImpl;
|
||||
import com.alterdekim.game.util.AuthenticationUtil;
|
||||
import com.alterdekim.game.util.Hash;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@ -19,32 +22,56 @@ public class StaticController {
|
||||
@Autowired
|
||||
private UserServiceImpl userService;
|
||||
|
||||
@Autowired
|
||||
private FriendServiceImpl friendService;
|
||||
|
||||
@GetMapping("/rules")
|
||||
public String rulesPage(Model model) {
|
||||
AuthenticationUtil.authProfile(model, userService);
|
||||
return "rules";
|
||||
}
|
||||
|
||||
@GetMapping("/game")
|
||||
public String gamePage(Model model) {
|
||||
return "game";
|
||||
}
|
||||
|
||||
@GetMapping("/games")
|
||||
public String gamesPage(Model model) {
|
||||
try {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
User u = userService.findByUsername(((org.springframework.security.core.userdetails.User) authentication.getPrincipal()).getUsername());
|
||||
Long userId = u.getId();
|
||||
User u = AuthenticationUtil.authProfile(model, userService);
|
||||
String apiKey = Hash.sha256((u.getId() + u.getUsername() + u.getPassword()).getBytes());
|
||||
model.addAttribute("auth_obj", new AuthApiObject(apiKey, userId, Hash.rnd()));
|
||||
model.addAttribute("auth_obj", new AuthApiObject(apiKey, u.getId(), Hash.rnd()));
|
||||
} catch ( Exception e ) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
return "games";
|
||||
}
|
||||
|
||||
@GetMapping("/friends")
|
||||
public String friendsPage(Model model) {
|
||||
Long userId = AuthenticationUtil.authProfile(model, userService).getId();
|
||||
model.addAttribute("friends", friendService.getFriendsOfUserId(userId).stream()
|
||||
.map(l -> userService.findById(l))
|
||||
.map(u -> new FriendPageResult("/profile/"+u.getId(), "background-image: url("https://i.dogecdn.wtf/wxEpEiovduvcXadQ");", u.getUsername(), u.getId())));
|
||||
return "friends";
|
||||
}
|
||||
|
||||
@GetMapping("/settings")
|
||||
public String settingsPage(Model model) {
|
||||
Long userId = AuthenticationUtil.authProfile(model, userService).getId();
|
||||
return "settings";
|
||||
}
|
||||
|
||||
@GetMapping("/")
|
||||
public String homePage(Model model) {
|
||||
AuthenticationUtil.authProfile(model, userService);
|
||||
return "index";
|
||||
}
|
||||
|
||||
@GetMapping("/access-denied")
|
||||
public String accessDenied(Model model) {
|
||||
AuthenticationUtil.authProfile(model, userService);
|
||||
model.addAttribute("title", "Access denied");
|
||||
return "access-denied";
|
||||
}
|
||||
|
15
src/main/java/com/alterdekim/game/dto/FriendPageResult.java
Normal file
15
src/main/java/com/alterdekim/game/dto/FriendPageResult.java
Normal file
@ -0,0 +1,15 @@
|
||||
package com.alterdekim.game.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
public class FriendPageResult {
|
||||
private String href;
|
||||
private String avatar;
|
||||
private String username;
|
||||
private Long id;
|
||||
}
|
@ -3,9 +3,11 @@ package com.alterdekim.game.repository;
|
||||
import com.alterdekim.game.entities.FriendStatus;
|
||||
import com.alterdekim.game.entities.Room;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -13,4 +15,9 @@ import java.util.List;
|
||||
public interface FriendRepository extends JpaRepository<FriendStatus, Long> {
|
||||
@Query(value = "SELECT IF(f.firstUserId = :userId, f.secondUserId, f.firstUserId) FROM FriendStatus f WHERE (f.firstUserId = :userId OR f.secondUserId = :userId) AND f.status = 2")
|
||||
List<Long> getFriendsOfUserId(@Param("userId") Long userId);
|
||||
|
||||
@Transactional
|
||||
@Modifying
|
||||
@Query(value = "DELETE FROM FriendStatus f WHERE ((f.firstUserId = :userId AND f.secondUserId = :friendId) OR (f.firstUserId = :friendId AND f.secondUserId = :userId)) AND f.status = 2")
|
||||
void removeFriend(@Param("userId") Long userId, @Param("friendId") Long friendId);
|
||||
}
|
@ -39,6 +39,8 @@ public class SpringSecurity {
|
||||
.requestMatchers("/games").hasAnyAuthority("ROLE_ADMIN")
|
||||
.requestMatchers("/profile/**").hasAnyAuthority("ROLE_ADMIN")
|
||||
.requestMatchers("/api/**").hasAnyAuthority("ROLE_ADMIN")
|
||||
.requestMatchers("/friends").hasAnyAuthority("ROLE_ADMIN")
|
||||
.requestMatchers("/settings").hasAnyAuthority("ROLE_ADMIN")
|
||||
.requestMatchers("/static/**").permitAll()
|
||||
.requestMatchers("/access-denied").permitAll()
|
||||
.requestMatchers("/signup").permitAll()
|
||||
|
@ -14,4 +14,8 @@ public class FriendServiceImpl {
|
||||
public List<Long> getFriendsOfUserId(Long userId) {
|
||||
return repository.getFriendsOfUserId(userId);
|
||||
}
|
||||
|
||||
public void removeFriend(Long userId, Long friendId) {
|
||||
repository.removeFriend(userId, friendId);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,26 @@
|
||||
package com.alterdekim.game.util;
|
||||
|
||||
import com.alterdekim.game.dto.FriendPageResult;
|
||||
import com.alterdekim.game.entities.User;
|
||||
import com.alterdekim.game.service.UserServiceImpl;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.ui.Model;
|
||||
|
||||
@Slf4j
|
||||
public class AuthenticationUtil {
|
||||
public static User authProfile(Model model, UserServiceImpl userService) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if( authentication.isAuthenticated() ) {
|
||||
try {
|
||||
User u = userService.findByUsername(((org.springframework.security.core.userdetails.User) authentication.getPrincipal()).getUsername());
|
||||
model.addAttribute("profile", new FriendPageResult("/profile/" + u.getId(), "", u.getUsername(), u.getId()));
|
||||
return u;
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
60
src/main/resources/static/css/friends.css
Normal file
60
src/main/resources/static/css/friends.css
Normal file
@ -0,0 +1,60 @@
|
||||
.block {
|
||||
display: block;
|
||||
border-bottom: 2px solid var(--dive-shadow-second);
|
||||
border-radius: 5px;
|
||||
padding-top: .1px;
|
||||
padding-bottom: .1px;
|
||||
width: 100%;
|
||||
background-color: var(--dive-white);
|
||||
max-width: 1000px;
|
||||
min-height: 30vh;
|
||||
}
|
||||
|
||||
.block-content {
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-top: 0.5rem;
|
||||
margin-left: 0.5rem;
|
||||
}
|
||||
|
||||
.friends-list-one-info-actions > button {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.friends-list {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.friends-list-one {
|
||||
float: left;
|
||||
width: 320px;
|
||||
height: 95px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.friends-list-one-avatar {
|
||||
float: left;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
border-radius: 3px;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.friends-list-one-info {
|
||||
float: left;
|
||||
padding-left: 15px;
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.friends-list-one-info-nick {
|
||||
height: 25px;
|
||||
font-weight: 300;
|
||||
font-size: 21px;
|
||||
line-height: 25px;
|
||||
}
|
69
src/main/resources/static/css/settings.css
Normal file
69
src/main/resources/static/css/settings.css
Normal file
@ -0,0 +1,69 @@
|
||||
.container {
|
||||
width: 1000px;
|
||||
}
|
||||
|
||||
.grid {
|
||||
display: grid !important;
|
||||
grid-template-columns: repeat(12,1fr);
|
||||
grid-column-gap: 25px;
|
||||
}
|
||||
|
||||
.g-col-8 {
|
||||
grid-column-end: span 8;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.g-col-4 {
|
||||
grid-column-end: span 4;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.block {
|
||||
display: block;
|
||||
border-bottom: 2px solid var(--dive-shadow-second);
|
||||
border-radius: 5px;
|
||||
padding-top: 0.1px;
|
||||
padding-bottom: 0.1px;
|
||||
width: 100%;
|
||||
min-height: 1px;
|
||||
background-color: var(--dive-white);
|
||||
}
|
||||
|
||||
.title {
|
||||
margin-bottom: 15px;
|
||||
font-size: 18px;
|
||||
margin-top: 20px;
|
||||
margin-right: 20px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
.block-content {
|
||||
justify-content: center;
|
||||
display: flex;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.text-glowing {
|
||||
color: var(--dive-primary-color) !important;
|
||||
}
|
||||
|
||||
.profile-img {
|
||||
width: 6.9rem;
|
||||
height: 6.9rem;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
color: var(--dive-dark-grey-second);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 5px 20px;
|
||||
height: 38px;
|
||||
cursor: pointer;
|
||||
font-size: 1.1rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.menu-item._selected {
|
||||
background-color: var(--dive-primary-color-trans);
|
||||
}
|
20
src/main/resources/static/javascript/friends.js
Normal file
20
src/main/resources/static/javascript/friends.js
Normal file
@ -0,0 +1,20 @@
|
||||
$(document).ready(function() {
|
||||
$(".friends-list-one").hover(function() {
|
||||
$(this).find(".friends-list-one-info").find(".friends-list-one-info-actions").css("display", "");
|
||||
}, function() {
|
||||
$(this).find(".friends-list-one-info").find(".friends-list-one-info-actions").css("display", "none");
|
||||
});
|
||||
});
|
||||
|
||||
function removeFriend(obj) {
|
||||
let friend_id = $(obj).attr("data-friend-id");
|
||||
$.ajax({
|
||||
url: "/api/v1/friends/remove/",
|
||||
method: "POST",
|
||||
data: {
|
||||
friend_id: friend_id
|
||||
}
|
||||
}).done(function() {
|
||||
$(obj).parent().parent().parent().remove();
|
||||
});
|
||||
}
|
@ -151,7 +151,7 @@ function successPolling(data) {
|
||||
}
|
||||
}
|
||||
fids.push({id: friend.id, username: friend.username});
|
||||
let fr_html = '<div class="friend-one" data-friend-id="'+friend.id+'"><a href="/profile/'+friend.id+'" class="navbar-btn"><img class="navbar-profile-img" src="https://avatars.githubusercontent.com/u/102559365?v=4"></a><span>'+friend.username+'</span><ion-icon onClick="sendInviteMessage('+friend.id+')" name="person-add-outline" role="img" class="md hydrated"></ion-icon></div>';
|
||||
let fr_html = '<div class="friend-one" data-friend-id="'+friend.id+'"><a href="/profile/'+friend.id+'" class="navbar-btn"><img class="navbar-profile-img" src="https://avatars.githubusercontent.com/u/102559365?v=4"></a><span>'+friend.username+'</span><ion-icon onClick="sendInviteMessage('+friend.id+')" name="person-add" role="img" class="md hydrated"></ion-icon></div>';
|
||||
$(".friends-online-list").append(fr_html);
|
||||
} else if( friend.action == 'REMOVE' ) {
|
||||
for( let u = 0; u < fids.length; u++ ) {
|
||||
|
@ -30,13 +30,13 @@
|
||||
<li class="nav-item">
|
||||
<div class="dropdown">
|
||||
<a class="navbar-btn dropdown-toggle" id="dropdownMenuButton1" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<img class="navbar-profile-img" src="https://avatars.githubusercontent.com/u/102559365?v=4">
|
||||
<img class="navbar-profile-img" th:src="${profile.avatar}">
|
||||
</a>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton1">
|
||||
<li><a class="dropdown-item">username</a></li>
|
||||
<li><a class="dropdown-item" th:text="${profile.username}"></a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" href="/profile/">Profile</a></li>
|
||||
<li><a class="dropdown-item" href="/settings/">Settings</a></li>
|
||||
<li><a class="dropdown-item" th:href="${profile.href}">Profile</a></li>
|
||||
<li><a class="dropdown-item" href="/settings">Settings</a></li>
|
||||
<li><a class="dropdown-item" href="/logout">Logout</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
34
src/main/resources/templates/friends.html
Normal file
34
src/main/resources/templates/friends.html
Normal file
@ -0,0 +1,34 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/head}"></th:block>
|
||||
<link rel="stylesheet" href="/static/css/friends.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/navbar}"></th:block>
|
||||
|
||||
<div class="container mt-5 block">
|
||||
<h2>Friends</h2>
|
||||
<div class="friends-list">
|
||||
<th:block th:each="friend: ${friends}">
|
||||
<div class="friends-list-one">
|
||||
<a th:href="${friend.href}">
|
||||
<div class="friends-list-one-avatar" th:style="${friend.avatar}"></div>
|
||||
</a>
|
||||
<div class="friends-list-one-info">
|
||||
<div class="friends-list-one-info-nick">
|
||||
<a th:href="${friend.href}" th:text="${friend.username}"></a>
|
||||
</div>
|
||||
<div class="friends-list-one-info-actions" style="display: none;">
|
||||
<button onClick="removeFriend(this)" class="btn btn-danger btn-sm" th:data-friend-id="${friend.id}">Remove</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<th:block th:insert="~{fragments/essentials}"></th:block>
|
||||
<script src="/static/javascript/friends.js"></script>
|
||||
</body>
|
||||
</html>
|
@ -27,7 +27,7 @@
|
||||
<div class="game">
|
||||
<div class="players">
|
||||
<th:block th:each="p: ${players}">
|
||||
<div class="player" data-pid="${p.id}" onClick="drop(this)">
|
||||
<div class="player" th:data-pid="${p.id}" onClick="drop(this)">
|
||||
<p class="timeout"></p>
|
||||
<p class="nickname" th:text="${p.name}"></p>
|
||||
<p class="money" th:text="${p.money}"></p>
|
||||
@ -215,7 +215,7 @@
|
||||
<div class="up"><div class="board_field corner"><img src="../static/images/start.png" style="width: 100%; height: 100%;" /></div></div>
|
||||
|
||||
<th:block th:each="f: ${fields_up}">
|
||||
<div th:data-fid="${f.uid}" class="board_field" style="grid-column: @{${f.id}}"> <!-- 2 + -->
|
||||
<div th:data-fid="${f.uid}" class="board_field" th:style="grid-column: @{${f.id}}"> <!-- 2 + -->
|
||||
<div class="cost" th:text="${f.cost}"></div>
|
||||
<div class="fh">
|
||||
<div class="iconH">
|
||||
|
94
src/main/resources/templates/settings.html
Normal file
94
src/main/resources/templates/settings.html
Normal file
@ -0,0 +1,94 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
|
||||
<head>
|
||||
<th:block th:insert="~{fragments/head}"></th:block>
|
||||
<link rel="stylesheet" href="/static/css/settings.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<th:block th:insert="~{fragments/navbar}"></th:block>
|
||||
<div class="container">
|
||||
<div class="grid mt-5">
|
||||
<div class="g-col-8">
|
||||
<div class="block" id="profile" style="margin-top: 15px;">
|
||||
<div class="title">Profile</div>
|
||||
<div class="block-content">
|
||||
<div class="grid">
|
||||
<div class="g-col-4" style="display: flex; justify-content: center;">
|
||||
<div style="width: 50%;">
|
||||
<img class="profile-img" src="https://tg.dogecdn.wtf/v2/AgACAgIAAx0EWSIHJgAC0MBf64kG8Q99Gm69NezdtLUxTJaBiQACvrExG1sQWEtraYhjusGQAAGJdBmYLgADAQADAgADeAAD8RcFAAEeBA.jpg">
|
||||
<button class="btn btn-primary" style="margin-top: 10px; font-size: 0.7rem;">Update avatar</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-col-8" style="padding: 5px;">
|
||||
<div class="mb-3">
|
||||
<label for="displayname-input" class="form-label">Display name (may contain unicode symbols)</label>
|
||||
<input type="text" class="form-control" id="displayname-input" autocomplete="off">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="nickname-input" class="form-label">Nickname</label>
|
||||
<input type="text" class="form-control" id="nickname-input" autocomplete="off">
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="pronouns-select" class="form-label">Pronouns</label>
|
||||
<select class="form-select" id="pronouns-select" aria-label="">
|
||||
<option value="1">One</option>
|
||||
<option value="2">Two</option>
|
||||
<option value="3">Three</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block" id="security" style="margin-top: 15px;">
|
||||
<div class="title">Security</div>
|
||||
<div class="block-content">
|
||||
<div class="grid">
|
||||
<div class="g-col-4" style="display: flex; justify-content: center;">
|
||||
|
||||
</div>
|
||||
<div class="g-col-8" style="padding: 5px;">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block" id="privacy" style="margin-top: 15px;">
|
||||
<div class="title">Privacy</div>
|
||||
<div class="block-content">
|
||||
<div class="grid">
|
||||
<div class="g-col-4" style="display: flex; justify-content: center;">
|
||||
|
||||
</div>
|
||||
<div class="g-col-8" style="padding: 5px;">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="g-col-4">
|
||||
<div class="block" style="margin-top: 15px;">
|
||||
<div class="title">Settings</div>
|
||||
<div class="block-content" style="display: block;">
|
||||
<a href="#profile" class="menu-item _selected">Profile</a>
|
||||
<a href="#security" class="menu-item">Security</a>
|
||||
<a href="#privacy" class="menu-item">Privacy</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="block" style="margin-top: 15px;">
|
||||
<div class="title">Data</div>
|
||||
<div class="block-content" style="display: block;">
|
||||
<a href="#blacklist" class="menu-item">Black list</a>
|
||||
<a href="#notes" class="menu-item">Notes</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<th:block th:insert="~{fragments/essentials}"></th:block>
|
||||
</body>
|
||||
</html>
|
Loading…
x
Reference in New Issue
Block a user