plz / static / js / tree.js
171 lines · 149 sloc · 4.66 KB · cc0e0b1afb9d8e496bb2de9849994f8b5163c647
Raw
1const branchSelectEl = document.querySelector(".branch-select");
2branchSelectEl.addEventListener("change", (event) => {
3 let nextUrl = TREE_BRANCH_PATH_TEMPLATE + event.target.value;
4 if (typeof TREE_MODE !== "undefined" && TREE_MODE === "top-files") {
5 nextUrl += "?mode=top-files";
6 }
7 window.location.href = nextUrl;
8});
9
10branchSelectEl.value = BRANCH_NAME;
11
12// Make the entire row clickable
13const fileEls = document.querySelectorAll(".file");
14
15fileEls.forEach(fileEl => {
16 fileEl.addEventListener("click", () => {
17 window.location = fileEl.querySelector("a").href;
18 });
19});
20
21const starButtonEl = document.querySelector(".star-button");
22
23async function starRepo(repoId) {
24 const url = "/api/v1/repos/" + repoId + "/star";
25 const response = await fetch(url, {
26 method: "POST"
27 });
28 const json = await response.json();
29
30 if (json.success) {
31 return json.result === "true";
32 } else {
33 throw new Error(json.message);
34 }
35}
36
37if (starButtonEl) {
38 starButtonEl.addEventListener("click", () => {
39 starRepo(REPO_ID)
40 .then(() => {
41 location.reload()
42 })
43 .catch((error) => {
44 alert(error.toString());
45 })
46 });
47}
48
49const copyCloneURLButton = document.querySelector(".copy-clone-url-button");
50if (copyCloneURLButton) {
51 copyCloneURLButton.addEventListener("click", async () => {
52 const url = document.querySelector(".clone-input-group > input").value;
53
54 if (navigator && navigator.clipboard && navigator.clipboard.writeText) {
55 return navigator.clipboard.writeText(url);
56 }
57
58 alert("The Clipboard API is not available.");
59 });
60}
61
62const watchButtonEl = document.querySelector(".watch-button");
63
64async function watchRepo(repoId) {
65 const url = "/api/v1/repos/" + repoId + "/watch";
66 const response = await fetch(url, {
67 method: "POST"
68 });
69 const json = await response.json();
70
71 if (json.success) {
72 return json.result;
73 } else {
74 throw new Error(json.message);
75 }
76}
77
78if (watchButtonEl) {
79 watchButtonEl.addEventListener("click", () => {
80 watchRepo(REPO_ID)
81 .then(() => {
82 location.reload()
83 })
84 .catch((error) => {
85 alert(error.toString());
86 })
87 });
88}
89
90// Poll for file commit info (last_msg, last_hash, last_time) that may still be loading
91(function() {
92 function findDataEl(attr, value) {
93 const els = document.querySelectorAll("[" + attr + "]");
94 for (const el of els) {
95 if (el.getAttribute(attr) === value) return el;
96 }
97 return null;
98 }
99
100 // Check if any file rows are missing delayed info
101 function hasMissingInfo() {
102 const msgEls = document.querySelectorAll("[data-msg-for]");
103 for (const el of msgEls) {
104 const link = el.querySelector("a");
105 if (!link || link.textContent.trim() === "") return true;
106 }
107 if (TREE_FOLDER_SIZE_ENABLED) {
108 const sizeEls = document.querySelectorAll("[data-size-for]");
109 for (const el of sizeEls) {
110 if (el.textContent.trim() === "") return true;
111 }
112 }
113 return false;
114 }
115
116 if (!hasMissingInfo()) return;
117
118 const path = typeof CURRENT_PATH !== "undefined" ? CURRENT_PATH : "";
119 const apiUrl = "/api/v1/repos/" + REPO_ID + "/tree/files?branch=" +
120 encodeURIComponent(BRANCH_NAME) + "&path=" + encodeURIComponent(path);
121
122 let attempts = 0;
123 const maxAttempts = 60;
124
125 function applyFiles(files) {
126 for (const file of files) {
127 if (file.last_msg) {
128 const msgEl = findDataEl("data-msg-for", file.name);
129 if (msgEl) {
130 const link = msgEl.querySelector("a");
131 if (link && link.textContent.trim() === "") {
132 link.textContent = file.last_msg;
133 if (file.last_hash) {
134 link.href = "/" + REPO_USER + "/" + REPO_NAME + "/commit/" + file.last_hash;
135 }
136 }
137 }
138 }
139 const timeEl = findDataEl("data-time-for", file.name);
140 if (timeEl && timeEl.textContent.trim() === "" && file.last_time) {
141 timeEl.textContent = file.last_time;
142 }
143 if (TREE_FOLDER_SIZE_ENABLED && file.size) {
144 const sizeEl = findDataEl("data-size-for", file.name);
145 if (sizeEl && sizeEl.textContent.trim() === "") {
146 sizeEl.textContent = file.size;
147 }
148 }
149 }
150 }
151
152 function poll() {
153 attempts++;
154 fetch(apiUrl)
155 .then(function(r) { return r.json(); })
156 .then(function(data) {
157 if (data && data.success && Array.isArray(data.result)) {
158 applyFiles(data.result);
159 }
160 })
161 .catch(function() {})
162 .finally(function() {
163 if (hasMissingInfo() && attempts < maxAttempts) {
164 setTimeout(poll, 2000);
165 }
166 });
167 }
168
169 // Start polling after a short delay to give the background task time to begin
170 setTimeout(poll, 1000);
171})();
172