Merge pull request #2 from 45Drives/dev-josh

Dev josh
This commit is contained in:
Josh Boudreau 2021-05-28 15:08:23 -03:00 committed by GitHub
commit 9b2886e81b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 197 additions and 16 deletions

View File

@ -22,7 +22,7 @@
--border: #bebebe;
--navigation: #fff;
--font: #1c1c1c;
--selected: #fff;
--selected: #f8f8f8;
--toggle-light: #151515;
--toggle-dark: #ccc;
--scrollbar-thumb: var(--border);
@ -31,8 +31,9 @@
--loading-bg-color: rgba(255, 255, 255, 0.5);
--textarea-bg: var(--navigation);
--logo-45: #333;
--nav-entry-color: #4f99e4;
--nav-entry-color: #555F6E;
--nav-border-radius: 4px;
--symlink-symbol-color: var(--navigation);
}
[data-theme="dark"] {
@ -48,7 +49,8 @@
--loading-bg-color: rgba(33, 36, 39, 0.5);
--textarea-bg: var(--navigation);
--logo-45: #fff;
--nav-entry-color: var(--border);
--nav-entry-color: #555F6E;
--symlink-symbol-color: var(--navigation);
}
.pf-c-button:disabled[data-theme="dark"] {
@ -215,12 +217,29 @@ input[type="text"] {
}
.nav-item .nav-item-icon {
position: relative;
text-align: center;
width: 100px;
font-size: 80px;
color: var(--nav-entry-color);
}
.nav-item-symlink-symbol-dir {
position: absolute;
color: var(--symlink-symbol-color);
font-size: 12pt;
bottom: 18%;
right: 15%;
}
.nav-item-symlink-symbol-file {
position: absolute;
color: var(--symlink-symbol-color);
font-size: 12pt;
bottom: 8%;
right: 25%;
}
.nav-info-column {
background-color: var(--container);
flex-basis: 0;

View File

@ -92,11 +92,19 @@
</div>
<div class="nav-property-pair">
<span class="nav-property-pair-key">Owner</span>
<input type="text" class="nav-property-pair-value" id="nav-edit-owner"></input>
<input type="text" list="possible-owners-list" autocomplete="off" class="nav-property-pair-value" id="nav-edit-owner"></input>
<datalist id="possible-owners-list">
<select id="possible-owners">
</select>
</datalist>
</div>
<div class="nav-property-pair">
<span class="nav-property-pair-key">Group</span>
<input type="text" class="nav-property-pair-value" id="nav-edit-group"></input>
<input type="text" list="possible-groups-list" autocomplete="off" class="nav-property-pair-value" id="nav-edit-group"></input>
<datalist id="possible-groups-list">
<select id="possible-groups">
</select>
</datalist>
</div>
<div class="nav-property-pair">
<span class="nav-property-pair-key">Mode</span>

View File

@ -404,6 +404,73 @@ class NavFile extends NavEntry {
}
}
class NavFileLink extends NavFile{
/**
*
* @param {string} path
* @param {object} stat
* @param {NavWindow} nav_window_ref
* @param {string} link_target
*/
constructor(path, stat, nav_window_ref, link_target) {
super(path, stat, nav_window_ref);
var link_icon = this.dom_element.nav_item_icon.link_icon = document.createElement("i");
link_icon.classList.add("fas", "fa-link", "nav-item-symlink-symbol-file");
this.dom_element.nav_item_icon.appendChild(link_icon);
this.double_click = false;
this.link_target = link_target;
}
show_properties() {
var extra_properties = property_entry_html("Link Target", this.link_target);
super.show_properties(extra_properties);
}
/**
*
* @returns {string}
*/
get_link_target_path() {
var target = "";
if(this.link_target.charAt(0) === '/')
target = this.link_target;
else
target = "/" + this.parent_dir().join("/") + "/" + this.link_target;
return target;
}
async show_edit_file_contents() {
for (let button of document.getElementsByTagName("button")) {
if (!button.classList.contains("editor-btn"))
button.disabled = true;
}
document.getElementById("pwd").disabled = true;
var target_path = this.get_link_target_path();
var proc_output = await cockpit.spawn(["file", "--mime-type", target_path], {superuser: "try"});
var fields = proc_output.split(':');
var type = fields[1].trim();
if(!(type.match(/^text/) || type.match(/^inode\/x-empty$/) || this.stat["size"] === 0)){
if(!window.confirm("File is of type `" + type + "`. Are you sure you want to edit it?"))
return;
}
var contents = await cockpit.spawn(["cat", target_path], {superuser: "try"});
document.getElementById("nav-edit-contents-textarea").value = contents;
document.getElementById("nav-cancel-edit-contents-btn").onclick = this.hide_edit_file_contents.bind(this);
document.getElementById("nav-continue-edit-contents-btn").onclick = this.write_to_file.bind(this);
document.getElementById("nav-edit-contents-header").innerText = "Editing " + this.path_str();
document.getElementById("nav-contents-view").style.display = "none";
document.getElementById("nav-edit-contents-view").style.display = "flex";
}
async write_to_file() {
var target_path = this.get_link_target_path();
var new_contents = document.getElementById("nav-edit-contents-textarea").value;
await cockpit.script("echo -n \"$1\" > $2", [new_contents, target_path], {superuser: "try"});
this.nav_window_ref.refresh();
this.hide_edit_file_contents();
}
}
class NavDir extends NavEntry {
/**
*
@ -465,10 +532,20 @@ class NavDir extends NavEntry {
var filename = entry["filename"];
var path = (this.path.length >= 1 && this.path[0]) ? [...this.path, filename] : [filename];
var stat = entry["stat"];
if (entry["isdir"])
children.push(new NavDir(path, stat, nav_window_ref));
else
children.push(new NavFile(path, stat, nav_window_ref));
switch(stat["mode-str"].charAt(0)) {
case 'd':
children.push(new NavDir(path, stat, nav_window_ref));
break;
case 'l':
if(entry["isdir"])
children.push(new NavDirLink(path, stat, nav_window_ref, entry["link-target"]));
else
children.push(new NavFileLink(path, stat, nav_window_ref, entry["link-target"]));
break;
default:
children.push(new NavFile(path, stat, nav_window_ref));
break;
}
});
children.sort((first, second) => {
if (first.nav_type === second.nav_type) {
@ -494,7 +571,7 @@ class NavDir extends NavEntry {
/**
*
* @returns {any}
* @returns {Object}
*/
async cephfs_dir_stats() {
try {
@ -508,8 +585,11 @@ class NavDir extends NavEntry {
}
}
async show_properties() {
var extra_properties = "";
/**
*
* @param {string} extra_properties
*/
async show_properties(extra_properties = "") {
if(!this.hasOwnProperty("ceph_stats"))
this.ceph_stats = await this.cephfs_dir_stats();
// See if a JSON object exists for folder we are currently looking at
@ -553,6 +633,40 @@ class NavDir extends NavEntry {
}
}
class NavDirLink extends NavDir{
/**
*
* @param {string|string[]} path
* @param {object} stat
* @param {NavWindow} nav_window_ref
* @param {string} link_target
*/
constructor(path, stat, nav_window_ref, link_target) {
super(path, stat, nav_window_ref);
var link_icon = this.dom_element.nav_item_icon.link_icon = document.createElement("i");
link_icon.classList.add("fas", "fa-link", "nav-item-symlink-symbol-dir");
this.dom_element.nav_item_icon.appendChild(link_icon);
this.double_click = false;
this.link_target = link_target;
}
async rm() {
var proc = cockpit.spawn(
["rm", "-f", this.path_str()],
{superuser: "try", err: "out"}
);
proc.fail((e, data) => {
window.alert(data);
});
await proc;
}
show_properties() {
var extra_properties = property_entry_html("Link Target", this.link_target);
super.show_properties(extra_properties);
}
}
class NavWindow {
constructor() {
this.path_stack = (localStorage.getItem('navigator-path') ?? '/').split('/');
@ -645,7 +759,7 @@ class NavWindow {
/**
*
* @param {any} entry
* @param {NavEntry} entry
*/
set_selected(entry) {
this.hide_edit_selected();
@ -828,7 +942,6 @@ class NavWindow {
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)
@ -876,6 +989,38 @@ class NavWindow {
}
this.refresh();
}
async get_system_users() {
var proc = cockpit.spawn(["getent", "passwd"], {err: "ignore", superuser: "try"});
var list = document.getElementById("possible-owners");
while(list.firstChild) {
list.removeChild(list.firstChild);
}
var passwd = await proc;
var passwd_entries = passwd.split("\n");
for (let entry of passwd_entries) {
var cols = entry.split(":");
var username = cols[0];
var option = document.createElement("option");
option.value = username;
list.appendChild(option);
}
}
async get_system_groups() {
var proc = cockpit.spawn(["getent", "group"], {err: "ignore", superuser: "try"});
var list = document.getElementById("possible-groups");
while(list.firstChild) {
list.removeChild(list.firstChild);
}
var group = await proc;
var group_entries = group.split("\n");
for (let entry of group_entries) {
var cols = entry.split(":");
var groupname = cols[0];
var option = document.createElement("option");
option.value = groupname;
list.appendChild(option);
}
}
}
let nav_window = new NavWindow();
@ -905,7 +1050,12 @@ function set_up_buttons() {
async function main() {
set_last_theme_state();
load_hidden_file_state(nav_window);
await nav_window.refresh();
var get_users = nav_window.get_system_users();
var get_groups = nav_window.get_system_groups();
var refresh = nav_window.refresh();
await get_users;
await get_groups;
await refresh;
set_up_buttons();
}

View File

@ -18,7 +18,7 @@
"""
import os
from stat import S_ISDIR, filemode
from stat import S_ISDIR, S_ISLNK, filemode
import json
import sys
from pwd import getpwuid
@ -31,6 +31,9 @@ def get_stat(full_path, filename = '/'):
isdir = S_ISDIR(os.stat(full_path).st_mode)
except OSError:
pass
link_target = '?'
if S_ISLNK(stats.st_mode):
link_target = os.readlink(full_path)
owner = '?'
try:
owner = getpwuid(stats.st_uid).pw_name
@ -44,6 +47,7 @@ def get_stat(full_path, filename = '/'):
response = {
"filename": filename,
"isdir": isdir,
"link-target": link_target,
"stat": {
"mode": stats.st_mode,
"mode-str": filemode(stats.st_mode),