Cleaned up exchange and account pages, and added custom site font.
This commit is contained in:
parent
cff73d9803
commit
f768d62342
|
@ -1,7 +1,6 @@
|
||||||
package nl.andrewl.coyotecredit.ctl;
|
package nl.andrewl.coyotecredit.ctl;
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import nl.andrewl.coyotecredit.ctl.dto.AddAccountPayload;
|
|
||||||
import nl.andrewl.coyotecredit.ctl.dto.EditExchangePayload;
|
import nl.andrewl.coyotecredit.ctl.dto.EditExchangePayload;
|
||||||
import nl.andrewl.coyotecredit.ctl.dto.InviteUserPayload;
|
import nl.andrewl.coyotecredit.ctl.dto.InviteUserPayload;
|
||||||
import nl.andrewl.coyotecredit.model.User;
|
import nl.andrewl.coyotecredit.model.User;
|
||||||
|
|
|
@ -3,6 +3,8 @@ package nl.andrewl.coyotecredit.ctl.dto;
|
||||||
public record ExchangeData(
|
public record ExchangeData(
|
||||||
long id,
|
long id,
|
||||||
String name,
|
String name,
|
||||||
String primaryTradeable
|
String description,
|
||||||
|
String primaryTradeable,
|
||||||
|
long primaryTradeableId
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,9 @@ public class AccountService {
|
||||||
new ExchangeData(
|
new ExchangeData(
|
||||||
account.getExchange().getId(),
|
account.getExchange().getId(),
|
||||||
account.getExchange().getName(),
|
account.getExchange().getName(),
|
||||||
account.getExchange().getPrimaryTradeable().getSymbol()
|
account.getExchange().getDescription(),
|
||||||
|
account.getExchange().getPrimaryTradeable().getSymbol(),
|
||||||
|
account.getExchange().getPrimaryTradeable().getId()
|
||||||
),
|
),
|
||||||
account.getBalances().stream()
|
account.getBalances().stream()
|
||||||
.map(b -> new BalanceData(
|
.map(b -> new BalanceData(
|
||||||
|
|
|
@ -106,29 +106,6 @@ public class ExchangeService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
|
||||||
public long addAccount(long exchangeId, User user, AddAccountPayload payload) {
|
|
||||||
Exchange exchange = exchangeRepository.findById(exchangeId)
|
|
||||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
|
||||||
Account account = accountRepository.findByUserAndExchange(user, exchange)
|
|
||||||
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND));
|
|
||||||
if (!account.isAdmin()) {
|
|
||||||
throw new ResponseStatusException(HttpStatus.NOT_FOUND);
|
|
||||||
}
|
|
||||||
User u = userRepository.save(new User(payload.username(), passwordEncoder.encode(payload.password()), payload.email()));
|
|
||||||
Account a = accountRepository.save(new Account(
|
|
||||||
AccountNumberUtils.generate(),
|
|
||||||
u,
|
|
||||||
payload.name(),
|
|
||||||
exchange
|
|
||||||
));
|
|
||||||
for (var t : exchange.getAllTradeables()) {
|
|
||||||
a.getBalances().add(new Balance(a, t, BigDecimal.ZERO));
|
|
||||||
}
|
|
||||||
a = accountRepository.save(a);
|
|
||||||
return a.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void removeAccount(long exchangeId, long accountId, User user) {
|
public void removeAccount(long exchangeId, long accountId, User user) {
|
||||||
Exchange exchange = exchangeRepository.findById(exchangeId)
|
Exchange exchange = exchangeRepository.findById(exchangeId)
|
||||||
|
@ -217,7 +194,13 @@ public class ExchangeService {
|
||||||
public List<ExchangeAccountData> getExchanges(User user) {
|
public List<ExchangeAccountData> getExchanges(User user) {
|
||||||
return accountRepository.findAllByUser(user).stream()
|
return accountRepository.findAllByUser(user).stream()
|
||||||
.map(a -> new ExchangeAccountData(
|
.map(a -> new ExchangeAccountData(
|
||||||
new ExchangeData(a.getExchange().getId(), a.getExchange().getName(), a.getExchange().getPrimaryTradeable().getSymbol()),
|
new ExchangeData(
|
||||||
|
a.getExchange().getId(),
|
||||||
|
a.getExchange().getName(),
|
||||||
|
a.getExchange().getDescription(),
|
||||||
|
a.getExchange().getPrimaryTradeable().getSymbol(),
|
||||||
|
a.getExchange().getPrimaryTradeable().getId()
|
||||||
|
),
|
||||||
new SimpleAccountData(
|
new SimpleAccountData(
|
||||||
a.getId(),
|
a.getId(),
|
||||||
user.getId(),
|
user.getId(),
|
||||||
|
|
|
@ -1,29 +1,38 @@
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: SpaceMono;
|
font-family: SpaceMono;
|
||||||
src: url("/static/font/SpaceMono-Regular.ttf");
|
src: url("/static/font/spacemono/SpaceMono-Regular.ttf");
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: SpaceMono;
|
||||||
|
src: url("/static/font/spacemono/SpaceMono-Italic.ttf");
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: SpaceMono;
|
||||||
|
src: url("/static/font/spacemono/SpaceMono-Bold.ttf");
|
||||||
|
font-style: normal;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
@font-face {
|
||||||
|
font-family: SpaceMono;
|
||||||
|
src: url("/static/font/spacemono/SpaceMono-BoldItalic.ttf");
|
||||||
|
font-style: italic;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: Pacifico;
|
||||||
|
src: url("/static/font/pacifico/Pacifico-Regular.ttf");
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: normal;
|
font-weight: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: SpaceMono;
|
font-family: Josefin Sans;
|
||||||
src: url("/static/font/SpaceMono-Italic.ttf");
|
src: url("/static/font/josefin-sans/JosefinSans-VariableFont_wght.ttf") format("truetype-variations");
|
||||||
font-style: italic;
|
|
||||||
font-weight: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: SpaceMono;
|
|
||||||
src: url("/static/font/SpaceMono-Bold.ttf");
|
|
||||||
font-style: normal;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
@font-face {
|
|
||||||
font-family: SpaceMono;
|
|
||||||
src: url("/static/font/SpaceMono-BoldItalic.ttf");
|
|
||||||
font-style: italic;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
|
@ -37,12 +46,17 @@
|
||||||
body{
|
body{
|
||||||
background-color: black;
|
background-color: black;
|
||||||
color: white;
|
color: white;
|
||||||
|
font-family: "Josefin Sans", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
.monospace {
|
.monospace {
|
||||||
font-family: SpaceMono, monospace;
|
font-family: SpaceMono, monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.font-pacifico {
|
||||||
|
font-family: Pacifico, serif;
|
||||||
|
}
|
||||||
|
|
||||||
.header-bar {
|
.header-bar {
|
||||||
--bs-bg-opacity: 1;
|
--bs-bg-opacity: 1;
|
||||||
background-color: var(--color-faded-blue);
|
background-color: var(--color-faded-blue);
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -8,50 +8,53 @@
|
||||||
<div id="content" class="container">
|
<div id="content" class="container">
|
||||||
<h1 class="display-4">Account <span th:text="${account.number()}"></span></h1>
|
<h1 class="display-4">Account <span th:text="${account.number()}"></span></h1>
|
||||||
|
|
||||||
<div class="card text-white bg-dark mb-3">
|
<div class="card-group mb-3">
|
||||||
<div class="card-body">
|
<div class="card text-white bg-dark">
|
||||||
<h5 class="card-title">Overview</h5>
|
<div class="card-body">
|
||||||
<dl class="row">
|
<h5 class="card-title">Overview</h5>
|
||||||
<dt class="col-sm-6">Number</dt>
|
<dl class="row">
|
||||||
<dd class="col-sm-6 monospace" th:text="${account.number()}"></dd>
|
<dt class="col-sm-6">Number</dt>
|
||||||
<dt class="col-sm-6">Account Holder Name</dt>
|
<dd class="col-sm-6 monospace" th:text="${account.number()}"></dd>
|
||||||
<dd class="col-sm-6" th:text="${account.name()}"></dd>
|
<dt class="col-sm-6">Account Holder Name</dt>
|
||||||
<dt class="col-sm-6">Exchange</dt>
|
<dd class="col-sm-6" th:text="${account.name()}"></dd>
|
||||||
<dd class="col-sm-6">
|
<dt class="col-sm-6">Exchange</dt>
|
||||||
<a class="colored-link" th:href="@{/exchanges/{id}(id=${account.exchange().id()})}" th:text="${account.exchange().name()}"></a>
|
<dd class="col-sm-6">
|
||||||
</dd>
|
<a class="colored-link" th:href="@{/exchanges/{id}(id=${account.exchange().id()})}" th:text="${account.exchange().name()}"></a>
|
||||||
<dt class="col-sm-6">Total Value</dt>
|
</dd>
|
||||||
<dd class="col-sm-6">
|
<dt class="col-sm-6">Total Value</dt>
|
||||||
<span class="monospace" th:text="${account.totalBalance()}"></span> <span th:text="${account.exchange().primaryTradeable()}"></span>
|
<dd class="col-sm-6">
|
||||||
</dd>
|
<span class="monospace" th:text="${account.totalBalance()}"></span> <span th:text="${account.exchange().primaryTradeable()}"></span>
|
||||||
</dl>
|
</dd>
|
||||||
<a class="btn btn-success" th:href="@{/trade/{account}(account=${account.id()})}">Trade</a>
|
</dl>
|
||||||
<a class="btn btn-success" th:href="@{/accounts/{aId}/transfer(aId=${account.id()})}">Transfer</a>
|
</div>
|
||||||
<a class="btn btn-primary" th:if="${account.userAdmin()}" th:href="@{/accounts/{aId}/editBalances(aId=${account.id()})}">Edit Balances</a>
|
<div class="card-footer">
|
||||||
|
<a class="btn btn-success" th:href="@{/trade/{account}(account=${account.id()})}">Trade</a>
|
||||||
|
<a class="btn btn-success" th:href="@{/accounts/{aId}/transfer(aId=${account.id()})}">Transfer</a>
|
||||||
|
<a class="btn btn-primary" th:if="${account.userAdmin()}" th:href="@{/accounts/{aId}/editBalances(aId=${account.id()})}">Edit Balances</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="card text-white bg-dark">
|
||||||
|
<div class="card-body">
|
||||||
<div class="card text-white bg-dark mb-3">
|
<h5 class="card-title">Tradeable Assets</h5>
|
||||||
<div class="card-body">
|
<table class="table table-dark">
|
||||||
<h5 class="card-title">Tradeable Assets</h5>
|
<thead class="d-block">
|
||||||
<table class="table table-dark">
|
<tr>
|
||||||
<thead>
|
<th>Asset</th>
|
||||||
<tr>
|
<th>Type</th>
|
||||||
<th>Asset</th>
|
<th>Balance</th>
|
||||||
<th>Type</th>
|
</tr>
|
||||||
<th>Balance</th>
|
</thead>
|
||||||
</tr>
|
<tbody class="d-block" style="height: 300px; overflow-y: scroll;">
|
||||||
</thead>
|
<tr th:each="bal : ${account.balances()}">
|
||||||
<tbody>
|
<td>
|
||||||
<tr th:each="bal : ${account.balances()}">
|
<a class="colored-link" th:href="@{/tradeables/{tId}(tId=${bal.id()})}" th:text="${bal.symbol()}"></a>
|
||||||
<td>
|
</td>
|
||||||
<a class="colored-link" th:href="@{/tradeables/{tId}(tId=${bal.id()})}" th:text="${bal.symbol()}"></a>
|
<td th:text="${bal.type()}"></td>
|
||||||
</td>
|
<td class="monospace" th:text="${bal.amount()}"></td>
|
||||||
<td th:text="${bal.type()}"></td>
|
</tr>
|
||||||
<td class="monospace" th:text="${bal.amount()}"></td>
|
</tbody>
|
||||||
</tr>
|
</table>
|
||||||
</tbody>
|
</div>
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -6,29 +6,28 @@
|
||||||
>
|
>
|
||||||
<div id="content" class="container">
|
<div id="content" class="container">
|
||||||
<h1 class="display-4">Exchanges</h1>
|
<h1 class="display-4">Exchanges</h1>
|
||||||
<table class="table table-dark">
|
|
||||||
<thead>
|
<div class="row row-cols-1 row-cols-sm-3 g-4">
|
||||||
<tr>
|
<div class="col" th:each="exchange: ${exchangeData}">
|
||||||
<th>Name</th>
|
<div class="card text-white bg-dark">
|
||||||
<th>Primary Asset</th>
|
<div class="card-body">
|
||||||
<th>Account</th>
|
<h5 class="card-title">
|
||||||
<th>Estimated Balance</th>
|
<a class="colored-link" th:href="@{/exchanges/{eId}(eId=${exchange.exchange().id()})}" th:text="${exchange.exchange().name()}"></a>
|
||||||
</tr>
|
</h5>
|
||||||
</thead>
|
<h6 class="card-subtitle text-muted mb-2">
|
||||||
<tbody>
|
Est. Account Balance:
|
||||||
<tr th:each="ed : ${exchangeData}">
|
<span class="badge bg-secondary">
|
||||||
<td>
|
<span class="font-monospace" th:text="${exchange.account().totalBalance()}"></span>
|
||||||
<a class="colored-link" th:text="${ed.exchange().name()}" th:href="@{/exchanges/{eId}(eId=${ed.exchange().id()})}"></a>
|
<a class="colored-link" th:text="${exchange.exchange().primaryTradeable()}" th:href="@{/tradeables/{tId}(tId=${exchange.exchange().primaryTradeableId()})}"></a>
|
||||||
</td>
|
</span>
|
||||||
<td th:text="${ed.exchange().primaryTradeable()}"></td>
|
</h6>
|
||||||
<td>
|
<p class="card-text" th:if="${exchange.exchange().description() != null}" th:text="${exchange.exchange().description()}"></p>
|
||||||
<a class="colored-link" th:text="${ed.account().number()}" th:href="@{/accounts/{aId}(aId=${ed.account().id()})}"></a>
|
</div>
|
||||||
</td>
|
</div>
|
||||||
<td class="monospace" th:text="${ed.account().totalBalance()}"></td>
|
</div>
|
||||||
</tr>
|
</div>
|
||||||
</tbody>
|
|
||||||
</table>
|
<p class="mt-3">
|
||||||
<p>
|
|
||||||
Use this page to view a list of all exchanges you're participating in. Click on the <strong>name</strong> of the exchange to view its page, and click on your <strong>account</strong> number to view your account information for a given exchange. The <strong>estimated balance</strong> shown in this overview may not be completely accurate. Navigate to your account page for a complete overview of your current account balances for stocks, fiat currencies, and more.
|
Use this page to view a list of all exchanges you're participating in. Click on the <strong>name</strong> of the exchange to view its page, and click on your <strong>account</strong> number to view your account information for a given exchange. The <strong>estimated balance</strong> shown in this overview may not be completely accurate. Navigate to your account page for a complete overview of your current account balances for stocks, fiat currencies, and more.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
|
@ -9,11 +9,11 @@
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<nav th:fragment="header" class="navbar navbar-expand-lg navbar-dark header-bar">
|
<nav th:fragment="header" class="navbar navbar-expand-lg navbar-dark header-bar mb-3">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<a class="navbar-brand" href="/">
|
<a class="navbar-brand" href="/">
|
||||||
<img src="/static/images/icon_256.png" alt="Coyote Credit" height="24" class="d-inline-block align-text-top"/>
|
<img src="/static/images/icon_256.png" alt="Coyote Credit" height="24" class="d-inline-block align-text-top"/>
|
||||||
Coyote Credit
|
<span class="font-pacifico">Coyote Credit</span>
|
||||||
</a>
|
</a>
|
||||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
|
||||||
<span class="navbar-toggler-icon"></span>
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
|
|
@ -6,10 +6,11 @@
|
||||||
>
|
>
|
||||||
<div id="content" class="container">
|
<div id="content" class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-5">
|
||||||
|
<div class="text-center">
|
||||||
|
<img src="/static/images/icon_256.png" alt="Coyote Credit Logo" width="256"/>
|
||||||
<h1>Login</h1>
|
</div>
|
||||||
|
<h1 class="text-center font-pacifico">Coyote Credit</h1>
|
||||||
<form th:action="@{/login/processing}" th:method="post">
|
<form th:action="@{/login/processing}" th:method="post">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="usernameInput" class="form-label">Username</label>
|
<label for="usernameInput" class="form-label">Username</label>
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<div id="content" class="container">
|
<div id="content" class="container">
|
||||||
<div class="row justify-content-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-lg-4">
|
<div class="col-lg-4">
|
||||||
<h1>Register</h1>
|
<h1 class="display-4">Register</h1>
|
||||||
<form th:action="@{/register}" th:method="post">
|
<form th:action="@{/register}" th:method="post">
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
<label for="usernameInput" class="form-label">Username</label>
|
<label for="usernameInput" class="form-label">Username</label>
|
||||||
|
@ -44,8 +44,9 @@
|
||||||
<input type="submit" class="btn btn-primary mb-3" value="Register">
|
<input type="submit" class="btn btn-primary mb-3" value="Register">
|
||||||
|
|
||||||
<p class="alert alert-dark">
|
<p class="alert alert-dark">
|
||||||
After registering, you will receive an email with a verification link. Please
|
<strong>Note!</strong> After registering, you will receive an email with a
|
||||||
click that link to verify your account before attempting to log in.
|
verification link. Please click that link to verify your account before
|
||||||
|
attempting to log in.
|
||||||
</p>
|
</p>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="card text-white bg-dark mb-3">
|
<div class="card text-white bg-dark mb-3" th:if="${!user.exchangeInvitations().isEmpty()}">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<h5 class="card-title">Exchange Invitations</h5>
|
<h5 class="card-title">Exchange Invitations</h5>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue