lfss 0.2.3__py3-none-any.whl → 0.2.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- frontend/index.html +1 -1
- frontend/popup.css +23 -0
- frontend/popup.js +41 -0
- frontend/scripts.js +33 -12
- frontend/styles.css +10 -2
- lfss/src/server.py +2 -0
- {lfss-0.2.3.dist-info → lfss-0.2.4.dist-info}/METADATA +1 -1
- {lfss-0.2.3.dist-info → lfss-0.2.4.dist-info}/RECORD +10 -10
- {lfss-0.2.3.dist-info → lfss-0.2.4.dist-info}/WHEEL +0 -0
- {lfss-0.2.3.dist-info → lfss-0.2.4.dist-info}/entry_points.txt +0 -0
frontend/index.html
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
<label for="endpoint">Endpoint</label>
|
14
14
|
<input type="text" id="endpoint" placeholder="http://localhost:8000" autocomplete="off">
|
15
15
|
</div>
|
16
|
-
<div class="input-group" style="min-width:
|
16
|
+
<div class="input-group" style="min-width: 300px;">
|
17
17
|
<label for="token">Token</label>
|
18
18
|
<input type="text" id="token" placeholder="" autocomplete="off">
|
19
19
|
</div>
|
frontend/popup.css
CHANGED
@@ -27,4 +27,27 @@ div.floating-window.window{
|
|
27
27
|
flex-direction: column;
|
28
28
|
justify-content: center;
|
29
29
|
align-items: center;
|
30
|
+
}
|
31
|
+
|
32
|
+
div.popup-window{
|
33
|
+
position: fixed;
|
34
|
+
top: 0.5rem;
|
35
|
+
right: 1rem;
|
36
|
+
border-radius: 0.5rem;
|
37
|
+
box-shadow: 0 5px 10px rgba(0,0,0,0.2);
|
38
|
+
color: white;
|
39
|
+
display: block;
|
40
|
+
text-align: left;
|
41
|
+
animation: popup-appear 0.5s ease;
|
42
|
+
}
|
43
|
+
|
44
|
+
@keyframes popup-appear{
|
45
|
+
from{
|
46
|
+
opacity: 0;
|
47
|
+
transform: translateX(1rem);
|
48
|
+
}
|
49
|
+
to{
|
50
|
+
opacity: 1;
|
51
|
+
transform: translateX(0);
|
52
|
+
}
|
30
53
|
}
|
frontend/popup.js
CHANGED
@@ -86,4 +86,45 @@ export function showFloatingWindowLineInput(onSubmit = (v) => {}, {
|
|
86
86
|
}
|
87
87
|
|
88
88
|
return [floatingWindow, closeWindow];
|
89
|
+
}
|
90
|
+
|
91
|
+
const shownPopups = [];
|
92
|
+
export function showPopup(content = '', {
|
93
|
+
level = "info",
|
94
|
+
width = "auto",
|
95
|
+
timeout = 3000,
|
96
|
+
showTime = true
|
97
|
+
} = {}){
|
98
|
+
const popup = document.createElement("div");
|
99
|
+
popup.classList.add("popup-window");
|
100
|
+
popup.innerHTML = showTime? `<span>[${new Date().toLocaleTimeString()}]</span> ${content}` : content;
|
101
|
+
popup.style.width = width;
|
102
|
+
const popupHeight = '1rem';
|
103
|
+
popup.style.height = popupHeight;
|
104
|
+
popup.style.maxHeight = popupHeight;
|
105
|
+
popup.style.minHeight = popupHeight;
|
106
|
+
const paddingHeight = '1rem';
|
107
|
+
popup.style.padding = paddingHeight;
|
108
|
+
|
109
|
+
// traverse shownPopups and update the top position of each popup
|
110
|
+
if (shownPopups.length > 0) {
|
111
|
+
for (let i = 0; i < shownPopups.length; i++) {
|
112
|
+
shownPopups[i].style.top = `${i * (parseInt(popupHeight) + 2*parseInt(paddingHeight))*1.2 + 0.5}rem`;
|
113
|
+
}
|
114
|
+
}
|
115
|
+
popup.style.top = `${shownPopups.length * (parseInt(popupHeight) + 2*parseInt(paddingHeight))*1.2 + 0.5}rem`;
|
116
|
+
|
117
|
+
if (level === "error") popup.style.backgroundColor = "darkred";
|
118
|
+
if (level === "warning") popup.style.backgroundColor = "darkorange";
|
119
|
+
if (level === "info") popup.style.backgroundColor = "darkblue";
|
120
|
+
if (level === "success") popup.style.backgroundColor = "darkgreen";
|
121
|
+
document.body.appendChild(popup);
|
122
|
+
shownPopups.push(popup);
|
123
|
+
window.setTimeout(() => {
|
124
|
+
if (popup.parentNode) document.body.removeChild(popup);
|
125
|
+
shownPopups.splice(shownPopups.indexOf(popup), 1);
|
126
|
+
for (let i = 0; i < shownPopups.length; i++) {
|
127
|
+
shownPopups[i].style.top = `${i * (parseInt(popupHeight) + 2*parseInt(paddingHeight))*1.2 + 0.5}rem`;
|
128
|
+
}
|
129
|
+
}, timeout);
|
89
130
|
}
|
frontend/scripts.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import Connector from './api.js';
|
2
2
|
import { permMap } from './api.js';
|
3
|
-
import { showFloatingWindowLineInput } from './popup.js';
|
3
|
+
import { showFloatingWindowLineInput, showPopup } from './popup.js';
|
4
4
|
import { formatSize, decodePathURI, ensurePathURI, copyToClipboard, getRandomString, cvtGMT2Local, debounce, encodePathURI } from './utils.js';
|
5
5
|
|
6
6
|
const conn = new Connector();
|
@@ -168,7 +168,12 @@ Are you sure you want to proceed?
|
|
168
168
|
let counter = 0;
|
169
169
|
async function uploadFile(...args){
|
170
170
|
const [file, path] = args;
|
171
|
-
|
171
|
+
try{
|
172
|
+
await conn.put(path, file);
|
173
|
+
}
|
174
|
+
catch (err){
|
175
|
+
showPopup('Failed to upload file [' + file.name + ']: ' + err, {level: 'error', timeout: 5000});
|
176
|
+
}
|
172
177
|
counter += 1;
|
173
178
|
console.log("Uploading file: ", counter, "/", files.length);
|
174
179
|
}
|
@@ -261,6 +266,7 @@ function refreshFileList(){
|
|
261
266
|
|
262
267
|
const deleteButton = document.createElement('a');
|
263
268
|
deleteButton.textContent = 'Delete';
|
269
|
+
deleteButton.classList.add('delete-btn');
|
264
270
|
deleteButton.href = '#';
|
265
271
|
deleteButton.addEventListener('click', () => {
|
266
272
|
const dirurl = dir.url + (dir.url.endsWith('/') ? '' : '/');
|
@@ -270,6 +276,8 @@ function refreshFileList(){
|
|
270
276
|
conn.delete(dirurl)
|
271
277
|
.then(() => {
|
272
278
|
refreshFileList();
|
279
|
+
}, (err)=>{
|
280
|
+
showPopup('Failed to delete path: ' + err, {level: 'error', timeout: 5000});
|
273
281
|
});
|
274
282
|
});
|
275
283
|
actContainer.appendChild(deleteButton);
|
@@ -332,7 +340,12 @@ function refreshFileList(){
|
|
332
340
|
console.warn("Permission string mismatch", permStr, permStrFromMap);
|
333
341
|
}
|
334
342
|
}
|
335
|
-
conn.setFilePermission(file.url, perm)
|
343
|
+
conn.setFilePermission(file.url, perm).then(
|
344
|
+
() => {},
|
345
|
+
(err) => {
|
346
|
+
showPopup('Failed to set permission: ' + err, {level: 'error', timeout: 5000});
|
347
|
+
}
|
348
|
+
);
|
336
349
|
});
|
337
350
|
|
338
351
|
accessTd.appendChild(select);
|
@@ -345,23 +358,24 @@ function refreshFileList(){
|
|
345
358
|
const actContainer = document.createElement('div');
|
346
359
|
actContainer.classList.add('action-container');
|
347
360
|
|
348
|
-
const viewButton = document.createElement('a');
|
349
|
-
viewButton.textContent = 'View';
|
350
|
-
viewButton.href = conn.config.endpoint + '/' + file.url + '?token=' + conn.config.token;
|
351
|
-
viewButton.target = '_blank';
|
352
|
-
actContainer.appendChild(viewButton);
|
353
|
-
|
354
361
|
const copyButton = document.createElement('a');
|
362
|
+
copyButton.style.cursor = 'pointer';
|
355
363
|
copyButton.textContent = 'Share';
|
356
|
-
copyButton.href = '#';
|
357
364
|
copyButton.addEventListener('click', () => {
|
358
365
|
copyToClipboard(conn.config.endpoint + '/' + file.url);
|
366
|
+
showPopup('Link copied to clipboard', {level: "success"});
|
359
367
|
});
|
360
368
|
actContainer.appendChild(copyButton);
|
361
369
|
|
370
|
+
const viewButton = document.createElement('a');
|
371
|
+
viewButton.textContent = 'View';
|
372
|
+
viewButton.href = conn.config.endpoint + '/' + file.url + '?token=' + conn.config.token;
|
373
|
+
viewButton.target = '_blank';
|
374
|
+
actContainer.appendChild(viewButton);
|
375
|
+
|
362
376
|
const moveButton = document.createElement('a');
|
363
377
|
moveButton.textContent = 'Move';
|
364
|
-
moveButton.
|
378
|
+
moveButton.style.cursor = 'pointer';
|
365
379
|
moveButton.addEventListener('click', () => {
|
366
380
|
showFloatingWindowLineInput((dstPath) => {
|
367
381
|
dstPath = encodePathURI(dstPath);
|
@@ -371,7 +385,11 @@ function refreshFileList(){
|
|
371
385
|
conn.moveFile(file.url, dstPath)
|
372
386
|
.then(() => {
|
373
387
|
refreshFileList();
|
374
|
-
}
|
388
|
+
},
|
389
|
+
(err) => {
|
390
|
+
showPopup('Failed to move file: ' + err, {level: 'error'});
|
391
|
+
}
|
392
|
+
);
|
375
393
|
}, {
|
376
394
|
text: 'Enter the destination path: ',
|
377
395
|
placeholder: 'Destination path',
|
@@ -388,6 +406,7 @@ function refreshFileList(){
|
|
388
406
|
|
389
407
|
const deleteButton = document.createElement('a');
|
390
408
|
deleteButton.textContent = 'Delete';
|
409
|
+
deleteButton.classList.add('delete-btn');
|
391
410
|
deleteButton.href = '#';
|
392
411
|
deleteButton.addEventListener('click', () => {
|
393
412
|
if (!confirm('Are you sure you want to delete ' + file.url + '?')){
|
@@ -396,6 +415,8 @@ function refreshFileList(){
|
|
396
415
|
conn.delete(file.url)
|
397
416
|
.then(() => {
|
398
417
|
refreshFileList();
|
418
|
+
}, (err) => {
|
419
|
+
showPopup('Failed to delete file: ' + err, {level: 'error', timeout: 5000});
|
399
420
|
});
|
400
421
|
});
|
401
422
|
actContainer.appendChild(deleteButton);
|
frontend/styles.css
CHANGED
@@ -14,7 +14,7 @@ input[type=button], button{
|
|
14
14
|
padding: 0.8rem;
|
15
15
|
margin: 0;
|
16
16
|
border: none;
|
17
|
-
border-radius: 0.
|
17
|
+
border-radius: 0.25rem;
|
18
18
|
cursor: pointer;
|
19
19
|
}
|
20
20
|
|
@@ -23,7 +23,7 @@ input[type=text], input[type=password]
|
|
23
23
|
width: 100%;
|
24
24
|
padding: 0.75rem;
|
25
25
|
border: 1px solid #ccc;
|
26
|
-
border-radius: 0.
|
26
|
+
border-radius: 0.25rem;
|
27
27
|
height: 1rem;
|
28
28
|
}
|
29
29
|
|
@@ -209,4 +209,12 @@ a{
|
|
209
209
|
background-color: #195f8b;
|
210
210
|
transform: scale(1.1);
|
211
211
|
color: white;
|
212
|
+
}
|
213
|
+
|
214
|
+
.delete-btn{
|
215
|
+
color: darkred !important;
|
216
|
+
}
|
217
|
+
.delete-btn:hover{
|
218
|
+
color: white !important;
|
219
|
+
background-color: #990511c7 !important;
|
212
220
|
}
|
lfss/src/server.py
CHANGED
@@ -206,6 +206,8 @@ router_api = APIRouter(prefix="/_api")
|
|
206
206
|
@router_api.get("/bundle")
|
207
207
|
async def bundle_files(path: str, user: DBUserRecord = Depends(get_current_user)):
|
208
208
|
logger.info(f"GET bundle({path}), user: {user.username}")
|
209
|
+
if user.id == 0:
|
210
|
+
raise HTTPException(status_code=401, detail="Permission denied")
|
209
211
|
path = ensure_uri_compnents(path)
|
210
212
|
assert path.endswith("/") or path == ""
|
211
213
|
|
@@ -2,11 +2,11 @@ Readme.md,sha256=HJTfAkTka7i9n8JaA_Sftn1RFOplCviJ16Rq4WsDOFc,1056
|
|
2
2
|
docs/Known_issues.md,sha256=rfdG3j1OJF-59S9E06VPyn0nZKbW-ybPxkoZ7MEZWp8,81
|
3
3
|
docs/Permission.md,sha256=EY1Y4tT5PDdHDb2pXsVgMAJXxkUihTZfPT0_z7Q53FA,1485
|
4
4
|
frontend/api.js,sha256=D_MaQlmBGzzSR30a23Kh3DxPeF8MpKYe5uXSb9srRTU,7281
|
5
|
-
frontend/index.html,sha256=
|
6
|
-
frontend/popup.css,sha256=
|
7
|
-
frontend/popup.js,sha256=
|
8
|
-
frontend/scripts.js,sha256=
|
9
|
-
frontend/styles.css,sha256=
|
5
|
+
frontend/index.html,sha256=JP6Sd-1JdlEfWQ4fjmSs-CrNw-2iq1RlS55SuXJq5lg,2019
|
6
|
+
frontend/popup.css,sha256=VzkjG1ZTLxhHMtTyobnlvqYmVsTmdbJJed2Pu1cc06c,1007
|
7
|
+
frontend/popup.js,sha256=dH5n7C2Vo9gCsMfQ4ajL4D1ETl0Wk9rIldxUb7x0f_c,4634
|
8
|
+
frontend/scripts.js,sha256=TJCTPag_7Dyn6HDB6Px0WO5sroFEZ9IjYDKmFlb5e2c,18053
|
9
|
+
frontend/styles.css,sha256=Ql_-W5dbh6LlJL2Kez8qsqPSF2fckFgmOYP4SMfKJVs,4065
|
10
10
|
frontend/utils.js,sha256=biE2te5ezswZyuwlDTYbHEt7VWKfCcUrusNt1lHjkLw,2263
|
11
11
|
lfss/cli/panel.py,sha256=iGdVmdWYjA_7a78ZzWEB_3ggIOBeUKTzg6F5zLaB25c,1401
|
12
12
|
lfss/cli/serve.py,sha256=bO3GT0kuylMGN-7bZWP4e71MlugGZ_lEMkYaYld_Ntg,985
|
@@ -16,9 +16,9 @@ lfss/src/config.py,sha256=rE2ZCpozSDqdFrVvpItfGb_O3wPh_ErotdLTZ1DA23s,280
|
|
16
16
|
lfss/src/database.py,sha256=2ZgQGd6tDR6daXl3jOOBO1-mHEwNd809m16PopQ8DZg,27535
|
17
17
|
lfss/src/error.py,sha256=S5ui3tJ0uKX4EZnt2Db-KbDmJXlECI_OY95cNMkuegc,218
|
18
18
|
lfss/src/log.py,sha256=7mRHFwhx7GKtm_cRryoEIlRQhHTLQC3Qd-N81YsoKao,5174
|
19
|
-
lfss/src/server.py,sha256=
|
19
|
+
lfss/src/server.py,sha256=j_dHb-EuPYhfkJ8pbGgJZLrOxWt1SqZmU2sP7FN3TBw,11582
|
20
20
|
lfss/src/utils.py,sha256=MrjKc8W2Y7AbgVGadSNAA50tRMbGYWRrA4KUhOCwuUU,694
|
21
|
-
lfss-0.2.
|
22
|
-
lfss-0.2.
|
23
|
-
lfss-0.2.
|
24
|
-
lfss-0.2.
|
21
|
+
lfss-0.2.4.dist-info/METADATA,sha256=k-moYayIKGuaxwrLFVht5MccgOv35lafbX4ODCBaaUQ,1715
|
22
|
+
lfss-0.2.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
23
|
+
lfss-0.2.4.dist-info/entry_points.txt,sha256=nUIJhenyZbcymvPVhrzV7SAtRhd7O52DflbRrpQUC04,110
|
24
|
+
lfss-0.2.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|