mirror of
https://github.com/qbittorrent/qBittorrent.git
synced 2025-12-17 22:18:05 -06:00
WebUI: prefer range based for loop
Using `entries()` can also save the work of manually handling the index variable. PR #23182.
This commit is contained in:
@@ -71,6 +71,7 @@ export default [
|
|||||||
"Stylistic/semi": "error",
|
"Stylistic/semi": "error",
|
||||||
"Stylistic/spaced-comment": ["error", "always", { exceptions: ["*"] }],
|
"Stylistic/spaced-comment": ["error", "always", { exceptions: ["*"] }],
|
||||||
"Unicorn/no-array-for-each": "error",
|
"Unicorn/no-array-for-each": "error",
|
||||||
|
"Unicorn/no-for-loop": "error",
|
||||||
"Unicorn/no-zero-fractions": "error",
|
"Unicorn/no-zero-fractions": "error",
|
||||||
"Unicorn/prefer-number-properties": "error",
|
"Unicorn/prefer-number-properties": "error",
|
||||||
"Unicorn/switch-case-braces": ["error", "avoid"]
|
"Unicorn/switch-case-braces": ["error", "avoid"]
|
||||||
|
|||||||
@@ -167,8 +167,7 @@
|
|||||||
span.textContent = "";
|
span.textContent = "";
|
||||||
|
|
||||||
// Update renamed column for matched rows
|
// Update renamed column for matched rows
|
||||||
for (let i = 0; i < matchedRows.length; ++i) {
|
for (const row of matchedRows) {
|
||||||
const row = matchedRows[i];
|
|
||||||
const element = document.getElementById(`filesTablefileRenamed${row.rowId}`);
|
const element = document.getElementById(`filesTablefileRenamed${row.rowId}`);
|
||||||
if (element === null)
|
if (element === null)
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -175,8 +175,7 @@ window.qBittorrent.Client ??= (() => {
|
|||||||
const uploadTorrentFiles = (files) => {
|
const uploadTorrentFiles = (files) => {
|
||||||
const fileNames = [];
|
const fileNames = [];
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
for (let i = 0; i < files.length; ++i) {
|
for (const [i, file] of files.entries()) {
|
||||||
const file = files[i];
|
|
||||||
fileNames.push(file.name);
|
fileNames.push(file.name);
|
||||||
// send dummy file name as file name won't be used and may not be encoded properly
|
// send dummy file name as file name won't be used and may not be encoded properly
|
||||||
formData.append("file", file, i);
|
formData.append("file", file, i);
|
||||||
@@ -193,8 +192,7 @@ window.qBittorrent.Client ??= (() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const json = await response.json();
|
const json = await response.json();
|
||||||
for (let i = 0; i < json.length; ++i) {
|
for (const [i, metadata] of json.entries()) {
|
||||||
const metadata = json[i];
|
|
||||||
const title = metadata.name || fileNames[i];
|
const title = metadata.name || fileNames[i];
|
||||||
const hash = metadata.infohash_v2 || metadata.infohash_v1;
|
const hash = metadata.infohash_v2 || metadata.infohash_v1;
|
||||||
createAddTorrentWindow(title, hash, metadata);
|
createAddTorrentWindow(title, hash, metadata);
|
||||||
|
|||||||
@@ -106,8 +106,7 @@ window.qBittorrent.ContextMenu ??= (() => {
|
|||||||
|
|
||||||
// position the sub-menu
|
// position the sub-menu
|
||||||
const uls = this.menu.getElementsByTagName("ul");
|
const uls = this.menu.getElementsByTagName("ul");
|
||||||
for (let i = 0; i < uls.length; ++i) {
|
for (const ul of uls) {
|
||||||
const ul = uls[i];
|
|
||||||
if (ul.classList.contains("scrollableMenu"))
|
if (ul.classList.contains("scrollableMenu"))
|
||||||
ul.style.maxHeight = `${scrollableMenuMaxHeight}px`;
|
ul.style.maxHeight = `${scrollableMenuMaxHeight}px`;
|
||||||
const rectParent = ul.parentNode.getBoundingClientRect();
|
const rectParent = ul.parentNode.getBoundingClientRect();
|
||||||
@@ -536,9 +535,7 @@ window.qBittorrent.ContextMenu ??= (() => {
|
|||||||
const sortedTags = [...tags.keys()];
|
const sortedTags = [...tags.keys()];
|
||||||
sortedTags.sort(window.qBittorrent.Misc.naturalSortCollator.compare);
|
sortedTags.sort(window.qBittorrent.Misc.naturalSortCollator.compare);
|
||||||
|
|
||||||
for (let i = 0; i < sortedTags.length; ++i) {
|
for (const [i, tagName] of sortedTags.entries()) {
|
||||||
const tagName = sortedTags[i];
|
|
||||||
|
|
||||||
const input = document.createElement("input");
|
const input = document.createElement("input");
|
||||||
input.type = "checkbox";
|
input.type = "checkbox";
|
||||||
input.addEventListener("click", (event) => {
|
input.addEventListener("click", (event) => {
|
||||||
|
|||||||
@@ -634,8 +634,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||||||
|
|
||||||
updateHeader(header) {
|
updateHeader(header) {
|
||||||
const ths = this.getRowCells(header);
|
const ths = this.getRowCells(header);
|
||||||
for (let i = 0; i < ths.length; ++i) {
|
for (const [i, th] of ths.entries()) {
|
||||||
const th = ths[i];
|
|
||||||
if (th.columnName !== this.columns[i].name) {
|
if (th.columnName !== this.columns[i].name) {
|
||||||
th.title = this.columns[i].caption;
|
th.title = this.columns[i].caption;
|
||||||
th.textContent = this.columns[i].caption;
|
th.textContent = this.columns[i].caption;
|
||||||
@@ -865,14 +864,14 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||||||
const trs = [...this.getTrs()];
|
const trs = [...this.getTrs()];
|
||||||
const trMap = new Map(trs.map(tr => [tr.rowId, tr]));
|
const trMap = new Map(trs.map(tr => [tr.rowId, tr]));
|
||||||
|
|
||||||
for (let rowPos = 0; rowPos < rows.length; ++rowPos) {
|
for (const row of rows) {
|
||||||
const rowId = rows[rowPos].rowId;
|
const rowId = row.rowId;
|
||||||
const existingTr = trMap.get(rowId);
|
const existingTr = trMap.get(rowId);
|
||||||
if (existingTr !== undefined) {
|
if (existingTr !== undefined) {
|
||||||
this.updateRow(existingTr, fullUpdate);
|
this.updateRow(existingTr, fullUpdate);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const tr = this.createRowElement(rows[rowPos]);
|
const tr = this.createRowElement(row);
|
||||||
|
|
||||||
// TODO look into using DocumentFragment or appending all trs at once for add'l performance gains
|
// TODO look into using DocumentFragment or appending all trs at once for add'l performance gains
|
||||||
// add to end of table - we'll move into the proper order later
|
// add to end of table - we'll move into the proper order later
|
||||||
@@ -885,8 +884,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||||||
|
|
||||||
// reorder table rows
|
// reorder table rows
|
||||||
let prevTr = null;
|
let prevTr = null;
|
||||||
for (let rowPos = 0; rowPos < rows.length; ++rowPos) {
|
for (const [rowPos, { rowId }] of rows.entries()) {
|
||||||
const { rowId } = rows[rowPos];
|
|
||||||
const tr = trMap.get(rowId);
|
const tr = trMap.get(rowId);
|
||||||
trMap.delete(rowId);
|
trMap.delete(rowId);
|
||||||
|
|
||||||
@@ -1061,8 +1059,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||||||
const selectedRowId = this.getSelectedRowId();
|
const selectedRowId = this.getSelectedRowId();
|
||||||
|
|
||||||
let selectedIndex = -1;
|
let selectedIndex = -1;
|
||||||
for (let i = 0; i < visibleRows.length; ++i) {
|
for (const [i, row] of visibleRows.entries()) {
|
||||||
const row = visibleRows[i];
|
|
||||||
if (row.getAttribute("data-row-id") === selectedRowId) {
|
if (row.getAttribute("data-row-id") === selectedRowId) {
|
||||||
selectedIndex = i;
|
selectedIndex = i;
|
||||||
break;
|
break;
|
||||||
@@ -1083,8 +1080,7 @@ window.qBittorrent.DynamicTable ??= (() => {
|
|||||||
const selectedRowId = this.getSelectedRowId();
|
const selectedRowId = this.getSelectedRowId();
|
||||||
|
|
||||||
let selectedIndex = -1;
|
let selectedIndex = -1;
|
||||||
for (let i = 0; i < visibleRows.length; ++i) {
|
for (const [i, row] of visibleRows.entries()) {
|
||||||
const row = visibleRows[i];
|
|
||||||
if (row.getAttribute("data-row-id") === selectedRowId) {
|
if (row.getAttribute("data-row-id") === selectedRowId) {
|
||||||
selectedIndex = i;
|
selectedIndex = i;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -383,8 +383,7 @@ const initializeWindows = () => {
|
|||||||
let torrentsHaveSameShareRatio = true;
|
let torrentsHaveSameShareRatio = true;
|
||||||
|
|
||||||
// check if all selected torrents have same share ratio
|
// check if all selected torrents have same share ratio
|
||||||
for (let i = 0; i < hashes.length; ++i) {
|
for (const hash of hashes) {
|
||||||
const hash = hashes[i];
|
|
||||||
const row = torrentsTable.getRow(hash).full_data;
|
const row = torrentsTable.getRow(hash).full_data;
|
||||||
const origValues = `${row.ratio_limit}|${row.seeding_time_limit}|${row.inactive_seeding_time_limit}|${row.max_ratio}`
|
const origValues = `${row.ratio_limit}|${row.seeding_time_limit}|${row.inactive_seeding_time_limit}|${row.max_ratio}`
|
||||||
+ `|${row.max_seeding_time}|${row.max_inactive_seeding_time}|${row.share_limit_action}`;
|
+ `|${row.max_seeding_time}|${row.max_inactive_seeding_time}|${row.share_limit_action}`;
|
||||||
@@ -1160,10 +1159,8 @@ const initializeWindows = () => {
|
|||||||
const names = [];
|
const names = [];
|
||||||
if (selectedRows.length > 0) {
|
if (selectedRows.length > 0) {
|
||||||
const rows = torrentsTable.getFilteredAndSortedRows();
|
const rows = torrentsTable.getFilteredAndSortedRows();
|
||||||
for (let i = 0; i < selectedRows.length; ++i) {
|
for (const hash of selectedRows)
|
||||||
const hash = selectedRows[i];
|
|
||||||
names.push(rows[hash].full_data.name);
|
names.push(rows[hash].full_data.name);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return names.join("\n");
|
return names.join("\n");
|
||||||
};
|
};
|
||||||
@@ -1198,10 +1195,8 @@ const initializeWindows = () => {
|
|||||||
const magnets = [];
|
const magnets = [];
|
||||||
if (selectedRows.length > 0) {
|
if (selectedRows.length > 0) {
|
||||||
const rows = torrentsTable.getFilteredAndSortedRows();
|
const rows = torrentsTable.getFilteredAndSortedRows();
|
||||||
for (let i = 0; i < selectedRows.length; ++i) {
|
for (const hash of selectedRows)
|
||||||
const hash = selectedRows[i];
|
|
||||||
magnets.push(rows[hash].full_data.magnet_uri);
|
magnets.push(rows[hash].full_data.magnet_uri);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return magnets.join("\n");
|
return magnets.join("\n");
|
||||||
};
|
};
|
||||||
@@ -1215,8 +1210,7 @@ const initializeWindows = () => {
|
|||||||
const comments = [];
|
const comments = [];
|
||||||
if (selectedRows.length > 0) {
|
if (selectedRows.length > 0) {
|
||||||
const rows = torrentsTable.getFilteredAndSortedRows();
|
const rows = torrentsTable.getFilteredAndSortedRows();
|
||||||
for (let i = 0; i < selectedRows.length; ++i) {
|
for (const hash of selectedRows) {
|
||||||
const hash = selectedRows[i];
|
|
||||||
const comment = rows[hash].full_data.comment;
|
const comment = rows[hash].full_data.comment;
|
||||||
if (comment && (comment !== ""))
|
if (comment && (comment !== ""))
|
||||||
comments.push(comment);
|
comments.push(comment);
|
||||||
|
|||||||
@@ -187,8 +187,7 @@ window.qBittorrent.MultiRename ??= (() => {
|
|||||||
const match = matches[i];
|
const match = matches[i];
|
||||||
let replacement = this.#inner_replacement;
|
let replacement = this.#inner_replacement;
|
||||||
// Replace numerical groups
|
// Replace numerical groups
|
||||||
for (let g = 0; g < match.length; ++g) {
|
for (const [g, group] of match.entries()) {
|
||||||
const group = match[g];
|
|
||||||
if (!group)
|
if (!group)
|
||||||
continue;
|
continue;
|
||||||
replacement = replaceGroup(replacement, `$${g}`, group, "\\", false);
|
replacement = replaceGroup(replacement, `$${g}`, group, "\\", false);
|
||||||
|
|||||||
@@ -772,9 +772,9 @@ window.qBittorrent.Search ??= (() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const getPlugin = (name) => {
|
const getPlugin = (name) => {
|
||||||
for (let i = 0; i < searchPlugins.length; ++i) {
|
for (const searchPlugin of searchPlugins) {
|
||||||
if (searchPlugins[i].name === name)
|
if (searchPlugin.name === name)
|
||||||
return searchPlugins[i];
|
return searchPlugin;
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -877,8 +877,7 @@ window.qBittorrent.Search ??= (() => {
|
|||||||
|
|
||||||
if (responseJSON.results) {
|
if (responseJSON.results) {
|
||||||
const results = responseJSON.results;
|
const results = responseJSON.results;
|
||||||
for (let i = 0; i < results.length; ++i) {
|
for (const result of results) {
|
||||||
const result = results[i];
|
|
||||||
const row = {
|
const row = {
|
||||||
rowId: state.rowId,
|
rowId: state.rowId,
|
||||||
descrLink: result.descrLink,
|
descrLink: result.descrLink,
|
||||||
|
|||||||
@@ -200,8 +200,7 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||||||
|
|
||||||
const selectComboboxPriority = (combobox, priority) => {
|
const selectComboboxPriority = (combobox, priority) => {
|
||||||
const options = combobox.options;
|
const options = combobox.options;
|
||||||
for (let i = 0; i < options.length; ++i) {
|
for (const option of options) {
|
||||||
const option = options[i];
|
|
||||||
if (normalizePriority(option.value) === priority)
|
if (normalizePriority(option.value) === priority)
|
||||||
option.selected = true;
|
option.selected = true;
|
||||||
else
|
else
|
||||||
@@ -404,8 +403,8 @@ window.qBittorrent.TorrentContent ??= (() => {
|
|||||||
|
|
||||||
const uniqueRowIds = new Set();
|
const uniqueRowIds = new Set();
|
||||||
const uniqueFileIds = new Set();
|
const uniqueFileIds = new Set();
|
||||||
for (let i = 0; i < rowIds.length; ++i) {
|
for (const [i, rowId] of rowIds.entries()) {
|
||||||
const rows = getAllChildren(rowIds[i], fileIds[i]);
|
const rows = getAllChildren(rowId, fileIds[i]);
|
||||||
for (const rowId of rows.rowIds)
|
for (const rowId of rows.rowIds)
|
||||||
uniqueRowIds.add(rowId);
|
uniqueRowIds.add(rowId);
|
||||||
for (const fileId of rows.fileIds)
|
for (const fileId of rows.fileIds)
|
||||||
|
|||||||
@@ -127,8 +127,7 @@
|
|||||||
const getSelectedRadioValue = (name) => {
|
const getSelectedRadioValue = (name) => {
|
||||||
const radios = document.getElementsByName(name);
|
const radios = document.getElementsByName(name);
|
||||||
|
|
||||||
for (let i = 0; i < radios.length; ++i) {
|
for (const radio of radios) {
|
||||||
const radio = radios[i];
|
|
||||||
if (radio.checked)
|
if (radio.checked)
|
||||||
return radio.value;
|
return radio.value;
|
||||||
}
|
}
|
||||||
@@ -137,8 +136,7 @@
|
|||||||
const setSelectedRadioValue = (name, value) => {
|
const setSelectedRadioValue = (name, value) => {
|
||||||
const radios = document.getElementsByName(name);
|
const radios = document.getElementsByName(name);
|
||||||
|
|
||||||
for (let i = 0; i < radios.length; ++i) {
|
for (const radio of radios) {
|
||||||
const radio = radios[i];
|
|
||||||
if (radio.value === value)
|
if (radio.value === value)
|
||||||
radio.checked = true;
|
radio.checked = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -387,27 +387,27 @@
|
|||||||
clearTimeout(logFilterTimer);
|
clearTimeout(logFilterTimer);
|
||||||
logFilterTimer = -1;
|
logFilterTimer = -1;
|
||||||
|
|
||||||
for (let i = 0; i < responseJSON.length; ++i) {
|
for (const logEntry of responseJSON) {
|
||||||
let row;
|
let row;
|
||||||
if (curTab === "main") {
|
if (curTab === "main") {
|
||||||
row = {
|
row = {
|
||||||
rowId: responseJSON[i].id,
|
rowId: logEntry.id,
|
||||||
message: responseJSON[i].message,
|
message: logEntry.message,
|
||||||
timestamp: responseJSON[i].timestamp,
|
timestamp: logEntry.timestamp,
|
||||||
type: responseJSON[i].type,
|
type: logEntry.type,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
row = {
|
row = {
|
||||||
rowId: responseJSON[i].id,
|
rowId: logEntry.id,
|
||||||
ip: responseJSON[i].ip,
|
ip: logEntry.ip,
|
||||||
timestamp: responseJSON[i].timestamp,
|
timestamp: logEntry.timestamp,
|
||||||
blocked: responseJSON[i].blocked,
|
blocked: logEntry.blocked,
|
||||||
reason: responseJSON[i].reason,
|
reason: logEntry.reason,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
tableInfo[curTab].instance.updateRowData(row);
|
tableInfo[curTab].instance.updateRowData(row);
|
||||||
tableInfo[curTab].last_id = Math.max(Number(responseJSON[i].id), tableInfo[curTab].last_id);
|
tableInfo[curTab].last_id = Math.max(Number(logEntry.id), tableInfo[curTab].last_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
tableInfo[curTab].instance.updateTable();
|
tableInfo[curTab].instance.updateTable();
|
||||||
|
|||||||
@@ -558,8 +558,7 @@
|
|||||||
// subtract 'unread' row
|
// subtract 'unread' row
|
||||||
if ((rssFeedRows.length - 1) === flattenedResp.length) {
|
if ((rssFeedRows.length - 1) === flattenedResp.length) {
|
||||||
match = true;
|
match = true;
|
||||||
for (let i = 0; i < flattenedResp.length; ++i) {
|
for (const [i, newData] of flattenedResp.entries()) {
|
||||||
const newData = flattenedResp[i];
|
|
||||||
const existingData = rssFeedRows[i + 1].full_data;
|
const existingData = rssFeedRows[i + 1].full_data;
|
||||||
|
|
||||||
if (newData.fullName !== existingData.dataPath) {
|
if (newData.fullName !== existingData.dataPath) {
|
||||||
@@ -578,14 +577,14 @@
|
|||||||
// partial refresh
|
// partial refresh
|
||||||
// update status
|
// update status
|
||||||
let statusDiffers = false;
|
let statusDiffers = false;
|
||||||
for (let i = 0; i < flattenedResp.length; ++i) {
|
for (const [i, item] of flattenedResp.entries()) {
|
||||||
const oldStatus = rssFeedRows[i + 1].full_data.status;
|
const oldStatus = rssFeedRows[i + 1].full_data.status;
|
||||||
let status = "default";
|
let status = "default";
|
||||||
if (flattenedResp[i].hasError)
|
if (item.hasError)
|
||||||
status = "hasError";
|
status = "hasError";
|
||||||
if (flattenedResp[i].isLoading)
|
if (item.isLoading)
|
||||||
status = "isLoading";
|
status = "isLoading";
|
||||||
if (flattenedResp[i].isFolder)
|
if (item.isFolder)
|
||||||
status = "isFolder";
|
status = "isFolder";
|
||||||
|
|
||||||
if (oldStatus !== status) {
|
if (oldStatus !== status) {
|
||||||
|
|||||||
@@ -178,16 +178,16 @@
|
|||||||
const updateTable = () => {
|
const updateTable = () => {
|
||||||
const oldPlugins = [...searchPluginsTable.getRowIds()];
|
const oldPlugins = [...searchPluginsTable.getRowIds()];
|
||||||
// remove old rows from the table
|
// remove old rows from the table
|
||||||
for (let i = 0; i < oldPlugins.length; ++i) {
|
for (const oldPlugin of oldPlugins) {
|
||||||
let found = false;
|
let found = false;
|
||||||
for (let j = 0; j < window.qBittorrent.Search.searchPlugins.length; ++j) {
|
for (let j = 0; j < window.qBittorrent.Search.searchPlugins.length; ++j) {
|
||||||
if (window.qBittorrent.Search.searchPlugins[j].name === oldPlugins[i]) {
|
if (window.qBittorrent.Search.searchPlugins[j].name === oldPlugin) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found)
|
if (!found)
|
||||||
searchPluginsTable.removeRow(oldPlugins[i]);
|
searchPluginsTable.removeRow(oldPlugin);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < window.qBittorrent.Search.searchPlugins.length; ++i) {
|
for (let i = 0; i < window.qBittorrent.Search.searchPlugins.length; ++i) {
|
||||||
|
|||||||
@@ -242,23 +242,23 @@
|
|||||||
table.clear();
|
table.clear();
|
||||||
|
|
||||||
if (responseJSON.length > 0) {
|
if (responseJSON.length > 0) {
|
||||||
for (let i = 0; i < responseJSON.length; ++i) {
|
for (const entry of responseJSON) {
|
||||||
const status = responseJSON[i].status;
|
const status = entry.status;
|
||||||
const row = {
|
const row = {
|
||||||
rowId: responseJSON[i].taskID,
|
rowId: entry.taskID,
|
||||||
source_path: responseJSON[i].sourcePath,
|
source_path: entry.sourcePath,
|
||||||
progress: status === "Finished" ? 100 : responseJSON[i].progress,
|
progress: status === "Finished" ? 100 : entry.progress,
|
||||||
status: status,
|
status: status,
|
||||||
torrent_format: responseJSON[i].format,
|
torrent_format: entry.format,
|
||||||
piece_size: responseJSON[i].pieceSize,
|
piece_size: entry.pieceSize,
|
||||||
private: responseJSON[i].private,
|
private: entry.private,
|
||||||
added_on: responseJSON[i].timeAdded,
|
added_on: entry.timeAdded,
|
||||||
start_on: responseJSON[i].timeStarted,
|
start_on: entry.timeStarted,
|
||||||
completion_on: responseJSON[i].timeFinished,
|
completion_on: entry.timeFinished,
|
||||||
trackers: responseJSON[i].trackers,
|
trackers: entry.trackers,
|
||||||
comment: responseJSON[i].comment,
|
comment: entry.comment,
|
||||||
source: responseJSON[i].source,
|
source: entry.source,
|
||||||
error_message: responseJSON[i].errorMessage,
|
error_message: entry.errorMessage,
|
||||||
};
|
};
|
||||||
|
|
||||||
table.updateRowData(row);
|
table.updateRowData(row);
|
||||||
|
|||||||
Reference in New Issue
Block a user