Cleaned up exchange and account pages, and added custom site font.

This commit is contained in:
Andrew Lalis 2022-02-16 12:02:14 +01:00
parent cff73d9803
commit f768d62342
18 changed files with 126 additions and 122 deletions

View File

@ -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;

View File

@ -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
) { ) {
} }

View File

@ -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(

View File

@ -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(),

View File

@ -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);

View File

@ -8,7 +8,8 @@
<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 text-white bg-dark">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Overview</h5> <h5 class="card-title">Overview</h5>
<dl class="row"> <dl class="row">
@ -25,24 +26,25 @@
<span class="monospace" th:text="${account.totalBalance()}"></span>&nbsp;<span th:text="${account.exchange().primaryTradeable()}"></span> <span class="monospace" th:text="${account.totalBalance()}"></span>&nbsp;<span th:text="${account.exchange().primaryTradeable()}"></span>
</dd> </dd>
</dl> </dl>
</div>
<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="@{/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-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> <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 text-white bg-dark mb-3">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">Tradeable Assets</h5> <h5 class="card-title">Tradeable Assets</h5>
<table class="table table-dark"> <table class="table table-dark">
<thead> <thead class="d-block">
<tr> <tr>
<th>Asset</th> <th>Asset</th>
<th>Type</th> <th>Type</th>
<th>Balance</th> <th>Balance</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody class="d-block" style="height: 300px; overflow-y: scroll;">
<tr th:each="bal : ${account.balances()}"> <tr th:each="bal : ${account.balances()}">
<td> <td>
<a class="colored-link" th:href="@{/tradeables/{tId}(tId=${bal.id()})}" th:text="${bal.symbol()}"></a> <a class="colored-link" th:href="@{/tradeables/{tId}(tId=${bal.id()})}" th:text="${bal.symbol()}"></a>
@ -54,6 +56,7 @@
</table> </table>
</div> </div>
</div> </div>
</div>
<div class="card text-white bg-dark mb-3" th:if="${!account.recentTransactions().isEmpty()}"> <div class="card text-white bg-dark mb-3" th:if="${!account.recentTransactions().isEmpty()}">
<div class="card-body"> <div class="card-body">

View File

@ -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>&nbsp;
<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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>