mirror of
https://github.com/plan-player-analytics/Plan.git
synced 2025-02-05 16:30:24 +08:00
View options added to the query
This commit is contained in:
parent
5c102458ae
commit
c7ed844c76
@ -42,6 +42,7 @@ public class Formatters {
|
||||
private final DayFormatter dayLongFormatter;
|
||||
private final SecondFormatter secondLongFormatter;
|
||||
private final ClockFormatter clockLongFormatter;
|
||||
private final JavascriptDateFormatter javascriptDateFormatter;
|
||||
private final ISO8601NoClockFormatter iso8601NoClockLongFormatter;
|
||||
private final ISO8601NoClockTZIndependentFormatter iso8601NoClockTZIndependentFormatter;
|
||||
|
||||
@ -57,6 +58,7 @@ public class Formatters {
|
||||
dayLongFormatter = new DayFormatter(config, locale);
|
||||
clockLongFormatter = new ClockFormatter(config, locale);
|
||||
secondLongFormatter = new SecondFormatter(config, locale);
|
||||
javascriptDateFormatter = new JavascriptDateFormatter(config, locale);
|
||||
iso8601NoClockLongFormatter = new ISO8601NoClockFormatter(config, locale);
|
||||
iso8601NoClockTZIndependentFormatter = new ISO8601NoClockTZIndependentFormatter();
|
||||
|
||||
@ -109,6 +111,10 @@ public class Formatters {
|
||||
return iso8601NoClockFormatter;
|
||||
}
|
||||
|
||||
public Formatter<Long> javascriptDateFormatterLong() {
|
||||
return javascriptDateFormatter;
|
||||
}
|
||||
|
||||
public Formatter<Long> iso8601NoClockLong() {
|
||||
return iso8601NoClockLongFormatter;
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.delivery.formatting.time;
|
||||
|
||||
import com.djrapitops.plan.settings.config.PlanConfig;
|
||||
import com.djrapitops.plan.settings.locale.Locale;
|
||||
|
||||
/**
|
||||
* Formats epoch milliseconds to the date format Javascript Date constructor expects.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
public class JavascriptDateFormatter extends DateFormatter {
|
||||
|
||||
public JavascriptDateFormatter(PlanConfig config, Locale locale) {
|
||||
super(config, locale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String apply(Long epochMs) {
|
||||
return format(epochMs, "dd/MM/yyyy kk:mm");
|
||||
}
|
||||
}
|
@ -16,6 +16,8 @@
|
||||
*/
|
||||
package com.djrapitops.plan.delivery.webserver.resolver.json;
|
||||
|
||||
import com.djrapitops.plan.delivery.formatting.Formatter;
|
||||
import com.djrapitops.plan.delivery.formatting.Formatters;
|
||||
import com.djrapitops.plan.delivery.web.resolver.MimeType;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Resolver;
|
||||
import com.djrapitops.plan.delivery.web.resolver.Response;
|
||||
@ -23,7 +25,7 @@ import com.djrapitops.plan.delivery.web.resolver.request.Request;
|
||||
import com.djrapitops.plan.delivery.web.resolver.request.WebUser;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.Filter;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.QueryFilters;
|
||||
import com.djrapitops.plan.utilities.java.Maps;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -31,17 +33,21 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Singleton
|
||||
public class FiltersJSONResolver implements Resolver {
|
||||
|
||||
private final QueryFilters filters;
|
||||
private final Formatters formatters;
|
||||
|
||||
@Inject
|
||||
public FiltersJSONResolver(
|
||||
QueryFilters filters
|
||||
QueryFilters filters,
|
||||
Formatters formatters
|
||||
) {
|
||||
this.filters = filters;
|
||||
this.formatters = formatters;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -58,21 +64,64 @@ public class FiltersJSONResolver implements Resolver {
|
||||
private Response getResponse() {
|
||||
return Response.builder()
|
||||
.setMimeType(MimeType.JSON)
|
||||
.setJSONContent(Maps.builder(String.class, Object.class)
|
||||
.put("filters", serializeFilters())
|
||||
.build())
|
||||
.build();
|
||||
.setJSONContent(new FilterResponseJSON(
|
||||
filters.getFilters(),
|
||||
new ViewJSON(formatters)
|
||||
)).build();
|
||||
}
|
||||
|
||||
private List<Map<String, Object>> serializeFilters() {
|
||||
List<Map<String, Object>> filterList = new ArrayList<>();
|
||||
for (Map.Entry<String, Filter> entry : filters.getFilters().entrySet()) {
|
||||
filterList.add(Maps.builder(String.class, Object.class)
|
||||
.put("kind", entry.getKey())
|
||||
.put("options", entry.getValue().getOptions())
|
||||
.put("expectedParameters", entry.getValue().getExpectedParameters())
|
||||
.build());
|
||||
/**
|
||||
* JSON serialization class.
|
||||
*/
|
||||
static class FilterResponseJSON {
|
||||
final List<FilterJSON> filters;
|
||||
final ViewJSON view;
|
||||
|
||||
public FilterResponseJSON(Map<String, Filter> filtersByKind, ViewJSON view) {
|
||||
this.filters = new ArrayList<>();
|
||||
for (Map.Entry<String, Filter> entry : filtersByKind.entrySet()) {
|
||||
filters.add(new FilterJSON(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
this.view = view;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON serialization class.
|
||||
*/
|
||||
static class FilterJSON {
|
||||
final String kind;
|
||||
final Map<String, Object> options;
|
||||
final String[] expectedParameters;
|
||||
|
||||
public FilterJSON(String kind, Filter filter) {
|
||||
this.kind = kind;
|
||||
this.options = filter.getOptions();
|
||||
this.expectedParameters = filter.getExpectedParameters();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON serialization class.
|
||||
*/
|
||||
static class ViewJSON {
|
||||
final String afterDate;
|
||||
final String afterTime;
|
||||
final String beforeDate;
|
||||
final String beforeTime;
|
||||
|
||||
public ViewJSON(Formatters formatters) {
|
||||
long now = System.currentTimeMillis();
|
||||
long monthAgo = now - TimeUnit.DAYS.toMillis(30);
|
||||
|
||||
Formatter<Long> formatter = formatters.javascriptDateFormatterLong();
|
||||
String[] after = StringUtils.split(formatter.apply(monthAgo), " ");
|
||||
String[] before = StringUtils.split(formatter.apply(now), " ");
|
||||
|
||||
this.afterDate = after[0];
|
||||
this.afterTime = after[1];
|
||||
this.beforeDate = before[0];
|
||||
this.beforeTime = before[1];
|
||||
}
|
||||
return filterList;
|
||||
}
|
||||
}
|
||||
|
@ -35,11 +35,14 @@ 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 com.google.gson.Gson;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.net.URLDecoder;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
@Singleton
|
||||
@ -81,6 +84,7 @@ 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);
|
||||
@ -90,23 +94,30 @@ public class QueryJSONResolver implements Resolver {
|
||||
.put("path", result.getResultPath())
|
||||
.build();
|
||||
if (!result.isEmpty()) {
|
||||
json.put("data", getDataFor(result.getResultUUIDs()));
|
||||
json.put("data", getDataFor(result.getResultUUIDs(), view));
|
||||
}
|
||||
return Response.builder()
|
||||
.setMimeType(MimeType.JSON)
|
||||
.setJSONContent(json)
|
||||
.build();
|
||||
|
||||
} catch (ParseException e) {
|
||||
throw new BadRequestException("'view' date format was incorrect (expecting afterDate dd/mm/yyyy, afterTime hh:mm, beforeDate dd/mm/yyyy, beforeTime hh:mm}): " + e.getMessage());
|
||||
} catch (IOException e) {
|
||||
throw new BadRequestException("Failed to parse json: '" + q + "'" + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Object> getDataFor(Set<UUID> playerUUIDs) {
|
||||
private Map<String, Object> getDataFor(Set<UUID> playerUUIDs, String view) throws ParseException {
|
||||
FiltersJSONResolver.ViewJSON viewJSON = new Gson().fromJson(view, FiltersJSONResolver.ViewJSON.class);
|
||||
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy kk:mm");
|
||||
long after = dateFormat.parse(viewJSON.afterDate + " " + viewJSON.afterTime).getTime();
|
||||
long before = dateFormat.parse(viewJSON.beforeDate + " " + viewJSON.beforeTime).getTime();
|
||||
|
||||
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))),
|
||||
database.query(new QueryTablePlayersQuery(playerUUIDs, after, before, config.get(TimeSettings.ACTIVE_PLAY_THRESHOLD))),
|
||||
Collections.emptyMap(),
|
||||
config.get(DisplaySettings.OPEN_PLAYER_LINKS_IN_NEW_TAB),
|
||||
formatters, locale
|
||||
|
@ -17,6 +17,7 @@
|
||||
package com.djrapitops.plan.storage.database.queries.filter;
|
||||
|
||||
import com.djrapitops.plan.delivery.web.resolver.exception.BadRequestException;
|
||||
import com.djrapitops.plan.storage.database.queries.filter.filters.AllPlayersFilter;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
@ -32,9 +33,14 @@ import java.util.*;
|
||||
public class QueryFilters {
|
||||
|
||||
private final Map<String, Filter> filters;
|
||||
private final AllPlayersFilter allPlayersFilter;
|
||||
|
||||
@Inject
|
||||
public QueryFilters(Set<Filter> filters) {
|
||||
public QueryFilters(
|
||||
Set<Filter> filters,
|
||||
AllPlayersFilter allPlayersFilter
|
||||
) {
|
||||
this.allPlayersFilter = allPlayersFilter;
|
||||
this.filters = new HashMap<>();
|
||||
put(filters);
|
||||
}
|
||||
@ -58,6 +64,7 @@ public class QueryFilters {
|
||||
*/
|
||||
public Filter.Result apply(List<FilterQuery> filterQueries) {
|
||||
Filter.Result current = null;
|
||||
if (filterQueries.isEmpty()) return allPlayersFilter.apply(null);
|
||||
for (FilterQuery filterQuery : filterQueries) {
|
||||
current = apply(current, filterQuery);
|
||||
if (current != null && current.isEmpty()) break;
|
||||
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.filter.filters;
|
||||
|
||||
import com.djrapitops.plan.storage.database.DBSystem;
|
||||
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.objects.UserIdentifierQueries;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Special filter only used in cases where no filters are specified.
|
||||
*
|
||||
* @author Rsl1122
|
||||
*/
|
||||
@Singleton
|
||||
public class AllPlayersFilter implements Filter {
|
||||
|
||||
private final DBSystem dbSystem;
|
||||
|
||||
@Inject
|
||||
public AllPlayersFilter(DBSystem dbSystem) {
|
||||
this.dbSystem = dbSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getKind() {
|
||||
return "all";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getExpectedParameters() {
|
||||
return new String[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<UUID> getMatchingUUIDs(FilterQuery query) {
|
||||
return dbSystem.getDatabase().query(UserIdentifierQueries.fetchAllPlayerUUIDs());
|
||||
}
|
||||
}
|
@ -40,10 +40,10 @@ public abstract class DateRangeFilter implements Filter {
|
||||
@Override
|
||||
public String[] getExpectedParameters() {
|
||||
return new String[]{
|
||||
"dateAfter",
|
||||
"timeAfter",
|
||||
"dateBefore",
|
||||
"timeBefore"
|
||||
"afterDate",
|
||||
"afterTime",
|
||||
"beforeDate",
|
||||
"beforeTime"
|
||||
};
|
||||
}
|
||||
|
||||
@ -61,11 +61,11 @@ public abstract class DateRangeFilter implements Filter {
|
||||
}
|
||||
|
||||
protected long getAfter(FilterQuery query) {
|
||||
return getTime(query, "dateAfter", "timeAfter");
|
||||
return getTime(query, "afterDate", "afterTime");
|
||||
}
|
||||
|
||||
protected long getBefore(FilterQuery query) {
|
||||
return getTime(query, "dateBefore", "timeBefore");
|
||||
return getTime(query, "beforeDate", "beforeTime");
|
||||
}
|
||||
|
||||
private long getTime(FilterQuery query, String dateKey, String timeKey) {
|
||||
|
@ -46,19 +46,21 @@ import static com.djrapitops.plan.storage.database.sql.building.Sql.*;
|
||||
public class QueryTablePlayersQuery implements Query<List<TablePlayer>> {
|
||||
|
||||
private final Collection<UUID> playerUUIDs;
|
||||
private final long date;
|
||||
private final long afterDate;
|
||||
private final long beforeDate;
|
||||
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 beforeDate Date used for Activity Index calculation
|
||||
* @param activeMsThreshold Playtime threshold for Activity Index calculation
|
||||
*/
|
||||
public QueryTablePlayersQuery(Collection<UUID> playerUUIDs, long date, long activeMsThreshold) {
|
||||
public QueryTablePlayersQuery(Collection<UUID> playerUUIDs, long afterDate, long beforeDate, long activeMsThreshold) {
|
||||
this.playerUUIDs = playerUUIDs;
|
||||
this.date = date;
|
||||
this.afterDate = afterDate;
|
||||
this.beforeDate = beforeDate;
|
||||
this.activeMsThreshold = activeMsThreshold;
|
||||
}
|
||||
|
||||
@ -88,7 +90,9 @@ public class QueryTablePlayersQuery implements Query<List<TablePlayer>> {
|
||||
"COUNT(1) as count," +
|
||||
"SUM(" + SessionsTable.SESSION_END + '-' + SessionsTable.SESSION_START + ") as playtime" +
|
||||
FROM + SessionsTable.TABLE_NAME + " s" +
|
||||
WHERE + "s." + SessionsTable.USER_UUID +
|
||||
WHERE + "s." + SessionsTable.SESSION_START + ">=?" +
|
||||
AND + "s." + SessionsTable.SESSION_END + "<=?" +
|
||||
AND + "s." + SessionsTable.USER_UUID +
|
||||
uuidsInSet +
|
||||
GROUP_BY + "s." + SessionsTable.USER_UUID;
|
||||
|
||||
@ -114,7 +118,9 @@ public class QueryTablePlayersQuery implements Query<List<TablePlayer>> {
|
||||
return db.query(new QueryStatement<List<TablePlayer>>(selectBaseUsers, 1000) {
|
||||
@Override
|
||||
public void prepare(PreparedStatement statement) throws SQLException {
|
||||
NetworkActivityIndexQueries.setSelectActivityIndexSQLParameters(statement, 1, activeMsThreshold, date);
|
||||
statement.setLong(1, afterDate);
|
||||
statement.setLong(2, beforeDate);
|
||||
NetworkActivityIndexQueries.setSelectActivityIndexSQLParameters(statement, 3, activeMsThreshold, beforeDate);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -129,7 +135,7 @@ public class QueryTablePlayersQuery implements Query<List<TablePlayer>> {
|
||||
.lastSeen(set.getLong("last_seen"))
|
||||
.sessionCount(set.getInt("count"))
|
||||
.playtime(set.getLong("playtime"))
|
||||
.activityIndex(new ActivityIndex(set.getDouble("activity_index"), date));
|
||||
.activityIndex(new ActivityIndex(set.getDouble("activity_index"), beforeDate));
|
||||
if (set.getBoolean(UserInfoTable.BANNED)) {
|
||||
player.banned();
|
||||
}
|
||||
|
@ -4,11 +4,11 @@ let filterCount = 0;
|
||||
id: "DOM id",
|
||||
options...
|
||||
}*/
|
||||
const filterView = {
|
||||
dateAfter: null,
|
||||
timeAfter: null,
|
||||
dateBefore: null,
|
||||
timeBefore: null
|
||||
let filterView = {
|
||||
afterDate: null,
|
||||
afterTime: null,
|
||||
beforeDate: null,
|
||||
beforeTime: null
|
||||
};
|
||||
const filterQuery = [];
|
||||
|
||||
@ -102,10 +102,10 @@ class BetweenDateFilter extends Filter {
|
||||
super(kind);
|
||||
this.id = id;
|
||||
this.label = label;
|
||||
this.dateAfter = options.after[0];
|
||||
this.timeAfter = options.after[1];
|
||||
this.dateBefore = options.before[0];
|
||||
this.timeBefore = options.before[1];
|
||||
this.afterDate = options.after[0];
|
||||
this.afterTime = options.after[1];
|
||||
this.beforeDate = options.before[0];
|
||||
this.beforeTime = options.before[1];
|
||||
}
|
||||
|
||||
render(filterCount) {
|
||||
@ -116,20 +116,20 @@ class BetweenDateFilter extends Filter {
|
||||
`<div id="${id}" class="mt-2 input-group input-row">` +
|
||||
`<div class="col-3"><div class="input-group mb-2">` +
|
||||
`<div class="input-group-prepend"><div class="input-group-text"><i class="far fa-calendar"></i></div></div>` +
|
||||
`<input id="${id}-afterdate" onkeyup="setFilterOption('${id}', '${id}-afterdate', 'dateAfter', isValidDate, correctDate)" class="form-control" placeholder="${this.dateAfter}" type="text">` +
|
||||
`<input id="${id}-afterdate" onkeyup="setFilterOption('${id}', '${id}-afterdate', 'afterDate', isValidDate, correctDate)" class="form-control" placeholder="${this.afterDate}" type="text">` +
|
||||
`</div></div>` +
|
||||
`<div class="col-2"><div class="input-group mb-2">` +
|
||||
`<div class="input-group-prepend"><div class="input-group-text"><i class="far fa-clock"></i></div></div>` +
|
||||
`<input id="${id}-aftertime" onkeyup="setFilterOption('${id}', '${id}-aftertime', 'timeAfter', isValidTime, correctTime)" class="form-control" placeholder="${this.timeAfter}" type="text">` +
|
||||
`<input id="${id}-aftertime" onkeyup="setFilterOption('${id}', '${id}-aftertime', 'afterTime', isValidTime, correctTime)" class="form-control" placeholder="${this.afterTime}" type="text">` +
|
||||
`</div></div>` +
|
||||
`<div class="col-auto"><label class="mt-2 mb-0" for="inlineFormCustomSelectPref">&</label></div>` +
|
||||
`<div class="col-3"><div class="input-group mb-2">` +
|
||||
`<div class="input-group-prepend"><div class="input-group-text"><i class="far fa-calendar"></i></div></div>` +
|
||||
`<input id="${id}-beforedate" onkeyup="setFilterOption('${id}', '${id}-beforedate', 'dateBefore', isValidDate, correctDate)" class="form-control" placeholder="${this.dateBefore}" type="text">` +
|
||||
`<input id="${id}-beforedate" onkeyup="setFilterOption('${id}', '${id}-beforedate', 'beforeDate', isValidDate, correctDate)" class="form-control" placeholder="${this.beforeDate}" type="text">` +
|
||||
`</div></div>` +
|
||||
`<div class="col-2"><div class="input-group mb-2">` +
|
||||
`<div class="input-group-prepend"><div class="input-group-text"><i class="far fa-clock"></i></div></div>` +
|
||||
`<input id="${id}-beforetime" onkeyup="setFilterOption('${id}', '${id}-beforetime', 'timeBefore', isValidTime, correctTime)" class="form-control" placeholder="${this.timeBefore}" type="text">` +
|
||||
`<input id="${id}-beforetime" onkeyup="setFilterOption('${id}', '${id}-beforetime', 'beforeTime', isValidTime, correctTime)" class="form-control" placeholder="${this.beforeTime}" type="text">` +
|
||||
`</div></div>` +
|
||||
`</div>`
|
||||
);
|
||||
@ -139,10 +139,10 @@ class BetweenDateFilter extends Filter {
|
||||
return {
|
||||
kind: this.kind,
|
||||
parameters: {
|
||||
dateAfter: this.dateAfter,
|
||||
timeAfter: this.timeAfter,
|
||||
dateBefore: this.dateBefore,
|
||||
timeBefore: this.timeBefore
|
||||
afterDate: this.afterDate,
|
||||
afterTime: this.afterTime,
|
||||
beforeDate: this.beforeDate,
|
||||
beforeTime: this.beforeTime
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -274,7 +274,7 @@ function performQuery() {
|
||||
if (json) console.log(json);
|
||||
if (error) console.error(error);
|
||||
|
||||
renderDataResultScreen();
|
||||
renderDataResultScreen(json.data.players.data.length);
|
||||
|
||||
$('.player-table').DataTable({
|
||||
responsive: true,
|
||||
@ -282,24 +282,41 @@ function performQuery() {
|
||||
data: json.data.players.data,
|
||||
order: [[5, "desc"]]
|
||||
})
|
||||
|
||||
const activityIndexHeader = document.querySelector("#DataTables_Table_0 thead th:nth-of-type(2)");
|
||||
const lastSeenHeader = document.querySelector("#DataTables_Table_0 thead th:nth-of-type(6)");
|
||||
|
||||
activityIndexHeader.innerHTML += ` (${filterView.beforeDate})`
|
||||
lastSeenHeader.innerHTML += ` (view)`
|
||||
});
|
||||
}
|
||||
|
||||
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>
|
||||
function renderDataResultScreen(resultCount) {
|
||||
document.querySelector('#content .tab').innerHTML =
|
||||
`<div class="container-fluid mt-4">
|
||||
<!-- Page Heading -->
|
||||
<div class="d-sm-flex align-items-center justify-content-between mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800"><i class="sidebar-toggler fa fa-fw fa-bars"></i>Plan ·
|
||||
Query Results</h1>
|
||||
<p class="mb-0 text-gray-800">(matched ${resultCount} players)</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-sm-12 col-lg-11">
|
||||
<div class="card shadow mb-4">
|
||||
<div class="card-header py-3 d-flex flex-row align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold col-black" title=" ${filterView.afterDate} ${filterView.afterTime} - ${filterView.beforeDate} ${filterView.beforeTime}"><i
|
||||
class="fas fa-fw fa-users col-black"></i>
|
||||
View: ${filterView.afterDate} - ${filterView.beforeDate}</h6>
|
||||
</div>
|
||||
<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>
|
||||
</div>`;
|
||||
</div>`;
|
||||
}
|
@ -43,7 +43,7 @@ function openPage() {
|
||||
|
||||
// Prepare tabs for display
|
||||
content.style.transform = "translate3d(0px,0px,0)";
|
||||
content.style.width = (tabCount * 100) + "%";
|
||||
content.style.width = (Math.max(100, tabCount * 100)) + "%";
|
||||
content.style.opacity = "1";
|
||||
for (let tab of tabs) {
|
||||
tab.style.width = (100 / tabCount) + "%";
|
||||
|
@ -93,7 +93,7 @@
|
||||
<div class="input-group-text"><i class="far fa-calendar"></i></div>
|
||||
</div>
|
||||
<input class="form-control" id="viewFromDateField"
|
||||
onkeyup="setFilterOption('view', 'viewFromDateField', 'dateBefore', isValidDate, correctDate)"
|
||||
onkeyup="setFilterOption('view', 'viewFromDateField', 'beforeDate', isValidDate, correctDate)"
|
||||
placeholder="31/12/2016"
|
||||
type="text">
|
||||
</div>
|
||||
@ -105,7 +105,7 @@
|
||||
<div class="input-group-text"><i class="far fa-clock"></i></div>
|
||||
</div>
|
||||
<input class="form-control" id="viewFromTimeField"
|
||||
onkeyup="setFilterOption('view', 'viewFromTimeField', 'timeBefore', isValidTime, correctTime)"
|
||||
onkeyup="setFilterOption('view', 'viewFromTimeField', 'beforeTime', isValidTime, correctTime)"
|
||||
placeholder="23:59"
|
||||
type="text">
|
||||
</div>
|
||||
@ -119,7 +119,7 @@
|
||||
<div class="input-group-text"><i class="far fa-calendar"></i></div>
|
||||
</div>
|
||||
<input class="form-control" id="viewToDateField"
|
||||
onkeyup="setFilterOption('view', 'viewToDateField', 'dateAfter', isValidDate, correctDate)"
|
||||
onkeyup="setFilterOption('view', 'viewToDateField', 'afterDate', isValidDate, correctDate)"
|
||||
placeholder="23/03/2020"
|
||||
type="text">
|
||||
</div>
|
||||
@ -130,7 +130,7 @@
|
||||
<div class="input-group-text"><i class="far fa-clock"></i></div>
|
||||
</div>
|
||||
<input class="form-control" id="viewToTimeField"
|
||||
onkeyup="setFilterOption('view', 'viewToTimeField', 'timeAfter', isValidTime, correctTime)"
|
||||
onkeyup="setFilterOption('view', 'viewToTimeField', 'afterTime', isValidTime, correctTime)"
|
||||
placeholder="21:26"
|
||||
type="text">
|
||||
</div>
|
||||
@ -325,6 +325,13 @@
|
||||
jsonRequest("./v1/filters", function (json, error) {
|
||||
filters.push(...json.filters);
|
||||
|
||||
filterView = json.view;
|
||||
|
||||
document.getElementById('viewFromDateField').setAttribute('placeholder', json.view.afterDate);
|
||||
document.getElementById('viewFromTimeField').setAttribute('placeholder', json.view.afterTime);
|
||||
document.getElementById('viewToDateField').setAttribute('placeholder', json.view.beforeDate);
|
||||
document.getElementById('viewToTimeField').setAttribute('placeholder', json.view.beforeTime);
|
||||
|
||||
let filterElements = '';
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
filterElements += createFilterSelector('#filters', i, filters[i]);
|
||||
|
Loading…
Reference in New Issue
Block a user