This commit is contained in:
AuroraLS3 2023-10-07 06:11:16 +00:00
parent bca79bf1ec
commit 4379ac2450
36 changed files with 747 additions and 303 deletions

View File

@ -24,8 +24,8 @@ command:
description: "要禁用的功能名称:${0}"
name: "功能"
group:
description: "Web Permission Group, case sensitive."
name: "group"
description: "Web权限组,区分大小写。"
name: "权限组"
importKind: "导入类型"
nameOrUUID:
description: "玩家的名称或 UUID"
@ -154,8 +154,8 @@ command:
description: "手动导出 html 或 json 文件"
inDepth: "把数据导出到配置文件中指定的导出位置。"
groups:
description: "List web permission groups."
inDepth: "List available web permission groups that are managed on the web interface."
description: "列出Web权限组。"
inDepth: "列出在Web界面上管理的可用Web权限组。"
import:
description: "导入数据"
inDepth: "执行导入,将数据加载到数据库。"
@ -200,8 +200,8 @@ command:
description: "列出数据库中的服务器"
inDepth: "列出数据库中所有服务器的ID、名称和UUID。"
setgroup:
description: "Change users web permission group."
inDepth: "Allows you to change a users web permission group to an existing web group. Use /plan groups for list of available groups."
description: "更改用户Web权限组。"
inDepth: "允许您将用户Web权限组更改为现有Web组。 使用 /plan groups 获取可用组的列表。"
unregister:
description: "注销一个 Plan 网页账户"
inDepth: "不含参数使用会注销当前绑定的账户,使用用户名作为参数能注销另一个用户。"
@ -248,16 +248,16 @@ html:
unique: "独立:"
description:
newPlayerRetention: "这个数值是基于之前的玩家数据预测的。"
noData24h: "Server has not sent data for over 24 hours."
noData30d: "Server has not sent data for over 30 days."
noData7d: "Server has not sent data for over 7 days."
noData24h: "服务器超过24小时未发送数据."
noData30d: "服务器超过30天没有发送数据."
noData7d: "服务器超过7天未发送数据."
noGameServers: "要获取某些数据,你需要将 Plan 安装在游戏服务器上。"
noGeolocations: "需要在配置文件中启用地理位置收集(Accept GeoLite2 EULA)。"
noServerOnlinActivity: "没有可显示在线活动的服务器"
noServers: "数据库中找不到服务器"
noServersLong: '看起来 Plan 没有安装在任何游戏服务器上或者游戏服务器未连接到相同的数据库。 群组网络教程请参见:<a href="https://github.com/plan-player-analytics/Plan/wiki">wiki</a>'
noSpongeChunks: "区块数据在 Sponge 服务端不可用"
performanceNoGameServers: "TPS, Entity or Chunk data is not gathered from proxy servers since they don't have game tick loop."
performanceNoGameServers: "TPS、实体或块数据不是从代理服务器收集的,因为它们没有游戏滴答循环。"
predictedNewPlayerRetention: "这个数值是基于之前的玩家数据预测的"
error:
401Unauthorized: "未认证"
@ -271,10 +271,10 @@ html:
emptyForm: "未指定用户名与密码"
expiredCookie: "用户 Cookie 已过期"
generic: "认证时发生错误"
groupNotFound: "Web Permission Group does not exist"
groupNotFound: "Web权限组不存在"
loginFailed: "用户名和密码不匹配"
noCookie: "用户 cookie 不存在"
noPermissionGroup: "Registration failed, player did not have any 'plan.webgroup.{name}' permission"
noPermissionGroup: "注册失败玩家没有任何“plan.webgroup.{名字}”权限"
registrationFailed: "注册失败,请重试(注册代码有效期 15 分钟)"
userNotFound: "用户名不存在"
authFailed: "认证失败。"
@ -325,17 +325,18 @@ html:
cpuUsage: "CPU 使用率"
currentPlayerbase: "当前玩家数"
currentUptime: "正常运行时间"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "按天查看"
dayOfweek: "星期"
deadliestWeapon: "最致命的 PVP 武器"
deaths: "死亡数"
disk: "硬盘空间"
diskSpace: "剩余硬盘空间"
docs: "Swagger Docs"
docs: "Swagger文档"
downtime: "停机时间"
duringLowTps: "持续低 TPS 时间"
entities: "实体"
errors: "Plan Error Logs"
errors: "Plan错误日志"
exported: "数据导出时间"
favoriteServer: "最喜爱的服务器"
firstSession: "第一次会话"
@ -349,8 +350,8 @@ html:
miller: "米勒投影"
ortographic: "正射投影"
geolocations: "地理位置"
groupPermissions: "Manage Groups"
groupUsers: "Manage Group Users"
groupPermissions: "管理权限组"
groupUsers: "管理权限组用户"
help:
activityIndexBasis: "活跃指数基于过去3周21天内的非AFK游戏时间。每周单独考虑。"
activityIndexExample1: "如果有人每周玩的时间达到阈值他们将获得活跃指数约为3。"
@ -358,66 +359,67 @@ html:
activityIndexExample3: "该指数无限趋近于5。"
activityIndexVisual: "这里是y = 活跃指数x = 每周游戏时间 / 阈值的曲线可视化。"
activityIndexWeek: "第{}周"
examples: "Examples"
examples: "示例"
graph:
labels: "You can hide/show a group by clicking on the label at the bottom."
title: "Graph"
zoom: "You can Zoom in by click + dragging on the graph."
labels: "您可以通过单击底部的标签来隐藏/显示组."
title: "图形"
zoom: "您可以通过单击+拖动图表来放大."
manage:
groups:
line-1: "This view allows you to modify web group permissions."
line-10: "<1>{{permission}}</> permissions determine what parts of the page are visible. These permissions also limit requests to the related data endpoints."
line-11: "<1>{{permission1}}</1> permissions are not required for data: <2>{{permission2}}</2> allows request to /v1/network/overview even without <3>{{permission3}}</3>."
line-12: "Saving changes"
line-13: "When you add a group or delete a group that action is saved immediately after confirm (no undo)."
line-14: "When you modify permissions those changes need to be saved by pressing the Save-button"
line-15: "Documentation can be found from <1>{{link}}</1>"
line-2: "User's web group is determined during <1>{{command}}</1> by checking if Player has <2>{{permission}}</2> permission."
line-3: "You can use <1>{{command}}</1> to change permission group after registering."
line-4: "<1>{{icon}}</1> If you ever accidentally delete all groups with <2>{{permission}}</2> permission just <3>{{command}}</3>."
line-5: "Permission inheritance"
line-6: "Permissions follow inheritance model, where higher level permission grants all lower ones, eg. <1>{{permission1}}</1> also gives <2>{{permission2}}</2>, etc."
line-7: "Access vs Page -permissions"
line-8: "You need to assign both access and page permissions for users."
line-9: "<1>{{permission1}}</1> permissions allow user make the request to specific address, eg. <2>{{permission2}}</2> allows request to /network."
line-1: "此视图允许您修改Web组权限。"
line-10: "<1>{{permission}}</>权限决定页面的哪些部分是可见的。这些权限还限制了对相关数据端点的请求。"
line-11: "<1>{{permission1}}</1>权限对于数据不是必需的:<2>{{permission2}}</2>允许在没有<3>{{permission3}}</3>的情况下对/v1/network/overview发起请求。"
line-12: "保存更改"
line-13: "当您添加或删除组时,确认后立即保存该操作(无法撤销)。"
line-14: "当您修改权限时,需要通过按下保存按钮来保存这些更改。"
line-15: "文档可以在<1>{{link}}</1>找到。"
line-2: "在<1>{{command}}</1>期间,通过检查玩家是否具有<2>{{permission}}</2>权限来确定用户的网络组。"
line-3: "您可以使用<1>{{command}}</1>在注册后更改权限组。"
line-4: "<1>{{icon}}</1> 如果您意外删除了所有具有<2>{{permission}}</2>权限的组,请使用<3>{{command}}</3>。"
line-5: "权限继承"
line-6: "权限遵循继承模型,其中较高级别的权限授予所有较低级别的权限,例如<1>{{permission1}}</1>也会给予<2>{{permission2}}</2>等等。"
line-7: "访问权限与页面权限"
line-8: "您需要为用户分配访问权限和页面权限。"
line-9: "<1>{{permission1}}</1>权限允许用户向特定地址发出请求,例如<2>{{permission2}}</2>允许请求/network。"
playtimeUnit: "小时"
retention:
calculationStep1: "First the data is filtered using '<>' option. Any players with 'registerDate' outside the time range are ignored."
calculationStep2: "Then it is grouped into groups of players using '<0>' option, eg. With '<1>': All players who registered in January 2023, February 2023, etc"
calculationStep3: "Then the '<0>' and '<1>' options select which visualization to render."
calculationStep4: "'<>' controls how many points the graph has, eg. 'Days' has one point per day."
calculationStep5: "On each calculated point all players are checked for the condition."
calculationStep6: "Select X Axis below to see conditions."
calculationStepDate: "This visualization shows the different groups of players that are still playing on your server. The visualization uses lastSeen date. If x < lastSeenDate, the player is visible on the graph."
calculationStepDeltas: "This visualization is most effective using Player Count as the Y Axis. The visualization shows net gain of players (How many players joined minus players who stopped playing). The visualization uses both registered and lastSeen dates. If registerDate < x < lastSeenDate, the player is visible on the graph."
calculationStepPlaytime: "This visualization tells how long the gameplay loop keeps players engaged on your server. The visualization uses playtime. If x < playtime, the player is visible on the graph."
calculationStepTime: "This visualization tells how long people keep coming back to play on the server after they join the first time. The visualization uses timeDifference. If x < timeDifference, the player is visible on the graph."
compareJoinAddress: "Grouping by join address allows measuring advertising campaigns on different sites."
compareMonths: "You can compare different months by changing the '<0>' option to '<1>'"
calculationStep1: "首先使用“<>”选项过滤数据。 任何“registerDate”超出时间范围的玩家都会被忽略."
calculationStep2: "然后使用“<0>”选项将其分组为玩家组,例如。 带“<1>”2023 年 1 月、2023 年 2 月等注册的所有玩家"
calculationStep3: "然后“<0>”和“<1>”选项选择要渲染的可视化."
calculationStep4: "'<>' 控制图表有多少个点,例如。 “天”每天有 1 分."
calculationStep5: "在每个计算点上,都会检查所有球员的状况."
calculationStep6: "选择下面的 X 轴查看条件."
calculationStepDate: "此可视化显示仍在您的服务器上玩游戏的不同玩家组。 可视化使用lastSeen 日期。 如果 x < lastSeenDate则玩家在图表上可见."
calculationStepDeltas: "使用玩家计数作为 Y 轴,这种可视化效果最为有效。 可视化显示玩家的净收益(加入的玩家数量减去停止玩游戏的玩家数量)。 可视化使用注册日期和上次查看日期。 如果 registerDate < x < lastSeenDate则玩家在图表上可见."
calculationStepPlaytime: "此可视化显示游戏循环让玩家在您的服务器上保持活跃的时间。 可视化使用游戏时间。 如果 x < 游戏时间,则玩家在图表上可见."
calculationStepTime: "此可视化显示人们在第一次加入后继续返回服务器玩游戏的时间。 可视化使用时差。 如果 x < timeDifference则玩家在图表上可见."
compareJoinAddress: "按加入地址分组可以衡量不同网站上的广告活动."
compareMonths: "您可以通过将“<0>”选项更改为“<1>”来比较不同月份"
examples:
adCampaign: "Comparing player gain of different ad campaigns using different Join Addresses (anonymized)"
deltas: "<> shows net gain of players."
pattern: "A general pattern emerges when all players start leaving the server at the same time"
plateau: "Comparing player gain of different months. Plateaus suggest there were players Plan doesn't know about. In this example Plan was installed in January 2022."
playtime: "Playtime tells how long the gameplay loop keeps players engaged on your server."
stack: "Cumulative player gain can be checked with stacked player count as Y axis"
howIsItCalculated: "How it is calculated"
howIsItCalculatedData: "The graph is generated from player data:"
options: "Select the options to analyze different aspects of Player Retention."
adCampaign: "比较使用不同加入地址的不同广告活动的玩家收益(匿名)"
deltas: "<>显示玩家的净收益."
pattern: "当所有玩家同时开始离开服务器时,就会出现一般模式"
plateau: "比较不同月份的玩家收益。 Plateaus 表明有一些 Plan 不知道的玩家。 在此示例中,计划于 2022 年 1 月安装."
playtime: "游戏时间表明游戏循环让玩家在服务器上保持活跃的时间."
stack: "可以使用堆叠玩家数作为 Y 轴来检查累积玩家增益"
howIsItCalculated: "计算方法"
howIsItCalculatedData: "该图表是根据玩家数据生成的:"
options: "选择选项来分析玩家保留的不同方面."
retentionBasis: "新玩家留坑率根据会话数据计算。如果注册玩家在时间跨度的后半段内有游戏记录,则被视为已留坑。"
testPrompt: "试一下:"
testResult: "测试结果"
threshold: "阈值"
thresholdUnit: "小时/周"
tips: "Tips"
usingTheGraph: "Using the Graph"
usingTheGraph: "使用图表"
hourByHour: "按小时查看"
inactive: "不活跃"
indexInactive: "不活跃"
indexRegular: "经常上线"
information: "信息"
insights: "Insights"
insights: "洞察"
insights30days: "30 天分析"
installed: "Installed"
irregular: "偶尔上线"
joinAddress: "加入地址"
joinAddresses: "加入地址"
@ -439,42 +441,43 @@ html:
longestSession: "最长会话时间"
lowTpsSpikes: "低 TPS 时间"
lowTpsSpikes7days: "低 TPS 时间7天"
manage: "Manage"
manage: "管理"
managePage:
addGroup:
header: "Add group"
invalidName: "Group name can be 100 characters maximum."
name: "Name of the group"
header: "添加权限组"
invalidName: "权限组名称最多可以有100个字符。"
name: "权限组名称"
alert:
groupAddFail: "Failed to add group: {{error}}"
groupAddSuccess: "Added group '{{groupName}}'"
groupDeleteFail: "Failed to delete group: {{error}}"
groupDeleteSuccess: "Deleted group '{{groupName}}'"
saveFail: "Failed to save changes: {{error}}"
saveSuccess: "Changes saved successfully!"
groupAddFail: "添加权限组失败:{{error}}"
groupAddSuccess: "已添加权限组 '{{groupName}}'"
groupDeleteFail: "删除权限组失败:{{error}}"
groupDeleteSuccess: "已删除权限组 '{{groupName}}'"
saveFail: "保存更改失败:{{error}}"
saveSuccess: "更改已成功保存!"
changes:
discard: "Discard Changes"
save: "Save"
unsaved: "Unsaved changes"
discard: "放弃更改"
save: "保存"
unsaved: "未保存的更改"
deleteGroup:
confirm: "Confirm & Delete {{groupName}}"
confirmDescription: "This will move all users of '{{groupName}}' to group '{{moveTo}}'. There is no undo!"
header: "Delete '{{groupName}}'"
moveToSelect: "Move remaining users to group"
groupHeader: "Manage Group Permissions"
groupPermissions: "Permissions of {{groupName}}"
confirm: "确认并删除 {{groupName}}"
confirmDescription: "这将把 '{{groupName}}' 的所有用户移到权限组 '{{moveTo}}'。这将无法撤销!"
header: "删除 '{{groupName}}'"
moveToSelect: "将剩余用户移到权限组"
groupHeader: "管理权限组权限"
groupPermissions: "{{groupName}} 的权限"
maxFreeDisk: "最大可用硬盘空间"
medianSessionLength: "会话长度中位数"
minFreeDisk: "最小可用硬盘空间"
mobDeaths: "被生物击杀数"
mobKdr: "生物 KDR"
mobKills: "生物击杀数"
modified: "Modified"
mostActiveGamemode: "最常玩的游戏模式"
mostPlayedWorld: "玩的最多的世界"
name: "名称"
network: "群组网络"
networkAsNumbers: "群组网络数据"
networkCalendar: "Network Calendar"
networkCalendar: "网络日历"
networkOnlineActivity: "群组网络在线活动"
networkOverview: "群组网络总览"
networkPage: "群组网络页面"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "在线玩家(当前)"
playersOnlineOverview: "在线活动总览"
playtime: "游玩时间"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "插件"
pluginsOverview: "插件总览"
punchcard: "打卡"
@ -532,19 +537,19 @@ html:
regularPlayers: "普通玩家"
relativeJoinActivity: "最近加入活动"
retention:
groupByNone: "No grouping"
groupByTime: "Group registered by"
inAnytime: "any time"
inLast180d: "in the last 6 months"
inLast30d: "in the last 30 days"
inLast365d: "in the last 12 months"
inLast730d: "in the last 24 months"
inLast7d: "in the last 7 days"
inLast90d: "in the last 3 months"
playersRegisteredInTime: "Players who registered"
retainedPlayersPercentage: "Retained Players %"
timeSinceRegistered: "Time since register date"
timeStep: "Time step"
groupByNone: "没有分组"
groupByTime: "组注册于"
inAnytime: "任何时间"
inLast180d: "在过去 6 个月内"
inLast30d: "在过去 30 天内"
inLast365d: "在过去 12 个月内"
inLast730d: "在过去 24 个月内"
inLast7d: "在过去 7 天内"
inLast90d: "在过去 3 个月内"
playersRegisteredInTime: "已注册玩家"
retainedPlayersPercentage: "留存玩家 %"
timeSinceRegistered: "自注册日期起的时间"
timeStep: "时间步长"
secondDeadliestWeapon: "第二致命的 PVP 武器"
seenNicknames: "用过的昵称"
server: "服务器"
@ -557,7 +562,7 @@ html:
serverPage: "服务器页面"
serverPlaytime: "服务器游戏时间"
serverPlaytime30days: "最近 30 天内的服务器游玩时间"
serverPossiblyOffline: "Possibly offline"
serverPossiblyOffline: "可能处于离线状态"
serverSelector: "服务器选择器"
servers: "服务器"
serversTitle: "服务器"
@ -570,23 +575,23 @@ html:
sortBy: "排序方式"
stacked: "堆叠"
table:
showNofM: "Showing {{n}} of {{m}} entries"
showPerPage: "Show per page"
visibleColumns: "Visible columns"
showNofM: "显示{{n}}条目中的{{m}}条"
showPerPage: "每页显示"
visibleColumns: "可见列"
themeSelect: "主题选择"
thirdDeadliestWeapon: "第三致命的 PVP 武器"
thirtyDays: "30 天"
thirtyDaysAgo: "30 天前"
time:
date: "Date"
day: "Day"
days: "Days"
hours: "Hours"
month: "Month"
months: "Months"
week: "Week"
weeks: "Weeks"
year: "Year"
date: "日期"
day: ""
days: ""
hours: "小时"
month: ""
months: ""
week: ""
weeks: ""
year: ""
timesKicked: "被踢出次数"
toMainPage: "回到主页面"
total: "总计"
@ -599,20 +604,22 @@ html:
tps: "TPS"
trend: "趋势"
trends30days: "30 天趋势"
uninstalled: "Uninstalled"
uniquePlayers: "独立玩家"
uniquePlayers7days: "独立玩家7天"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
percentage: "百分比"
playerCount: "玩家数量"
users: "管理用户"
version: "Version"
veryActive: "非常活跃"
weekComparison: "每周对比"
weekdays: "'星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'"
world: "世界加载"
worldPlaytime: "世界游玩时间"
worstPing: "最高延迟"
xAxis: "X Axis"
yAxis: "Y Axis"
xAxis: "X"
yAxis: "Y"
login:
failed: "登录失败:"
forgotPassword: "忘记密码?"
@ -628,87 +635,87 @@ html:
manage:
permission:
description:
access: "Controls access to pages"
access_docs: "Allows accessing /docs page"
access_errors: "Allows accessing /errors page"
access_network: "Allows accessing /network page"
access_player: "Allows accessing any /player pages"
access_player_self: "Allows accessing own /player page"
access_players: "Allows accessing /players page"
access_query: "Allows accessing /query and Query results pages"
access_raw_player_data: "Allows accessing /player/{uuid}/raw json data. Follows 'access.player' permissions."
access_server: "Allows accessing all /server pages"
manage_groups: "Allows modifying group permissions & Access to /manage/groups page"
manage_users: "Allows modifying what users belong to what group"
page: "Controls what is visible on pages"
page_network: "See all of network page"
page_network_geolocations: "See Geolocations tab"
page_network_geolocations_map: "See Geolocations Map"
page_network_geolocations_ping_per_country: "See Ping Per Country table"
page_network_join_addresses: "See Join Addresses -tab"
page_network_join_addresses_graphs: "See Join Address graphs"
page_network_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_network_join_addresses_graphs_time: "See Join Addresses over time graph"
page_network_overview: "See Network Overview -tab"
page_network_overview_graphs: "See Network Overview graphs"
page_network_overview_graphs_calendar: "See Network calendar"
page_network_overview_graphs_day_by_day: "See Day by Day graph"
page_network_overview_graphs_hour_by_hour: "See Hour by Hour graph"
page_network_overview_graphs_online: "See Players Online graph"
page_network_overview_numbers: "See Network Overview numbers"
page_network_performance: "See network Performance tab"
page_network_playerbase: "See Playerbase Overview -tab"
page_network_playerbase_graphs: "See Playerbase Overview graphs"
page_network_playerbase_overview: "See Playerbase Overview numbers"
page_network_players: "See Player list -tab"
page_network_plugins: "See Plugins tab of Proxy"
page_network_retention: "See Player Retention -tab"
page_network_server_list: "See list of servers"
page_network_sessions: "See Sessions tab"
page_network_sessions_list: "See list of sessions"
page_network_sessions_overview: "See Session insights"
page_network_sessions_server_pie: "See Server Pie graph"
page_network_sessions_world_pie: "See World Pie graph"
page_player: "See all of player page"
page_player_overview: "See Player Overview -tab"
page_player_plugins: "See Plugins -tabs"
page_player_servers: "See Servers -tab"
page_player_sessions: "See Player Sessions -tab"
page_player_versus: "See PvP & PvE -tab"
page_server: "See all of server page"
page_server_geolocations: "See Geolocations tab"
page_server_geolocations_map: "See Geolocations Map"
page_server_geolocations_ping_per_country: "See Ping Per Country table"
page_server_join_addresses: "See Join Addresses -tab"
page_server_join_addresses_graphs: "See Join Address graphs"
page_server_join_addresses_graphs_pie: "See Latest Join Addresses graph"
page_server_join_addresses_graphs_time: "See Join Addresses over time graph"
page_server_online_activity: "See Online Activity -tab"
page_server_online_activity_graphs: "See Online Activity graphs"
page_server_online_activity_graphs_calendar: "See Server calendar"
page_server_online_activity_graphs_day_by_day: "See Day by Day graph"
page_server_online_activity_graphs_hour_by_hour: "See Hour by Hour graph"
page_server_online_activity_graphs_punchcard: "See Punchcard graph"
page_server_online_activity_overview: "See Online Activity numbers"
page_server_overview: "See Server Overview -tab"
page_server_overview_numbers: "See Server Overview numbers"
page_server_overview_players_online_graph: "See Players Online graph"
page_server_performance: "See Performance tab"
page_server_performance_graphs: "See Performance graphs"
page_server_performance_overview: "See Performance numbers"
page_server_player_versus: "See PvP & PvE -tab"
page_server_player_versus_kill_list: "See Player kill and death lists"
page_server_player_versus_overview: "See PvP & PvE numbers"
page_server_playerbase: "See Playerbase Overview -tab"
page_server_playerbase_graphs: "See Playerbase Overview graphs"
page_server_playerbase_overview: "See Playerbase Overview numbers"
page_server_players: "See Player list -tab"
page_server_plugins: "See Plugins -tabs of servers"
page_server_retention: "See Player Retention -tab"
page_server_sessions: "See Sessions tab"
page_server_sessions_list: "See list of sessions"
page_server_sessions_overview: "See Session insights"
page_server_sessions_world_pie: "See World Pie graph"
access: "控制对页面的访问权限"
access_docs: "允许访问/docs页面"
access_errors: "允许访问/errors页面"
access_network: "允许访问/network页面"
access_player: "允许访问任何/player页面"
access_player_self: "允许访问自己的/player页面"
access_players: "允许访问/players页面"
access_query: "允许访问/query和查询结果页面"
access_raw_player_data: "允许访问/player/{uuid}/raw json数据。遵循'access.player'权限。"
access_server: "允许访问所有/server页面"
manage_groups: "允许修改群组权限和访问/manage/groups页面"
manage_users: "允许修改用户所属群组"
page: "控制页面上可见的内容"
page_network: "查看所有网络页面"
page_network_geolocations: "查看地理位置选项卡"
page_network_geolocations_map: "查看地理位置地图"
page_network_geolocations_ping_per_country: "查看按国家划分的Ping表"
page_network_join_addresses: "查看加入地址选项卡"
page_network_join_addresses_graphs: "查看加入地址图表"
page_network_join_addresses_graphs_pie: "查看最新加入地址图表"
page_network_join_addresses_graphs_time: "查看加入地址随时间变化的图表"
page_network_overview: "查看网络概览选项卡"
page_network_overview_graphs: "查看网络概览图表"
page_network_overview_graphs_calendar: "查看网络日历"
page_network_overview_graphs_day_by_day: "查看逐日图表"
page_network_overview_graphs_hour_by_hour: "查看逐时图表"
page_network_overview_graphs_online: "查看在线玩家图表"
page_network_overview_numbers: "查看网络概览数字"
page_network_performance: "查看网络性能选项卡"
page_network_playerbase: "查看玩家基础选项卡"
page_network_playerbase_graphs: "查看玩家基础图表"
page_network_playerbase_overview: "查看玩家基础数字"
page_network_players: "查看玩家列表选项卡"
page_network_plugins: "查看代理的插件选项卡"
page_network_retention: "查看玩家保留选项卡"
page_network_server_list: "查看服务器列表"
page_network_sessions: "查看会话选项卡"
page_network_sessions_list: "查看会话列表"
page_network_sessions_overview: "查看会话洞察力"
page_network_sessions_server_pie: "查看服务器饼图"
page_network_sessions_world_pie: "查看世界饼图"
page_player: "查看所有玩家页面"
page_player_overview: "查看玩家概览选项卡"
page_player_plugins: "查看插件选项卡"
page_player_servers: "查看服务器选项卡"
page_player_sessions: "查看玩家会话选项卡"
page_player_versus: "查看PvP和PvE选项卡"
page_server: "查看所有服务器页面"
page_server_geolocations: "查看服务器地理位置选项卡"
page_server_geolocations_map: "查看服务器地理位置地图"
page_server_geolocations_ping_per_country: "查看按国家划分的Ping表"
page_server_join_addresses: "查看服务器加入地址选项卡"
page_server_join_addresses_graphs: "查看服务器加入地址图表"
page_server_join_addresses_graphs_pie: "查看最新加入地址图表"
page_server_join_addresses_graphs_time: "查看服务器加入地址随时间变化的图表"
page_server_online_activity: "查看在线活动选项卡"
page_server_online_activity_graphs: "查看在线活动图表"
page_server_online_activity_graphs_calendar: "查看服务器日历"
page_server_online_activity_graphs_day_by_day: "查看逐日图表"
page_server_online_activity_graphs_hour_by_hour: "查看逐时图表"
page_server_online_activity_graphs_punchcard: "查看打卡图表"
page_server_online_activity_overview: "查看在线活动数字"
page_server_overview: "查看服务器概览选项卡"
page_server_overview_numbers: "查看服务器概览数字"
page_server_overview_players_online_graph: "查看在线玩家图表"
page_server_performance: "查看服务器性能选项卡"
page_server_performance_graphs: "查看服务器性能图表"
page_server_performance_overview: "查看服务器性能数字"
page_server_player_versus: "查看PvP和PvE选项卡"
page_server_player_versus_kill_list: "查看玩家杀死和死亡列表"
page_server_player_versus_overview: "查看PvP和PvE数字"
page_server_playerbase: "查看服务器玩家基础选项卡"
page_server_playerbase_graphs: "查看服务器玩家基础图表"
page_server_playerbase_overview: "查看服务器玩家基础数字"
page_server_players: "查看服务器玩家列表选项卡"
page_server_plugins: "查看服务器的插件选项卡"
page_server_retention: "查看玩家保留选项卡"
page_server_sessions: "查看服务器会话选项卡"
page_server_sessions_list: "查看会话列表"
page_server_sessions_overview: "查看会话洞察力"
page_server_sessions_world_pie: "查看世界饼图"
modal:
info:
bugs: "报告问题"
@ -800,7 +807,7 @@ html:
completion3: "在游戏中使用以下命令完成注册:"
completion4: "或使用控制台:"
createNewUser: "创建一个新用户"
disabled: "Registering new users has been disabled in the config."
disabled: "配置中已禁用注册新用户."
error:
checkFailed: "检查注册状态失败:"
failed: "注册失败:"
@ -883,7 +890,7 @@ plugin:
unknown: "位置"
yes: "是"
yesterday: "'昨天'"
localeReloaded: "Custom locale.yml was modified so it was reloaded and is now in use."
localeReloaded: "自定义 locale.yml 已被修改,因此已重新加载并且现在正在使用。"
version:
checkFail: "无法检查最新版本号"
checkFailGithub: "无法从 Github/versions.txt 加载版本信息"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Aktuální základna hráčů"
currentUptime: "Aktuální doba zapnutí"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Den po dni"
dayOfweek: "Den týdne"
deadliestWeapon: "Nejsmrtelnější PvP zbraň"
@ -418,6 +419,7 @@ html:
information: "INFORMACE"
insights: "Postřehy"
insights30days: "Postřehy za 30 dní"
installed: "Installed"
irregular: "Nepravidelný"
joinAddress: "Adresa Připojení"
joinAddresses: "IP Připojení"
@ -469,6 +471,7 @@ html:
mobDeaths: "Smrti způsobené moby"
mobKdr: "Mob KDR"
mobKills: "Zabití mobové"
modified: "Modified"
mostActiveGamemode: "Nejvíce aktivní mód"
mostPlayedWorld: "Nejvíc hraný svět"
name: "Jméno"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Hráči online (Nyní)"
playersOnlineOverview: "Přehled online aktivity"
playtime: "Herní čas"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Pluginy"
pluginsOverview: "Přehled pluginů"
punchcard: "Štítky"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Trend"
trends30days: "Trendy za 30 dní"
uninstalled: "Uninstalled"
uniquePlayers: "Unikátní hráči"
uniquePlayers7days: "Unikátních hráčů (7 dní)"
unit:
percentage: "Procento"
playerCount: "Počet hráčů"
users: "Manage Users"
version: "Version"
veryActive: "Velmi aktivní"
weekComparison: "Týdenní srovnání"
weekdays: "'Pondělí', 'Úterý', 'Středa', 'Čtvrtek', 'Pátek', 'Sobota', 'Neděle'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Aktuelle Spielerbasis"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Tag für Tag"
dayOfweek: "Tag der Woche"
deadliestWeapon: "Tödlichste PvP Waffe"
@ -418,6 +419,7 @@ html:
information: "INFORMATION"
insights: "Insights"
insights30days: "Insights for 30 days"
installed: "Installed"
irregular: "Unregelmäßig"
joinAddress: "Join Address"
joinAddresses: "Join Addresses"
@ -469,6 +471,7 @@ html:
mobDeaths: "Tode durch Mobs"
mobKdr: "Mob KDR"
mobKills: "Mob Kills"
modified: "Modified"
mostActiveGamemode: "Meist genutzter Spielmodus"
mostPlayedWorld: "Meist gespielte Welt"
name: "Name"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Online Aktivitätsübersicht"
playtime: "Spielzeit"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Plugins"
pluginsOverview: "Plugins Overview"
punchcard: "Lochkarte"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Trend"
trends30days: "Trends für 30 Tage"
uninstalled: "Uninstalled"
uniquePlayers: "Einzigartige Spieler"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Sehr aktiv"
weekComparison: "Wochenvergleich"
weekdays: "'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Current Playerbase"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Day by Day"
dayOfweek: "Day of the Week"
deadliestWeapon: "Deadliest PvP Weapon"
@ -418,6 +419,7 @@ html:
information: "INFORMATION"
insights: "Insights"
insights30days: "Insights for 30 days"
installed: "Installed"
irregular: "Irregular"
joinAddress: "Join Address"
joinAddresses: "Join Addresses"
@ -469,6 +471,7 @@ html:
mobDeaths: "Mob caused Deaths"
mobKdr: "Mob KDR"
mobKills: "Mob Kills"
modified: "Modified"
mostActiveGamemode: "Most Active Gamemode"
mostPlayedWorld: "Most played World"
name: "Name"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Online Activity Overview"
playtime: "Playtime"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Plugins"
pluginsOverview: "Plugins Overview"
punchcard: "Punchcard"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Trend"
trends30days: "Trends for 30 days"
uninstalled: "Uninstalled"
uniquePlayers: "Unique Players"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Very Active"
weekComparison: "Week Comparison"
weekdays: "'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "base del jugador actual"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Día a día"
dayOfweek: "Dia de la semana"
deadliestWeapon: "Arma PvP más mortal"
@ -418,6 +419,7 @@ html:
information: "INFORMACIÓN"
insights: "Insights"
insights30days: "Ideas por 30 días"
installed: "Installed"
irregular: "Irregular"
joinAddress: "Join Address"
joinAddresses: "Direcciones de entrada"
@ -469,6 +471,7 @@ html:
mobDeaths: "Muertes causadas por mobs"
mobKdr: "KDR de mobs"
mobKills: "Asesinatos de mobs"
modified: "Modified"
mostActiveGamemode: "Modo de juego mas activo"
mostPlayedWorld: "Mundo más jugado"
name: "Nombre"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Vista general de la actividad online"
playtime: "Tiempo de juego"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Plugins"
pluginsOverview: "Plugins Overview"
punchcard: "Tarjeta"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Tendencia"
trends30days: "Tendencias de 30 días"
uninstalled: "Uninstalled"
uniquePlayers: "Jugadores únicos"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Muy activo"
weekComparison: "Comparación semanal"
weekdays: "'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado', 'Domingo'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "Suorittimen käyttö"
currentPlayerbase: "Nykyiset pelaajat"
currentUptime: "Käynnissäoloaika"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Päivittäinen katsaus"
dayOfweek: "Viikonpäivä"
deadliestWeapon: "Tappavin PvP Ase"
@ -418,6 +419,7 @@ html:
information: "TIETOJA"
insights: "Katsaukset"
insights30days: "Katsauksia 30 päivälle"
installed: "Installed"
irregular: "Epäsäännöllinen"
joinAddress: "Liittymisosoite"
joinAddresses: "Liittymisosoitteet"
@ -469,6 +471,7 @@ html:
mobDeaths: "Otusten aiheuttamat Kuolemat"
mobKdr: "Otus-Tapposuhde"
mobKills: "Tapetut Otukset"
modified: "Modified"
mostActiveGamemode: "Aktiivisin pelitila"
mostPlayedWorld: "Eniten pelattu maailma"
name: "Nimi"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Pelaajia paikalla (Nyt)"
playersOnlineOverview: "Yhteenveto Paikallaolosta"
playtime: "Peliaika"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Lisäosat"
pluginsOverview: "Lisäosien Yhteenveto"
punchcard: "Reikäkortti"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Suunta"
trends30days: "Suunnat 30 päivälle"
uninstalled: "Uninstalled"
uniquePlayers: "Uniikkeja pelaajia"
uniquePlayers7days: "Uniikkeja pelaajia (7 päivää)"
unit:
percentage: "Prosentti"
playerCount: "Pelaajamäärä"
users: "Manage Users"
version: "Version"
veryActive: "Todella Aktiivinen"
weekComparison: "Viikkojen vertaus"
weekdays: "'Maanantai', 'Tiistai', 'Keskiviikko', 'Torstai', 'Perjantai', 'Lauantai', 'Sunnuntai'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Base de Joueurs actuelle"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Jour par Jour"
dayOfweek: "Jour de la Semaine"
deadliestWeapon: "1ère Arme de Combat (la plus mortelle)"
@ -418,6 +419,7 @@ html:
information: "INFORMATIONS"
insights: "Insights"
insights30days: "Perspectives sur 30 jours"
installed: "Installed"
irregular: "Irrégulier"
joinAddress: "Join Address"
joinAddresses: "Adresses de Connexion"
@ -469,6 +471,7 @@ html:
mobDeaths: "Morts causées par un Mob"
mobKdr: "Ratio - Kills / Morts de Mobs -"
mobKills: "Kills de Mobs"
modified: "Modified"
mostActiveGamemode: "Mode de Jeu le plus utilisé"
mostPlayedWorld: "Monde le plus Fréquenté"
name: "Nom"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Aperçu de l'Activité en Ligne"
playtime: "Temps de Jeu"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Plugins"
pluginsOverview: "Plugins Overview"
punchcard: "Carte Perforée"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Tendances"
trends30days: "Tendances sur 30 Jours"
uninstalled: "Uninstalled"
uniquePlayers: "Joueurs Uniques"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Très Actif"
weekComparison: "Comparaison Hebdomadaire"
weekdays: "'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi', 'Dimanche'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Playerbase Corrente"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Giorno Per Giorno"
dayOfweek: "Giorno della Settimana"
deadliestWeapon: "Arma PvP Preferita"
@ -418,6 +419,7 @@ html:
information: "INFORMAZIONE"
insights: "Insights"
insights30days: "Grafico in 30 giorni"
installed: "Installed"
irregular: "Irregolare"
joinAddress: "Join Address"
joinAddresses: "Join Addresses"
@ -469,6 +471,7 @@ html:
mobDeaths: "Mob che hanno causato la Morte"
mobKdr: "Mob KDR"
mobKills: "Mob uccisi"
modified: "Modified"
mostActiveGamemode: "La Gamemode più attiva"
mostPlayedWorld: "Mondo più giocato"
name: "Nome"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Panoramica delle attività online"
playtime: "Gioco"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Plugins"
pluginsOverview: "Plugins Overview"
punchcard: "Presenza Settimanale"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Tendenza"
trends30days: "Tendenza per 30 giorni"
uninstalled: "Uninstalled"
uniquePlayers: "Giocatori unici"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Molto Attivo"
weekComparison: "Confronto settimanale"
weekdays: "'Lunedì', 'Martedì', 'Mercoledì', 'Giovedì', 'Venerdì', 'Sabato', 'Domenica'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU使用率"
currentPlayerbase: "ログインプレイヤー"
currentUptime: "現状のアップタイム"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "詳細情報"
dayOfweek: "曜日"
deadliestWeapon: "最もPvPで使用されている武器"
@ -418,6 +419,7 @@ html:
information: "インフォメーション"
insights: "Insights"
insights30days: "1ヶ月のパンチボード"
installed: "Installed"
irregular: "たまにログインしている"
joinAddress: "参加したサーバーのアドレス"
joinAddresses: "参加したサーバーのアドレス"
@ -469,6 +471,7 @@ html:
mobDeaths: "Mobによって殺された回数"
mobKdr: "Mobに対してのKDR"
mobKills: "Mobを殺した回数"
modified: "Modified"
mostActiveGamemode: "最も使用したゲームモード"
mostPlayedWorld: "よくプレイしているワールド"
name: "名前"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "オンラインのプレイヤー(今)"
playersOnlineOverview: "接続状況の概要"
playtime: "プレイ時間"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "プラグイン"
pluginsOverview: "プラグイン一覧"
punchcard: "パンチカード"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "増減"
trends30days: "1ヶ月間の増減"
uninstalled: "Uninstalled"
uniquePlayers: "接続したプレイヤーの総数"
uniquePlayers7days: "直近7日間のユニークプレイヤー数"
unit:
percentage: "パーセンテージ"
playerCount: "プレイヤー数"
users: "Manage Users"
version: "Version"
veryActive: "とてもログインしている"
weekComparison: "直近1週間での比較"
weekdays: "'月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日', '日曜日'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "현재 플레이어 베이스"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Day by Day"
dayOfweek: "요일"
deadliestWeapon: "치명적인 PvP 무기"
@ -418,6 +419,7 @@ html:
information: "정보"
insights: "Insights"
insights30days: "30일 동안의 인사이트"
installed: "Installed"
irregular: "불규칙한"
joinAddress: "Join Address"
joinAddresses: "Join Addresses"
@ -469,6 +471,7 @@ html:
mobDeaths: "몬스터한테 죽은 횟수"
mobKdr: "몬스터 KDR"
mobKills: "몬스터 킬수"
modified: "Modified"
mostActiveGamemode: "가장 활동적인 게임모드"
mostPlayedWorld: "가장 많이 플레이 한 맵"
name: "이름"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "온라인 활동 개요"
playtime: "플레이타임"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "플러그인"
pluginsOverview: "Plugins Overview"
punchcard: "펀치 카드"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "트렌드"
trends30days: "30일 동안의 트렌드"
uninstalled: "Uninstalled"
uniquePlayers: "기존 플레이어"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "매우 활성화된"
weekComparison: "주 비교"
weekdays: "'월요일', '화요일', '수요일', '목요일', '금요일', '토요일', '일요일'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Huidige spelerbasis"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Dag voor dag"
dayOfweek: "Dag van de Week"
deadliestWeapon: "Dodelijkste PvP-wapen"
@ -418,6 +419,7 @@ html:
information: "INFORMATIE"
insights: "Insights"
insights30days: "Inzichten voor 30 dagen"
installed: "Installed"
irregular: "Onregelmatig"
joinAddress: "Join Address"
joinAddresses: "Inlog adressen"
@ -469,6 +471,7 @@ html:
mobDeaths: "Mob veroorzaakt doden"
mobKdr: "Mob KDR"
mobKills: "Mob Moorden"
modified: "Modified"
mostActiveGamemode: "Meest actieve spelmodus"
mostPlayedWorld: "Meest gespeelde wereld"
name: "Naam"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Overzicht van online activiteiten"
playtime: "Speeltijd"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Plugins"
pluginsOverview: "Plugins Overview"
punchcard: "Ponskaart"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Trend"
trends30days: "Trends voor 30 dagen"
uninstalled: "Uninstalled"
uniquePlayers: "Unieke spelers"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Heel Actief"
weekComparison: "Weekvergelijking"
weekdays: "'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrijdag', 'Zaterdag', 'Zondag'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Base de Jogadores Atual"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Day by Day"
dayOfweek: "Day of the Week"
deadliestWeapon: "Deadliest PvP Weapon"
@ -418,6 +419,7 @@ html:
information: "INFORMATION"
insights: "Insights"
insights30days: "Insights for 30 days"
installed: "Installed"
irregular: "Irregular"
joinAddress: "Join Address"
joinAddresses: "Join Addresses"
@ -469,6 +471,7 @@ html:
mobDeaths: "Mortes causadas por Mobs"
mobKdr: "KDR por Mob"
mobKills: "Assassinato de Mobs"
modified: "Modified"
mostActiveGamemode: "Most Active Gamemode"
mostPlayedWorld: "Most played World"
name: "Nome"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Online Activity Overview"
playtime: "Tempo de Jogo"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Plugins"
pluginsOverview: "Plugins Overview"
punchcard: "Punchcard"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Trend"
trends30days: "Trends for 30 days"
uninstalled: "Uninstalled"
uniquePlayers: "Jogadores Únicos"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Muito Ativo"
weekComparison: "Week Comparison"
weekdays: "'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "Использование ЦП"
currentPlayerbase: "Текущая база игроков"
currentUptime: "Время безотказной работы"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Статистика по дням"
dayOfweek: "День недели"
deadliestWeapon: "Самое смертоносное оружие в PvP"
@ -418,6 +419,7 @@ html:
information: "ИНФОРМАЦИЯ"
insights: "Инсайты"
insights30days: "Статистика за 30 дней"
installed: "Installed"
irregular: "Нерегулярный"
joinAddress: "Адрес входа"
joinAddresses: "Адресы Входа"
@ -469,6 +471,7 @@ html:
mobDeaths: "Смерть из-за мобов"
mobKdr: "Моб KDR"
mobKills: "Убийства мобов"
modified: "Modified"
mostActiveGamemode: "Самый активный игровой режим"
mostPlayedWorld: "Самый популярный мир"
name: "Имя"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Обзор сетевой активности"
playtime: "Время игры"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Плагины"
pluginsOverview: "Обзор плагинов"
punchcard: "Перфокарты"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Тенденция"
trends30days: "тенденция за 30 дней"
uninstalled: "Uninstalled"
uniquePlayers: "Уникальные игроки"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Очень активный"
weekComparison: "Сравнение за неделю"
weekdays: "'Понедельник', 'Вторник', 'Среда', 'Четверг', 'Пятница', 'Суббота', 'Воскресенье'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU Usage"
currentPlayerbase: "Şuanki Oyuncu Tabanı"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Gün gün"
dayOfweek: "Day of the Week"
deadliestWeapon: "En Ölümcül PvP Silahı"
@ -418,6 +419,7 @@ html:
information: "DANIŞMA"
insights: "Insights"
insights30days: "30 günlük bilgiler"
installed: "Installed"
irregular: "Düzensiz"
joinAddress: "Join Address"
joinAddresses: "Adreslere Katıl"
@ -469,6 +471,7 @@ html:
mobDeaths: "Yaratık Yüzünden ölümler"
mobKdr: "Mob İstatistiği"
mobKills: "Öldürülen Mob"
modified: "Modified"
mostActiveGamemode: "En Aktif Oyun Modu"
mostPlayedWorld: "En çok oynanan Dünya"
name: "İsim"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Players Online (Now)"
playersOnlineOverview: "Çevrimiçi Etkinliğe Genel Bakış"
playtime: "Oyun Süresi"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Pluginler"
pluginsOverview: "Plugins Overview"
punchcard: "Punchcard"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Trend"
trends30days: "30 günlük trendler"
uninstalled: "Uninstalled"
uniquePlayers: "Sunucuya İlk Defa Girenler"
uniquePlayers7days: "Unique Players (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "Çok Aktif"
weekComparison: "Hafta Karşılaştırması"
weekdays: "'Pazartesi', 'Salı', 'Çarşamba', 'Perşembe', 'Cuma', 'Cumartesi', 'Pazar'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "Використання ЦП"
currentPlayerbase: "Поточна база гравців"
currentUptime: "Час безвідмовної роботи"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "Статистика за днями"
dayOfweek: "День тижня"
deadliestWeapon: "Найсмертоносніша зброя в PvP"
@ -418,6 +419,7 @@ html:
information: "Інформація"
insights: "Інсайти"
insights30days: "Статистика за 30 днів"
installed: "Installed"
irregular: "Нерегулярний"
joinAddress: "Адреса входу"
joinAddresses: "Адреси входу"
@ -469,6 +471,7 @@ html:
mobDeaths: "Смерть через мобів"
mobKdr: "Моб KDR"
mobKills: "Вбивства мобів"
modified: "Modified"
mostActiveGamemode: "Найактивніший ігровий режим"
mostPlayedWorld: "Найпопулярніший світ"
name: "Ім'я"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "Гравці онлайн (зараз)"
playersOnlineOverview: "Огляд мережевої активності"
playtime: "Час гри"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "Плагіни"
pluginsOverview: "Огляд плагінів"
punchcard: "Перфокарти"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "Тенденція"
trends30days: "Тенденція за 30 днів"
uninstalled: "Uninstalled"
uniquePlayers: "Унікальні гравці"
uniquePlayers7days: "Унікальні гравці (7 днів)"
unit:
percentage: "Відсоток"
playerCount: "Кількість гравців"
users: "Manage Users"
version: "Version"
veryActive: "Дуже активний"
weekComparison: "Порівняння за тиждень"
weekdays: "'Понеділок', 'Вівторок', 'Середа', 'Четвер', 'П`ятниця', 'Субота', 'Неділя'"

