divan/DiwanRazor/Areas/User/Pages/MySessions.cshtml
Anas Rashid e8f2306422 Rename Ganjoor -> Diwan throughout the code
Projects (GanjooRazor -> DiwanRazor, GanjoorService.sln -> DiwanService.sln), files,
folders, classes, namespaces, settings, API routes (/api/diwan) and DB tables (Diwan*).
External addresses (ganjoor.net, github.com/ganjoor) unchanged. Migrations renamed
consistently (no pending model changes); requires a fresh database.
Upstream RUNNING_LOCALLY/SEMANTIC_SEARCH docs archived unmodified under docs/.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-04 23:49:01 +02:00

117 lines
5.6 KiB
Plaintext

@page
@model DiwanRazor.Areas.User.Pages.MySessionsModel
@using DNTPersianUtils.Core
@using System.Linq
@{
Layout = "_UserPanelLayout";
ViewData["Title"] = "نشست‌های من";
await DiwanRazor.Utils.DiwanSessionChecker.ApplyPermissionsToViewData(Request, Response, ViewData);
}
<div class="up-page-header">
<h1>@ViewData["Title"]</h1>
<div class="up-page-subtitle">دستگاه‌ها و مرورگرهایی که هم‌اکنون با حساب کاربری شما وارد دیوان شده‌اند. اگر دستگاهی را نمی‌شناسید یا دیگر از آن استفاده نمی‌کنید، آن را از این فهرست خارج کنید.</div>
</div>
@if (Model.LastError == "" && Model.Sessions != null && Model.Sessions.Count(s => s.Id != Model.CurrentSessionId) > 0)
{
<div style="margin-bottom: var(--up-space-3);">
<a role="button" onclick="logoutOtherSessions()" class="up-btn up-btn--danger" id="logout-others-btn">
خروج از سایر دستگاه‌ها
</a>
</div>
}
@if (Model.LastError != "")
{
<div class="up-alert up-alert--danger">@Model.LastError</div>
}
else
{
<script>
async function deleteSession(sessionId, isCurrent) {
var message = isCurrent
? 'این همان نشستی است که هم‌اکنون با آن وارد شده‌اید. با حذف آن از این دستگاه هم خارج خواهید شد. آیا ادامه می‌دهید؟'
: 'آیا از خروج این دستگاه از حساب کاربری خود اطمینان دارید؟';
var ok = await upConfirm(message);
if (!ok) return;
$.ajax({
type: "DELETE",
url: '?handler=Session',
data: { id: sessionId },
success: function (res) {
if (res && res.loggedOutSelf) {
upToast('از این دستگاه خارج شدید.', 'success');
location.href = '/';
return;
}
$('#session-' + sessionId).remove();
upToast('نشست حذف شد.', 'success');
},
error: function (e) {
upToast(e.responseText || 'حذف نشست با خطا مواجه شد.', 'error');
}
});
}
async function logoutOtherSessions() {
var ok = await upConfirm('با این کار از حساب کاربری خود در تمام دستگاه‌ها و مرورگرهای دیگر (به‌جز همین یکی) خارج خواهید شد. آیا ادامه می‌دهید؟');
if (!ok) return;
$.ajax({
type: "DELETE",
url: '?handler=LogoutOthers',
success: function (res) {
var removedCount = (res && res.removedCount) || 0;
$('.up-list-item').each(function () {
if (this.id !== 'session-@Model.CurrentSessionId') {
$(this).remove();
}
});
$('#logout-others-btn').closest('div').remove();
upToast(removedCount > 0 ? 'از ' + removedCount.toLocaleString('ur-PK-u-nu-arabext') + ' دستگاه دیگر خارج شدید.' : 'دستگاه دیگری برای خروج یافت نشد.', 'success');
},
error: function (e) {
upToast(e.responseText || 'خروج از سایر دستگاه‌ها با خطا مواجه شد.', 'error');
}
});
}
</script>
@if (Model.Sessions.Count == 0)
{
<partial name="_EmptyState" model="@("هیچ نشست فعالی یافت نشد.")" />
}
else
{
<div class="up-list">
@foreach (var session in Model.Sessions)
{
bool isCurrent = session.Id == Model.CurrentSessionId;
<div class="up-list-item" id="session-@session.Id">
<div>
<strong>@(string.IsNullOrEmpty(session.ClientAppName) ? "برنامهٔ نامشخص" : session.ClientAppName)</strong>
@if (isCurrent)
{
<span class="up-badge up-badge--primary">این دستگاه</span>
}
<div class="up-list-item__meta up-field--ltr" style="direction: ltr; text-align: right; unicode-bidi: plaintext;">
@session.ClientIPAddress
</div>
<div class="up-list-item__meta">
ورود: @session.LoginTime.ToLongPersianDateTimeString()
&nbsp;·&nbsp;
آخرین تمدید: @session.LastRenewal.ToLongPersianDateTimeString()
&nbsp;·&nbsp;
معتبر تا: @session.ValidUntil.ToLongPersianDateTimeString()
</div>
</div>
<div class="up-list-item__actions">
<a role="button" onclick="deleteSession('@session.Id', @(isCurrent ? "true" : "false"))" class="up-icon-btn" title="خروج این دستگاه" aria-label="خروج این دستگاه از حساب کاربری">
<i class="noindent-info-button delete-icon"></i>
</a>
</div>
</div>
}
</div>
}
}