mirror of
https://github.com/arcan1s/ffxivbis.git
synced 2025-07-17 07:39:59 +00:00
migrate to bootstrap (#14)
This commit is contained in:
349
src/main/resources/html/bis.html
Normal file
349
src/main/resources/html/bis.html
Normal file
@ -0,0 +1,349 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Best in slot</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="/static/favicon.ico" rel="shortcut icon">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous" type="text/css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
|
||||
|
||||
|
||||
<link href="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="/static/styles.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg justify-content-between align-items-center border-bottom">
|
||||
<a class="navbar-brand" id="navbar-title">Party</a>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-bis">best in slot</a>
|
||||
<a class="nav-item nav-link" id="navbar-loot">looted items</a>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-users">users</a>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="alert-placeholder" class="container"></div>
|
||||
|
||||
<div class="container">
|
||||
<h2>Best in slot</h2>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="toolbar">
|
||||
<button id="update-btn" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#update-bis-dialog" hidden>
|
||||
<i class="bi bi-plus"></i> update
|
||||
</button>
|
||||
<button class="btn btn-secondary" onclick="reload()">
|
||||
<i class="bi bi-arrow-clockwise"></i> reload
|
||||
</button>
|
||||
<button id="remove-btn" class="btn btn-danger" onclick="removePiece()" disabled hidden>
|
||||
<i class="bi bi-trash"></i> remove
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table id="bis" class="table table-striped table-hover"
|
||||
data-click-to-select="true"
|
||||
data-export-options='{"fileName": "bis"}'
|
||||
data-page-list="[25, 50, 100, all]"
|
||||
data-page-size="25"
|
||||
data-pagination="true"
|
||||
data-resizable="true"
|
||||
data-search="true"
|
||||
data-show-columns="true"
|
||||
data-show-columns-search="true"
|
||||
data-show-columns-toggle-all="true"
|
||||
data-show-export="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-search-clear-button="true"
|
||||
data-single-select="true"
|
||||
data-sortable="true"
|
||||
data-sort-reset="true"
|
||||
data-toolbar="#toolbar">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-checkbox="true"></th>
|
||||
<th data-sortable="true" data-switchable="false" data-field="nick">nick</th>
|
||||
<th data-sortable="true" data-switchable="false" data-field="job">job</th>
|
||||
<th data-sortable="true" data-field="piece">piece</th>
|
||||
<th data-sortable="true" data-field="pieceType">piece type</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="update-bis-dialog" tabindex="-1" role="dialog" class="modal fade">
|
||||
<div class="modal-dialog" role="document">
|
||||
<form class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div class="btn-group" role="group" aria-label="Update bis">
|
||||
<input id="add-piece-btn" name="update-bis" type="radio" class="btn-check" autocomplete="off" checked>
|
||||
<label class="btn btn-outline-primary" for="add-piece-btn">add piece</label>
|
||||
|
||||
<input id="update-bis-btn" name="update-bis" type="radio" class="btn-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="update-bis-btn">update bis</label>
|
||||
</div>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="player">player</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="player" name="player" class="form-control" title="player"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="piece-row" class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="piece">piece</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="piece" name="piece" class="form-control" title="piece"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="piece-type-row" class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="piece-type">piece type</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="piece-type" name="pieceType" class="form-control" title="piece-type"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div id="bis-link-row" class="form-group row" style="display: none">
|
||||
<label class="col-sm-4 col-form-label" for="bis-link">link</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="bis-link" name="link" class="form-control" placeholder="link to bis" onkeyup="disableSubmitBisButton()">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">close</button>
|
||||
<button id="submit-add-bis-btn" type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="addPiece()" disabled>add</button>
|
||||
<button id="submit-update-bis-btn" type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="setBis()" style="display: none" disabled>set</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="d-flex flex-wrap justify-content-between align-items-center border-top">
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="/" title="home">home</a></li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis" title="sources">ffxivbis</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/releases" title="releases list">releases</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/issues" title="issues tracker">report a bug</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/tableexport.jquery.plugin/tableExport.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/export/bootstrap-table-export.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/resizable/bootstrap-table-resizable.js"></script>
|
||||
|
||||
<script src="/static/utils.js"></script>
|
||||
<script src="/static/load.js"></script>
|
||||
|
||||
<script>
|
||||
const [partyId, isReadOnly] = getPartyId();
|
||||
const table = $("#bis");
|
||||
const removeButton = $("#remove-btn");
|
||||
const updateButton = $("#update-btn");
|
||||
|
||||
const submitAddBisButton = $("#submit-add-bis-btn");
|
||||
const submitUpdateBisButton = $("#submit-update-bis-btn");
|
||||
const updateBisDialog = $("#update-bis-dialog");
|
||||
|
||||
const addPieceButton = $("#add-piece-btn");
|
||||
const updateBisButton = $("#update-bis-btn");
|
||||
|
||||
const bisLinkRow = $("#bis-link-row");
|
||||
const pieceRow = $("#piece-row");
|
||||
const pieceTypeRow = $("#piece-type-row");
|
||||
|
||||
const linkInput = $("#bis-link");
|
||||
const pieceInput = $("#piece");
|
||||
const pieceTypeInput = $("#piece-type");
|
||||
const playerInput = $("#player");
|
||||
|
||||
function addPiece() {
|
||||
const player = getCurrentOption(playerInput);
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/bis`,
|
||||
data: JSON.stringify({
|
||||
action: "add",
|
||||
piece: {
|
||||
pieceType: pieceTypeInput.val(),
|
||||
job: player.dataset.job,
|
||||
piece: pieceInput.val(),
|
||||
},
|
||||
playerId: {
|
||||
partyId: partyId,
|
||||
nick: player.dataset.nick,
|
||||
job: player.dataset.job,
|
||||
},
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function disableSubmitBisButton() {
|
||||
const nonEmpty = (playerInput.val() !== null); // well lol
|
||||
submitUpdateBisButton.attr("disabled", !(nonEmpty && linkInput.val()));
|
||||
submitAddBisButton.attr("disabled", !(nonEmpty));
|
||||
}
|
||||
|
||||
function hideControls() {
|
||||
removeButton.attr("hidden", isReadOnly);
|
||||
updateButton.attr("hidden", isReadOnly);
|
||||
}
|
||||
|
||||
function hideLinkPart() {
|
||||
disableSubmitBisButton();
|
||||
bisLinkRow.hide();
|
||||
submitUpdateBisButton.hide();
|
||||
pieceRow.show();
|
||||
pieceTypeRow.show();
|
||||
submitAddBisButton.show();
|
||||
}
|
||||
|
||||
function hidePiecePart() {
|
||||
disableSubmitBisButton();
|
||||
bisLinkRow.show();
|
||||
submitUpdateBisButton.show();
|
||||
pieceRow.hide();
|
||||
pieceTypeRow.hide();
|
||||
submitAddBisButton.hide();
|
||||
}
|
||||
|
||||
function reload() {
|
||||
table.bootstrapTable("showLoading");
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}`,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
const items = data.map(function (player) {
|
||||
return player.bis.map(function (loot) {
|
||||
return {
|
||||
nick: player.nick,
|
||||
job: player.job,
|
||||
piece: loot.piece,
|
||||
pieceType: loot.pieceType,
|
||||
};
|
||||
});
|
||||
});
|
||||
const payload = items.reduce(function (left, right) { return left.concat(right); }, []);
|
||||
table.bootstrapTable("load", payload);
|
||||
table.bootstrapTable("uncheckAll");
|
||||
table.bootstrapTable("hideLoading");
|
||||
|
||||
const options = data.map(function (player) {
|
||||
const option = document.createElement("option");
|
||||
option.innerText = formatPlayerId(player);
|
||||
option.dataset.nick = player.nick;
|
||||
option.dataset.job = player.job;
|
||||
return option;
|
||||
});
|
||||
playerInput.empty().append(options);
|
||||
disableSubmitBisButton();
|
||||
},
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function removePiece() {
|
||||
const pieces = table.bootstrapTable("getSelections");
|
||||
pieces.map(function (loot) {
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/bis`,
|
||||
data: JSON.stringify({
|
||||
action: "remove",
|
||||
piece: {
|
||||
pieceType: loot.pieceType,
|
||||
job: loot.job,
|
||||
piece: loot.piece,
|
||||
},
|
||||
playerId: {
|
||||
partyId: partyId,
|
||||
job: loot.job,
|
||||
nick: loot.nick,
|
||||
},
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function reset() {
|
||||
if (updateBisButton.is(":checked")) {
|
||||
hidePiecePart();
|
||||
}
|
||||
if (addPieceButton.is(":checked")) {
|
||||
hideLinkPart();
|
||||
}
|
||||
}
|
||||
|
||||
function setBis() {
|
||||
const player = getCurrentOption(playerInput);
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/bis`,
|
||||
data: JSON.stringify({
|
||||
link: linkInput.val(),
|
||||
playerId: {
|
||||
partyId: partyId,
|
||||
nick: player.dataset.nick,
|
||||
job: player.dataset.job,
|
||||
},
|
||||
}),
|
||||
type: "PUT",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
setupFormClear(updateBisDialog, reset);
|
||||
setupRemoveButton(table, removeButton);
|
||||
|
||||
loadHeader(partyId);
|
||||
loadTypes("/api/v1/types/pieces", pieceInput);
|
||||
loadTypes("/api/v1/types/pieces/types", pieceTypeInput);
|
||||
|
||||
hideControls();
|
||||
|
||||
updateBisButton.click(function () { reset(); });
|
||||
addPieceButton.click(function () { reset(); });
|
||||
|
||||
table.bootstrapTable({});
|
||||
reload();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
183
src/main/resources/html/index.html
Normal file
183
src/main/resources/html/index.html
Normal file
@ -0,0 +1,183 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>FFXIV loot helper</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="/static/favicon.ico" rel="shortcut icon">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous" type="text/css">
|
||||
|
||||
<link href="/static/styles.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="alert-placeholder" class="container"></div>
|
||||
|
||||
<div class="container mb-5">
|
||||
<div class="form-group row">
|
||||
<div class="btn-group" role="group" aria-label="Sign in">
|
||||
<input id="signin-btn" name="signin" type="radio" class="btn-check" autocomplete="off" checked>
|
||||
<label class="btn btn-outline-primary" for="signin-btn">login to existing party</label>
|
||||
|
||||
<input id="signup-btn" name="signin" type="radio" class="btn-check" autocomplete="off">
|
||||
<label class="btn btn-outline-primary" for="signup-btn">create a new party</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<form id="signup-form" class="container mb-5" style="display: none">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label" for="alias">party alias</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="alias" name="alias" class="form-control" placeholder="alias">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label" for="username">username</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="username" name="username" class="form-control" placeholder="admin user name" onkeyup="disableAddButton()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label for="password" class="col-sm-2 col-form-label">password</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="password" name="password" type="password" class="form-control" placeholder="admin password" onkeyup="disableAddButton()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button id="add-btn" type="button" class="btn btn-primary" onclick="createParty()" disabled>add</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<form id="signin-form" class="container mb-5">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-2 col-form-label" for="party-id">party id</label>
|
||||
<div class="col-sm-10">
|
||||
<input id="party-id" name="partyId" class="form-control" placeholder="id" onkeyup="disableRedirectButton()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-sm-10">
|
||||
<button id="redirect-btn" type="button" class="btn btn-primary" onclick="redirectToParty()" disabled>go</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="container">
|
||||
<footer class="d-flex flex-wrap justify-content-between align-items-center border-top">
|
||||
<ul class="nav"></ul>
|
||||
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis" title="sources">ffxivbis</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/releases" title="releases list">releases</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/issues" title="issues tracker">report a bug</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
|
||||
<script>
|
||||
const signinButton = $("#signin-btn");
|
||||
const signupButton = $("#signup-btn");
|
||||
|
||||
const addButton = $("#add-btn");
|
||||
const redirectButton = $("#redirect-btn");
|
||||
const signinForm = $("#signin-form");
|
||||
const signupForm = $("#signup-form");
|
||||
|
||||
const aliasInput = $("#alias");
|
||||
const partyIdInput = $("#party-id");
|
||||
const passwordInput = $("#password");
|
||||
const usernameInput = $("#username");
|
||||
|
||||
function createDescription(partyId) {
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/description`,
|
||||
data: JSON.stringify({
|
||||
partyId: partyId,
|
||||
partyAlias: aliasInput.val(),
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { doRedirect(partyId); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function createParty() {
|
||||
$.ajax({
|
||||
url: `/api/v1/party`,
|
||||
data: JSON.stringify({
|
||||
partyId: "",
|
||||
username: usernameInput.val(),
|
||||
password: passwordInput.val(),
|
||||
permission: "admin",
|
||||
}),
|
||||
type: "PUT",
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
if (aliasInput.val()) {
|
||||
createDescription(data.partyId);
|
||||
} else {
|
||||
doRedirect(data.partyId);
|
||||
}
|
||||
},
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function disableAddButton() {
|
||||
addButton.attr("disabled", !(passwordInput.val() && usernameInput.val()));
|
||||
}
|
||||
|
||||
function disableRedirectButton() {
|
||||
redirectButton.attr("disabled", !partyIdInput.val());
|
||||
}
|
||||
|
||||
function doRedirect(partyId) {
|
||||
location.href = `/party/${partyId}`;
|
||||
}
|
||||
|
||||
function hideSigninPart() {
|
||||
signinForm.hide();
|
||||
signupForm.show();
|
||||
}
|
||||
|
||||
function hideSignupPart() {
|
||||
signinForm.show();
|
||||
signupForm.hide();
|
||||
}
|
||||
|
||||
function redirectToParty() {
|
||||
return doRedirect(partyIdInput.val());
|
||||
}
|
||||
|
||||
function reset() {
|
||||
signinForm.trigger("reset");
|
||||
signupForm.trigger("reset");
|
||||
if (signinButton.is(":checked")) {
|
||||
hideSignupPart();
|
||||
}
|
||||
if (signupButton.is(":checked")) {
|
||||
hideSigninPart();
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
signinButton.click(function () { reset(); });
|
||||
signupButton.click(function () { reset(); });
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
338
src/main/resources/html/loot.html
Normal file
338
src/main/resources/html/loot.html
Normal file
@ -0,0 +1,338 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Loot table</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="/static/favicon.ico" rel="shortcut icon">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous" type="text/css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
|
||||
|
||||
|
||||
<link href="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="/static/styles.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg justify-content-between align-items-center border-bottom">
|
||||
<a class="navbar-brand" id="navbar-title">Party</a>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-bis">best in slot</a>
|
||||
<a class="nav-item nav-link" id="navbar-loot">looted items</a>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-users">users</a>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="alert-placeholder" class="container"></div>
|
||||
|
||||
<div class="container">
|
||||
<h2>Looted items</h2>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="toolbar">
|
||||
<button id="add-btn" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#add-loot-dialog" hidden>
|
||||
<i class="bi bi-plus"></i> add
|
||||
</button>
|
||||
<button class="btn btn-secondary" onclick="reload()">
|
||||
<i class="bi bi-arrow-clockwise"></i> reload
|
||||
</button>
|
||||
<button id="remove-btn" class="btn btn-danger" onclick="removeLoot()" disabled hidden>
|
||||
<i class="bi bi-trash"></i> remove
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table id="loot" class="table table-striped table-hover"
|
||||
data-click-to-select="true"
|
||||
data-export-options='{"fileName": "loot"}'
|
||||
data-page-list="[25, 50, 100, all]"
|
||||
data-page-size="25"
|
||||
data-pagination="true"
|
||||
data-resizable="true"
|
||||
data-search="true"
|
||||
data-show-columns="true"
|
||||
data-show-columns-search="true"
|
||||
data-show-columns-toggle-all="true"
|
||||
data-show-export="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-search-clear-button="true"
|
||||
data-single-select="true"
|
||||
data-sortable="true"
|
||||
data-sort-reset="true"
|
||||
data-toolbar="#toolbar">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-checkbox="true"></th>
|
||||
<th data-sortable="true" data-switchable="false" data-field="nick">nick</th>
|
||||
<th data-sortable="true" data-switchable="false" data-field="job">job</th>
|
||||
<th data-sortable="true" data-field="piece">piece</th>
|
||||
<th data-sortable="true" data-field="pieceType">piece type</th>
|
||||
<th data-sortable="true" data-field="isFreeLoot">is free loot</th>
|
||||
<th data-sortable="true" data-field="timestamp">date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="add-loot-dialog" tabindex="-1" role="dialog" class="modal fade">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">add looted piece</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
|
||||
<form class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="player">player</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="player" name="player" class="form-control" title="player"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="piece">piece</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="piece" name="piece" class="form-control" title="piece"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="piece-type">piece type</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="piece-type" name="pieceType" class="form-control" title="pieceType"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="job">job</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="job" name="job" class="form-control" title="job"></select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table id="stats" class="table table-striped table-hover">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-field="nick">nick</th>
|
||||
<th data-field="job">job</th>
|
||||
<th data-field="isRequired">required</th>
|
||||
<th data-field="lootCount">these pieces looted</th>
|
||||
<th data-field="lootCountBiS">total bis pieces looted</th>
|
||||
<th data-field="lootCountTotal">total pieces looted</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<div class="modal-footer">
|
||||
<div class="form-check form-switch">
|
||||
<input id="free-loot" name="freeLoot" type="checkbox" class="form-check-input">
|
||||
<label class="form-check-label" for="free-loot">as free loot</label>
|
||||
</div>
|
||||
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">close</button>
|
||||
<button type="button" class="btn btn-secondary" onclick="suggestLoot()">suggest</button>
|
||||
<button id="submit-btn" type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="addLoot()" disabled>add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="d-flex flex-wrap justify-content-between align-items-center border-top">
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="/" title="home">home</a></li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis" title="sources">ffxivbis</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/releases" title="releases list">releases</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/issues" title="issues tracker">report a bug</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/tableexport.jquery.plugin/tableExport.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/export/bootstrap-table-export.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/resizable/bootstrap-table-resizable.js"></script>
|
||||
|
||||
<script src="/static/utils.js"></script>
|
||||
<script src="/static/load.js"></script>
|
||||
|
||||
<script>
|
||||
const [partyId, isReadOnly] = getPartyId();
|
||||
const table = $("#loot");
|
||||
const stats = $("#stats");
|
||||
const addButton = $("#add-btn");
|
||||
const removeButton = $("#remove-btn");
|
||||
|
||||
const submitLootButton = $("#submit-btn");
|
||||
const addLootDialog = $("#add-loot-dialog");
|
||||
|
||||
const freeLootInput = $("#free-loot");
|
||||
const jobInput = $("#job");
|
||||
const pieceInput = $("#piece");
|
||||
const pieceTypeInput = $("#piece-type");
|
||||
const playerInput = $("#player");
|
||||
|
||||
function addLoot() {
|
||||
const player = getCurrentOption(playerInput);
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/loot`,
|
||||
data: JSON.stringify({
|
||||
action: "add",
|
||||
piece: {
|
||||
pieceType: pieceTypeInput.val(),
|
||||
job: player.dataset.job,
|
||||
piece: pieceInput.val(),
|
||||
},
|
||||
playerId: {
|
||||
partyId: partyId,
|
||||
nick: player.dataset.nick,
|
||||
job: player.dataset.job,
|
||||
},
|
||||
isFreeLoot: freeLootInput.is(":checked"),
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function hideControls() {
|
||||
addButton.attr("hidden", isReadOnly);
|
||||
removeButton.attr("hidden", isReadOnly);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
table.bootstrapTable("showLoading");
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}`,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
const items = data.map(function (player) {
|
||||
return player.loot.map(function (loot) {
|
||||
return {
|
||||
nick: player.nick,
|
||||
job: player.job,
|
||||
piece: loot.piece.piece,
|
||||
pieceType: loot.piece.pieceType,
|
||||
isFreeLoot: loot.isFreeLoot ? "yes" : "no",
|
||||
timestamp: loot.timestamp,
|
||||
};
|
||||
});
|
||||
});
|
||||
const payload = items.reduce(function (left, right) { return left.concat(right); }, []);
|
||||
table.bootstrapTable("load", payload);
|
||||
table.bootstrapTable("uncheckAll");
|
||||
table.bootstrapTable("hideLoading");
|
||||
|
||||
const options = data.map(function (player) {
|
||||
const option = document.createElement("option");
|
||||
option.innerText = formatPlayerId(player);
|
||||
option.dataset.nick = player.nick;
|
||||
option.dataset.job = player.job;
|
||||
return option;
|
||||
});
|
||||
playerInput.empty().append(options);
|
||||
submitLootButton.attr("disabled", options.length === 0);
|
||||
},
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function removeLoot() {
|
||||
const pieces = table.bootstrapTable("getSelections");
|
||||
pieces.map(function (loot) {
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/loot`,
|
||||
data: JSON.stringify({
|
||||
action: "remove",
|
||||
piece: {
|
||||
pieceType: loot.pieceType,
|
||||
job: loot.job,
|
||||
piece: loot.piece,
|
||||
},
|
||||
playerId: {
|
||||
partyId: partyId,
|
||||
nick: loot.nick,
|
||||
job: loot.job,
|
||||
},
|
||||
isFreeLoot: loot.isFreeLoot === "yes",
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function suggestLoot() {
|
||||
stats.bootstrapTable("showLoading");
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/loot`,
|
||||
data: JSON.stringify({
|
||||
pieceType: pieceTypeInput.val(),
|
||||
job: jobInput.val(),
|
||||
piece: pieceInput.val(),
|
||||
}),
|
||||
type: "PUT",
|
||||
contentType: "application/json",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
const payload = data.map(function (stat) {
|
||||
return {
|
||||
nick: stat.nick,
|
||||
job: stat.job,
|
||||
isRequired: stat.isRequired,
|
||||
lootCount: stat.lootCount,
|
||||
lootCountBiS: stat.lootCountBiS,
|
||||
lootCountTotal: stat.lootCountTotal,
|
||||
};
|
||||
});
|
||||
stats.bootstrapTable("load", payload);
|
||||
stats.bootstrapTable("uncheckAll");
|
||||
stats.bootstrapTable("hideLoading");
|
||||
},
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
setupFormClear(addLootDialog);
|
||||
setupRemoveButton(table, removeButton);
|
||||
|
||||
loadHeader(partyId);
|
||||
loadTypes("/api/v1/types/jobs/all", jobInput);
|
||||
loadTypes("/api/v1/types/pieces", pieceInput);
|
||||
loadTypes("/api/v1/types/pieces/types", pieceTypeInput);
|
||||
|
||||
hideControls();
|
||||
|
||||
table.bootstrapTable({});
|
||||
stats.bootstrapTable({});
|
||||
reload();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
258
src/main/resources/html/party.html
Normal file
258
src/main/resources/html/party.html
Normal file
@ -0,0 +1,258 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>FFXIV loot helper</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="/static/favicon.ico" rel="shortcut icon">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous" type="text/css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
|
||||
|
||||
|
||||
<link href="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="/static/styles.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg justify-content-between align-items-center border-bottom">
|
||||
<a class="navbar-brand" id="navbar-title">Party</a>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-bis">best in slot</a>
|
||||
<a class="nav-item nav-link" id="navbar-loot">looted items</a>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-users">users</a>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="alert-placeholder" class="container"></div>
|
||||
|
||||
<div class="container">
|
||||
<div id="toolbar">
|
||||
<button id="add-btn" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#add-player-dialog" hidden>
|
||||
<i class="bi bi-plus"></i> add
|
||||
</button>
|
||||
<button class="btn btn-secondary" onclick="reload()">
|
||||
<i class="bi bi-arrow-clockwise"></i> reload
|
||||
</button>
|
||||
<button id="remove-btn" class="btn btn-danger" onclick="removePlayers()" disabled hidden>
|
||||
<i class="bi bi-trash"></i> remove
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table id="players" class="table table-striped table-hover"
|
||||
data-click-to-select="true"
|
||||
data-export-options='{"fileName": "players"}'
|
||||
data-page-list="[25, 50, 100, all]"
|
||||
data-page-size="25"
|
||||
data-pagination="true"
|
||||
data-resizable="true"
|
||||
data-search="true"
|
||||
data-show-columns="true"
|
||||
data-show-columns-search="true"
|
||||
data-show-columns-toggle-all="true"
|
||||
data-show-export="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-search-clear-button="true"
|
||||
data-single-select="true"
|
||||
data-sortable="true"
|
||||
data-sort-reset="true"
|
||||
data-toolbar="#toolbar">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-checkbox="true"></th>
|
||||
<th data-sortable="true" data-switchable="false" data-field="nick">nick</th>
|
||||
<th data-sortable="true" data-field="job">job</th>
|
||||
<th data-sortable="true" data-field="link" data-formatter="bisLinkFormatter">best in slot link</th>
|
||||
<th data-sortable="true" data-field="lootCountBiS">total bis pieces looted</th>
|
||||
<th data-sortable="true" data-field="lootCountTotal">total pieces looted</th>
|
||||
<th data-sortable="true" data-field="priority">priority</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="add-player-dialog" tabindex="-1" role="dialog" class="modal fade">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">add new player</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
|
||||
<form class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="nick">player name</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="nick" name="nick" class="form-control" placeholder="nick" onkeyup="disableAddPlayerForm()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="job">player job</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="job" name="job" class="form-control" title="job"></select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="link">link to best in slot</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="link" name="link" class="form-control" placeholder="link to bis">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="priority">priority</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="priority" name="priority" type="number" class="form-control" value="0">
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">close</button>
|
||||
<button id="submit-player-btn" type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="addPlayer()" disabled>add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="d-flex flex-wrap justify-content-between align-items-center border-top">
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="/" title="home">home</a></li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis" title="sources">ffxivbis</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/releases" title="releases list">releases</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/issues" title="issues tracker">report a bug</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/tableexport.jquery.plugin/tableExport.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/export/bootstrap-table-export.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/resizable/bootstrap-table-resizable.js"></script>
|
||||
|
||||
<script src="/static/utils.js"></script>
|
||||
<script src="/static/load.js"></script>
|
||||
|
||||
<script>
|
||||
const [partyId, isReadOnly] = getPartyId();
|
||||
const table = $("#players");
|
||||
const addButton = $("#add-btn");
|
||||
const removeButton = $("#remove-btn");
|
||||
|
||||
const addPlayerDialog = $("#add-player-dialog");
|
||||
const submitPlayerButton = $("#submit-player-btn");
|
||||
|
||||
const jobInput = $("#job");
|
||||
const linkInput = $("#link");
|
||||
const nickInput = $("#nick");
|
||||
const priorityInput = $("#priority");
|
||||
|
||||
function addPlayer() {
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}`,
|
||||
data: JSON.stringify({
|
||||
action: "add",
|
||||
playerId: {
|
||||
partyId: partyId,
|
||||
job: jobInput.val(),
|
||||
nick: nickInput.val(),
|
||||
link: linkInput.val() || null,
|
||||
priority: parseInt(priorityInput.val(), 10),
|
||||
},
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function bisLinkFormatter(link, row) {
|
||||
if (link) {
|
||||
return `<a href="${safe(link)}" title="${safe(row.nick)} best in slot for ${safe(row.job)}">${safe(link)}</a>`;
|
||||
} else {
|
||||
return "-";
|
||||
}
|
||||
}
|
||||
|
||||
function disableAddPlayerForm() {
|
||||
submitPlayerButton.attr("disabled", !nickInput.val());
|
||||
}
|
||||
|
||||
function hideControls() {
|
||||
addButton.attr("hidden", isReadOnly);
|
||||
removeButton.attr("hidden", isReadOnly);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
table.bootstrapTable("showLoading");
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}`,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
table.bootstrapTable("load", data);
|
||||
table.bootstrapTable("uncheckAll");
|
||||
table.bootstrapTable("hideLoading");
|
||||
},
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function removePlayers() {
|
||||
const players = table.bootstrapTable("getSelections");
|
||||
players.map(function (player) {
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}`,
|
||||
data: JSON.stringify({
|
||||
action: "remove",
|
||||
playerId: {
|
||||
partyId: partyId,
|
||||
job: player.job,
|
||||
nick: player.nick,
|
||||
},
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
setupFormClear(addPlayerDialog);
|
||||
setupRemoveButton(table, removeButton);
|
||||
|
||||
loadHeader(partyId);
|
||||
loadTypes("/api/v1/types/jobs", jobInput);
|
||||
|
||||
hideControls();
|
||||
|
||||
table.bootstrapTable({});
|
||||
reload();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
19
src/main/resources/html/redoc.html
Normal file
19
src/main/resources/html/redoc.html
Normal file
@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>FFXIV loot helper API</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="/static/favicon.ico" rel="shortcut icon">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<redoc spec-url="/api-docs/swagger.json"></redoc>
|
||||
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,24 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>FFXIV loot tracker API</title>
|
||||
<!-- needed for adaptive design -->
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat:300,400,700|Roboto:300,400,700" rel="stylesheet">
|
||||
|
||||
<!--
|
||||
ReDoc doesn't change outer page styles
|
||||
-->
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<redoc spec-url='/api-docs/swagger.json'></redoc>
|
||||
<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"> </script>
|
||||
</body>
|
||||
</html>
|
230
src/main/resources/html/users.html
Normal file
230
src/main/resources/html/users.html
Normal file
@ -0,0 +1,230 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>User management</title>
|
||||
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<link href="/static/favicon.ico" rel="shortcut icon">
|
||||
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous" type="text/css">
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.css" rel="stylesheet" type="text/css">
|
||||
|
||||
|
||||
<link href="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.css" rel="stylesheet" type="text/css">
|
||||
|
||||
<link href="/static/styles.css" rel="stylesheet" type="text/css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg justify-content-between align-items-center border-bottom">
|
||||
<a class="navbar-brand" id="navbar-title">Party</a>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-bis">best in slot</a>
|
||||
<a class="nav-item nav-link" id="navbar-loot">looted items</a>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<a class="nav-item nav-link" id="navbar-users">users</a>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<div id="alert-placeholder" class="container"></div>
|
||||
|
||||
<div class="container">
|
||||
<h2>Users</h2>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<div id="toolbar">
|
||||
<button id="add-btn" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#add-user-dialog" hidden>
|
||||
<i class="bi bi-plus"></i> add
|
||||
</button>
|
||||
<button class="btn btn-secondary" onclick="reload()">
|
||||
<i class="bi bi-arrow-clockwise"></i> reload
|
||||
</button>
|
||||
<button id="remove-btn" class="btn btn-danger" onclick="removeUsers()" disabled hidden>
|
||||
<i class="bi bi-trash"></i> remove
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<table id="users" class="table table-striped table-hover"
|
||||
data-click-to-select="true"
|
||||
data-export-options='{"fileName": "users"}'
|
||||
data-page-list="[25, 50, 100, all]"
|
||||
data-page-size="25"
|
||||
data-pagination="true"
|
||||
data-resizable="true"
|
||||
data-search="true"
|
||||
data-show-columns="true"
|
||||
data-show-columns-search="true"
|
||||
data-show-columns-toggle-all="true"
|
||||
data-show-export="true"
|
||||
data-show-fullscreen="true"
|
||||
data-show-search-clear-button="true"
|
||||
data-single-select="true"
|
||||
data-sortable="true"
|
||||
data-sort-reset="true"
|
||||
data-toolbar="#toolbar">
|
||||
<thead class="table-primary">
|
||||
<tr>
|
||||
<th data-checkbox="true"></th>
|
||||
<th data-sortable="true" data-switchable="false" data-field="username">username</th>
|
||||
<th data-sortable="true" data-field="permission">permission</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="add-user-dialog" tabindex="-1" role="dialog" class="modal fade">
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title">add new user</h4>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="close"></button>
|
||||
</div>
|
||||
|
||||
<form class="modal-body">
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="username">login</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="username" name="username" class="form-control" placeholder="username" onkeyup="disableAddUserForm()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="password">password</label>
|
||||
<div class="col-sm-8">
|
||||
<input id="password" name="password" type="password" class="form-control" placeholder="password" onkeyup="disableAddUserForm()">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<label class="col-sm-4 col-form-label" for="permission">permission</label>
|
||||
<div class="col-sm-8">
|
||||
<select id="permission" name="permission" class="form-control" title="permission"></select>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-danger" data-bs-dismiss="modal">close</button>
|
||||
<button id="submit-btn" type="button" class="btn btn-primary" data-bs-dismiss="modal" onclick="addUser()" disabled>add</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<footer class="d-flex flex-wrap justify-content-between align-items-center border-top">
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="/" title="home">home</a></li>
|
||||
</ul>
|
||||
|
||||
<ul class="nav">
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis" title="sources">ffxivbis</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/releases" title="releases list">releases</a></li>
|
||||
<li><a class="nav-link" href="https://github.com/arcan1s/ffxivbis/issues" title="issues tracker">report a bug</a></li>
|
||||
</ul>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/jquery/dist/jquery.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/tableexport.jquery.plugin/tableExport.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/jquery-resizable-columns@0.2.3/dist/jquery.resizableColumns.min.js"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p" crossorigin="anonymous"></script>
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/bootstrap-table.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/export/bootstrap-table-export.min.js"></script>
|
||||
|
||||
<script src="https://unpkg.com/bootstrap-table@1.19.1/dist/extensions/resizable/bootstrap-table-resizable.js"></script>
|
||||
|
||||
<script src="/static/utils.js"></script>
|
||||
<script src="/static/load.js"></script>
|
||||
|
||||
<script>
|
||||
const [partyId, isReadOnly] = getPartyId();
|
||||
const table = $("#users");
|
||||
const addButton = $("#add-btn");
|
||||
const removeButton = $("#remove-btn");
|
||||
|
||||
const addUserDialog = $("#add-user-dialog");
|
||||
const submitUserButton = $("#submit-btn");
|
||||
|
||||
const usernameInput = $("#username");
|
||||
const passwordInput = $("#password");
|
||||
const permissionInput = $("#permission");
|
||||
|
||||
function addUser() {
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/users`,
|
||||
data: JSON.stringify({
|
||||
partyId: partyId,
|
||||
username: usernameInput.val(),
|
||||
password: passwordInput.val(),
|
||||
permission: permissionInput.val(),
|
||||
}),
|
||||
type: "POST",
|
||||
contentType: "application/json",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function disableAddUserForm() {
|
||||
submitUserButton.attr("disabled", !(usernameInput.val() && passwordInput.val()));
|
||||
}
|
||||
|
||||
function hideControls() {
|
||||
addButton.attr("hidden", isReadOnly);
|
||||
removeButton.attr("hidden", isReadOnly);
|
||||
}
|
||||
|
||||
function reload() {
|
||||
table.bootstrapTable("showLoading");
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/users`,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function (data) {
|
||||
table.bootstrapTable("load", data);
|
||||
table.bootstrapTable("uncheckAll");
|
||||
table.bootstrapTable("hideLoading");
|
||||
},
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
}
|
||||
|
||||
function removeUsers() {
|
||||
const users = table.bootstrapTable("getSelections");
|
||||
users.map(function (user) {
|
||||
$.ajax({
|
||||
url: `/api/v1/party/${partyId}/users/${user.username}`,
|
||||
type: "DELETE",
|
||||
success: function (_) { reload(); },
|
||||
error: function (jqXHR, _, errorThrown) { requestAlert(jqXHR, errorThrown); },
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(function () {
|
||||
setupFormClear(addUserDialog);
|
||||
setupRemoveButton(table, removeButton);
|
||||
|
||||
loadHeader(partyId);
|
||||
loadTypes("/api/v1/types/permissions", permissionInput);
|
||||
|
||||
hideControls();
|
||||
|
||||
table.bootstrapTable({});
|
||||
reload();
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user