-
Notifications
You must be signed in to change notification settings - Fork 0
/
script.js
366 lines (304 loc) · 11 KB
/
script.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/* Fetch list of CIDs being pinned */
async function fetchData() {
chrome.storage.local.get(["node_ip", "node_port"]).then(async (keys) => {
const response = await fetch(
`http://${keys.node_ip}:${keys.node_port}/api/v0/pin/ls`,
{
method: "POST",
headers: {
accept: "*/*",
},
}
);
const result = await response.json();
/* Append data to table in Pins tab */
if (Object.keys(result.Keys).length > 0) {
const tableBody = document.querySelector("#pins tbody");
tableBody.innerHTML = "";
for (let x = 0; x < Object.keys(result.Keys).length; x++) {
const row = document.createElement("tr");
const indexCell = document.createElement("td");
indexCell.textContent = x + 1;
const cidCell = document.createElement("td");
// apply CID value to id attribute
const cid_value = Object.keys(result.Keys)[x];
cidCell.textContent = Object.keys(result.Keys)[x].slice(0, 24) + "...";
const typeCell = document.createElement("td");
typeCell.textContent = result.Keys[Object.keys(result.Keys)[x]].Type;
row.appendChild(indexCell);
row.appendChild(cidCell);
row.appendChild(typeCell);
// Add remove button to row
row.appendChild(addRemoveButtonToRow(cid_value));
tableBody.appendChild(row);
}
}
});
}
async function fetchMFSData(directory) {
console.log(directory);
let dir = "";
if (directory == "" || directory == null) {
dir = "/"
} else {
dir = directory
}
const curr = document.getElementById("current-dir");
curr.textContent = `Directory: ${dir}`;
curr.setAttribute("data-dir", dir);
chrome.storage.local.get(["node_ip", "node_port"]).then(async (keys) => {
const response = await fetch(
`http://${keys.node_ip}:${keys.node_port}/api/v0/files/ls?arg=${dir}&long=true&U=true`,
{
method: "POST",
headers: {
accept: "*/*",
},
}
);
const result = await response.json();
if (result.Entries.length > 0) {
const tableBody = document.querySelector("#pins tbody");
tableBody.innerHTML = "";
for (let x = 0; x < result.Entries.length; x++) {
const row = document.createElement("tr");
const indexCell = document.createElement("td");
indexCell.textContent = x + 1;
const nameCell = document.createElement("td");
nameCell.textContent = result.Entries[x].Name.length > 12 ? result.Entries[x].Name.slice(0, 12) + "..." : result.Entries[x].Name;
const cidCell = document.createElement("td");
// apply CID value to id attribute
const cid_value = result.Entries[x].Hash;
cidCell.textContent = "..." + result.Entries[x].Hash.slice(36);
const typeCell = document.createElement("td");
typeCell.textContent = result.Entries[x].Type == 1 ? "Directory" : "File";
// Add onclick handler to cidCell if type is Directory
if (result.Entries[x].Type == 1) {
// Make it appear as a link
cidCell.style.color = "blue";
cidCell.style.textDecoration = "underline";
cidCell.style.cursor = "pointer";
cidCell.onclick = function() {
let ep = `${dir}${result.Entries[x].Name}/`
fetchMFSData(ep)
};
}
row.appendChild(indexCell);
row.append(nameCell);
row.appendChild(cidCell);
row.appendChild(typeCell);
// Add remove button to row
row.appendChild(addRemoveButtonToRow(cid_value, result.Entries[x].Name));
tableBody.appendChild(row);
}
}
});
}
/* Add remove button to row */
function addRemoveButtonToRow(cid, fileName) {
// Create a div and a button to display remove pin option
const container = document.createElement("div");
const hiddenInput = document.createElement("input");
const button = document.createElement("button");
// Setting style and attributes for button
button.innerText = "X";
button.id = "remove-pin";
button.classList.add("btn", "btn-danger");
// Setting style and attributes for hidden value
hiddenInput.type = "hidden";
hiddenInput.id = "pin-id";
hiddenInput.value = cid;
const nameInput = document.createElement("input");
nameInput.type = "hidden";
nameInput.id = "fileName";
nameInput.value = fileName;
// Add elements to container
container.appendChild(hiddenInput);
container.appendChild(nameInput);
container.appendChild(button);
return container;
}
/*Event action that removes the Pinned id from local IPFS node */
async function removePin(cid, fileName, rowid) {
chrome.storage.local.get(["node_ip", "node_port"]).then(async (keys) => {
const curr = document.getElementById("current-dir");
const file = `${curr.getAttribute("data-dir")}${fileName}`;
let response = await fetch(
`http://${keys.node_ip}:${keys.node_port}/api/v0/pin/rm?arg=${cid}`,
{
method: "POST",
}
);
response = await fetch(
`http://${keys.node_ip}:${keys.node_port}/api/v0/files/rm?arg=${file}&recursive=true&force=true`,
{
method: "POST",
}
);
if (response.status === 200) {
const table = document.getElementById("pins");
table.deleteRow(rowid);
alert("Successfully removed pin!")
} else {
alert("Failed to remove pin!");
}
});
}
/* Return an array rows in the table that are not hidden based on filters */
function getVisibleRows(table) {
const rows = table.getElementsByTagName("tr");
const visibleRows = Array.from(rows).filter((row) => {
return (
!row.hasAttribute("style") ||
row.getAttribute("style") !== "display: none;"
);
});
return visibleRows;
}
/* Switch to settings tab */
function clickedSettings() {
let tab = document.getElementById("pin-tab");
let other = document.getElementById("settings-tab");
tab.classList.remove("active");
other.classList.add("active");
let settings = document.getElementById("settings");
settings.style.display = "block";
let pins = document.getElementById("pins");
pins.style.display = "none";
chrome.storage.local.get(["node_ip", "node_port", "node_dir"]).then((result) => {
document.getElementById("ip").value = result.node_ip;
document.getElementById("port").value = result.node_port;
document.getElementById("dir").value = result.node_dir;
});
}
/* Switch to pins tab */
function clickedPins() {
let tab = document.getElementById("pin-tab");
let other = document.getElementById("settings-tab");
tab.classList.add("active");
other.classList.remove("active");
let settings = document.getElementById("settings");
settings.style.display = "none";
let pins = document.getElementById("pins");
pins.style.display = "block";
// Fetch data, capture the unique `Type` values and add them to the filter options
fetchMFSData();
getUniqueTypes();
}
/* Get unique types and add them to the filter options */
function getUniqueTypes() {
// Get the value of the input field with id="filterInput"
const typeFilter = document.getElementById("type-filter");
// create a set to store unique values
const types = new Set();
// Add an "All" option to the filter
types.add("All");
types.add("Directory");
types.add("File");
// If the drop down already has options, remove them
if (typeFilter.options.length > 0) {
typeFilter.innerHTML = "";
}
// Add the unique values to the drop down
types.forEach((type) => {
const option = document.createElement("option");
option.value = type;
option.text = type;
typeFilter.add(option);
});
}
/* Filter table based on the selected type in the drop down menu */
function filterTable() {
// Declare variables
let input, filter, table, tr, td, i, txtValue;
input = document.getElementById("type-filter");
filter = input.value.toUpperCase();
table = document.getElementById("pins");
rows = table.getElementsByTagName("tr");
// Loop through all table rows, and hide those who don't match the filter
for (i = 1; i < rows.length; i++) {
td = rows[i].getElementsByTagName("td")[3]; // assuming "Type" column is the third column
if (td) {
txtValue = td.textContent || td.innerText;
if (filter === "ALL" || txtValue.toUpperCase().indexOf(filter) > -1) {
rows[i].style.display = "";
} else {
rows[i].style.display = "none";
}
}
}
}
/* Save node configuration */
async function saveSettings() {
let dir = document.getElementById("dir").value;
let ip = document.getElementById("ip").value;
let port = document.getElementById("port").value;
// Check edge cases
if (dir != "") {
if (dir[0] != "/") {
alert('Directory must start with "/"');
return;
}
if (dir[dir.length - 1] == "/") {
alert('Directory must not end with "/"');
return;
}
await createMFSDir(ip, port, dir);
}
chrome.storage.local
.set({
node_ip: ip,
node_port: port,
node_dir: dir,
})
.then(() => {
alert("Saved configuration!");
});
}
function resetDirectory() {
const curr = document.getElementById("current-dir");
fetchMFSData(`${curr.getAttribute("data-dir").split("/").slice(0, -2).join("/")}`);
}
/*Create MFS directory in IPFS node*/
async function createMFSDir(node_ip, node_port, directory) {
const response = await fetch(
`http://${node_ip}:${node_port}/api/v0/files/mkdir?arg=${directory}&cid-version=1&parents=true`,
{
method: "POST",
}
);
if (response.status !== 200) {
alert("Failed to create MFS directory pin!");
}
}
/* Event listener actions*/
// Add event listener to the settings tab
document
.getElementById("settings-tab")
.addEventListener("click", clickedSettings);
// Add event listener to the pins tab
document.getElementById("pin-tab").addEventListener("click", clickedPins);
// Add event listener to the filter table based on the selected type in the drop down menu
document.getElementById("type-filter").addEventListener("change", filterTable);
// Add event listener when the `remove-pin` button is clicked and activate the `removePin` function by passing in
// the corresponding value associated with the hidden `pin-id` element
document.addEventListener("click", function (event) {
if (event.target.matches("#remove-pin")) {
// Get the CID value from the hidden input element
const fileName = event.target.parentElement.children[1].value;
const pinId = event.target.parentElement.firstChild.value;
// Get the row index of the button that was clicked. Note that the index starts at 0 but the first row is the header
const rowId = event.target.parentElement.parentElement.rowIndex;
removePin(pinId, fileName, rowId);
}
});
document
.getElementById("save-settings")
.addEventListener("click", saveSettings);
document
.getElementById("back")
.addEventListener("click", resetDirectory);
// Create variable that stores the default dropdown value for the `Type` filter
let lastState = localStorage.setItem("filterType", "All");
fetchMFSData();
getUniqueTypes();