Added a player table as a result to the query

Rewrote PlayersTableJSONCreator to not use String format anymore
This commit is contained in:
Risto Lahtela 2021-01-10 11:53:57 +02:00
parent 80e5d797b5
commit 5c102458ae
11 changed files with 297 additions and 75 deletions

View File

@ -41,6 +41,8 @@ import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.analysis.PlayerCountQueries;
import com.djrapitops.plan.storage.database.queries.objects.*;
import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery;
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
import com.djrapitops.plan.utilities.comparators.SessionStartComparator;
import javax.inject.Inject;
@ -80,7 +82,7 @@ public class JSONFactory {
this.formatters = formatters;
}
public String serverPlayersTableJSON(UUID serverUUID) {
public Map<String, Object> serverPlayersTableJSON(UUID serverUUID) {
Integer xMostRecentPlayers = config.get(DisplaySettings.PLAYERS_PER_SERVER_PAGE);
Long playtimeThreshold = config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD);
boolean openPlayerLinksInNewTab = config.isTrue(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB);
@ -92,10 +94,10 @@ public class JSONFactory {
database.query(new ExtensionServerPlayerDataTableQuery(serverUUID, xMostRecentPlayers)),
openPlayerLinksInNewTab,
formatters, locale
).toJSONString();
).toJSONMap();
}
public String networkPlayersTableJSON() {
public Map<String, Object> networkPlayersTableJSON() {
Integer xMostRecentPlayers = config.get(DisplaySettings.PLAYERS_PER_PLAYERS_PAGE);
Long playtimeThreshold = config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD);
boolean openPlayerLinksInNewTab = config.isTrue(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB);
@ -110,7 +112,7 @@ public class JSONFactory {
pluginData,
openPlayerLinksInNewTab,
formatters, locale
).toJSONString();
).toJSONMap();
}
public List<Map<String, Object>> serverSessionsAsJSONMap(UUID serverUUID) {

View File

@ -28,6 +28,7 @@ import com.djrapitops.plan.extension.icon.Color;
import com.djrapitops.plan.extension.implementation.results.*;
import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.settings.locale.lang.HtmlLang;
import com.djrapitops.plan.utilities.java.Maps;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringEscapeUtils;
@ -94,38 +95,32 @@ public class PlayersTableJSONCreator {
}
}
public String toJSONString() {
String data = createData();
String columnHeaders = createColumnHeaders();
return "{\"columns\":" + columnHeaders + ",\"data\":" + data + '}';
public Map<String, Object> toJSONMap() {
return Maps.builder(String.class, Object.class)
.put("columns", createColumnHeaders())
.put("data", createData())
.build();
}
private String createData() {
StringBuilder dataJSON = new StringBuilder("[");
private List<Map<String, Object>> createData() {
List<Map<String, Object>> dataJson = new ArrayList<>();
int currentPlayerNumber = 0;
ExtensionTabData emptyExtensionData = new ExtensionTabData.Builder(null).build();
for (TablePlayer player : players) {
UUID playerUUID = player.getPlayerUUID();
if (playerUUID == null) {
continue;
}
if (currentPlayerNumber > 0) {
dataJSON.append(','); // Previous item
}
dataJSON.append('{'); // Start new item
appendPlayerData(dataJSON, player);
appendExtensionData(dataJSON, extensionData.getOrDefault(playerUUID, new ExtensionTabData.Builder(null).build()));
dataJSON.append('}'); // Close new item
currentPlayerNumber++;
Map<String, Object> playerEntry = new HashMap<>();
addPlayerData(playerEntry, player);
addExtensionData(playerEntry, extensionData.getOrDefault(playerUUID, emptyExtensionData));
dataJson.add(playerEntry);
}
return dataJSON.append(']').toString();
return dataJson;
}
private void appendPlayerData(StringBuilder dataJSON, TablePlayer player) {
private void addPlayerData(Map<String, Object> dataJson, TablePlayer player) {
String name = player.getName().orElse(player.getPlayerUUID().toString());
String url = "../player/" + Html.encodeToURL(name);
@ -143,33 +138,35 @@ public class PlayersTableJSONCreator {
Html link = openPlayerPageInNewTab ? Html.LINK_EXTERNAL : Html.LINK;
dataJSON.append(makeDataEntry(link.create(url, StringUtils.replace(StringEscapeUtils.escapeHtml4(name), "\\", "\\\\")), "name")).append(',') // Backslashes escaped to prevent json errors
.append(makeDataEntry(activityIndex.getValue(), activityString, "index")).append(',')
.append(makeDataEntry(playtime, numberFormatters.get(FormatType.TIME_MILLISECONDS).apply(playtime), "playtime")).append(',')
.append(makeDataEntry(loginTimes, "sessions")).append(',')
.append(makeDataEntry(registered, numberFormatters.get(FormatType.DATE_YEAR).apply(registered), "registered")).append(',')
.append(makeDataEntry(lastSeen, numberFormatters.get(FormatType.DATE_YEAR).apply(lastSeen), "seen")).append(',')
.append(makeDataEntry(geolocation, "geolocation"));
putDataEntry(dataJson, link.create(url, StringUtils.replace(StringEscapeUtils.escapeHtml4(name), "\\", "\\\\") /* Backslashes escaped to prevent json errors */), "name");
putDataEntry(dataJson, activityIndex.getValue(), activityString, "index");
putDataEntry(dataJson, playtime, numberFormatters.get(FormatType.TIME_MILLISECONDS).apply(playtime), "playtime");
putDataEntry(dataJson, loginTimes, "sessions");
putDataEntry(dataJson, registered, numberFormatters.get(FormatType.DATE_YEAR).apply(registered), "registered");
putDataEntry(dataJson, lastSeen, numberFormatters.get(FormatType.DATE_YEAR).apply(lastSeen), "seen");
putDataEntry(dataJson, geolocation, "geolocation");
}
private String makeDataEntry(Object data, String dataName) {
return "\"" + dataName + "\":\"" + StringEscapeUtils.escapeJson(data.toString()) + "\"";
private void putDataEntry(Map<String, Object> dataJson, Object data, String dataName) {
dataJson.put(dataName, data.toString());
}
private String makeDataEntry(Object data, String formatted, String dataName) {
return "\"" + dataName + "\":{\"v\":\"" + StringEscapeUtils.escapeJson(data.toString()) + "\", \"d\":\"" + StringEscapeUtils.escapeJson(formatted) + "\"}";
private void putDataEntry(Map<String, Object> dataJson, Object data, String formatted, String dataName) {
dataJson.put(dataName, Maps.builder(String.class, Object.class)
.put("v", data.toString())
.put("d", formatted)
.build());
}
private void appendExtensionData(StringBuilder dataJSON, ExtensionTabData tabData) {
private void addExtensionData(Map<String, Object> dataJson, ExtensionTabData tabData) {
for (ExtensionDescriptive descriptive : extensionDescriptives) {
dataJSON.append(',');
String key = descriptive.getName();
// If it's a double, append a double
Optional<ExtensionDoubleData> doubleValue = tabData.getDouble(key);
if (doubleValue.isPresent()) {
dataJSON.append(makeDataEntry(doubleValue.get().getRawValue(), doubleValue.get().getFormattedValue(decimalFormatter), key));
putDataEntry(dataJson, doubleValue.get().getRawValue(), doubleValue.get().getFormattedValue(decimalFormatter), key);
continue;
}
@ -177,48 +174,53 @@ public class PlayersTableJSONCreator {
if (numberValue.isPresent()) {
ExtensionNumberData numberData = numberValue.get();
FormatType formatType = numberData.getFormatType();
dataJSON.append(makeDataEntry(numberData.getRawValue(), numberData.getFormattedValue(numberFormatters.get(formatType)), key));
putDataEntry(dataJson, numberData.getRawValue(), numberData.getFormattedValue(numberFormatters.get(formatType)), key);
continue;
}
// If it's a String append a String, otherwise the player has no value for this extension provider.
// If it's a String add a String, otherwise the player has no value for this extension provider.
String stringValue = tabData.getString(key).map(ExtensionStringData::getFormattedValue).orElse("-");
dataJSON.append(makeDataEntry(stringValue, stringValue, key));
putDataEntry(dataJson, stringValue, stringValue, key);
}
}
private String createColumnHeaders() {
StringBuilder columnHeaders = new StringBuilder("[");
private List<Map<String, Object>> createColumnHeaders() {
List<Map<String, Object>> columnHeaders = new ArrayList<>();
// Is the data for the column formatted
columnHeaders.add(makeColumnHeader(Icon.called("user") + " " + locale.get(HtmlLang.LABEL_NAME), "name"));
columnHeaders.add(makeFColumnHeader(Icon.called("check") + " " + locale.get(HtmlLang.LABEL_ACTIVITY_INDEX), "index"));
columnHeaders.add(makeFColumnHeader(Icon.called("clock").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_PLAYTIME), "playtime"));
columnHeaders.add(makeColumnHeader(Icon.called("calendar-plus").of(Family.REGULAR) + " " + locale.get(HtmlLang.SIDE_SESSIONS), "sessions"));
columnHeaders.add(makeFColumnHeader(Icon.called("user-plus") + " " + locale.get(HtmlLang.LABEL_REGISTERED), "registered"));
columnHeaders.add(makeFColumnHeader(Icon.called("calendar-check").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_LAST_SEEN), "seen"));
columnHeaders.add(makeColumnHeader(Icon.called("globe") + " " + locale.get(HtmlLang.TITLE_COUNTRY), "geolocation"));
columnHeaders
.append(makeColumnHeader(Icon.called("user") + " " + locale.get(HtmlLang.LABEL_NAME), "name")).append(',')
.append(makeFColumnHeader(Icon.called("check") + " " + locale.get(HtmlLang.LABEL_ACTIVITY_INDEX), "index")).append(',')
.append(makeFColumnHeader(Icon.called("clock").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_PLAYTIME), "playtime")).append(',')
.append(makeColumnHeader(Icon.called("calendar-plus").of(Family.REGULAR) + " " + locale.get(HtmlLang.SIDE_SESSIONS), "sessions")).append(',')
.append(makeFColumnHeader(Icon.called("user-plus") + " " + locale.get(HtmlLang.LABEL_REGISTERED), "registered")).append(',')
.append(makeFColumnHeader(Icon.called("calendar-check").of(Family.REGULAR) + " " + locale.get(HtmlLang.LABEL_LAST_SEEN), "seen")).append(',')
.append(makeColumnHeader(Icon.called("globe") + " " + locale.get(HtmlLang.TITLE_COUNTRY), "geolocation"));
addExtensionHeaders(columnHeaders);
appendExtensionHeaders(columnHeaders);
return columnHeaders.append(']').toString();
return columnHeaders;
}
private String makeColumnHeader(String title, String dataProperty) {
return "{\"title\": \"" + StringEscapeUtils.escapeJson(title) + "\",\"data\":\"" + dataProperty + "\"}";
private Map<String, Object> makeColumnHeader(String title, String dataProperty) {
return Maps.builder(String.class, Object.class)
.put("title", title)
.put("data", dataProperty)
.build();
}
private String makeFColumnHeader(String title, String dataProperty) {
return "{\"title\": \"" + StringEscapeUtils.escapeJson(title) + "\",\"data\":{\"_\":\"" + dataProperty + ".v\",\"display\":\"" + dataProperty + ".d\"}}";
private Map<String, Object> makeFColumnHeader(String title, String dataProperty) {
return Maps.builder(String.class, Object.class)
.put("title", title)
.put("data", Maps.builder(String.class, String.class)
.put("_", dataProperty + ".v")
.put("display", dataProperty + ".d")
.build()
).build();
}
private void appendExtensionHeaders(StringBuilder columnHeaders) {
private void addExtensionHeaders(List<Map<String, Object>> columnHeaders) {
for (ExtensionDescriptive provider : extensionDescriptives) {
columnHeaders.append(',');
String headerText = Icon.fromExtensionIcon(provider.getIcon().setColor(Color.NONE)).toHtml().replace('"', '\'') + ' ' + provider.getText();
columnHeaders.append(makeFColumnHeader(headerText, provider.getName()));
columnHeaders.add(makeFColumnHeader(headerText, provider.getName()));
}
}
}

View File

@ -16,34 +16,55 @@
*/
package com.djrapitops.plan.delivery.webserver.resolver.json;
import com.djrapitops.plan.delivery.formatting.Formatters;
import com.djrapitops.plan.delivery.rendering.json.PlayersTableJSONCreator;
import com.djrapitops.plan.delivery.web.resolver.MimeType;
import com.djrapitops.plan.delivery.web.resolver.Resolver;
import com.djrapitops.plan.delivery.web.resolver.Response;
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
import com.djrapitops.plan.delivery.web.resolver.request.Request;
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
import com.djrapitops.plan.settings.config.PlanConfig;
import com.djrapitops.plan.settings.config.paths.DisplaySettings;
import com.djrapitops.plan.settings.config.paths.TimeSettings;
import com.djrapitops.plan.settings.locale.Locale;
import com.djrapitops.plan.storage.database.DBSystem;
import com.djrapitops.plan.storage.database.Database;
import com.djrapitops.plan.storage.database.queries.filter.Filter;
import com.djrapitops.plan.storage.database.queries.filter.FilterQuery;
import com.djrapitops.plan.storage.database.queries.filter.QueryFilters;
import com.djrapitops.plan.storage.database.queries.objects.playertable.QueryTablePlayersQuery;
import com.djrapitops.plan.utilities.java.Maps;
import javax.inject.Inject;
import javax.inject.Singleton;
import java.io.IOException;
import java.net.URLDecoder;
import java.util.List;
import java.util.Optional;
import java.util.*;
@Singleton
public class QueryJSONResolver implements Resolver {
private final QueryFilters filters;
private final PlanConfig config;
private final DBSystem dbSystem;
private final Locale locale;
private final Formatters formatters;
@Inject
public QueryJSONResolver(
QueryFilters filters
QueryFilters filters,
PlanConfig config,
DBSystem dbSystem,
Locale locale,
Formatters formatters
) {
this.filters = filters;
this.config = config;
this.dbSystem = dbSystem;
this.locale = locale;
this.formatters = formatters;
}
@Override
@ -59,20 +80,37 @@ public class QueryJSONResolver implements Resolver {
private Response getResponse(Request request) {
String q = request.getQuery().get("q").orElseThrow(() -> new BadRequestException("'q' parameter not set (expecting json array)"));
String view = request.getQuery().get("view").orElseThrow(() -> new BadRequestException("'view' parameter not set (expecting json object {afterDate, afterTime, beforeDate, beforeTime})"));
try {
q = URLDecoder.decode(q, "UTF-8");
List<FilterQuery> queries = FilterQuery.parse(q);
Filter.Result result = filters.apply(queries);
Map<String, Object> json = Maps.builder(String.class, Object.class)
.put("path", result.getResultPath())
.build();
if (!result.isEmpty()) {
json.put("data", getDataFor(result.getResultUUIDs()));
}
return Response.builder()
.setMimeType(MimeType.JSON)
.setJSONContent(Maps.builder(String.class, Object.class)
.put("path", result.getResultPath())
.put("uuids", result.getResultUUIDs())
.build())
.setJSONContent(json)
.build();
} catch (IOException e) {
throw new BadRequestException("Failed to parse json: '" + q + "'" + e.getMessage());
}
}
private Map<String, Object> getDataFor(Set<UUID> playerUUIDs) {
Database database = dbSystem.getDatabase();
return Maps.builder(String.class, Object.class)
.put("players", new PlayersTableJSONCreator(
database.query(new QueryTablePlayersQuery(playerUUIDs, System.currentTimeMillis(), config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD))),
Collections.emptyMap(),
config.get(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB),
formatters, locale
).toJSONMap())
.build();
}
}

View File

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.storage.database.queries.objects;
package com.djrapitops.plan.storage.database.queries.objects.playertable;
import com.djrapitops.plan.delivery.domain.TablePlayer;
import com.djrapitops.plan.delivery.domain.mutators.ActivityIndex;

View File

@ -0,0 +1,142 @@
/*
* This file is part of Player Analytics (Plan).
*
* Plan is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License v3 as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Plan is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.storage.database.queries.objects.playertable;
import com.djrapitops.plan.delivery.domain.TablePlayer;
import com.djrapitops.plan.delivery.domain.mutators.ActivityIndex;
import com.djrapitops.plan.storage.database.SQLDB;
import com.djrapitops.plan.storage.database.queries.Query;
import com.djrapitops.plan.storage.database.queries.QueryStatement;
import com.djrapitops.plan.storage.database.queries.analysis.NetworkActivityIndexQueries;
import com.djrapitops.plan.storage.database.sql.tables.GeoInfoTable;
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import org.apache.commons.text.TextStringBuilder;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.UUID;
import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
/**
* Query for displaying players on /query page players table.
*
* @author Rsl1122
*/
public class QueryTablePlayersQuery implements Query<List<TablePlayer>> {
private final Collection<UUID> playerUUIDs;
private final long date;
private final long activeMsThreshold;
/**
* Create a new query.
*
* @param playerUUIDs UUIDs of the players in the query
* @param date Date used for Activity Index calculation
* @param activeMsThreshold Playtime threshold for Activity Index calculation
*/
public QueryTablePlayersQuery(Collection<UUID> playerUUIDs, long date, long activeMsThreshold) {
this.playerUUIDs = playerUUIDs;
this.date = date;
this.activeMsThreshold = activeMsThreshold;
}
@Override
public List<TablePlayer> executeQuery(SQLDB db) {
String uuidsInSet = " IN ('" + new TextStringBuilder().appendWithSeparators(playerUUIDs, "','").build() + "')";
String selectGeolocations = SELECT + DISTINCT +
GeoInfoTable.USER_UUID + ", " +
GeoInfoTable.GEOLOCATION + ", " +
GeoInfoTable.LAST_USED +
FROM + GeoInfoTable.TABLE_NAME;
String selectLatestGeolocationDate = SELECT +
GeoInfoTable.USER_UUID + ", " +
"MAX(" + GeoInfoTable.LAST_USED + ") as last_used_g" +
FROM + GeoInfoTable.TABLE_NAME +
GROUP_BY + GeoInfoTable.USER_UUID;
String selectLatestGeolocations = SELECT +
"g1." + GeoInfoTable.GEOLOCATION + ',' +
"g1." + GeoInfoTable.USER_UUID +
FROM + "(" + selectGeolocations + ") AS g1" +
INNER_JOIN + "(" + selectLatestGeolocationDate + ") AS g2 ON g1.uuid = g2.uuid" +
WHERE + GeoInfoTable.LAST_USED + "=last_used_g";
String selectSessionData = SELECT + "s." + SessionsTable.USER_UUID + ',' +
"MAX(" + SessionsTable.SESSION_END + ") as last_seen," +
"COUNT(1) as count," +
"SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" +
FROM + SessionsTable.TABLE_NAME + " s" +
WHERE + "s." + SessionsTable.USER_UUID +
uuidsInSet +
GROUP_BY + "s." + SessionsTable.USER_UUID;
String selectBaseUsers = SELECT +
"u." + UsersTable.USER_UUID + ',' +
"u." + UsersTable.USER_NAME + ',' +
"u." + UsersTable.REGISTERED + ',' +
UserInfoTable.BANNED + ',' +
"geoloc." + GeoInfoTable.GEOLOCATION + ',' +
"ses.last_seen," +
"ses.count," +
"ses.playtime," +
"act.activity_index" +
FROM + UsersTable.TABLE_NAME + " u" +
INNER_JOIN + UserInfoTable.TABLE_NAME + " on u." + UsersTable.USER_UUID + "=" + UserInfoTable.TABLE_NAME + '.' + UserInfoTable.USER_UUID +
LEFT_JOIN + '(' + selectLatestGeolocations + ") geoloc on geoloc." + GeoInfoTable.USER_UUID + "=u." + UsersTable.USER_UUID +
LEFT_JOIN + '(' + selectSessionData + ") ses on ses." + SessionsTable.USER_UUID + "=u." + UsersTable.USER_UUID +
LEFT_JOIN + '(' + NetworkActivityIndexQueries.selectActivityIndexSQL() + ") act on u." + SessionsTable.USER_UUID + "=act." + UserInfoTable.USER_UUID +
WHERE + "u." + UserInfoTable.USER_UUID +
uuidsInSet +
ORDER_BY + "ses.last_seen DESC";
return db.query(new QueryStatement<List<TablePlayer>>(selectBaseUsers, 1000) {
@Override
public void prepare(PreparedStatement statement) throws SQLException {
NetworkActivityIndexQueries.setSelectActivityIndexSQLParameters(statement, 1, activeMsThreshold, date);
}
@Override
public List<TablePlayer> processResults(ResultSet set) throws SQLException {
List<TablePlayer> players = new ArrayList<>();
while (set.next()) {
TablePlayer.Builder player = TablePlayer.builder()
.uuid(UUID.fromString(set.getString(UsersTable.USER_UUID)))
.name(set.getString(UsersTable.USER_NAME))
.geolocation(set.getString(GeoInfoTable.GEOLOCATION))
.registered(set.getLong(UsersTable.REGISTERED))
.lastSeen(set.getLong("last_seen"))
.sessionCount(set.getInt("count"))
.playtime(set.getLong("playtime"))
.activityIndex(new ActivityIndex(set.getDouble("activity_index"), date));
if (set.getBoolean(UserInfoTable.BANNED)) {
player.banned();
}
players.add(player.build());
}
return players;
}
});
}
}

View File

@ -14,7 +14,7 @@
* You should have received a copy of the GNU Lesser General Public License
* along with Plan. If not, see <https://www.gnu.org/licenses/>.
*/
package com.djrapitops.plan.storage.database.queries.objects;
package com.djrapitops.plan.storage.database.queries.objects.playertable;
import com.djrapitops.plan.delivery.domain.TablePlayer;
import com.djrapitops.plan.delivery.domain.mutators.ActivityIndex;

View File

@ -258,6 +258,10 @@ function setFilterOption(
}
function performQuery() {
const queryButton = document.querySelector('#query-button');
queryButton.setAttribute('disabled', 'true');
queryButton.classList.add('disabled');
const query = [];
for (filter of filterQuery) {
query.push(filter.toObject());
@ -269,5 +273,33 @@ function performQuery() {
console.log(filterQuery);
if (json) console.log(json);
if (error) console.error(error);
renderDataResultScreen();
$('.player-table').DataTable({
responsive: true,
columns: json.data.players.columns,
data: json.data.players.data,
order: [[5, "desc"]]
})
});
}
function renderDataResultScreen() {
document.querySelector('#content .tab').innerHTML +=
`<div class="row">
<div class="col-xs-12 col-sm-12 col-lg-11">
<div class="card shadow mb-4">
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered table-striped table-hover player-table dataTable">
<tr>
<td>Loading..</td>
</tr>
</table>
</div>
</div>
</div>
</div>
</div>`;
}

View File

@ -151,7 +151,7 @@
</div>
</div>
</div>
<button class="mt-2 mb-2 btn col-plan" onclick="performQuery()"><i
<button class="mt-2 mb-2 btn col-plan" id="query-button" onclick="performQuery()"><i
class="fa fa-search"></i> Perform Query!
</button>
</div>
@ -313,6 +313,10 @@
<script src="./js/xmlhttprequests.js"></script>
<script src="./js/color-selector.js"></script>
<!-- Page level plugins -->
<script src="vendor/datatables/jquery.dataTables.min.js"></script>
<script src="vendor/datatables/dataTables.bootstrap4.min.js"></script>
<!-- Page level custom scripts -->
<script src='./js/query.js'></script>

View File

@ -32,6 +32,8 @@ import com.djrapitops.plan.storage.database.queries.*;
import com.djrapitops.plan.storage.database.queries.containers.ContainerFetchQueries;
import com.djrapitops.plan.storage.database.queries.containers.ServerPlayerContainersQuery;
import com.djrapitops.plan.storage.database.queries.objects.*;
import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery;
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
import com.djrapitops.plan.storage.database.sql.building.Sql;
import com.djrapitops.plan.storage.database.sql.tables.UserInfoTable;
import com.djrapitops.plan.storage.database.transactions.StoreConfigTransaction;

View File

@ -23,9 +23,9 @@ import com.djrapitops.plan.delivery.domain.mutators.SessionsMutator;
import com.djrapitops.plan.gathering.domain.Session;
import com.djrapitops.plan.storage.database.DatabaseTestPreparer;
import com.djrapitops.plan.storage.database.queries.analysis.ActivityIndexQueries;
import com.djrapitops.plan.storage.database.queries.objects.NetworkTablePlayersQuery;
import com.djrapitops.plan.storage.database.queries.objects.ServerTablePlayersQuery;
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
import com.djrapitops.plan.storage.database.queries.objects.playertable.NetworkTablePlayersQuery;
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
import com.djrapitops.plan.storage.database.sql.tables.SessionsTable;
import com.djrapitops.plan.storage.database.sql.tables.UsersTable;
import com.djrapitops.plan.storage.database.transactions.events.PlayerServerRegisterTransaction;

View File

@ -26,9 +26,9 @@ import com.djrapitops.plan.gathering.domain.WorldTimes;
import com.djrapitops.plan.storage.database.DatabaseTestPreparer;
import com.djrapitops.plan.storage.database.queries.containers.PlayerContainerQuery;
import com.djrapitops.plan.storage.database.queries.objects.KillQueries;
import com.djrapitops.plan.storage.database.queries.objects.ServerTablePlayersQuery;
import com.djrapitops.plan.storage.database.queries.objects.SessionQueries;
import com.djrapitops.plan.storage.database.queries.objects.WorldTimesQueries;
import com.djrapitops.plan.storage.database.queries.objects.playertable.ServerTablePlayersQuery;
import com.djrapitops.plan.storage.database.transactions.Transaction;
import com.djrapitops.plan.storage.database.transactions.commands.RemoveEverythingTransaction;
import com.djrapitops.plan.storage.database.transactions.events.PlayerServerRegisterTransaction;