< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_Studio2_Views_Profile_Index
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/Profile/Index.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 56
Coverable lines: 56
Total lines: 190
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 66
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
ExecuteAsync()0%109201040%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/Studio2/Views/Profile/Index.cshtml

#LineLine coverage
 1@using OzonDomains.Models.AccessControl
 2@using OzonOrdersWeb.ViewModels.UserViewModels
 3@model UserProfileViewModel
 4
 5@{
 06    ViewData["Title"] = "Мой профиль";
 07    Layout = "~/Views/Shared/_Layout.cshtml";
 8
 09    var userName = Model.User.GoogleDisplayName ?? Model.User.UserName ?? Model.User.Email ?? "Пользователь";
 010    var loginName = Model.User.UserName ?? Model.User.Email ?? "Пользователь";
 011    var avatarUrl = Model.User.GoogleAvatarUrl;
 012    var initialsSource = string.IsNullOrWhiteSpace(userName) ? "U" : userName.Trim();
 013    var initials = initialsSource.Substring(0, Math.Min(2, initialsSource.Length)).ToUpperInvariant();
 014    var roles = Model.Roles?.Where(r => !string.IsNullOrWhiteSpace(r)).Distinct().OrderBy(r => r).ToList() ?? new List<s
 015    var scopeItems = Model.ScopeItems ?? new List<DataScopeSetItem>();
 016    var availableColumns = Model.AvailableOrderColumns?.Where(c => !string.IsNullOrWhiteSpace(c)).Distinct().OrderBy(c =
 017    var dataScopeSets = Model.AccessProfile?.DataScopeSets?.OrderBy(s => s.Name).ToList() ?? new List<DataScopeSet>();
 18}
 19
 20<link rel="stylesheet" href="~/css/Studio2/Profile/profile-index.css" asp-append-version="true"/>
 21
 22<div class="profile-page">
 23    <section class="profile-hero app-section-hero app-section-hero--import">
 024        @if (!string.IsNullOrWhiteSpace(avatarUrl))
 25        {
 26            <img class="profile-hero-avatar profile-hero-avatar-image" src="@avatarUrl" alt="@userName" referrerpolicy="
 27        }
 28        else
 29        {
 030            <div class="profile-hero-avatar">@initials</div>
 31        }
 32        <div>
 33            <h1>Профиль пользователя</h1>
 034            <p class="subtitle">@userName</p>
 035            @if (!string.Equals(userName, loginName, StringComparison.OrdinalIgnoreCase))
 36            {
 037                <p class="subtitle-help">Логин: @loginName</p>
 38            }
 39            <p class="subtitle-help">
 40                Страница показывает ваш текущий набор прав: роли, профиль доступа, разрешённые поля таблицы заказов и ог
 41            </p>
 42        </div>
 43    </section>
 44
 45    <nav class="profile-quick-links app-section-hero__quick-links" aria-label="Связанные разделы">
 46        <a asp-area="Studio2" asp-controller="Orders" asp-action="Index">Заказы</a>
 047        @if (roles.Contains("Admin", StringComparer.OrdinalIgnoreCase))
 48        {
 49            <a asp-area="Studio2" asp-controller="User" asp-action="UserList">Пользователи</a>
 50            <a asp-area="Studio2" asp-controller="AccessProfiles" asp-action="Index">Профили доступа</a>
 51        }
 52    </nav>
 53
 54    <section class="profile-intro">
 55        <i class="fas fa-circle-info" aria-hidden="true"></i>
 56        <div>
 57            <strong>Как читать права:</strong> роли отвечают за доступ к разделам, профиль доступа ограничивает видимые 
 58            а правила ниже показывают фактические ограничения в заказах.
 59        </div>
 60    </section>
 61
 62    <section class="profile-grid">
 63        <article class="profile-card">
 64            <h2>Основные данные</h2>
 65            <dl class="profile-kv">
 66                <div>
 67                    <dt>Email</dt>
 068                    <dd>@(Model.User.Email ?? "—")</dd>
 69                </div>
 70                <div>
 71                    <dt>Логин</dt>
 072                    <dd>@(Model.User.UserName ?? "—")</dd>
 73                </div>
 74                <div>
 75                    <dt>ID пользователя</dt>
 076                    <dd>@Model.User.Id</dd>
 77                </div>
 78                <div>
 79                    <dt>Профиль доступа</dt>
 080                    <dd>@(Model.AccessProfile?.Name ?? "Не назначен (полный доступ)")</dd>
 81                </div>
 82            </dl>
 83        </article>
 84
 85        <article class="profile-card">
 86            <h2>Роли</h2>
 087            @if (roles.Count == 0)
 88            {
 89                <p class="profile-empty">Роли не назначены.</p>
 90            }
 91            else
 92            {
 93                <div class="profile-badges">
 094                    @foreach (var role in roles)
 95                    {
 96                        <span class="profile-badge @(role.Equals("Admin", StringComparison.OrdinalIgnoreCase) ? "is-admi
 097                            @role
 98                        </span>
 99                    }
 100                </div>
 101                <p class="profile-field-hint">Роли определяют доступ к разделам Studio2 и административным операциям.</p
 102            }
 103        </article>
 104
 105        <article class="profile-card">
 106            <h2>Доступные поля заказа</h2>
 0107            @if (availableColumns.Count == 0)
 108            {
 109                <p class="profile-empty">Ограничений по колонкам нет: доступны все поля таблицы заказов.</p>
 110            }
 111            else
 112            {
 113                <div class="profile-badges">
 0114                    @foreach (var column in availableColumns)
 115                    {
 0116                        <span class="profile-badge is-column">@column</span>
 117                    }
 118                </div>
 119                <p class="profile-field-hint">Отображаются только перечисленные колонки в таблице заказов.</p>
 120            }
 121        </article>
 122
 123        <article class="profile-card">
 124            <h2>Наборы ограничений</h2>
 0125            @if (dataScopeSets.Count == 0)
 126            {
 127                <p class="profile-empty">Наборы не назначены: видны все записи без фильтрации по справочникам.</p>
 128            }
 129            else
 130            {
 131                <ul class="profile-list">
 0132                    @foreach (var scopeSet in dataScopeSets)
 133                    {
 134                        <li>
 0135                            <strong>@scopeSet.Name</strong>
 0136                            @if (!string.IsNullOrWhiteSpace(scopeSet.Description))
 137                            {
 0138                                <span>— @scopeSet.Description</span>
 139                            }
 140                        </li>
 141                    }
 142                </ul>
 143            }
 144        </article>
 145    </section>
 146
 147    <section class="profile-card profile-card-full">
 148        <h2>Правила доступа к данным</h2>
 0149        @if (!scopeItems.Any())
 150        {
 151            <p class="profile-empty">Ограничений по данным нет: доступны все статусы, поставщики, клиенты, склады и служ
 152        }
 153        else
 154        {
 0155            var grouped = scopeItems.GroupBy(x => x.ScopeType).OrderBy(g => g.Key.ToString());
 156            <div class="profile-rules-grid">
 0157                @foreach (var group in grouped)
 158                {
 0159                    var label = group.Key switch
 0160                    {
 0161                        DataScopeType.AppStatus => "Статусы заказов",
 0162                        DataScopeType.Supplier => "Поставщики",
 0163                        DataScopeType.OzonClient => "Клиенты Ozon",
 0164                        DataScopeType.Warehouse => "Склады",
 0165                        DataScopeType.DeliveryProvider => "Службы доставки",
 0166                        _ => group.Key.ToString()
 0167                    };
 168                    <article class="profile-rule">
 0169                        <h3>@label <span class="count">@group.Count()</span></h3>
 170                        <div class="profile-badges">
 0171                            @foreach (var item in group.OrderBy(x => x.ReferenceId))
 172                            {
 0173                                var name = group.Key switch
 0174                                {
 0175                                    DataScopeType.AppStatus => Model.AppStatuses.FirstOrDefault(x => x.Id == item.Refere
 0176                                    DataScopeType.Supplier => Model.Suppliers.FirstOrDefault(x => x.Id == item.Reference
 0177                                    DataScopeType.OzonClient => Model.OzonClients.FirstOrDefault(x => x.Id == item.Refer
 0178                                    DataScopeType.Warehouse => Model.Warehouses.FirstOrDefault(x => x.Id == item.Referen
 0179                                    DataScopeType.DeliveryProvider => Model.DeliveryProviders.FirstOrDefault(x => x.Id =
 0180                                    _ => $"#{item.ReferenceId}"
 0181                                };
 0182                                <span class="profile-badge is-scope">@name</span>
 183                            }
 184                        </div>
 185                    </article>
 186                }
 187            </div>
 188        }
 189    </section>
 190</div>

Methods/Properties

ExecuteAsync()