From ea07f04a347f393ac03d8f0d12aa1b95a2564ea4 Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Wed, 26 May 2021 13:25:11 -0300 Subject: [PATCH 01/22] add forward and back button instead of just up --- navigator/navigator.html | 4 ++++ navigator/navigator.js | 22 ++++++++++++++++++---- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/navigator/navigator.html b/navigator/navigator.html index f6bb570..caf2832 100644 --- a/navigator/navigator.html +++ b/navigator/navigator.html @@ -33,6 +33,10 @@
- + + + +
diff --git a/navigator/navigator.js b/navigator/navigator.js index b2d40ae..6ce9e02 100644 --- a/navigator/navigator.js +++ b/navigator/navigator.js @@ -206,11 +206,12 @@ class NavDir extends NavEntry { } super.handleEvent(e); } - async get_children(nav_window_ref) { + async get_children(nav_window_ref, no_alert = false) { var children = []; var proc = cockpit.spawn(["/usr/share/cockpit/navigator/scripts/ls.py", this.path_str()], {err:"out", superuser: "try"}); proc.fail((e, data) => { - window.alert(data); + if(!no_alert) + window.alert(data); }) var data = await proc; var response = JSON.parse(data); @@ -284,7 +285,7 @@ class NavWindow { file.show(); this.entries.push(file); }); - document.getElementById("pwd").innerText = this.pwd().path_str(); + document.getElementById("pwd").value = this.pwd().path_str(); this.set_selected(this.pwd()); this.show_selected_properties(); } @@ -427,6 +428,44 @@ class NavWindow { await proc; this.refresh(); } + nav_bar_event_handler(e) { + switch(e.key){ + case 'Enter': + this.nav_bar_cd(); + break; + default: + break; + } + } + nav_bar_cd() { + var new_path = document.getElementById("pwd").value; + this.cd(new NavDir(new_path)); + } + async nav_bar_update_choices() { + var list = document.getElementById("possible-paths"); + var partial_path_str = document.getElementById("pwd").value; + var last_delim = partial_path_str.lastIndexOf('/'); + if(last_delim === -1) + return; + var parent_path_str = partial_path_str.slice(0, last_delim); + if(this.nav_bar_last_parent_path_str === parent_path_str) + return; + this.nav_bar_last_parent_path_str = parent_path_str; + var parent_dir = new NavDir(parent_path_str); + console.log(parent_dir.path_str()); + var error = false; + var objs = await parent_dir.get_children(this, true).catch(() => {error = true}); + if(error) + return; + objs = objs.filter((child) => {return child.nav_type === "dir"}); + while(list.firstChild) + list.removeChild(list.firstChild); + objs.forEach((obj) => { + var option = document.createElement("option"); + option.value = obj.path_str(); + list.appendChild(option); + }); + } } let nav_window = new NavWindow(); @@ -446,6 +485,9 @@ function set_up_buttons() { for(let checkbox of mode_checkboxes){ checkbox.addEventListener("change", nav_window.update_permissions_preview.bind(nav_window)); } + document.getElementById("pwd").addEventListener("input", nav_window.nav_bar_update_choices.bind(nav_window), false); + document.getElementById("pwd").addEventListener("focus", nav_window.nav_bar_update_choices.bind(nav_window), false); + document.getElementById("pwd").addEventListener("keydown", nav_window.nav_bar_event_handler.bind(nav_window)); } async function main() { From 19620e11af1e8d19ced8b2a6740d182b6ad781a4 Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Wed, 26 May 2021 17:15:28 -0300 Subject: [PATCH 05/22] implement file editor --- navigator/navigator.css | 19 +++++++++++++++++ navigator/navigator.html | 11 ++++++++++ navigator/navigator.js | 44 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/navigator/navigator.css b/navigator/navigator.css index 676830d..43b6b50 100644 --- a/navigator/navigator.css +++ b/navigator/navigator.css @@ -145,4 +145,23 @@ flex-flow: row nowrap; justify-content: flex-end; align-items: flex-start; +} + +.editor-header { + font-weight: bold; +} + +.edit-file-contents { + height: 100%; + flex-basis: 0; + flex-grow: 8; + flex-flow: column nowrap; + align-items: stretch; +} + +.edit-file-contents > textarea { + flex-grow: 1; + white-space: pre; + overflow: auto; + resize: none; } \ No newline at end of file diff --git a/navigator/navigator.html b/navigator/navigator.html index 98f937a..f6269d8 100644 --- a/navigator/navigator.html +++ b/navigator/navigator.html @@ -55,6 +55,17 @@
+
+
diff --git a/navigator/navigator.js b/navigator/navigator.js index d51ff45..998a8fe 100644 --- a/navigator/navigator.js +++ b/navigator/navigator.js @@ -39,12 +39,17 @@ function format_permissions(/*int*/ mode) { function set_last_theme_state() { var toggle_switch = document.getElementById("toggle-theme"); var state = localStorage.getItem("houston-theme-state"); + var icon = document.getElementById("houston-theme-icon"); if (state === "light") { toggle_switch.checked = false; document.documentElement.setAttribute("data-theme", "light"); + icon.classList.remove("fa-moon"); + icon.classList.add("fa-sun"); } else if (state === "dark") { toggle_switch.checked = true; document.documentElement.setAttribute("data-theme", "dark"); + icon.classList.remove("fa-sun"); + icon.classList.add("fa-moon"); } else { toggle_switch.checked = false; state = "light"; @@ -53,11 +58,16 @@ function set_last_theme_state() { } function switch_theme(/*event*/ e) { + var icon = document.getElementById("houston-theme-icon"); var state = ""; if (e.target.checked) { state = "dark"; + icon.classList.remove("fa-sun"); + icon.classList.add("fa-moon"); } else { state = "light"; + icon.classList.remove("fa-moon"); + icon.classList.add("fa-sun"); } document.documentElement.setAttribute("data-theme", state); localStorage.setItem("houston-theme-state", state); From 827b138d57a741ff5a8b6fd24d8368c4f4822933 Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Thu, 27 May 2021 14:57:35 -0300 Subject: [PATCH 09/22] color scrollbar, add spinner, disable btns on edit --- navigator/navigator.css | 75 ++++++++++++++++++++++++++++++++++++++++ navigator/navigator.html | 9 +++-- navigator/navigator.js | 23 ++++++++++++ 3 files changed, 105 insertions(+), 2 deletions(-) diff --git a/navigator/navigator.css b/navigator/navigator.css index 0339a72..559f749 100644 --- a/navigator/navigator.css +++ b/navigator/navigator.css @@ -7,6 +7,10 @@ --selected: #fff; --toggle-light: #151515; --toggle-dark: #ccc; + --scrollbar-thumb: var(--border); + --scrollbar-bg: var(--navigation); + --scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-bg); + --loading-bg-color: rgba(255, 255, 255, 0.5); } [data-theme="dark"] { @@ -16,8 +20,79 @@ --navigation: #151515; --font: #fff; --selected: #191a1b; + --scrollbar-thumb: var(--container); + --scrollbar-bg: var(--navigation); + --scrollbar-color: var(--scrollbar-thumb) var(--scrollbar-bg); + --loading-bg-color: rgba(33, 36, 39, 0.5); } +.pf-c-button:disabled[data-theme="dark"] { + background-color: var(--border); +} + +.nav-loader-container { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + background-color: var(--loading-bg-color); + z-index: 10; +} + +.nav-loader-centerer { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 27%; + display: flex; + align-items: center; + align-content: center; +} + +.nav-loader { + margin: auto; + border: 6px solid rgba(0,0,0,0); + border-radius: 50%; + border-top: 6px solid var(--border); + width: 100px; + height: 100px; + -webkit-animation: spin 2s linear infinite; /* Safari */ + animation: spin 2s linear infinite; +} + +/* Safari */ +@-webkit-keyframes spin { + 0% { -webkit-transform: rotate(0deg); } + 100% { -webkit-transform: rotate(360deg); } +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +body::-webkit-scrollbar { + width: 11px; +} + +body { + scrollbar-width: thin; + scrollbar-color: var(--scrollbar-color); +} + +body::-webkit-scrollbar-track { + background: var(--scrollbar-bg); +} + +body::-webkit-scrollbar-thumb { + background-color: var(--scrollbar-thumb) ; + border-radius: 6px; + border: 3px solid var(--scrollbar-bg); +} + + .flex-row { display: flex; flex-direction: row; diff --git a/navigator/navigator.html b/navigator/navigator.html index fc71317..4ad9451 100644 --- a/navigator/navigator.html +++ b/navigator/navigator.html @@ -30,6 +30,11 @@ +
diff --git a/navigator/navigator.js b/navigator/navigator.js index 998a8fe..4c4c7f8 100644 --- a/navigator/navigator.js +++ b/navigator/navigator.js @@ -227,6 +227,10 @@ class NavFile extends NavEntry { await proc; } async show_edit_file_contents() { + for (let button of document.getElementsByTagName("button")) { + if (!button.classList.contains("editor-btn")) + button.disabled = true; + } var proc_output = await cockpit.spawn(["file", "--mime-type", this.path_str()], {superuser: "try"}); var fields = proc_output.split(':'); var type = fields[1].trim(); @@ -251,6 +255,9 @@ class NavFile extends NavEntry { hide_edit_file_contents() { document.getElementById("nav-edit-contents-view").style.display = "none"; document.getElementById("nav-contents-view").style.display = "flex"; + for (let button of document.getElementsByTagName("button")) { + button.disabled = false; + } } } @@ -396,6 +403,7 @@ class NavWindow { } } async refresh() { + this.start_load(); var files = await this.pwd().get_children(this); while (this.entries.length) { var entry = this.entries.pop(); @@ -408,6 +416,7 @@ class NavWindow { document.getElementById("pwd").value = this.pwd().path_str(); this.set_selected(this.pwd()); this.show_selected_properties(); + this.stop_load(); } pwd() { return this.path_stack[this.path_stack_index]; @@ -611,6 +620,20 @@ class NavWindow { list.appendChild(option); }); } + start_load() { + document.getElementById("nav-loader-container").hidden = false; + var buttons = document.getElementsByTagName("button"); + for (let button of buttons) { + button.disabled = true; + } + } + stop_load() { + document.getElementById("nav-loader-container").hidden = true; + var buttons = document.getElementsByTagName("button"); + for (let button of buttons) { + button.disabled = false; + } + } } let nav_window = new NavWindow(); From 15dc03dcb47b6cf0d87e135d11a43ea8e53a0d56 Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Thu, 27 May 2021 15:21:49 -0300 Subject: [PATCH 10/22] add copyright disclaimer --- navigator/navigator.css | 18 ++++++++++++++++++ navigator/navigator.html | 12 ++++++------ navigator/navigator.js | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/navigator/navigator.css b/navigator/navigator.css index 559f749..8d2922b 100644 --- a/navigator/navigator.css +++ b/navigator/navigator.css @@ -1,3 +1,21 @@ +/* + Cockpit Navigator - A filesystem browser for Cockpit. + Copyright (C) 2021 Josh Boudreau + Copyright (C) 2021 Sam Silver + + This file is part of Cockpit Navigator. + Cockpit Navigator is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Cockpit Navigator is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Cockpit Navigator. If not, see . + */ + :root { /* white style */ --container: #fff; diff --git a/navigator/navigator.html b/navigator/navigator.html index 4ad9451..11eb70d 100644 --- a/navigator/navigator.html +++ b/navigator/navigator.html @@ -1,20 +1,20 @@ - diff --git a/navigator/navigator.js b/navigator/navigator.js index 4c4c7f8..c9806f5 100644 --- a/navigator/navigator.js +++ b/navigator/navigator.js @@ -1,3 +1,21 @@ +/* + Cockpit Navigator - A filesystem browser for Cockpit. + Copyright (C) 2021 Josh Boudreau + Copyright (C) 2021 Sam Silver + + This file is part of Cockpit Navigator. + Cockpit Navigator is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + Cockpit Navigator is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with Cockpit Navigator. If not, see . + */ + function property_entry_html(/*string*/ key, /*string*/ value) { var html = ' @@ -122,9 +122,9 @@
- + + diff --git a/navigator/navigator.js b/navigator/navigator.js index 7d4e9dd..416e490 100644 --- a/navigator/navigator.js +++ b/navigator/navigator.js @@ -423,6 +423,8 @@ class NavWindow { } } async refresh() { + var num_dirs = 0; + var num_files = 0; this.start_load(); var files = await this.pwd().get_children(this); while (this.entries.length) { @@ -430,12 +432,18 @@ class NavWindow { entry.destroy(); } files.forEach((file) => { + if (file.nav_type === "dir") + num_dirs++; + else + num_files++; file.show(); this.entries.push(file); }); document.getElementById("pwd").value = this.pwd().path_str(); this.set_selected(this.pwd()); this.show_selected_properties(); + document.getElementById("nav-num-dirs").innerText = num_dirs.toString(); + document.getElementById("nav-num-files").innerText = num_files.toString(); this.stop_load(); } pwd() { From fa75722d3a69fc80b1fd9b2bd54e528537a043cc Mon Sep 17 00:00:00 2001 From: joshuaboud Date: Thu, 27 May 2021 16:22:43 -0300 Subject: [PATCH 19/22] default num dirs and files to "-" --- navigator/navigator.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/navigator/navigator.html b/navigator/navigator.html index 637838d..44a224e 100644 --- a/navigator/navigator.html +++ b/navigator/navigator.html @@ -131,7 +131,7 @@