mirror of
https://github.com/4cuck/nitter-status.git
synced 2026-10-26 00:52:25 +00:00
move admin overview and fixup
This commit is contained in:
1 parent
49fd5b14fb
commit
f6622564d2
5 files changed
+144
-113
No files matched your search
+2
-36
@@ -56,6 +56,7 @@ pub use logs::log_view;
|
||||
pub use stats::stats_view;
|
||||
pub use stats::health_csv_api;
|
||||
pub use stats::stats_csv_api;
|
||||
pub use stats::overview_csv_api;
|
||||
|
||||
/// Stored session login information
|
||||
#[derive(Serialize, Deserialize, Default)]
|
||||
@@ -332,7 +333,7 @@ pub async fn overview(
|
||||
context.insert("instances", &hosts);
|
||||
context.insert("is_admin", &login.admin);
|
||||
|
||||
let res = Html(template.render("admin.html.j2", &context)?).into_response();
|
||||
let res = Html(template.render("admin_index.html.j2", &context)?).into_response();
|
||||
drop(guard);
|
||||
res
|
||||
};
|
||||
@@ -367,41 +368,6 @@ pub async fn history_json(
|
||||
.into_response())
|
||||
}
|
||||
|
||||
pub async fn history_json_specific(
|
||||
State(ref db): State<DatabaseConnection>,
|
||||
session: Session,
|
||||
Path(host): Path<i32>,
|
||||
Json(input): Json<DateRangeInput>,
|
||||
) -> Result<axum::response::Response> {
|
||||
let (host, _login) = get_specific_login_host(host, &session, db).await?;
|
||||
#[derive(Debug, Serialize)]
|
||||
struct ReturnData {
|
||||
pub stats: Vec<instance_stats::Model>,
|
||||
pub health: Vec<health_check::Model>,
|
||||
}
|
||||
|
||||
let history_health: Vec<health_check::Model> = health_check::Entity::find()
|
||||
.filter(health_check::Column::Host.eq(host.id))
|
||||
.order_by_asc(health_check::Column::Time)
|
||||
.filter(health_check::Column::Time.between(input.start.timestamp(), input.end.timestamp()))
|
||||
.all(db)
|
||||
.await?;
|
||||
let history_stats: Vec<instance_stats::Model> = instance_stats::Entity::find()
|
||||
.filter(instance_stats::Column::Host.eq(host.id))
|
||||
.order_by_asc(instance_stats::Column::Time)
|
||||
.filter(
|
||||
instance_stats::Column::Time.between(input.start.timestamp(), input.end.timestamp()),
|
||||
)
|
||||
.all(db)
|
||||
.await?;
|
||||
|
||||
Ok(Json(ReturnData {
|
||||
health: history_health,
|
||||
stats: history_stats,
|
||||
})
|
||||
.into_response())
|
||||
}
|
||||
|
||||
pub async fn history_view(
|
||||
State(ref app_state): State<AppState>,
|
||||
State(ref template): State<Arc<tera::Tera>>,
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
document.addEventListener("DOMContentLoaded", function (event) {
|
||||
const startDateInput = document.getElementById('startDate');
|
||||
const endDateInput = document.getElementById('endDate');
|
||||
const submitTime = document.getElementById('submitDateRange');
|
||||
|
||||
// Set initial values in UTC
|
||||
const initialEndDate = moment.utc();
|
||||
const initialStartDate = moment().subtract(30, 'days').utc();
|
||||
startDateInput.value = initialStartDate.format('YYYY-MM-DD');
|
||||
endDateInput.value = initialEndDate.format('YYYY-MM-DD');;
|
||||
|
||||
submitTime.addEventListener('click', function() {
|
||||
const startDate = moment(startDateInput.value, 'YYYY-MM-DD');
|
||||
const endDate = moment(endDateInput.value, 'YYYY-MM-DD');
|
||||
|
||||
if (!startDate.isValid() || !endDate.isValid()) {
|
||||
alert('Invalid date format. Please use the YYYY-MM-DD format.');
|
||||
} else if (startDate.isAfter(endDate)) {
|
||||
alert('Invalid date range. Start date must be before the end date.');
|
||||
} else {
|
||||
fetchDataAndCreateChart(startDate,endDate);
|
||||
}
|
||||
});
|
||||
fetchDataAndCreateChart(initialStartDate,initialEndDate);
|
||||
});
|
||||
|
||||
async function fetchDataAndCreateChart(startDate,endDate) {
|
||||
let graphDiv = document.getElementById('graph-health');
|
||||
try {
|
||||
let g = new Dygraph(
|
||||
graphDiv,
|
||||
"/admin/api/graphs/overview",
|
||||
{
|
||||
title: 'Health Overview Instances',
|
||||
showRangeSelector: true,
|
||||
width: '100%',
|
||||
rangeSelectorPlotFillColor: 'MediumSlateBlue',
|
||||
rangeSelectorPlotFillGradientColor: 'rgba(123, 104, 238, 0)',
|
||||
colorValue: 0.9,
|
||||
fillAlpha: 0.4,
|
||||
drawPoints: true,
|
||||
strokeWidth: 0.0,
|
||||
colors: ['#008000', '#ffa500'],
|
||||
ylabel: 'Nitter Instances',
|
||||
}
|
||||
);
|
||||
g.ready(function () {
|
||||
g.setAnnotations([
|
||||
{
|
||||
series: "Healthy",
|
||||
x: "2023-08-15T07:10:17Z",
|
||||
shortText: "G",
|
||||
text: "First API Change"
|
||||
},
|
||||
{
|
||||
series: "Dead",
|
||||
x: "2023-10-21T14:37:44Z",
|
||||
shortText: "C",
|
||||
text: "Wiki Cleanup"
|
||||
},
|
||||
{
|
||||
series: "Healthy",
|
||||
x: "2024-01-25T15:24:16Z",
|
||||
shortText: "R",
|
||||
text: "API Shutdown"
|
||||
}
|
||||
]);
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch data:', error);
|
||||
graphDiv.textContent = "Failed to load data.";
|
||||
}
|
||||
}
|
||||
@@ -25,24 +25,6 @@ document.addEventListener("DOMContentLoaded", function() {
|
||||
fetchDataAndCreateChart(initialStartDate,initialEndDate);
|
||||
});
|
||||
|
||||
function mapKey(key) {
|
||||
const keyMappings = {
|
||||
"limited_accs": "Limited Accs",
|
||||
"total_accs": "Total Accs",
|
||||
"total_requests": "Total Requests",
|
||||
"req_photo_rail": "PhotoRail Requests",
|
||||
"req_user_screen_name": "UserScreeName Req.",
|
||||
"req_search": "Search Requests",
|
||||
"req_list_tweets": "ListTeweets Req.",
|
||||
"req_user_media": "UserMedia Req.",
|
||||
"req_tweet_detail": "TweetDetail Req.",
|
||||
"req_list": "List Requests",
|
||||
"req_user_tweets": "UserTweets Req.",
|
||||
"req_user_tweets_and_replies": "UserTweetsAndReplies Req.",
|
||||
}
|
||||
return keyMappings[key];
|
||||
}
|
||||
|
||||
async function fetchDataAndCreateChart(startDate,endDate) {
|
||||
let jsonData;
|
||||
try {
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
{# SPDX-License-Identifier: AGPL-3.0-only #}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="/static/bootstrap.min.css" rel="stylesheet">
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="" />
|
||||
<title>Admin Interface</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Admin Interface</h1>
|
||||
<p><a href="/admin/logout">Logout</a> <a href="/admin/login">Add more instances</a></p>
|
||||
{% if is_admin %}<p><a href="/admin/logs">Settings Logs</a></p>{% endif %}
|
||||
|
||||
<h4>Instances</h4>
|
||||
{% if is_admin %}<p class="text-danger-emphasis">root mode</p>{% endif %}
|
||||
<div><canvas id="graph-health" width="600" height="200"></canvas><noscript>History feature works only with javascript enabled.</noscript></div>
|
||||
<div class="container mt-5">
|
||||
<form>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label for="startDate">Start Date:</label>
|
||||
<input type="date" class="form-control" id="startDate" name="startDate">
|
||||
</div>
|
||||
<div class="col">
|
||||
<label for="endDate">End Date:</label>
|
||||
<input type="date" class="form-control" id="endDate" name="endDate">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary mt-1" id="submitDateRange">Change</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table id="status-tbl" class="table sortable table-hover table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Instance</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for instance in instances -%}
|
||||
<tr>
|
||||
<td>{{instance.domain}}</td>
|
||||
<td><a href="/admin/instance/stats/{{instance.id}}">Stats</a></td>
|
||||
<td><a href="/admin/instance/errors/{{instance.id}}">Errors</a> <a href="/admin/instance/settings/{{instance.id}}">Settings</a></td>
|
||||
</tr>
|
||||
{%- endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<script src="/static/moment.min_2.29.4.js"></script>
|
||||
<script src="/static/chart.min_4.4.0.js"></script>
|
||||
<script src="/static/chartjs-adapter-moment_1.0.1.js"></script>
|
||||
<script src="/static/admin.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,69 @@
|
||||
{# SPDX-License-Identifier: AGPL-3.0-only #}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" data-bs-theme="dark">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<link href="/static/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="/static/dygraph.min.css" rel="stylesheet">
|
||||
{% include "dygraph_fix.html.j2" %}
|
||||
<meta name="robots" content="noindex,nofollow" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="author" content="" />
|
||||
<title>Admin Interface</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>Admin Interface</h1>
|
||||
<p><a href="/admin/logout">Logout</a> <a href="/admin/login">Add more instances</a></p>
|
||||
{% if is_admin %}<p><a href="/admin/logs">Settings Logs</a></p>{% endif %}
|
||||
|
||||
<h4>Instances</h4>
|
||||
{% if is_admin %}<p class="text-danger-emphasis">root mode</p>{% endif %}
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div id="graph-health" class="graph" style="height: 400px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<form>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<label for="startDate">Start Date:</label>
|
||||
<input type="date" class="form-control" id="startDate" name="startDate">
|
||||
</div>
|
||||
<div class="col">
|
||||
<label for="endDate">End Date:</label>
|
||||
<input type="date" class="form-control" id="endDate" name="endDate">
|
||||
</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-primary mt-1" id="submitDateRange">Change</button>
|
||||
</form>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table id="status-tbl" class="table sortable table-hover table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Instance</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for instance in instances -%}
|
||||
<tr>
|
||||
<td>{{instance.domain}}</td>
|
||||
<td><a href="/admin/instance/stats/{{instance.id}}">Stats</a></td>
|
||||
<td><a href="/admin/instance/errors/{{instance.id}}">Errors</a> <a
|
||||
href="/admin/instance/settings/{{instance.id}}">Settings</a></td>
|
||||
</tr>
|
||||
{%- endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<script src="/static/moment.min_2.29.4.js"></script>
|
||||
<script src="/static/dygraph.min.js"></script>
|
||||
<script src="/static/admin_index.js"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in new issue
Block a user