View File

@ -325,6 +325,7 @@ html:
cpuUsage: "CPU 使用率"
currentPlayerbase: "目前玩家數量"
currentUptime: "Current Uptime"
currentlyInstalledPlugins: "Currently Installed Plugins"
dayByDay: "按天查看"
dayOfweek: "星期"
deadliestWeapon: "最致命的 PvP 武器"
@ -418,6 +419,7 @@ html:
information: "訊息"
insights: "Insights"
insights30days: "30 天分析"
installed: "Installed"
irregular: "偶爾上線"
joinAddress: "Join Address"
joinAddresses: "加入位址"
@ -469,6 +471,7 @@ html:
mobDeaths: "被生物擊殺數"
mobKdr: "生物 KDR"
mobKills: "生物擊殺數"
modified: "Modified"
mostActiveGamemode: "最常玩的遊戲模式"
mostPlayedWorld: "玩的最多的世界"
name: "名稱"
@ -512,6 +515,8 @@ html:
playersOnlineNow: "線上玩家 (Now)"
playersOnlineOverview: "線上活動概覽"
playtime: "遊玩時間"
pluginHistory: "Plugin History"
pluginVersionHistory: "Plugin Version History"
plugins: "插件"
pluginsOverview: "插件概覽"
punchcard: "打卡"
@ -599,12 +604,14 @@ html:
tps: "TPS"
trend: "趨勢"
trends30days: "30 天趨勢"
uninstalled: "Uninstalled"
uniquePlayers: "獨立玩家"
uniquePlayers7days: "獨立玩家 (7 days)"
unit:
percentage: "Percentage"
playerCount: "Player Count"
users: "Manage Users"
version: "Version"
veryActive: "非常活躍"
weekComparison: "每週對比"
weekdays: "'星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'"

