< Summary

Information
Class: AspNetCoreGeneratedDocument.Areas_OzonCards_Views_Cards_Index
Assembly: OzonOrdersWeb
File(s): /home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/OzonCards/Views/Cards/Index.cshtml
Line coverage
0%
Covered lines: 0
Uncovered lines: 2
Coverable lines: 2
Total lines: 491
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 20
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%420200%

File(s)

/home/runner/work/Studio2Prod/Studio2Prod/OzonOrdersWeb/Areas/OzonCards/Views/Cards/Index.cshtml

#LineLine coverage
 1@using System.Web
 2<!DOCTYPE html>
 3<html lang="ru">
 4<head>
 5    <meta charset="UTF-8">
 6    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 7    <title>Дерево категорий</title>
 8    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
 9    <link rel="stylesheet" href="https://code.jquery.com/ui/1.13.2/themes/base/jquery-ui.css"/>
 10    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
 11    <link href="~/css/tree-cards.css" rel="stylesheet" />
 12    <style>
 13        /* Устанавливаем 100% высоты для body и html */
 14        body, html {
 15            height: 100%;
 16            margin: 0;
 17            padding: 0;
 18        }
 19
 20        /* Добавляем прокрутку для контейнеров */
 21        #categoryTree, #categoryAttributes {
 22            overflow-y: auto;
 23            max-height: 80vh; /* Максимальная высота 80% окна браузера */
 24        }
 25
 26        /* Для страницы с прокруткой на весь экран */
 27        body {
 28            overflow-y: scroll; /* Включаем прокрутку на всей странице */
 29        }
 30    </style>
 31</head>
 32<body>
 33
 34<input type="text" id="typeName" placeholder="Введите имя типа">
 35<button id="loadTree">Загрузить дерево</button>
 36<div id="categoryTree"></div>
 37<div id="categoryAttributes"></div>
 38
 39<script>
 40    var publicDescriptionCategoryId = 0;
 41    $(document).ready(function() {
 42        // Функция для выполнения поиска
 43        function executeSearch(typeName) {
 44            typeName = encodeURIComponent(typeName.trim());
 45            if (!typeName) {
 46                alert("Введите имя типа");
 47                return;
 48            }
 49
 50            if (window.SkeletonLoader) SkeletonLoader.lines('#categoryTree', { count: 6 });
 51
 52            $.ajax({
 53                url: `https://card-api.interparts.ru/api/Category/find-by-type-name/${typeName}`,
 54                method: "GET",
 55                dataType: "json",
 56                success: function(response) {
 57                    if (!response.error) {
 58                        if (window.SkeletonLoader) SkeletonLoader.finish('#categoryTree');
 59                        let treeHtml = buildCategoryTree(response.result);
 60                        $("#categoryTree").html(treeHtml);
 61
 62                        let lastCategory = getLastCategory(response.result);
 63                        if (lastCategory && lastCategory.typeId && lastCategory.parentId) {
 64                            publicDescriptionCategoryId = lastCategory.parentId;
 65                            loadCategoryAttributes(lastCategory.typeId, lastCategory.parentId);
 66                        }
 67                    } else {
 68                        console.error("Ошибка запроса: ", response.message);
 69                    }
 70                },
 71                error: function(xhr, status, error) {
 72                    if (window.SkeletonLoader) SkeletonLoader.finish('#categoryTree');
 73                    $('#categoryTree').html('<p class="text-danger">Не удалось загрузить дерево категорий.</p>');
 74                    console.error("Ошибка AJAX-запроса: ", error);
 75                }
 76            });
 77        }
 78
 79        // Обработчик клика на кнопке
 80        $("#loadTree").click(function() {
 81            let typeName = $("#typeName").val();
 82            executeSearch(typeName);
 83        });
 84
 85        // Автоматический поиск при загрузке, если есть ViewBag.TypeName
 086        @if (!string.IsNullOrEmpty(ViewBag.TypeName))
 87        {
 88        <text>
 089        var typeName = '@Html.Raw(HttpUtility.JavaScriptStringEncode(ViewBag.TypeName.ToString()))';
 90        $("#typeName").val(decodeURIComponent(typeName));
 91        executeSearch(typeName); // Выполняем поиск сразу
 92        </text>
 93        }
 94
 95        function buildCategoryTree(category) {
 96            if (!category) return "";
 97            let html = `<ul><li>${category.name}${category.typeId ? ' ' + category.typeId : ''}`;
 98            if (category.children && category.children.length > 0) {
 99                html += "<ul>";
 100                category.children.forEach(child => {
 101                    html += buildCategoryTree(child);
 102                });
 103                html += "</ul>";
 104            }
 105            if (category.typeName) {
 106                html += ` <strong>(${category.typeName})</strong>`;
 107            }
 108            html += "</li></ul>";
 109            return html;
 110        }
 111
 112        function getLastCategory(category, parent = null) {
 113            if (!category.children || category.children.length === 0) {
 114                return { typeId: category.typeId, parentId: parent ? parent.id : null };
 115            }
 116            return getLastCategory(category.children[category.children.length - 1], category);
 117        }
 118
 119        function loadCategoryAttributes(typeId, descriptionCategoryId) {
 120            if (window.SkeletonLoader) SkeletonLoader.lines('#categoryAttributes', { count: 8 });
 121            $.ajax({
 122                url: "https://card-api.interparts.ru/api/OzonApi/description-category-attributes",
 123                method: "POST",
 124                contentType: "application/json",
 125                data: JSON.stringify({
 126                    descriptionCategoryId: descriptionCategoryId,
 127                    language: "DEFAULT",
 128                    typeId: typeId
 129                }),
 130                dataType: "json",
 131                success: function(response) {
 132                    if (!response.error) {
 133                        if (window.SkeletonLoader) SkeletonLoader.finish('#categoryAttributes');
 134                        let attributesHtml = buildAttributesList(response.result.result, typeId, descriptionCategoryId);
 135                        $("#categoryAttributes").html(attributesHtml);
 136                    } else {
 137                        console.error("Ошибка запроса: ", response.message);
 138                    }
 139                },
 140                error: function(xhr, status, error) {
 141                    if (window.SkeletonLoader) SkeletonLoader.finish('#categoryAttributes');
 142                    $('#categoryAttributes').html('<p class="text-danger">Не удалось загрузить атрибуты категории.</p>')
 143                    console.error("Ошибка AJAX-запроса: ", error);
 144                }
 145            });
 146        }
 147
 148        function buildAttributesList(attributes, typeId, descriptionCategoryId) {
 149            if (!attributes || attributes.length === 0) return "<p>Нет доступных атрибутов</p>";
 150            let html = `<h3>Введите Mongo ID:</h3><input type="text" id="mongoId" placeholder="Введите Mongo ID"> <butto
 151            html += "<h3>Атрибуты категории:</h3><ul>";
 152
 153            attributes.forEach(attr => {
 154                let attrHtml = `<li><strong>${attr.name}</strong>`;
 155                if (attr.description) attrHtml += `: ${attr.description}`;
 156
 157                const isRequired = attr.isRequired ? "required style='border: 2px solid red;'" : "";
 158                attrHtml += `<br/><input type="text" class="attribute-value" data-attribute-id="${attr.id}" data-attribu
 159
 160                // Проверяем dictionaryId
 161                if (attr.dictionaryId && attr.dictionaryId !== 0) {
 162                    attrHtml += `<div id="attr-values-${attr.id}">Загрузка значений...</div>`;
 163                    loadAttributeValues(attr.id, typeId, descriptionCategoryId, attr.dictionaryId, `#attr-values-${attr.
 164                }
 165
 166                attrHtml += "</li>";
 167                html += attrHtml;
 168            });
 169
 170            html += "</ul>";
 171
 172            // Форма для параметров карточки товара
 173            html += `
 174                    <h3>Данные карточки товара:</h3>
 175                    <label>Название товара (name):</label><br>
 176                    <input type="text" id="product-name" placeholder="Например, 'Смартфон XYZ'" style="width: 400px;"><b
 177
 178                    <label>Штрихкод (barcode):</label><br>
 179                    <input type="text" id="product-barcode" placeholder="Уникальный код товара" style="width: 400px;"><b
 180
 181                    <label>Идентификатор предложения (offer_id):</label><br>
 182                    <input type="text" id="product-offerId" placeholder="Уникальный идентификатор товара продавца" style
 183
 184                    <label>Цена (price):</label><br>
 185                    <input type="text" id="product-price" placeholder="Текущая цена товара" style="width: 400px;"><br>
 186
 187                    <label>Старая цена (old_price):</label><br>
 188                    <input type="text" id="product-oldPrice" placeholder="Цена до скидки, если товар участвует в акции" 
 189
 190                    <label>Ставка НДС (vat):</label><br>
 191                    <input type="text" id="product-vat" placeholder="Например, 0.1 для 10% НДС" style="width: 400px;"><b
 192
 193                    <label>Код валюты (currency_code):</label><br>
 194                    <input type="text" id="product-currencyCode" placeholder="Например, 'RUB' для рублей" style="width: 
 195
 196                    <label>Единица измерения (размер) (dimension_unit):</label><br>
 197                    <input type="text" id="product-dimensionUnit" placeholder="Например, 'mm' для миллиметров" style="wi
 198
 199                    <label>Единица измерения (вес) (weight_unit):</label><br>
 200                    <input type="text" id="product-weightUnit" placeholder="Например, 'g' для граммов" style="width: 400
 201
 202                    <label>Вес (weight):</label><br>
 203                    <input type="text" id="product-weight" placeholder="Вес товара в указанных единицах" style="width: 4
 204
 205                    <label>Ширина (width):</label><br>
 206                    <input type="text" id="product-width" placeholder="Ширина товара в указанных единицах" style="width:
 207
 208                    <label>Высота (height):</label><br>
 209                    <input type="text" id="product-height" placeholder="Высота товара в указанных единицах" style="width
 210
 211                    <label>Глубина (depth):</label><br>
 212                    <input type="text" id="product-depth" placeholder="Глубина товара в указанных единицах" style="width
 213
 214                    <label>Основное изображение (primary_image):</label><br>
 215                    <input type="text" id="product-primaryImage" placeholder="URL изображения в формате JPG или PNG" sty
 216
 217                    <label>Цветовое изображение (color_image):</label><br>
 218                    <input type="text" id="product-colorImage" placeholder="URL изображения цвета" style="width: 400px;"
 219
 220                    <label>Изображения (images):</label><br>
 221                    <input type="text" id="product-images" placeholder="Список URL изображений через запятую" style="wid
 222
 223                    <label>Изображения 360 (images360):</label><br>
 224                    <input type="text" id="product-images360" placeholder="Список URL изображений 360 через запятую" sty
 225
 226                    <label>PDF файлы (pdf_list):</label><br>
 227                    <input type="text" id="product-pdfList" placeholder="Список URL PDF файлов через запятую" style="wid
 228                    <br>
 229                    <button id="create-product">Создать карточку</button><br>
 230                `;
 231
 232            return html;
 233        }
 234
 235        // Обработчик клика по кнопке "Создать карточку"
 236        $(document).on("click", "#create-product", function() {
 237
 238            let isValid = true;
 239
 240            // Проверяем все обязательные поля
 241            $(".attribute-value[required]").each(function () {
 242                if (!$(this).val().trim()) {
 243                    $(this).css("border", "2px solid red");
 244                    isValid = false;
 245                } else {
 246                    $(this).css("border", ""); // Сброс рамки, если поле заполнено
 247                }
 248            });
 249
 250            if (!isValid) {
 251                alert("Пожалуйста, заполните все обязательные поля.");
 252                return; // Отменяем отправку
 253            }
 254
 255            let attributes = [];
 256
 257            var productData = generateProductData();
 258            console.log(productData)
 259
 260            console.log(productData)
 261
 262            // Отправляем запрос
 263            $.ajax({
 264                url: "https://card-api.interparts.ru/api/OzonApi/product-import",
 265                method: "POST",
 266                contentType: "application/json",
 267                data: JSON.stringify(productData),
 268                dataType: "json",
 269                success: function(response) {
 270                    alert("Карточка успешно создана!");
 271                    console.log(response);
 272
 273                    // Вызываем /api/dynamic/{collectionName}
 274                    $.ajax({
 275                        url: `https://card-api.interparts.ru/api/dynamic/CardsData`,
 276                        method: "POST",
 277                        contentType: "application/json",
 278                        data: JSON.stringify(productData),
 279                        dataType: "json",
 280                        success: function(dynamicResponse) {
 281                            console.log("Документ успешно создан:", dynamicResponse);
 282
 283                            // Вызываем /api/tasks с телом
 284                            const taskData = {
 285                                taskId: response.result.result.taskId,
 286                                mongoId: dynamicResponse.result,
 287                                name: $("#typeName").val(),
 288                                ozonClient: 482702,
 289                                lastStatus: "Создан"
 290                            };
 291
 292                            $.ajax({
 293                                url: "https://card-api.interparts.ru/api/tasks",
 294                                method: "POST",
 295                                contentType: "application/json",
 296                                data: JSON.stringify(taskData),
 297                                dataType: "json",
 298                                success: function(taskResponse) {
 299                                    console.log("Задача успешно создана:", taskResponse);
 300                                },
 301                                error: function(xhr, status, error) {
 302                                    console.error("Ошибка при вызове /api/tasks:", error);
 303                                }
 304                            });
 305                        },
 306                        error: function(xhr, status, error) {
 307                            console.error("Ошибка при вызове /api/dynamic:", error);
 308                        }
 309                    });
 310                },
 311                error: function(xhr, status, error) {
 312                    console.log(JSON.stringify(productData));
 313                    console.error("Ошибка создания карточки:", error);
 314                }
 315            });
 316        });
 317
 318        function loadAttributeValues(attributeId, typeId, descriptionCategoryId, dictionaryId, parentHtml) {
 319            if (window.SkeletonLoader) SkeletonLoader.appendLines(parentHtml, { count: 3 });
 320            $.ajax({
 321                url: "https://card-api.interparts.ru/api/OzonApi/description-category-attribute-values",
 322                method: "POST",
 323                contentType: "application/json",
 324                data: JSON.stringify({
 325                    attributeId: attributeId,
 326                    descriptionCategoryId: descriptionCategoryId,
 327                    language: "DEFAULT",
 328                    lastValueId: 0,
 329                    limit: 100,
 330                    typeId: typeId
 331                }),
 332                dataType: "json",
 333                success: function(response) {
 334                    if (!response.error) {
 335                        if (window.SkeletonLoader) SkeletonLoader.finish(parentHtml);
 336                        let values = response.result.result;
 337                        let valuesHtml = "<ul>";
 338
 339                        values.forEach((val, index) => {
 340                            let listItemClass = index < 10 ? "" : "hidden-value";
 341                            let listItemStyle = index < 10 ? "cursor: pointer;" : "display: none; cursor: pointer;";
 342
 343                            valuesHtml += `<li class="${listItemClass}" style="${listItemStyle}" data-attribute-id="${at
 344                        });
 345
 346                        if (values.length > 10) {
 347                            valuesHtml += `<li class="show-more" style="color: blue; cursor: pointer;">Развернуть</li>`;
 348                        }
 349
 350                        valuesHtml += "</ul>";
 351
 352                        $(parentHtml).append(valuesHtml);
 353
 354                        $(parentHtml).find(".show-more").on("click", function() {
 355                            $(parentHtml).find(".hidden-value").slideToggle();
 356                            $(this).remove();
 357                        });
 358
 359                        $(parentHtml).find("li[data-attribute-id]").on("click", function() {
 360                            let selectedValue = $(this).text();
 361                            let attributeId = $(this).data("attribute-id");
 362                            $(`input.attribute-value[data-attribute-id="${attributeId}"]`).val(selectedValue);
 363                        });
 364
 365                    } else {
 366                        if (window.SkeletonLoader) SkeletonLoader.finish(parentHtml);
 367                        console.error("Ошибка запроса: ", response.message);
 368                    }
 369                },
 370                error: function(xhr, status, error) {
 371                    if (window.SkeletonLoader) SkeletonLoader.finish(parentHtml);
 372                    console.error("Ошибка AJAX-запроса: ", error);
 373                }
 374            });
 375        }
 376    });
 377
 378    function generateProductData() {
 379        let attributes = [];
 380
 381        $(".attribute-value").each(function() {
 382            let attrId = $(this).data("attribute-id");
 383            let value = $(this).val();
 384            let inputId = $(`.attribute-id[data-attribute-id="${attrId}"]`).val();
 385
 386            if (value && attrId) {
 387                attributes.push({
 388                    complex_id: 0,
 389                    id: parseInt(attrId),
 390                    values: [{ value: value }]
 391                });
 392            }
 393        });
 394
 395        let productData = {
 396            items: [
 397                {
 398                    attributes: attributes,
 399                    barcode: $("#product-barcode").val() || "",
 400                    description_category_id: publicDescriptionCategoryId,
 401                    new_description_category_id: 0,
 402                    color_image: $("#product-colorImage").val() || "",
 403                    complex_attributes: [],
 404                    currency_code: $("#product-currencyCode").val() || "RUB",
 405                    depth: parseFloat($("#product-depth").val()) || 0,
 406                    dimension_unit: $("#product-dimensionUnit").val() || "mm",
 407                    height: parseFloat($("#product-height").val()) || 0,
 408                    images: $("#product-images").val() ? $("#product-images").val().split(",") : [],
 409                    images360: $("#product-images360").val() ? $("#product-images360").val().split(",") : [],
 410                    name: $("#product-name").val() || "",
 411                    offer_id: $("#product-offerId").val() || "",
 412                    old_price: $("#product-oldPrice").val() || "0",
 413                    pdf_list: $("#product-pdfList").val() ? $("#product-pdfList").val().split(",") : [],
 414                    price: $("#product-price").val() || "0",
 415                    primary_image: $("#product-primaryImage").val() || "",
 416                    vat: $("#product-vat").val() || "0.1",
 417                    weight: parseFloat($("#product-weight").val()) || 0,
 418                    weight_unit: $("#product-weightUnit").val() || "g",
 419                    width: parseFloat($("#product-width").val()) || 0
 420                }
 421            ]
 422        };
 423
 424        console.log(productData);
 425        return productData;
 426    }
 427
 428    $(document).on("click", "#load-data", function() {
 429        let mongoId = $("#mongoId").val().trim();
 430        console.log(mongoId);
 431        if (!mongoId) {
 432            alert("Введите Mongo ID!");
 433            return;
 434        }
 435
 436        $.ajax({
 437            url: `https://card-api.interparts.ru/api/dynamic/CardsData/${mongoId}`,
 438            method: "GET",
 439            dataType: "json",
 440            success: function(jsonResponse) {
 441                if (jsonResponse.items && jsonResponse.items.length > 0) {
 442                    let item = jsonResponse.items[0];
 443
 444                    $("#product-name").val(item.name || "");
 445                    $("#product-barcode").val(item.barcode || "");
 446                    $("#product-offerId").val(item.offer_id || "");
 447                    $("#product-price").val(item.price || "");
 448                    $("#product-oldPrice").val(item.old_price || "");
 449                    $("#product-vat").val(item.vat || "");
 450                    $("#product-currencyCode").val(item.currency_code || "");
 451                    $("#product-dimensionUnit").val(item.dimension_unit || "");
 452                    $("#product-weightUnit").val(item.weight_unit || "");
 453                    $("#product-weight").val(item.weight || "");
 454                    $("#product-width").val(item.width || "");
 455                    $("#product-height").val(item.height || "");
 456                    $("#product-depth").val(item.depth || "");
 457                    $("#product-primaryImage").val(item.primary_image || "");
 458                    $("#product-colorImage").val(item.color_image || "");
 459                    $("#product-images").val((item.images || []).join(", "));
 460                    $("#product-images360").val((item.images360 || []).join(", "));
 461                    $("#product-pdfList").val((item.pdf_list || []).join(", "));
 462
 463                    if (item.attributes && item.attributes.length > 0) {
 464                        item.attributes.forEach(attr => {
 465                            let inputField;
 466                            if(attr.id === 0){
 467                                inputField = $(`input.attribute-value[data-attribute-name='${attr.name}']`);
 468                            }
 469                            else{
 470                                inputField = $(`input.attribute-value[data-attribute-id='${attr.id}']`);
 471                            }
 472
 473                            if (inputField.length > 0) {
 474                                let value = attr.values.length > 0 ? attr.values[0].value : "";
 475                                inputField.val(value);
 476                            }
 477                        });
 478                    }
 479                } else {
 480                    alert("Ошибка: Данные не найдены.");
 481                }
 482            },
 483            error: function(xhr, status, error) {
 484                console.error("Ошибка при получении JSON данных:", error);
 485                alert("Ошибка загрузки данных. Проверьте Mongo ID.");
 486            }
 487        });
 488    });
 489</script>
 490</body>
 491</html>

Methods/Properties

<ExecuteAsync()