Dmitriy | Инициализация.
This commit is contained in:
62
assets/css/options-page.css
Normal file
62
assets/css/options-page.css
Normal file
@@ -0,0 +1,62 @@
|
||||
.price-updates-options {
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.price-updates-options input,
|
||||
.price-updates-options label,
|
||||
.price-updates-options button {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
.price-updates-options__input-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.price-updates-options__input-wrapper input[type="text"] {
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.price-updates-options__submit-wrapper {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.price-updates-options__submit {
|
||||
width: 200px;
|
||||
padding: 12px 16px;
|
||||
text-align: center;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
color: #fff;
|
||||
background: radial-gradient(278.91% 196.13% at 128.36% -48.29%, #ee6868 0%, #569ef0 57.69%);
|
||||
cursor: pointer;
|
||||
transition: filter 0.3s ease;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.price-updates-options__submit:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
.price-updates-options__success-message,
|
||||
.price-updates-options__error-message {
|
||||
width: max-content;
|
||||
padding: 16px 20px;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.price-updates-options__success-message {
|
||||
color: #fff;
|
||||
background-color: #19a917;
|
||||
}
|
||||
|
||||
.price-updates-options__error-message {
|
||||
color: #fff;
|
||||
background-color: #fa0505;
|
||||
}
|
||||
181
assets/css/price-updates-page.css
Normal file
181
assets/css/price-updates-page.css
Normal file
@@ -0,0 +1,181 @@
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.price-updates-wrapper {
|
||||
margin-right: 20px;
|
||||
padding: 12px;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.price-updates-wrapper input,
|
||||
.price-updates-wrapper label,
|
||||
.price-updates-wrapper button {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
|
||||
.price-updates-variations {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.price-updates-contents {
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.price-updates-contents form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.price-updates-contents input {
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.price-updates-contents input[type="url"] {
|
||||
width: 600px;
|
||||
}
|
||||
|
||||
.price-updates-contents button {
|
||||
width: 200px;
|
||||
padding: 12px 16px;
|
||||
text-align: center;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
color: #fff;
|
||||
background: radial-gradient(278.91% 196.13% at 128.36% -48.29%, #ee6868 0%, #569ef0 57.69%);
|
||||
cursor: pointer;
|
||||
transition: filter 0.3s ease;
|
||||
}
|
||||
|
||||
.price-updates-contents button:hover {
|
||||
filter: brightness(0.9);
|
||||
}
|
||||
|
||||
.price-updates-caption {
|
||||
display: block;
|
||||
margin-bottom: 12px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.price-updates-count {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.price-updates-count-success span {
|
||||
color: #19a917;
|
||||
}
|
||||
|
||||
.price-updates-count-error span {
|
||||
color: #fa0505;
|
||||
}
|
||||
|
||||
.price-updates-response {
|
||||
width: 100%;
|
||||
max-height: 800px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.price-updates-response table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.price-updates-response thead th {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
padding-block: 12px;
|
||||
background-color: #f0f0f1;
|
||||
}
|
||||
|
||||
.price-updates-response tbody td {
|
||||
text-align: center;
|
||||
padding-block: 12px;
|
||||
}
|
||||
|
||||
.price-updates-error {
|
||||
width: max-content;
|
||||
padding: 16px 20px;
|
||||
border-radius: 8px;
|
||||
color: #fff;
|
||||
background-color: #fa0505;
|
||||
}
|
||||
|
||||
.price-updates-loader-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
background-color: rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
.price-updates-loader {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
max-width: 6rem;
|
||||
margin-top: 3rem;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
.price-updates-loader:before,
|
||||
.price-updates-loader:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
border-radius: 50%;
|
||||
animation: pulsOut 1.8s ease-in-out infinite;
|
||||
filter: drop-shadow(0 0 1rem rgba(255, 255, 255, 0.75));
|
||||
}
|
||||
|
||||
.price-updates-loader:before {
|
||||
width: 100%;
|
||||
padding-bottom: 100%;
|
||||
box-shadow: inset 0 0 0 1rem #fff;
|
||||
animation-name: pulsIn;
|
||||
}
|
||||
|
||||
.price-updates-loader:after {
|
||||
width: calc(100% - 2rem);
|
||||
padding-bottom: calc(100% - 2rem);
|
||||
box-shadow: 0 0 0 0 #fff;
|
||||
}
|
||||
|
||||
@keyframes pulsIn {
|
||||
0% {
|
||||
box-shadow: inset 0 0 0 1rem #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
50%, 100% {
|
||||
box-shadow: inset 0 0 0 0 #fff;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes pulsOut {
|
||||
0%, 50% {
|
||||
box-shadow: 0 0 0 0 #fff;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
box-shadow: 0 0 0 1rem #fff;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
69
assets/js/options-page.js
Normal file
69
assets/js/options-page.js
Normal file
@@ -0,0 +1,69 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
const $form = $(".price-updates-options__form");
|
||||
const $loaderWrapper = $(".price-updates-loader-wrapper");
|
||||
|
||||
const $success = $(".price-updates-options__success-message");
|
||||
const $error = $(".price-updates-options__error-message");
|
||||
|
||||
function hideMessages() {
|
||||
$success.addClass("hidden");
|
||||
$error.addClass("hidden")
|
||||
}
|
||||
|
||||
// [Событие] Сохранение настроек
|
||||
$form.on("submit", function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$loaderWrapper.removeClass("hidden");
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: priceUpdatesOptionsSettings.ajaxUrl + "/update",
|
||||
data: $(this).serializeArray(),
|
||||
success: function (response) {
|
||||
hideMessages();
|
||||
|
||||
$success.removeClass("hidden");
|
||||
$success.text("Настройки обновлены.");
|
||||
},
|
||||
error: function (error) {
|
||||
console.error(error)
|
||||
|
||||
hideMessages();
|
||||
|
||||
$error.removeClass("hidden");
|
||||
$error.text("Ошибка при обновлении настроек.");
|
||||
},
|
||||
complete: function () {
|
||||
$loaderWrapper.addClass("hidden");
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
$loaderWrapper.removeClass("hidden");
|
||||
|
||||
// [Ajax] Подгружаем настройки
|
||||
$.ajax({
|
||||
method: "GET",
|
||||
url: priceUpdatesOptionsSettings.ajaxUrl + "/get",
|
||||
success: function (response) {
|
||||
if (!response) return;
|
||||
|
||||
for (const [key, value] of Object.entries(response)) {
|
||||
const $input = $form.find(`input[name="${key}"]`);
|
||||
$input.val(JSON.stringify(value).slice(1, -1));
|
||||
}
|
||||
},
|
||||
error: function (error) {
|
||||
console.error(error);
|
||||
|
||||
hideMessages();
|
||||
|
||||
$error.removeClass("hidden");
|
||||
$error.text("Ошибка при загрузке настроек.");
|
||||
},
|
||||
complete: function () {
|
||||
$loaderWrapper.addClass("hidden");
|
||||
}
|
||||
})
|
||||
});
|
||||
205
assets/js/price-updates-page.js
Normal file
205
assets/js/price-updates-page.js
Normal file
@@ -0,0 +1,205 @@
|
||||
jQuery(document).ready(function ($) {
|
||||
const $variantons = $('input[name="price-updates-variant"]');
|
||||
const $contents = $("form[data-price-updates-variant]");
|
||||
|
||||
const $count = $(".price-updates-count");
|
||||
const $countSuccess = $(".price-updates-count-success");
|
||||
const $countError = $(".price-updates-count-error");
|
||||
|
||||
const $tableWrapper = $(".price-updates-response");
|
||||
const $error = $(".price-updates-error");
|
||||
const $loaderWrapper = $(".price-updates-loader-wrapper");
|
||||
|
||||
// [Событие] Смена варианита обновления цен
|
||||
$variantons.on("change", function () {
|
||||
const $varianton = $(this);
|
||||
|
||||
$tableWrapper.find("tbody").html("");
|
||||
$tableWrapper.addClass("hidden");
|
||||
|
||||
updatePriceUpdatesCountSuccess(0);
|
||||
updatePriceUpdatesCountError(0);
|
||||
|
||||
$count.addClass("hidden");
|
||||
$countSuccess.addClass("hidden");
|
||||
$countError.addClass("hidden");
|
||||
|
||||
$contents.each(function() {
|
||||
const $content = $(this);
|
||||
|
||||
if ($varianton.val() != $content.data("price-updates-variant")) {
|
||||
$content.addClass("hidden");
|
||||
} else {
|
||||
$content.removeClass("hidden");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Инициализация вариантов обновления цен
|
||||
$variantons.each(function() {
|
||||
const $varianton = $(this);
|
||||
|
||||
$contents.each(function() {
|
||||
const $content = $(this);
|
||||
|
||||
if (!$varianton.is(":checked") && $varianton.val() == $content.data("price-updates-variant")) {
|
||||
$content.addClass("hidden");
|
||||
} else {
|
||||
$content.removeClass("hidden");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function getCount(response) {
|
||||
if (!response?.length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let success = 0;
|
||||
let error = 0;
|
||||
|
||||
for (const item of response) {
|
||||
if (!item?.isError) {
|
||||
success += 1;
|
||||
} else {
|
||||
error += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return { success, error };
|
||||
}
|
||||
|
||||
function updatePriceUpdatesCountSuccess(count) {
|
||||
if (typeof count !== "number") return;
|
||||
|
||||
$count.removeClass("hidden");
|
||||
|
||||
$countSuccess.removeClass("hidden");
|
||||
$countSuccess.html(`Измененно элементов: <span>${count}</span>`);
|
||||
}
|
||||
|
||||
function updatePriceUpdatesCountError(count) {
|
||||
if (typeof count !== "number") return;
|
||||
|
||||
$count.removeClass("hidden");
|
||||
|
||||
$countError.removeClass("hidden");
|
||||
$countError.html(`Неудалось изменить элементов: <span>${count}</span>`);
|
||||
}
|
||||
|
||||
function getTableRow(data) {
|
||||
const row = document.createElement("tr");
|
||||
|
||||
const tempData = { ...data };
|
||||
|
||||
delete tempData.url;
|
||||
delete tempData.currency;
|
||||
|
||||
for (const [key, value] of Object.entries(tempData)) {
|
||||
const ceil = document.createElement("td");
|
||||
|
||||
if (key === "sku") {
|
||||
const link = document.createElement("a");
|
||||
|
||||
link.href = data.url;
|
||||
link.textContent = value;
|
||||
|
||||
ceil.appendChild(link);
|
||||
} else if (key === "regular" || key === "sale") {
|
||||
ceil.textContent = value["old"] != value["new"] ? `${value["old"]} ${data.currency} -> ${value["new"]} ${data.currency}` : `${value["new"]} ${data.currency}`;
|
||||
}
|
||||
|
||||
row.appendChild(ceil);
|
||||
}
|
||||
|
||||
return $(row);
|
||||
}
|
||||
|
||||
function getTableRowError(data) {
|
||||
const row = document.createElement("tr");
|
||||
|
||||
const tempData = {
|
||||
sku: data?.sku,
|
||||
message: data?.message
|
||||
};
|
||||
|
||||
for (const [key, value] of Object.entries(tempData)) {
|
||||
const ceil = document.createElement("td");
|
||||
|
||||
ceil.textContent = value;
|
||||
|
||||
if (key === "message") {
|
||||
ceil.colSpan = 2;
|
||||
}
|
||||
|
||||
row.appendChild(ceil);
|
||||
}
|
||||
|
||||
return $(row);
|
||||
}
|
||||
|
||||
// [Событие] Отправка формы
|
||||
$contents.on("submit", function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
$loaderWrapper.removeClass("hidden");
|
||||
|
||||
$.ajax({
|
||||
method: "POST",
|
||||
url: priceUpdatesSettings.ajaxUrl + "/update",
|
||||
processData: false,
|
||||
contentType: false,
|
||||
data: new FormData(this),
|
||||
success: function (response) {
|
||||
$error.addClass("hidden");
|
||||
|
||||
$tableWrapper.find("tbody").html("");
|
||||
|
||||
if (!response?.length) {
|
||||
$tableWrapper.addClass("hidden");
|
||||
|
||||
updatePriceUpdatesCountSuccess(0);
|
||||
updatePriceUpdatesCountError(0);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const count = getCount(response);
|
||||
|
||||
updatePriceUpdatesCountSuccess(count.success);
|
||||
updatePriceUpdatesCountError(count.error);
|
||||
|
||||
$tableWrapper.removeClass("hidden");
|
||||
|
||||
for (const item of response) {
|
||||
let $row = null;
|
||||
|
||||
if (!item?.isError) {
|
||||
$row = getTableRow(item);
|
||||
} else {
|
||||
$row = getTableRowError(item);
|
||||
}
|
||||
|
||||
$tableWrapper.find("tbody").append($row);
|
||||
}
|
||||
},
|
||||
error: function (error) {
|
||||
$tableWrapper.find("tbody").html("");
|
||||
$tableWrapper.addClass("hidden");
|
||||
|
||||
updatePriceUpdatesCountSuccess(0);
|
||||
updatePriceUpdatesCountError(0);
|
||||
|
||||
$count.addClass("hidden");
|
||||
$countSuccess.addClass("hidden");
|
||||
$countError.addClass("hidden");
|
||||
|
||||
$error.removeClass("hidden");
|
||||
$error.text(error?.responseJSON?.message || "Неизвестная ошибка");
|
||||
},
|
||||
complete: function () {
|
||||
$loaderWrapper.addClass("hidden");
|
||||
}
|
||||
})
|
||||
})
|
||||
});
|
||||
Reference in New Issue
Block a user