View File

@ -19,7 +19,7 @@
"@testing-library/jest-dom": "^6.1.3",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.5.1",
"axios": "^1.5.0",
"axios": "^1.5.1",
"bootstrap": "^5.3.2",
"highcharts": "^10.3.3",
"i18next": "^23.5.1",
@ -29,16 +29,16 @@
"masonry-layout": "^4.2.2",
"moment": "^2.29.4",
"react": "^18.2.0",
"react-bootstrap": "^2.8.0",
"react-bootstrap": "^2.9.0",
"react-bootstrap-range-slider": "^3.0.8",
"react-dom": "^18.2.0",
"react-i18next": "^13.2.2",
"react-mcjsonchat": "^1.0.0",
"react-router-dom": "6",
"react-scripts": "5.0.1",
"sass": "^1.68.0",
"sass": "^1.69.0",
"source-map-explorer": "^2.5.2",
"swagger-ui": "^5.7.2",
"swagger-ui": "^5.9.0",
"web-vitals": "^3.0.2"
},
"scripts": {

View File

@ -36,6 +36,7 @@ const PlayerbaseOverview = React.lazy(() => import("./views/server/PlayerbaseOve
const ServerPlayers = React.lazy(() => import("./views/server/ServerPlayers"));
const ServerGeolocations = React.lazy(() => import("./views/server/ServerGeolocations"));
const ServerPerformance = React.lazy(() => import("./views/server/ServerPerformance"));
const ServerPluginHistory = React.lazy(() => import('./views/server/ServerPluginHistory'));
const ServerPluginData = React.lazy(() => import("./views/server/ServerPluginData"));
const ServerWidePluginData = React.lazy(() => import("./views/server/ServerWidePluginData"));
const ServerJoinAddresses = React.lazy(() => import("./views/server/ServerJoinAddresses"));
@ -50,6 +51,7 @@ const NetworkPlayerRetention = React.lazy(() => import("./views/network/NetworkP
const NetworkGeolocations = React.lazy(() => import("./views/network/NetworkGeolocations"));
const NetworkPlayerbaseOverview = React.lazy(() => import("./views/network/NetworkPlayerbaseOverview"));
const NetworkPerformance = React.lazy(() => import("./views/network/NetworkPerformance"));
const NetworkPluginHistory = React.lazy(() => import('./views/network/NetworkPluginHistory'));
const PlayersPage = React.lazy(() => import("./views/layout/PlayersPage"));
const AllPlayers = React.lazy(() => import("./views/players/AllPlayers"));
@ -163,6 +165,7 @@ function App() {
<Route path="players" element={<Lazy><ServerPlayers/></Lazy>}/>
<Route path="geolocations" element={<Lazy><ServerGeolocations/></Lazy>}/>
<Route path="performance" element={<Lazy><ServerPerformance/></Lazy>}/>
<Route path="plugin-history" element={<Lazy><ServerPluginHistory/></Lazy>}/>
<Route path="plugins-overview" element={<Lazy><ServerPluginData/></Lazy>}/>
<Route path="plugins/:plugin" element={<Lazy><ServerWidePluginData/></Lazy>}/>
<Route path="*" element={<ErrorView error={{
@ -183,6 +186,7 @@ function App() {
<Route path="join-addresses" element={<Lazy><NetworkJoinAddresses/></Lazy>}/>
<Route path="players" element={<Lazy><AllPlayers/></Lazy>}/>
<Route path="geolocations" element={<Lazy><NetworkGeolocations/></Lazy>}/>
<Route path="plugin-history" element={<Lazy><NetworkPluginHistory/></Lazy>}/>
<Route path="plugins-overview" element={<Lazy><ServerPluginData/></Lazy>}/>
<Route path="plugins/:plugin" element={<Lazy><ServerWidePluginData/></Lazy>}/>
<Route path="*" element={<ErrorView error={{

View File

@ -2,11 +2,12 @@ import React, {useEffect, useState} from "react";
import {useLocation, useNavigate} from "react-router-dom";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
const TabButton = ({id, name, href, icon, color, active}) => {
const TabButton = ({id, name, href, icon, color, active, disabled}) => {
const navigate = useNavigate();
return (
<li className="nav-item" id={id}>
<button className={"nav-link col-black" + (active ? ' active' : '')} aria-selected={active} role="tab"
<li className={"nav-item" + (disabled ? ' disabled' : '')} id={id}>
<button disabled={disabled} className={"nav-link col-black" + (active ? ' active' : '')}
aria-selected={active} role="tab"
onClick={() => navigate('#' + href, {replace: true})}>
<Fa icon={icon} className={'col-' + color}/> {name}
</button>
@ -26,6 +27,7 @@ const TabButtons = ({tabs, selectedTab}) => {
icon={tab.icon}
color={tab.color}
active={tab.href === selectedTab}
disabled={tab.disabled}
/>
))}
</ul>

View File

@ -0,0 +1,68 @@
import React from 'react';
import CardHeader from "../CardHeader";
import {faCube, faCubes, faSignal} from "@fortawesome/free-solid-svg-icons";
import {Card} from "react-bootstrap";
import {ErrorViewCard} from "../../../views/ErrorView";
import FormattedDate from "../../text/FormattedDate";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faCalendar} from "@fortawesome/free-regular-svg-icons";
import {useTranslation} from "react-i18next";
import {CardLoader} from "../../navigation/Loader";
import DataTablesTable from "../../table/DataTablesTable";
const PluginCurrentCard = ({data, loadingError}) => {
const {t} = useTranslation();
if (loadingError) return <ErrorViewCard error={loadingError}/>;
if (!data) return <CardLoader/>;
const history = [];
for (const entry of data.history) {
if (history.find(e => e.name === entry.name)) continue;
history.push(entry);
}
const table = {
columns: [{
title: <><Fa icon={faCube}/> {t('html.label.name')}</>,
data: "name"
}, {
title: <><Fa icon={faSignal}/> {t('html.label.version')}</>,
data: "version"
}, {
title: <><Fa icon={faCalendar}/> {t('html.label.modified')}</>,
data: {_: "modified", display: "modifiedDisplay"}
}],
data: history.length ? history.filter(entry => entry.version)
.map(entry => {
return {
name: entry.name,
version: t(entry.version),
modified: entry.modified,
modifiedDisplay: <FormattedDate date={entry.modified}/>
}
}) : [{name: t('generic.noData'), version: '', 'modified': 0, modifiedDisplay: ''}]
};
const options = {
responsive: true,
deferRender: true,
columns: table.columns,
data: table.data,
pagingType: "numbers",
order: [[0, "desc"]]
}
const rowKeyFunction = (row, column) => {
return row.name + "-" + row.version + '-' + row.modified + '-' + JSON.stringify(column?.data);
}
return (
<Card>
<CardHeader icon={faCubes} label={'html.label.currentlyInstalledPlugins'} color={"indigo"}/>
<DataTablesTable id={"plugin-current"} options={options} rowKeyFunction={rowKeyFunction}/>
</Card>
)
};
export default PluginCurrentCard

View File

@ -0,0 +1,62 @@
import React from 'react';
import CardHeader from "../CardHeader";
import {faCodeCompare, faCube, faSignal} from "@fortawesome/free-solid-svg-icons";
import {Card} from "react-bootstrap";
import {ErrorViewCard} from "../../../views/ErrorView";
import FormattedDate from "../../text/FormattedDate";
import {FontAwesomeIcon as Fa} from "@fortawesome/react-fontawesome";
import {faCalendar} from "@fortawesome/free-regular-svg-icons";
import {useTranslation} from "react-i18next";
import {CardLoader} from "../../navigation/Loader";
import DataTablesTable from "../../table/DataTablesTable";
const PluginHistoryCard = ({data, loadingError}) => {
const {t} = useTranslation();
if (loadingError) return <ErrorViewCard error={loadingError}/>;
if (!data) return <CardLoader/>;
const history = data.history;
const table = {
columns: [{
title: <><Fa icon={faCube}/> {t('html.label.name')}</>,
data: "name"
}, {
title: <><Fa icon={faSignal}/> {t('html.label.version')}</>,
data: "version"
}, {
title: <><Fa icon={faCalendar}/> {t('html.label.modified')}</>,
data: {_: "modified", display: "modifiedDisplay"}
}],
data: history.length ? history.map(entry => {
return {
name: entry.name,
version: t(entry.version || 'html.label.uninstalled'),
modified: entry.modified,
modifiedDisplay: <FormattedDate date={entry.modified}/>
}
}) : [{name: t('generic.noData'), version: '', 'modified': 0, modifiedDisplay: ''}]
};
const options = {
responsive: true,
deferRender: true,
columns: table.columns,
data: table.data,
pagingType: "numbers",
order: [[2, "desc"]]
}
const rowKeyFunction = (row, column) => {
return row.name + "-" + row.version + '-' + row.modified + '-' + JSON.stringify(column?.data);
}
return (
<Card>
<CardHeader icon={faCodeCompare} label={'html.label.pluginVersionHistory'} color={"indigo"}/>
<DataTablesTable id={"plugin-history"} options={options} rowKeyFunction={rowKeyFunction}/>
</Card>
)
};
export default PluginHistoryCard

View File

@ -153,13 +153,16 @@ const PerformanceGraphsCard = ({data}) => {
setPerformanceSeries(series);
}, [data, setPerformanceSeries])
const dataIncludesGameServers = useMemo(() => data.servers && Boolean(data.servers.filter(server => !server.proxy).length), [data]);
const tabs = useMemo(() => [
{
name: t('html.label.playersOnline'), icon: faUser, color: 'light-blue', href: 'players-online',
element: <Tab data={performanceSeries.players} yAxis={yAxisConfigurations.PLAYERS_ONLINE}/>
}, {
name: t('html.label.tps'), icon: faTachometerAlt, color: 'red', href: 'tps',
element: <Tab data={performanceSeries.tps} yAxis={yAxisConfigurations.TPS}/>
element: <Tab data={performanceSeries.tps} yAxis={yAxisConfigurations.TPS}/>,
disabled: !dataIncludesGameServers
}, {
name: t('html.label.cpu'), icon: faTachometerAlt, color: 'amber', href: 'cpu',
element: <Tab data={performanceSeries.cpu} yAxis={yAxisConfigurations.CPU}/>
@ -168,10 +171,12 @@ const PerformanceGraphsCard = ({data}) => {
element: <Tab data={performanceSeries.ram} yAxis={yAxisConfigurations.RAM_OR_DISK}/>
}, {
name: t('html.label.entities'), icon: faDragon, color: 'purple', href: 'entities',
element: <Tab data={performanceSeries.entities} yAxis={yAxisConfigurations.ENTITIES}/>
element: <Tab data={performanceSeries.entities} yAxis={yAxisConfigurations.ENTITIES}/>,
disabled: !dataIncludesGameServers
}, {
name: t('html.label.loadedChunks'), icon: faMap, color: 'blue-grey', href: 'chunks',
element: <Tab data={performanceSeries.chunks} yAxis={yAxisConfigurations.CHUNKS}/>
element: <Tab data={performanceSeries.chunks} yAxis={yAxisConfigurations.CHUNKS}/>,
disabled: !dataIncludesGameServers
}, {
name: t('html.label.diskSpace'), icon: faHdd, color: 'green', href: 'disk',
element: <Tab data={performanceSeries.disk} yAxis={yAxisConfigurations.RAM_OR_DISK}/>
@ -180,7 +185,7 @@ const PerformanceGraphsCard = ({data}) => {
element: networkMetadata ? <PingTab identifier={networkMetadata.currentServer.serverUUID}/> :
<ChartLoader/>
},
], [performanceSeries, networkMetadata, t]);
], [performanceSeries, networkMetadata, t, dataIncludesGameServers]);
if (!data || !Object.values(data).length) return <CardLoader/>
if (data.errors.length) {

View File

@ -1,6 +1,6 @@
import {useParams} from "react-router-dom";
import {useDataRequest} from "../../../../hooks/dataFetchHook";
import {fetchOptimizedPerformance, fetchPingGraph} from "../../../../service/serverService";
import {fetchOptimizedPerformance, fetchPingGraph, fetchPluginHistory} from "../../../../service/serverService";
import {ErrorViewBody} from "../../../../views/ErrorView";
import {useTranslation} from "react-i18next";
import {Card} from "react-bootstrap";
@ -15,40 +15,46 @@ import WorldPerformanceGraph from "../../../graphs/performance/WorldPerformanceG
import DiskPerformanceGraph from "../../../graphs/performance/DiskPerformanceGraph";
import PingGraph from "../../../graphs/performance/PingGraph";
import {mapPerformanceDataToSeries} from "../../../../util/graphs";
import {useAuth} from "../../../../hooks/authenticationHook";
const AllGraphTab = ({data, dataSeries, loadingError}) => {
const AllGraphTab = ({data, dataSeries, pluginHistorySeries, loadingError}) => {
if (loadingError) return <ErrorViewBody error={loadingError}/>
if (!dataSeries) return <ChartLoader style={{height: "450px"}}/>;
return <AllPerformanceGraph id="server-performance-all-chart" data={data} dataSeries={dataSeries}/>
return <AllPerformanceGraph id="server-performance-all-chart" data={data} dataSeries={dataSeries}
pluginHistorySeries={pluginHistorySeries}/>
}
const TpsGraphTab = ({data, dataSeries, loadingError}) => {
const TpsGraphTab = ({data, dataSeries, pluginHistorySeries, loadingError}) => {
if (loadingError) return <ErrorViewBody error={loadingError}/>
if (!dataSeries) return <ChartLoader style={{height: "450px"}}/>;
return <TpsPerformanceGraph id="server-performance-tps-chart" data={data} dataSeries={dataSeries}/>
return <TpsPerformanceGraph id="server-performance-tps-chart" data={data} dataSeries={dataSeries}
pluginHistorySeries={pluginHistorySeries}/>
}
const CpuRamGraphTab = ({data, dataSeries, loadingError}) => {
const CpuRamGraphTab = ({data, dataSeries, pluginHistorySeries, loadingError}) => {
if (loadingError) return <ErrorViewBody error={loadingError}/>
if (!dataSeries) return <ChartLoader style={{height: "450px"}}/>;
return <CpuRamPerformanceGraph id="server-performance-cpuram-chart" data={data} dataSeries={dataSeries}/>
return <CpuRamPerformanceGraph id="server-performance-cpuram-chart" data={data} dataSeries={dataSeries}
pluginHistorySeries={pluginHistorySeries}/>
}
const WorldGraphTab = ({data, dataSeries, loadingError}) => {
const WorldGraphTab = ({data, dataSeries, pluginHistorySeries, loadingError}) => {
if (loadingError) return <ErrorViewBody error={loadingError}/>
if (!dataSeries) return <ChartLoader style={{height: "450px"}}/>;
return <WorldPerformanceGraph id="server-performance-world-chart" data={data} dataSeries={dataSeries}/>
return <WorldPerformanceGraph id="server-performance-world-chart" data={data} dataSeries={dataSeries}
pluginHistorySeries={pluginHistorySeries}/>
}
const DiskGraphTab = ({data, dataSeries, loadingError}) => {
const DiskGraphTab = ({data, dataSeries, pluginHistorySeries, loadingError}) => {
if (loadingError) return <ErrorViewBody error={loadingError}/>
if (!dataSeries) return <ChartLoader style={{height: "450px"}}/>;
return <DiskPerformanceGraph id="server-performance-disk-chart" data={data} dataSeries={dataSeries}/>
return <DiskPerformanceGraph id="server-performance-disk-chart" data={data} dataSeries={dataSeries}
pluginHistorySeries={pluginHistorySeries}/>
}
const PingGraphTab = ({identifier}) => {
@ -61,37 +67,79 @@ const PingGraphTab = ({identifier}) => {
const PerformanceGraphsCard = () => {
const {t} = useTranslation();
const {authRequired, hasPermission} = useAuth();
const {identifier} = useParams();
const {data, loadingError} = useDataRequest(fetchOptimizedPerformance, [identifier]);
const [parsedData, setParsedData] = useState(undefined)
const [parsedData, setParsedData] = useState(undefined);
const {
data: pluginHistory,
loadingError: pluginHistoryLoadingError
} = useDataRequest(fetchPluginHistory, [identifier], authRequired && hasPermission('page.server.plugin.history'));
const [pluginHistorySeries, setPluginHistorySeries] = useState({});
useEffect(() => {
if (data) {
mapPerformanceDataToSeries(data.values).then(parsed => setParsedData(parsed))
}
}, [data, setParsedData]);
useEffect(() => {
// https://stackoverflow.com/a/34890276/20825073
const groupBy = function (xs, key) {
return xs.reduce(function (rv, x) {
(rv[x[key]] = rv[x[key]] || []).push(x);
return rv;
}, {});
};
if (pluginHistory) {
const grouped = groupBy(pluginHistory.history.reverse(), 'modified');
setPluginHistorySeries({
type: 'flags',
accessibility: {
exposeAsGroupOnly: true,
description: t('html.label.pluginVersionHistory')
},
tooltip: {headerFormat: ''},
data: Object.entries(grouped).map(entry => {
const installedLines = entry[1].filter(p => p.version).map(plugin => plugin.name + ': ' + plugin.version).join(', <br>');
const uninstalledLines = entry[1].filter(p => !p.version).map(plugin => plugin.name).join(', <br>');
return {
x: entry[0],
title: entry[1].length,
text: (installedLines.length ? '<b>' + t('html.label.installed') + '</b><br>' + installedLines : '') +
(uninstalledLines.length ? '<b>' + t('html.label.uninstalled') + '</b><br>' + uninstalledLines : '')
}
})
})
}
}, [pluginHistory, setPluginHistorySeries, t]);
return <Card id={"performance-graphs"}>
<CardTabs tabs={[
{
name: t('html.label.all'), icon: faGears, color: 'blue-grey', href: 'all',
element: <AllGraphTab data={data} dataSeries={parsedData} loadingError={loadingError}/>
element: <AllGraphTab data={data} dataSeries={parsedData} pluginHistorySeries={pluginHistorySeries}
loadingError={loadingError || pluginHistoryLoadingError}/>
}, {
name: t('html.label.tps'), icon: faTachometerAlt, color: 'red', href: 'tps',
element: <TpsGraphTab data={data} dataSeries={parsedData} loadingError={loadingError}/>
element: <TpsGraphTab data={data} dataSeries={parsedData} pluginHistorySeries={pluginHistorySeries}
loadingError={loadingError || pluginHistoryLoadingError}/>
}, {
name: t('html.label.cpuRam'), icon: faMicrochip, color: 'light-green', href: 'cpu-ram',
element: <CpuRamGraphTab data={data} dataSeries={parsedData} loadingError={loadingError}/>
element: <CpuRamGraphTab data={data} dataSeries={parsedData} pluginHistorySeries={pluginHistorySeries}
loadingError={loadingError || pluginHistoryLoadingError}/>
}, {
name: t('html.label.world'), icon: faMap, color: 'purple', href: 'world-load',
element: <WorldGraphTab data={data} dataSeries={parsedData} loadingError={loadingError}/>
element: <WorldGraphTab data={data} dataSeries={parsedData} pluginHistorySeries={pluginHistorySeries}
loadingError={loadingError || pluginHistoryLoadingError}/>
}, {
name: t('html.label.ping'), icon: faSignal, color: 'amber', href: 'ping',
element: <PingGraphTab identifier={identifier}/>
}, {
name: t('html.label.diskSpace'), icon: faHdd, color: 'green', href: 'disk',
element: <DiskGraphTab data={data} dataSeries={parsedData} loadingError={loadingError}/>
element: <DiskGraphTab data={data} dataSeries={parsedData} pluginHistorySeries={pluginHistorySeries}
loadingError={loadingError || pluginHistoryLoadingError}/>
},
]}/>
</Card>

View File

@ -1,9 +1,10 @@
import React from 'react';
import PerformanceAsNumbersTable from "../../../table/PerformanceAsNumbersTable";
import CardHeader from "../../CardHeader";
import {faBookOpen} from "@fortawesome/free-solid-svg-icons";
import {Card} from "react-bootstrap";
import {faBookOpen, faInfoCircle} from "@fortawesome/free-solid-svg-icons";
import {Alert, Card} from "react-bootstrap";
import {useTranslation} from "react-i18next";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
const PerformanceAsNumbersCard = ({data, servers}) => {
const {t} = useTranslation();
@ -15,11 +16,15 @@ const PerformanceAsNumbersCard = ({data, servers}) => {
: (noData7d ? <p className={"alert alert-warning mb-0"}>{t('html.description.noData7d')}</p>
: (noData24h ? <p className={"alert alert-warning mb-0"}>{t('html.description.noData24h')}</p>
: ''));
const dataIncludesGameServers = !servers || Boolean(servers.filter(server => !server.proxy).length);
return (
<Card id={"performance-as-numbers"}>
<CardHeader icon={faBookOpen} color="blue-grey" label={"html.label.performanceAsNumbers"}/>
{noDataAlert}
{!dataIncludesGameServers && <Alert className='alert-warning mb-0'>
<FontAwesomeIcon icon={faInfoCircle}/> {t('html.description.performanceNoGameServers')}
</Alert>}
<PerformanceAsNumbersTable data={data} servers={servers}/>
</Card>
)

View File

@ -62,7 +62,7 @@ const yAxis = [
}
]
const AllPerformanceGraph = ({id, data, dataSeries}) => {
const AllPerformanceGraph = ({id, data, dataSeries, pluginHistorySeries}) => {
const {t} = useTranslation();
const {graphTheming, nightModeEnabled} = useTheme();
const {timeZoneOffsetMinutes} = useMetadata();
@ -178,9 +178,9 @@ const AllPerformanceGraph = ({id, data, dataSeries}) => {
time: {
timezoneOffset: timeZoneOffsetMinutes
},
series: [series.playersOnline, series.tps, series.cpu, series.ram, series.entities, series.chunks]
series: [series.playersOnline, series.tps, series.cpu, series.ram, series.entities, series.chunks, pluginHistorySeries]
});
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes])
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes, pluginHistorySeries])
return (
<div className="chart-area" style={{height: "450px"}} id={id}>

View File

@ -9,7 +9,7 @@ import {withReducedSaturation} from "../../../util/colors";
import Accessibility from "highcharts/modules/accessibility";
import {useMetadata} from "../../../hooks/metadataHook";
const CpuRamPerformanceGraph = ({id, data, dataSeries}) => {
const CpuRamPerformanceGraph = ({id, data, dataSeries, pluginHistorySeries}) => {
const {t} = useTranslation();
const {graphTheming, nightModeEnabled} = useTheme();
const {timeZoneOffsetMinutes} = useMetadata();
@ -90,9 +90,9 @@ const CpuRamPerformanceGraph = ({id, data, dataSeries}) => {
time: {
timezoneOffset: timeZoneOffsetMinutes
},
series: [series.playersOnline, series.cpu, series.ram]
series: [series.playersOnline, series.cpu, series.ram, pluginHistorySeries]
});
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes])
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes, pluginHistorySeries])
return (
<div className="chart-area" style={{height: "450px"}} id={id}>

View File

@ -9,7 +9,7 @@ import {withReducedSaturation} from "../../../util/colors";
import Accessibility from "highcharts/modules/accessibility";
import {useMetadata} from "../../../hooks/metadataHook";
const DiskPerformanceGraph = ({id, data, dataSeries}) => {
const DiskPerformanceGraph = ({id, data, dataSeries, pluginHistorySeries}) => {
const {t} = useTranslation();
const {graphTheming, nightModeEnabled} = useTheme();
const {timeZoneOffsetMinutes} = useMetadata();
@ -71,9 +71,9 @@ const DiskPerformanceGraph = ({id, data, dataSeries}) => {
time: {
timezoneOffset: timeZoneOffsetMinutes
},
series: [series.disk]
series: [series.disk, pluginHistorySeries]
});
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes])
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes, pluginHistorySeries])
return (
<div className="chart-area" style={{height: "450px"}} id={id}>

View File

@ -9,7 +9,7 @@ import {withReducedSaturation} from "../../../util/colors";
import Accessibility from "highcharts/modules/accessibility";
import {useMetadata} from "../../../hooks/metadataHook";
const TpsPerformanceGraph = ({id, data, dataSeries}) => {
const TpsPerformanceGraph = ({id, data, dataSeries, pluginHistorySeries}) => {
const {t} = useTranslation();
const {graphTheming, nightModeEnabled} = useTheme();
const {timeZoneOffsetMinutes} = useMetadata();
@ -87,9 +87,9 @@ const TpsPerformanceGraph = ({id, data, dataSeries}) => {
time: {
timezoneOffset: timeZoneOffsetMinutes
},
series: [series.playersOnline, series.tps]
series: [series.playersOnline, series.tps, pluginHistorySeries]
});
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes])
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes, pluginHistorySeries])
return (
<div className="chart-area" style={{height: "450px"}} id={id}>

View File

@ -9,7 +9,7 @@ import {withReducedSaturation} from "../../../util/colors";
import Accessibility from "highcharts/modules/accessibility";
import {useMetadata} from "../../../hooks/metadataHook";
const WorldPerformanceGraph = ({id, data, dataSeries}) => {
const WorldPerformanceGraph = ({id, data, dataSeries, pluginHistorySeries}) => {
const {t} = useTranslation();
const {graphTheming, nightModeEnabled} = useTheme();
const {timeZoneOffsetMinutes} = useMetadata();
@ -89,9 +89,9 @@ const WorldPerformanceGraph = ({id, data, dataSeries}) => {
time: {
timezoneOffset: timeZoneOffsetMinutes
},
series: [series.playersOnline, series.entities, series.chunks]
series: [series.playersOnline, series.entities, series.chunks, pluginHistorySeries]
});
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes])
}, [data, dataSeries, graphTheming, nightModeEnabled, id, t, timeZoneOffsetMinutes, pluginHistorySeries])
return (
<div className="chart-area" style={{height: "450px"}} id={id}>

View File

@ -332,4 +332,10 @@ const fetchNetworkPlayerJoinAddresses = async (timestamp) => {
let url = `/v1/joinAddresses`;
if (staticSite) url = `/data/joinAddresses.json`;
return doGetRequest(url, timestamp);
}
export const fetchPluginHistory = async (timestamp, identifier) => {
let url = `/v1/pluginHistory?server=${identifier}`;
if (staticSite) url = `/data/pluginHistory-${identifier}.json`;
return doGetRequest(url, timestamp);
}

View File

@ -1495,4 +1495,8 @@ ul.filters {
.group-help i {
color: var(--color-plan)
}
.nav-item.disabled {
opacity: 30%;
}

View File

@ -4,6 +4,7 @@ import {Outlet} from "react-router-dom";
import {useNavigation} from "../../hooks/navigationHook";
import {
faChartLine,
faCodeCompare,
faCogs,
faCubes,
faGlobe,
@ -32,13 +33,14 @@ const HelpModal = React.lazy(() => import("../../components/modal/HelpModal"));
const NetworkSidebar = () => {
const {t, i18n} = useTranslation();
const {authRequired} = useAuth();
const {sidebarItems, setSidebarItems} = useNavigation();
const {networkMetadata} = useMetadata();
const {extensionData} = useServerExtensionContext();
useEffect(() => {
const servers = networkMetadata?.servers || [];
const items = [
let items = [
{
name: 'html.label.networkOverview',
icon: faInfoCircle,
@ -119,6 +121,13 @@ const NetworkSidebar = () => {
},
{},
{name: 'html.label.plugins', permission: 'page.network.plugins'},
{
name: 'html.label.pluginHistory',
icon: faCodeCompare,
href: "plugin-history",
permission: 'page.network.plugin.history',
authRequired: true
},
{
name: 'html.label.pluginsOverview',
icon: faCubes,
@ -147,10 +156,13 @@ const NetworkSidebar = () => {
{name: 'html.label.query', icon: faSearch, href: "/query", permission: 'access.query'}
);
}
// Filter out items that need authentication
items = items
.filter(item => !item.authRequired || (authRequired && item.authRequired))
setSidebarItems(items);
window.document.title = `Plan | Network`;
}, [t, i18n, extensionData, setSidebarItems, networkMetadata])
}, [t, i18n, extensionData, setSidebarItems, networkMetadata, authRequired])
return (
<Sidebar items={sidebarItems}/>

View File

@ -6,6 +6,7 @@ import {
faCampground,
faChartArea,
faChartLine,
faCodeCompare,
faCogs,
faCubes,
faGlobe,
@ -35,11 +36,12 @@ const HelpModal = React.lazy(() => import("../../components/modal/HelpModal"));
const ServerSidebar = () => {
const {t, i18n} = useTranslation();
const {authRequired} = useAuth();
const {sidebarItems, setSidebarItems} = useNavigation();
const {extensionData} = useServerExtensionContext();
useEffect(() => {
const items = [
let items = [
{
name: 'html.label.serverOverview',
icon: faInfoCircle,
@ -113,6 +115,13 @@ const ServerSidebar = () => {
{name: 'html.label.performance', icon: faCogs, href: "performance", permission: 'page.server.performance'},
{},
{name: 'html.label.plugins', permission: 'page.server.plugins'},
{
name: 'html.label.pluginHistory',
icon: faCodeCompare,
href: "plugin-history",
permission: 'page.server.plugin.history',
authRequired: true
},
{
name: 'html.label.pluginsOverview',
icon: faCubes,
@ -142,9 +151,12 @@ const ServerSidebar = () => {
);
}
// Filter out items that need authentication
items = items
.filter(item => !item.authRequired || (authRequired && item.authRequired))
setSidebarItems(items);
window.document.title = `Plan | Server Analysis`;
}, [t, i18n, extensionData, setSidebarItems])
}, [t, i18n, extensionData, setSidebarItems, authRequired])
return (
<Sidebar items={sidebarItems}/>

View File

@ -0,0 +1,72 @@
import {Col, InputGroup} from "react-bootstrap";
import React, {useEffect, useState} from "react";
import LoadIn from "../../components/animation/LoadIn";
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
import {useAuth} from "../../hooks/authenticationHook";
import PluginHistoryCard from "../../components/cards/common/PluginHistoryCard";
import {useDataRequest} from "../../hooks/dataFetchHook";
import {fetchPluginHistory} from "../../service/serverService";
import PluginCurrentCard from "../../components/cards/common/PluginCurrentCard";
import {useMetadata} from "../../hooks/metadataHook";
import Select from "../../components/input/Select";
import {useTranslation} from "react-i18next";
import InputGroupText from "react-bootstrap/InputGroupText";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faServer} from "@fortawesome/free-solid-svg-icons";
const NetworkPluginHistory = () => {
const {t} = useTranslation();
const {authRequired, hasPermission} = useAuth();
const seeHistory = authRequired && hasPermission('page.network.plugin.history');
const {networkMetadata} = useMetadata();
const [serverOptions, setServerOptions] = useState([]);
const [selectedOption, setSelectedOption] = useState(0);
const [identifier, setIdentifier] = useState(undefined);
useEffect(() => {
if (networkMetadata) {
const options = networkMetadata.servers;
setServerOptions(options);
const indexOfProxy = options
.findIndex(option => option.serverName === networkMetadata.currentServer.serverName);
setSelectedOption(indexOfProxy);
}
}, [networkMetadata, setSelectedOption, setServerOptions]);
useEffect(() => {
if (serverOptions.length) {
setIdentifier(serverOptions[selectedOption].serverUUID);
}
}, [selectedOption, serverOptions])
let {data, loadingError} = useDataRequest(fetchPluginHistory, [identifier], Boolean(identifier) && seeHistory);
if (!identifier) data = {history: []};
return (
<LoadIn>
{seeHistory && <section id="network-plugin-history">
<ExtendableRow id={'row-network-plugin-history-0'}>
<Col md={4} className={"mb-4"}>
<InputGroup>
<InputGroupText><FontAwesomeIcon icon={faServer}/> {t('html.label.serverSelector')}
</InputGroupText>
<Select options={serverOptions.map(server => server.serverName)}
selectedIndex={selectedOption} setSelectedIndex={setSelectedOption}/>
</InputGroup>
</Col>
</ExtendableRow>
<ExtendableRow id={'row-network-plugin-history-1'}>
<Col md={6}>
<PluginCurrentCard data={data} loadingError={loadingError}/>
</Col>
<Col md={6}>
<PluginHistoryCard data={data} loadingError={loadingError}/>
</Col>
</ExtendableRow>
</section>}
</LoadIn>
)
}
export default NetworkPluginHistory;

View File

@ -0,0 +1,34 @@
import {Col} from "react-bootstrap";
import React from "react";
import LoadIn from "../../components/animation/LoadIn";
import {useParams} from "react-router-dom";
import ExtendableRow from "../../components/layout/extension/ExtendableRow";
import {useAuth} from "../../hooks/authenticationHook";
import PluginHistoryCard from "../../components/cards/common/PluginHistoryCard";
import {useDataRequest} from "../../hooks/dataFetchHook";
import {fetchPluginHistory} from "../../service/serverService";
import PluginCurrentCard from "../../components/cards/common/PluginCurrentCard";
const ServerPluginHistory = () => {
const {authRequired, hasPermission} = useAuth();
const {identifier} = useParams();
const seeHistory = authRequired && hasPermission('page.server.plugin.history');
const {data, loadingError} = useDataRequest(fetchPluginHistory, [identifier], seeHistory);
return (
<LoadIn>
{seeHistory && <section id="server-plugin-history">
<ExtendableRow id={'row-server-plugin-history-0'}>
<Col md={6}>
<PluginCurrentCard data={data} loadingError={loadingError}/>
</Col>
<Col md={6}>
<PluginHistoryCard data={data} loadingError={loadingError}/>
</Col>
</ExtendableRow>
</section>}
</LoadIn>
)
}
export default ServerPluginHistory;

View File

@ -1116,22 +1116,15 @@
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
"@babel/runtime-corejs3@^7.20.7", "@babel/runtime-corejs3@^7.22.11", "@babel/runtime-corejs3@^7.22.15":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.22.15.tgz#7aeb9460598a997b0fe74982a5b02fb9e5d264d9"
integrity sha512-SAj8oKi8UogVi6eXQXKNPu8qZ78Yzy7zawrlTr0M+IuW/g8Qe9gVDhGcF9h1S69OyACpYoLxEzpjs1M15sI5wQ==
"@babel/runtime-corejs3@^7.20.7", "@babel/runtime-corejs3@^7.22.15", "@babel/runtime-corejs3@^7.23.1":
version "7.23.1"
resolved "https://registry.yarnpkg.com/@babel/runtime-corejs3/-/runtime-corejs3-7.23.1.tgz#d03f5819f4ba81a21dd1f80edfb19983e9e20fc1"
integrity sha512-OKKfytwoc0tr7cDHwQm0RLVR3y+hDGFz3EPuvLNU/0fOeXJeKNIHj7ffNVFnncWt3sC58uyUCRSzf8nBQbyF6A==
dependencies:
core-js-pure "^3.30.2"
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.8.4":
version "7.22.11"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.11.tgz#7a9ba3bbe406ad6f9e8dd4da2ece453eb23a77a4"
integrity sha512-ee7jVNlWN09+KftVOu9n7S8gQzD/Z6hN/I8VBRXW4P1+Xe7kJGXMwu8vds4aGIMHZnNbdpSWCfZZtinytpcAvA==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.12.1", "@babel/runtime@^7.21.0", "@babel/runtime@^7.21.5", "@babel/runtime@^7.22.15", "@babel/runtime@^7.22.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.1", "@babel/runtime@^7.12.5", "@babel/runtime@^7.16.3", "@babel/runtime@^7.20.7", "@babel/runtime@^7.21.0", "@babel/runtime@^7.21.5", "@babel/runtime@^7.22.15", "@babel/runtime@^7.22.5", "@babel/runtime@^7.3.1", "@babel/runtime@^7.5.5", "@babel/runtime@^7.6.3", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.22.15"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.22.15.tgz#38f46494ccf6cf020bd4eed7124b425e83e523b8"
integrity sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==
@ -1751,10 +1744,10 @@
dependencies:
"@swc/helpers" "^0.4.14"
"@remix-run/router@1.8.0":
version "1.8.0"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.8.0.tgz#e848d2f669f601544df15ce2a313955e4bf0bafc"
integrity sha512-mrfKqIHnSZRyIzBcanNJmVQELTnX+qagEDlcKO90RgRBVOZGSGvZKeDihTRfWcqoDn5N/NkUcwWTccnpN18Tfg==
"@remix-run/router@1.9.0":
version "1.9.0"
resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.9.0.tgz#9033238b41c4cbe1e961eccb3f79e2c588328cf6"
integrity sha512-bV63itrKBC0zdT27qYm6SDZHlkXwFL1xMBuhkn+X7l0+IIhNaH5wuuvZKp6eKhCD4KFhujhfhCT1YxXW6esUIA==
"@restart/hooks@^0.4.9":
version "0.4.9"
@ -1763,10 +1756,10 @@
dependencies:
dequal "^2.0.2"
"@restart/ui@^1.6.3":
version "1.6.3"
resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.6.3.tgz#8063f5b5e0131d41db2cefe148b20cb08a208e76"
integrity sha512-7HM5aiSWvJBWr+FghZj/n3PSuH2kUrOPiu/D92aIv1zTL8IBwFoQ3oz/f76svoN5v2PKaP6pQbg6vTcIiSffzg==
"@restart/ui@^1.6.6":
version "1.6.6"
resolved "https://registry.yarnpkg.com/@restart/ui/-/ui-1.6.6.tgz#3481e2eaf15d7cae55bb2f518624e10d19c75800"
integrity sha512-eC3puKuWE1SRYbojWHXnvCNHGgf3uzHCb6JOhnF4OXPibOIPEkR1sqDSkL643ydigxwh+ruCa1CmYHlzk7ikKA==
dependencies:
"@babel/runtime" "^7.21.0"
"@popperjs/core" "^2.11.6"
@ -1775,7 +1768,7 @@
"@types/warning" "^3.0.0"
dequal "^2.0.3"
dom-helpers "^5.2.0"
uncontrollable "^7.2.1"
uncontrollable "^8.0.1"
warning "^4.0.3"
"@rollup/plugin-babel@^5.2.0":
@ -2566,10 +2559,10 @@
dependencies:
"@types/react" "*"
"@types/react-transition-group@^4.4.5":
version "4.4.5"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.5.tgz#aae20dcf773c5aa275d5b9f7cdbca638abc5e416"
integrity sha512-juKD/eiSM3/xZYzjuzH6ZwpP+/lejltmiS3QEzV/vmb/Q8+HfDmxu+Baga8UEMGBqV88Nbg4l2hY/K2DkyaLLA==
"@types/react-transition-group@^4.4.6":
version "4.4.7"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.7.tgz#bf69f269d74aa78b99097673ca6dd6824a68ef1c"
integrity sha512-ICCyBl5mvyqYp8Qeq9B5G/fyBSRC0zx3XM3sCC6KkcMsNeAHqXBKkmat4GqdJET5jtYUpZXrxI5flve5qhi2Eg==
dependencies:
"@types/react" "*"
@ -3261,10 +3254,10 @@ axe-core@^4.6.2:
resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.2.tgz#040a7342b20765cb18bb50b628394c21bccc17a0"
integrity sha512-zIURGIS1E1Q4pcrMjp+nnEh+16G56eG/MUllJH8yEvw7asDo7Ac9uhC9KIH5jzpITueEZolfYglnCGIuSBz39g==
axios@^1.4.0, axios@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.0.tgz#f02e4af823e2e46a9768cfc74691fdd0517ea267"
integrity sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==
axios@^1.4.0, axios@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.5.1.tgz#11fbaa11fc35f431193a9564109c88c1f27b585f"
integrity sha512-Q28iYCWzNHjAm+yEAot5QaAMxhMghWLFVf7rRdwhUI+c2jix2DUXjAHXVi+s1ibs3mjPO/cCgbA++3BjD0vP/A==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
@ -4439,10 +4432,10 @@ domhandler@^4.0.0, domhandler@^4.2.0, domhandler@^4.3.1:
dependencies:
domelementtype "^2.2.0"
dompurify@=3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.5.tgz#eb3d9cfa10037b6e73f32c586682c4b2ab01fbed"
integrity sha512-F9e6wPGtY+8KNMRAVfxeCOHU0/NPWMSENNq4pQctuXRqqdEPW7q3CrLbR5Nse044WwacyjHGOMlvNsBe1y6z9A==
dompurify@=3.0.6:
version "3.0.6"
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-3.0.6.tgz#925ebd576d54a9531b5d76f0a5bef32548351dae"
integrity sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==
domutils@^1.7.0:
version "1.7.0"
@ -8591,15 +8584,15 @@ react-bootstrap-range-slider@^3.0.8:
classnames "^2.3.1"
prop-types "^15.7.2"
react-bootstrap@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.8.0.tgz#781f254b33090c1d50ed521b40697727267c6add"
integrity sha512-e/aNtxl0Z2ozrIaR82jr6Zz7ss9GSoaXpQaxmvtDUsTZIq/XalkduR/ZXP6vbQHz2T4syvjA+4FbtwELxxmpww==
react-bootstrap@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/react-bootstrap/-/react-bootstrap-2.9.0.tgz#10493a3bb7c0429fee886f5571b195ece6c436f0"
integrity sha512-dGh6fGjqR9MBzPOp2KbXJznt1Zy6SWepXYUdxMT18Zu/wJ73HCU8JNZe9dfzjmVssZYsJH9N3HHE4wAtQvNz7g==
dependencies:
"@babel/runtime" "^7.21.0"
"@babel/runtime" "^7.22.5"
"@restart/hooks" "^0.4.9"
"@restart/ui" "^1.6.3"
"@types/react-transition-group" "^4.4.5"
"@restart/ui" "^1.6.6"
"@types/react-transition-group" "^4.4.6"
classnames "^2.3.2"
dom-helpers "^5.2.1"
invariant "^2.2.4"
@ -8745,19 +8738,19 @@ react-refresh@^0.11.0:
integrity sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==
react-router-dom@6:
version "6.15.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.15.0.tgz#6da7db61e56797266fbbef0d5e324d6ac443ee40"
integrity sha512-aR42t0fs7brintwBGAv2+mGlCtgtFQeOzK0BM1/OiqEzRejOZtpMZepvgkscpMUnKb8YO84G7s3LsHnnDNonbQ==
version "6.16.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-6.16.0.tgz#86f24658da35eb66727e75ecbb1a029e33ee39d9"
integrity sha512-aTfBLv3mk/gaKLxgRDUPbPw+s4Y/O+ma3rEN1u8EgEpLpPe6gNjIsWt9rxushMHHMb7mSwxRGdGlGdvmFsyPIg==
dependencies:
"@remix-run/router" "1.8.0"
react-router "6.15.0"
"@remix-run/router" "1.9.0"
react-router "6.16.0"
react-router@6.15.0:
version "6.15.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.15.0.tgz#bf2cb5a4a7ed57f074d4ea88db0d95033f39cac8"
integrity sha512-NIytlzvzLwJkCQj2HLefmeakxxWHWAP+02EGqWEZy+DgfHHKQMUoBBjUQLOtFInBMhWtb3hiUy6MfFgwLjXhqg==
react-router@6.16.0:
version "6.16.0"
resolved "https://registry.yarnpkg.com/react-router/-/react-router-6.16.0.tgz#abbf3d5bdc9c108c9b822a18be10ee004096fb81"
integrity sha512-VT4Mmc4jj5YyjpOi5jOf0I+TYzGpvzERy4ckNSvSh2RArv8LLoCxlsZ2D+tc7zgjxcY34oTz2hZaeX5RVprKqA==
dependencies:
"@remix-run/router" "1.8.0"
"@remix-run/router" "1.9.0"
react-scripts@5.0.1:
version "5.0.1"
@ -9212,10 +9205,10 @@ sass-loader@^12.3.0:
klona "^2.0.4"
neo-async "^2.6.2"
sass@^1.68.0:
version "1.68.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.68.0.tgz#0034b0cc9a50248b7d1702ac166fd25990023669"
integrity sha512-Lmj9lM/fef0nQswm1J2HJcEsBUba4wgNx2fea6yJHODREoMFnwRpZydBnX/RjyXw2REIwdkbqE4hrTo4qfDBUA==
sass@^1.69.0:
version "1.69.0"
resolved "https://registry.yarnpkg.com/sass/-/sass-1.69.0.tgz#5195075371c239ed556280cf2f5944d234f42679"
integrity sha512-l3bbFpfTOGgQZCLU/gvm1lbsQ5mC/WnLz3djL2v4WCJBDrWm58PO+jgngcGRNnKUh6wSsdm50YaovTqskZ0xDQ==
dependencies:
chokidar ">=3.0.0 <4.0.0"
immutable "^4.0.0"
@ -9848,7 +9841,7 @@ svgo@^2.7.0:
picocolors "^1.0.0"
stable "^0.1.8"
swagger-client@^3.22.1:
swagger-client@^3.22.3:
version "3.22.3"
resolved "https://registry.yarnpkg.com/swagger-client/-/swagger-client-3.22.3.tgz#32c27d529ae603ddee91ef17d55f519bd743173a"
integrity sha512-9I3BGD/6LItBzvJoKaRZ+QQ7IcEKq+iVlvvvcfZz65WgnXkORM1uj5+M+Oa5d8Tu5qABuOXd1UnlClBPuTITBA==
@ -9869,18 +9862,18 @@ swagger-client@^3.22.1:
traverse "~0.6.6"
undici "^5.24.0"
swagger-ui@^5.7.2:
version "5.7.2"
resolved "https://registry.yarnpkg.com/swagger-ui/-/swagger-ui-5.7.2.tgz#c9e2e44390ee8823f7282b6d156edd0958519cd5"
integrity sha512-Z8FxNAP+Bpe+SnfXZZUxNSE2mXe171WS3G1KxM3fM/imrMKOX53In7/y+xDoJ5BJaY9b1oxIoSKe66l1oXddOQ==
swagger-ui@^5.9.0:
version "5.9.0"
resolved "https://registry.yarnpkg.com/swagger-ui/-/swagger-ui-5.9.0.tgz#ebefc213d8596eb380fb2bcab9a672dab41d54ee"
integrity sha512-x+FB8V7RtFaXdwWx0dNbI1nqaDCQI1yhJ5Db0obh8Fu3zr832VEXLbMi9hixQCRWv7FcbWy0baQA0x/4oHhqyw==
dependencies:
"@babel/runtime-corejs3" "^7.22.11"
"@babel/runtime-corejs3" "^7.23.1"
"@braintree/sanitize-url" "=6.0.4"
base64-js "^1.5.1"
classnames "^2.3.1"
css.escape "1.5.1"
deep-extend "0.6.0"
dompurify "=3.0.5"
dompurify "=3.0.6"
ieee754 "^1.2.1"
immutable "^3.x.x"
js-file-download "^0.4.12"
@ -9905,7 +9898,7 @@ swagger-ui@^5.7.2:
reselect "^4.1.8"
serialize-error "^8.1.0"
sha.js "^2.4.11"
swagger-client "^3.22.1"
swagger-client "^3.22.3"
url-parse "^1.5.10"
xml "=1.0.1"
xml-but-prettier "^1.0.1"
@ -10317,6 +10310,11 @@ uncontrollable@^7.2.1:
invariant "^2.2.4"
react-lifecycles-compat "^3.0.4"
uncontrollable@^8.0.1:
version "8.0.4"
resolved "https://registry.yarnpkg.com/uncontrollable/-/uncontrollable-8.0.4.tgz#a0a8307f638795162fafd0550f4a1efa0f8c5eb6"
integrity sha512-ulRWYWHvscPFc0QQXvyJjY6LIXU56f0h8pQFvhxiKk5V1fcI8gp9Ht9leVAhrVjzqMw0BgjspBINx9r6oyJUvQ==
undici@^5.24.0:
version "5.25.1"
resolved "https://registry.yarnpkg.com/undici/-/undici-5.25.1.tgz#3fa537eb89a6a0bb576b395f0f7bcdedf7b8336a"