update config live / sandbox
This commit is contained in:
parent
e211e0e521
commit
513dca2a9a
|
|
@ -1,19 +1,10 @@
|
|||
/* #bid-extension body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #121212;
|
||||
color: #e0e0e0;
|
||||
font-family: 'Segoe UI', Tahoma, sans-serif;
|
||||
width: 320px;
|
||||
} */
|
||||
|
||||
#bid-extension {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #121212;
|
||||
color: #e0e0e0;
|
||||
font-family: "Segoe UI", Tahoma, sans-serif;
|
||||
width: 320px;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
#bid-extension .container {
|
||||
|
|
@ -36,8 +27,9 @@
|
|||
}
|
||||
|
||||
#bid-extension input,
|
||||
#bid-extension select,
|
||||
#bid-extension textarea {
|
||||
padding: 8px;
|
||||
padding: 4px 8px;
|
||||
background-color: #1e1e1e;
|
||||
color: #ffffff;
|
||||
border: 1px solid #333;
|
||||
|
|
@ -45,9 +37,11 @@
|
|||
font-size: 14px;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
#bid-extension input:focus,
|
||||
#bid-extension select:focus,
|
||||
#bid-extension textarea:focus {
|
||||
border-color: #4a90e2;
|
||||
outline: none;
|
||||
|
|
@ -71,12 +65,12 @@
|
|||
|
||||
#bid-extension button {
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
background: linear-gradient(to right, #4a90e2, #357abd);
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
font-size: 15px;
|
||||
height: 36px;
|
||||
cursor: pointer;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
|
@ -129,6 +123,12 @@
|
|||
height: 14px;
|
||||
}
|
||||
|
||||
#bid-extension .sub-col {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
#toggle-bid-extension svg {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
|
|
|||
234
content.js
234
content.js
|
|
@ -157,12 +157,73 @@ async function handleUpdate(event, formElements, id) {
|
|||
quantity: isNaN(quantity) ? null : quantity,
|
||||
};
|
||||
|
||||
const keys = Object.values(formElements.form)
|
||||
.filter((item) => {
|
||||
return [
|
||||
"mode_key",
|
||||
"early_tracking_seconds",
|
||||
"arrival_offset_seconds",
|
||||
].includes(item?.id);
|
||||
})
|
||||
.reduce((prev, cur) => {
|
||||
prev[cur.id] = cur.value;
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
const earlyTracking = parseInt(keys.early_tracking_seconds, 10);
|
||||
const arrivalOffset = parseInt(keys.arrival_offset_seconds, 10);
|
||||
|
||||
if (earlyTracking < 600) {
|
||||
alert("Early Tracking Seconds must be at least 600 seconds (10 minutes).");
|
||||
return;
|
||||
}
|
||||
|
||||
if (arrivalOffset < 60) {
|
||||
alert("Arrival Offset Seconds must be at least 60 seconds (1 minute).");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate required fields
|
||||
if (payload.max_price === null) {
|
||||
alert("Please fill out the URL and Max Price fields correctly.");
|
||||
return;
|
||||
}
|
||||
|
||||
const localKeyName = keys["mode_key"];
|
||||
|
||||
const newKeys = Object.entries(keys).reduce((prev, [key, value]) => {
|
||||
if (key === "mode_key") {
|
||||
prev[key] = value;
|
||||
} else {
|
||||
prev[`${key}_${localKeyName}`] = Number(value);
|
||||
}
|
||||
return prev;
|
||||
}, {});
|
||||
|
||||
let metadata = [];
|
||||
|
||||
if (
|
||||
window.__result.metadata.length > 0 &&
|
||||
window.__result.metadata.some((item) => item.key_name === "mode_key")
|
||||
) {
|
||||
metadata = window.__result.metadata.map((item) => {
|
||||
if (Object.keys(newKeys).includes(item.key_name)) {
|
||||
return {
|
||||
...item,
|
||||
value: newKeys[item.key_name],
|
||||
};
|
||||
}
|
||||
return { ...item };
|
||||
});
|
||||
} else {
|
||||
metadata = Object.entries(newKeys).map(([key, value]) => {
|
||||
return {
|
||||
key_name: key,
|
||||
value,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`${CONFIG.API_BASE_URL}/bids/info/${id}`, {
|
||||
method: "PUT",
|
||||
|
|
@ -170,7 +231,7 @@ async function handleUpdate(event, formElements, id) {
|
|||
"Content-Type": "application/json",
|
||||
Authorization: key,
|
||||
},
|
||||
body: JSON.stringify(removeFalsyValues(payload)),
|
||||
body: JSON.stringify(removeFalsyValues({ ...payload, metadata })),
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
|
@ -179,6 +240,8 @@ async function handleUpdate(event, formElements, id) {
|
|||
} catch (error) {
|
||||
alert("Error: " + error.message);
|
||||
console.error("API Error:", error);
|
||||
} finally {
|
||||
await showInfo();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,6 +352,81 @@ const isValidModel = () => {
|
|||
return !!model;
|
||||
};
|
||||
|
||||
const renderValueModeMetadata = (data, formElements, mode = null) => {
|
||||
const early_tracking_seconds = getEarlyTrackingSeconds(data, mode);
|
||||
const arrival_offset_seconds = getArrivalOffsetSeconds(data, mode);
|
||||
|
||||
formElements.metadataMode.arrival_offset_seconds.value =
|
||||
arrival_offset_seconds;
|
||||
|
||||
formElements.metadataMode.early_tracking_seconds.value =
|
||||
early_tracking_seconds;
|
||||
|
||||
return { early_tracking_seconds, arrival_offset_seconds };
|
||||
};
|
||||
|
||||
function formatTimeFromMinutes(minutes) {
|
||||
// Tính ngày, giờ, phút từ số phút
|
||||
const days = Math.floor(minutes / (60 * 24));
|
||||
const hours = Math.floor((minutes % (60 * 24)) / 60);
|
||||
const mins = minutes % 60;
|
||||
|
||||
let result = "";
|
||||
|
||||
if (days > 0) result += `${days} ${days > 1 ? "days" : "day"} `;
|
||||
if (hours > 0) result += `${hours} ${hours > 1 ? "hours" : "hour"} `;
|
||||
if (mins > 0 || result === "") result += `${mins} minutes`;
|
||||
|
||||
return result.trim();
|
||||
}
|
||||
|
||||
function toReadableLabel(input) {
|
||||
return input
|
||||
.split("_") // Tách chuỗi theo dấu gạch dưới
|
||||
.map((word) => word.charAt(0).toUpperCase() + word.slice(1)) // Viết hoa chữ cái đầu
|
||||
.join(" "); // Nối lại bằng khoảng trắng
|
||||
}
|
||||
|
||||
const setMinusLabel = (input, minutes = null) => {
|
||||
const label = document.querySelector(`[for="${input?.id}"]`);
|
||||
|
||||
const text = toReadableLabel(input.id);
|
||||
|
||||
label.textContent = `${text} (${formatTimeFromMinutes(
|
||||
minutes || Number(input.value) || 300 / 60
|
||||
)})`;
|
||||
};
|
||||
|
||||
const renderMetadaMode = (data, formElements, mode = null) => {
|
||||
const mode_key = mode ? mode : getMode(data);
|
||||
|
||||
formElements.metadataModeBox.style.display = "flex";
|
||||
|
||||
renderValueModeMetadata(data, formElements, mode_key);
|
||||
|
||||
Object.values(formElements.form).forEach((item) => {
|
||||
if (item?.id === "mode_key") {
|
||||
item.value = mode_key;
|
||||
|
||||
item.addEventListener("change", (e) => {
|
||||
renderValueModeMetadata(data, formElements, e.target.value);
|
||||
|
||||
Object.values(formElements.metadataMode).forEach((i) => {
|
||||
setMinusLabel(i);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Object.values(formElements.metadataMode).forEach((item) => {
|
||||
setMinusLabel(item);
|
||||
|
||||
item.addEventListener("input", (e) => {
|
||||
setMinusLabel(item, Number(e.target.value));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const createInfoColumn = (data, formElements) => {
|
||||
const inputsContainer = document.querySelector("#bid-extension .inputs");
|
||||
const urlCol = document.querySelector("#url-col");
|
||||
|
|
@ -297,9 +435,19 @@ const createInfoColumn = (data, formElements) => {
|
|||
|
||||
// 1. Thêm ID và Name vào đầu inputsContainer
|
||||
const otherEls = `
|
||||
<div class="col">
|
||||
<label>ID</label>
|
||||
<input readonly value="${data?.id || "None"}" type="text" id="id" />
|
||||
<div class="sub-col">
|
||||
<div class="col">
|
||||
<label>ID</label>
|
||||
<input readonly value="${data?.id || "None"}" type="text" id="id" />
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<label for="mode_key">Mode</label>
|
||||
<select id="mode_key" name="mode_key">
|
||||
<option value="live">Live</option>
|
||||
<option value="sandbox">Sandbox</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
|
|
@ -324,6 +472,65 @@ const createInfoColumn = (data, formElements) => {
|
|||
|
||||
formElements.quantity.value = data?.quantity || 1;
|
||||
formElements.plusPrice.value = data?.plus_price || 0;
|
||||
|
||||
renderMetadaMode(data, formElements);
|
||||
};
|
||||
|
||||
const showCompetitor = () => {
|
||||
const script = document.createElement("script");
|
||||
script.src = chrome.runtime.getURL("injected.js");
|
||||
script.onload = function () {
|
||||
this.remove();
|
||||
};
|
||||
(document.head || document.documentElement).appendChild(script);
|
||||
|
||||
// Nghe dữ liệu trả về
|
||||
window.addEventListener("message", function (event) {
|
||||
if (event.source !== window) return;
|
||||
if (event.data && event.data.source === "my-extension") {
|
||||
const bidHistory = event.data?.bidHistory || [];
|
||||
const maxProxy = bidHistory.reduce((max, curr) => {
|
||||
return curr.proxyamount > max.proxyamount ? curr : max;
|
||||
}, bidHistory[0]);
|
||||
|
||||
console.log({ bidHistory });
|
||||
|
||||
const competitorEl = document.getElementById("competitor-max-bid-col");
|
||||
const competitorInput = document.querySelector(
|
||||
"#competitor-max-bid-col input"
|
||||
);
|
||||
|
||||
competitorEl.style.display = "block";
|
||||
|
||||
competitorInput.value = maxProxy?.proxyamount || "None";
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
const getMode = (data) => {
|
||||
return (
|
||||
data.metadata.find((item) => item.key_name === "mode_key")?.value || "live"
|
||||
);
|
||||
};
|
||||
|
||||
const getEarlyTrackingSeconds = (data, outsiteMode = null) => {
|
||||
const mode = outsiteMode ? outsiteMode : getMode(data);
|
||||
|
||||
return (
|
||||
data.metadata.find(
|
||||
(item) => item.key_name === `early_tracking_seconds_${mode}`
|
||||
)?.value || data.web_bid.early_tracking_seconds
|
||||
);
|
||||
};
|
||||
|
||||
const getArrivalOffsetSeconds = (data, outsiteMode = null) => {
|
||||
const mode = outsiteMode ? outsiteMode : getMode(data);
|
||||
|
||||
return (
|
||||
data.metadata.find(
|
||||
(item) => item.key_name === `arrival_offset_seconds_${mode}`
|
||||
)?.value || data.web_bid.arrival_offset_seconds
|
||||
);
|
||||
};
|
||||
|
||||
const showInfo = async (model, formElements) => {
|
||||
|
|
@ -353,6 +560,8 @@ const showInfo = async (model, formElements) => {
|
|||
return null;
|
||||
}
|
||||
|
||||
window["__result"] = result.data;
|
||||
|
||||
formElements.maxPrice.value = result.data.max_price;
|
||||
|
||||
createInfoColumn(result.data, formElements);
|
||||
|
|
@ -368,13 +577,22 @@ const showInfo = async (model, formElements) => {
|
|||
(async () => {
|
||||
await showPage();
|
||||
handleToogle();
|
||||
|
||||
const formElements = {
|
||||
url: document.querySelector("#form-bid #url"),
|
||||
maxPrice: document.querySelector("#form-bid #maxPrice"),
|
||||
plusPrice: document.querySelector("#form-bid #plusPrice"),
|
||||
quantity: document.querySelector("#form-bid #quantity"),
|
||||
createBtn: document.querySelector("#form-bid #createBtn"),
|
||||
modeKey: document.querySelector("#form-bid #mode_key"),
|
||||
metadataModeBox: document.querySelector("#form-bid #metadataMode"),
|
||||
metadataMode: {
|
||||
arrival_offset_seconds: document.querySelector(
|
||||
"#form-bid #arrival_offset_seconds"
|
||||
),
|
||||
early_tracking_seconds: document.querySelector(
|
||||
"#form-bid #early_tracking_seconds"
|
||||
),
|
||||
},
|
||||
form: document.querySelector("#form-bid form"),
|
||||
};
|
||||
|
||||
|
|
@ -391,6 +609,12 @@ const showInfo = async (model, formElements) => {
|
|||
|
||||
if (!model) return;
|
||||
|
||||
switch (extractDomain(currentUrl)) {
|
||||
case webs.allbids: {
|
||||
showCompetitor();
|
||||
}
|
||||
}
|
||||
|
||||
// set url on form
|
||||
formElements.url.value = currentUrl;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,16 @@
|
|||
(function () {
|
||||
let data = null;
|
||||
const elements = document.querySelectorAll(".ng-scope");
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
const scope = window.angular?.element(elements[i]).scope();
|
||||
if (scope && scope.auction) {
|
||||
console.log("Found at index:", i, "Auction:", scope.bidHistory);
|
||||
data = scope.bidHistory;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (data) {
|
||||
window.postMessage({ source: "my-extension", bidHistory: data }, "*");
|
||||
}
|
||||
})();
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Bid Extension",
|
||||
"version": "1.2",
|
||||
"version": "1.3",
|
||||
"description": "Bid Extension",
|
||||
"action": {
|
||||
"default_popup": "pages/popup/popup.html",
|
||||
|
|
@ -28,7 +28,8 @@
|
|||
"pages/popup/popup.html",
|
||||
"assets/css/index.css",
|
||||
"config.js",
|
||||
"assets/icons/*"
|
||||
"assets/icons/*",
|
||||
"injected.js"
|
||||
],
|
||||
"matches": ["<all_urls>"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
id="toggle-bid-extension"
|
||||
style="
|
||||
padding: 12px 20px;
|
||||
max-height: 44px;
|
||||
background: #2c2f36;
|
||||
color: #ffffff;
|
||||
border: none;
|
||||
|
|
@ -96,7 +97,7 @@
|
|||
border-radius: 12px;
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
|
||||
padding: 20px;
|
||||
width: 320px;
|
||||
width: 500px;
|
||||
"
|
||||
>
|
||||
<!-- Form bid -->
|
||||
|
|
@ -104,25 +105,72 @@
|
|||
<form class="container">
|
||||
<h2>Bid</h2>
|
||||
<div class="inputs">
|
||||
<div style="display: none" id="competitor-max-bid-col" class="col">
|
||||
<label>Competior max bid</label>
|
||||
<input readonly type="text" id="competitor-max-bid" />
|
||||
</div>
|
||||
|
||||
<div id="url-col" class="col">
|
||||
<label>Url</label>
|
||||
<input readonly type="text" id="url" />
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<div id="max-price-col" class="col">
|
||||
<label>Max price</label>
|
||||
<input type="number" id="maxPrice" />
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<label>Plus price</label>
|
||||
<input type="number" id="plusPrice" />
|
||||
<div class="sub-col">
|
||||
<div class="col">
|
||||
<label>Plus price</label>
|
||||
<input type="number" id="plusPrice" />
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<label>Quantity</label>
|
||||
<input type="number" id="quantity" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<label>Quantity</label>
|
||||
<input type="number" id="quantity" />
|
||||
<div style="display: none" id="metadataMode" class="sub-col">
|
||||
<div class="col">
|
||||
<label for="arrival_offset_seconds">Arrival offset seconds</label>
|
||||
<input
|
||||
type="number"
|
||||
id="arrival_offset_seconds"
|
||||
name="arrival_offset_seconds"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<label for="early_tracking_seconds">Early tracking seconds</label>
|
||||
<input
|
||||
type="number"
|
||||
id="early_tracking_seconds"
|
||||
name="early_tracking_seconds"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div style="display: none" id="metadata-mode-sandbox" class="sub-col">
|
||||
<div class="col">
|
||||
<label>Arrival offset seconds</label>
|
||||
<input
|
||||
type="number"
|
||||
id="arrival_offset_seconds_sandbox"
|
||||
name="arrival_offset_seconds_sandbox"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="col">
|
||||
<label>Early tracking seconds</label>
|
||||
<input
|
||||
type="number"
|
||||
id="early_tracking_seconds_sandbox"
|
||||
name="early_tracking_seconds_sandbox"
|
||||
/>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
<button type="submit" id="createBtn">Create</button>
|
||||
</form>
|
||||
|
|
|
|||
Loading…
Reference in New Issue