mirror of
https://github.com/45Drives/cockpit-navigator.git
synced 2025-07-29 16:45:13 +02:00
Merge pull request #32 from 45Drives/dev-josh
Fix permissions & ownership while editing files, add edit and upload buttons
This commit is contained in:
commit
0f4b9d07de
@ -1,6 +1,4 @@
|
||||
## Cockpit Navigator 0.5.4-1
|
||||
## Cockpit Navigator 0.5.5-1
|
||||
|
||||
* Add fuzzy search.
|
||||
* Optimize folder uploads.
|
||||
* Fix bugs with selecting entries and renaming files.
|
||||
* Stop user from deleting or renaming system-critical paths.
|
||||
* Fix maintaining file permissions and ownership after editing file.
|
||||
* Add file upload button to top bar.
|
10
README.md
10
README.md
@ -23,17 +23,17 @@ With no command line use needed, you can:
|
||||
# Installation
|
||||
## From Github Release
|
||||
### Ubuntu
|
||||
1. `$ wget https://github.com/45Drives/cockpit-navigator/releases/download/v0.5.4/cockpit-navigator_0.5.4-1focal_all.deb`
|
||||
1. `# apt install ./cockpit-navigator_0.5.4-1focal_all.deb`
|
||||
1. `$ wget https://github.com/45Drives/cockpit-navigator/releases/download/v0.5.5/cockpit-navigator_0.5.5-1focal_all.deb`
|
||||
1. `# apt install ./cockpit-navigator_0.5.5-1focal_all.deb`
|
||||
### EL7
|
||||
1. `# yum install https://github.com/45Drives/cockpit-navigator/releases/download/v0.5.4/cockpit-navigator-0.5.4-1.el7.noarch.rpm`
|
||||
1. `# yum install https://github.com/45Drives/cockpit-navigator/releases/download/v0.5.5/cockpit-navigator-0.5.5-1.el7.noarch.rpm`
|
||||
### EL8
|
||||
1. `# dnf install https://github.com/45Drives/cockpit-navigator/releases/download/v0.5.4/cockpit-navigator-0.5.4-1.el8.noarch.rpm`
|
||||
1. `# dnf install https://github.com/45Drives/cockpit-navigator/releases/download/v0.5.5/cockpit-navigator-0.5.5-1.el8.noarch.rpm`
|
||||
## From Source
|
||||
1. Ensure dependencies are installed: `cockpit`, `python3`, `rsync`, `zip`.
|
||||
1. `$ git clone https://github.com/45Drives/cockpit-navigator.git`
|
||||
1. `$ cd cockpit-navigator`
|
||||
1. `$ git checkout <version>` (v0.5.4 is latest)
|
||||
1. `$ git checkout <version>` (v0.5.5 is latest)
|
||||
1. `# make install`
|
||||
## From 45Drives Repositories
|
||||
### Automatic Repo Setup with Script
|
||||
|
@ -3,7 +3,7 @@
|
||||
"name": "cockpit-navigator",
|
||||
"title": "Cockpit Navigator",
|
||||
"prerelease": false,
|
||||
"version": "0.5.4",
|
||||
"version": "0.5.5",
|
||||
"buildVersion": "1",
|
||||
"author": "Josh Boudreau <jboudreau@45drives.com>",
|
||||
"url": "https://github.com/45Drives/cockpit-navigator",
|
||||
@ -54,7 +54,7 @@
|
||||
],
|
||||
"changelog": {
|
||||
"urgency": "medium",
|
||||
"version": "0.5.4",
|
||||
"version": "0.5.5",
|
||||
"buildVersion": "1",
|
||||
"ignore": [],
|
||||
"date": null,
|
||||
|
@ -17,9 +17,9 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {NavWindow} from "./NavWindow.js";
|
||||
import {format_time_remaining} from "../functions.js";
|
||||
import {ModalPrompt} from "./ModalPrompt.js";
|
||||
import { NavWindow } from "./NavWindow.js";
|
||||
import { format_time_remaining } from "../functions.js";
|
||||
import { ModalPrompt } from "./ModalPrompt.js";
|
||||
|
||||
export class FileUpload {
|
||||
/**
|
||||
|
@ -17,8 +17,8 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {FileUpload} from "./FileUpload.js";
|
||||
import {NavWindow} from "./NavWindow.js";
|
||||
import { FileUpload } from "./FileUpload.js";
|
||||
import { NavWindow } from "./NavWindow.js";
|
||||
|
||||
export class FileUploadManager {
|
||||
/**
|
||||
|
@ -1,20 +1,19 @@
|
||||
/*
|
||||
Cockpit Navigator - A File System Browser for Cockpit.
|
||||
ModalPrompt - A Custom Prompt Module for Cockpit Plugins.
|
||||
Copyright (C) 2021 Josh Boudreau <jboudreau@45drives.com>
|
||||
Copyright (C) 2021 Sam Silver <ssilver@45drives.com>
|
||||
Copyright (C) 2021 Dawson Della Valle <ddellavalle@45drives.com>
|
||||
|
||||
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
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the Lesser 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,
|
||||
|
||||
This program 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 <https://www.gnu.org/licenses/>.
|
||||
Lesser GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the Lesser GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -168,8 +167,20 @@ export class ModalPrompt {
|
||||
this.footer.innerHTML = "";
|
||||
this.footer.append(this.cancel, this.ok);
|
||||
let inputs = [];
|
||||
let simple_prompt = false;
|
||||
|
||||
|
||||
if (typeof requests === "string") {
|
||||
let label = requests;
|
||||
simple_prompt = true;
|
||||
requests = {
|
||||
"key": {
|
||||
"label": label,
|
||||
"type": "text"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof requests === "object") {
|
||||
let req_holder = document.createElement("div");
|
||||
req_holder.style.display = "flex";
|
||||
req_holder.style.flexFlow = "column nowrap";
|
||||
@ -208,7 +219,6 @@ export class ModalPrompt {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.show();
|
||||
inputs[0].focus();
|
||||
@ -222,7 +232,11 @@ export class ModalPrompt {
|
||||
}
|
||||
return new Promise((resolve, reject) => {
|
||||
this.ok.onclick = () => {
|
||||
let response = {};
|
||||
let response
|
||||
if (simple_prompt) {
|
||||
response = inputs[0].value;
|
||||
} else {
|
||||
response = {};
|
||||
for (let input of inputs) {
|
||||
switch (input.type) {
|
||||
case "checkbox":
|
||||
@ -234,6 +248,7 @@ export class ModalPrompt {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
resolve(response);
|
||||
this.hide();
|
||||
}
|
||||
|
@ -17,10 +17,10 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {NavEntry} from "./NavEntry.js";
|
||||
import {NavFile, NavFileLink} from "./NavFile.js";
|
||||
import {NavDir, NavDirLink} from "./NavDir.js";
|
||||
import {NavDownloader} from "./NavDownloader.js";
|
||||
import { NavEntry } from "./NavEntry.js";
|
||||
import { NavFile, NavFileLink } from "./NavFile.js";
|
||||
import { NavDir, NavDirLink } from "./NavDir.js";
|
||||
import { NavDownloader } from "./NavDownloader.js";
|
||||
|
||||
export class NavContextMenu {
|
||||
/**
|
||||
|
@ -17,10 +17,10 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {NavEntry} from "./NavEntry.js";
|
||||
import {NavFile, NavFileLink} from "./NavFile.js";
|
||||
import {NavWindow} from "./NavWindow.js";
|
||||
import {property_entry_html} from "../functions.js";
|
||||
import { NavEntry } from "./NavEntry.js";
|
||||
import { NavFile, NavFileLink } from "./NavFile.js";
|
||||
import { NavWindow } from "./NavWindow.js";
|
||||
import { property_entry_html } from "../functions.js";
|
||||
|
||||
export class NavDir extends NavEntry {
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {NavFile} from "./NavFile.js";
|
||||
import { NavFile } from "./NavFile.js";
|
||||
|
||||
export class NavDownloader {
|
||||
/**
|
||||
|
@ -17,10 +17,10 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {FileUpload} from "./FileUpload.js";
|
||||
import {ModalPrompt} from "./ModalPrompt.js";
|
||||
import {NavWindow} from "./NavWindow.js";
|
||||
import {FileUploadManager} from "./FileUploadManager.js";
|
||||
import { FileUpload } from "./FileUpload.js";
|
||||
import { ModalPrompt } from "./ModalPrompt.js";
|
||||
import { NavWindow } from "./NavWindow.js";
|
||||
import { FileUploadManager } from "./FileUploadManager.js";
|
||||
|
||||
export class NavDragDrop {
|
||||
/**
|
||||
@ -37,6 +37,21 @@ export class NavDragDrop {
|
||||
this.nav_window_ref = nav_window_ref;
|
||||
this.modal_prompt = new ModalPrompt();
|
||||
this.upload_manager = new FileUploadManager(this.nav_window_ref, 6);
|
||||
this.upload_element = document.createElement('input');
|
||||
this.upload_element.type = 'file';
|
||||
this.upload_element.multiple = true;
|
||||
this.upload_element.onchange = async e => {
|
||||
var uploads = []
|
||||
for (const file of e.target.files) {
|
||||
let uploader = new FileUpload(file, this.nav_window_ref);
|
||||
uploader.using_webkit = false;
|
||||
uploads.push(uploader);
|
||||
}
|
||||
uploads = await this.handle_conflicts(uploads);
|
||||
this.upload_manager.add(... uploads);
|
||||
this.nav_window_ref.stop_load();
|
||||
}
|
||||
document.getElementById("nav-upload-btn").addEventListener("click", this.upload_dialog.bind(this));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -196,4 +211,9 @@ export class NavDragDrop {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
upload_dialog() {
|
||||
this.nav_window_ref.start_load();
|
||||
this.upload_element.click();
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,8 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {NavWindow} from "./NavWindow.js";
|
||||
import {format_bytes, property_entry_html, format_time, check_if_exists} from "../functions.js";
|
||||
import { NavWindow } from "./NavWindow.js";
|
||||
import { format_bytes, property_entry_html, format_time, check_if_exists } from "../functions.js";
|
||||
|
||||
export class NavEntry {
|
||||
/**
|
||||
|
@ -17,10 +17,10 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {NavEntry} from "./NavEntry.js";
|
||||
import {NavDownloader} from "./NavDownloader.js";
|
||||
import {NavWindow} from "./NavWindow.js";
|
||||
import {property_entry_html} from "../functions.js";
|
||||
import { NavEntry } from "./NavEntry.js";
|
||||
import { NavDownloader } from "./NavDownloader.js";
|
||||
import { NavWindow } from "./NavWindow.js";
|
||||
import { property_entry_html, simple_spawn } from "../functions.js";
|
||||
|
||||
export class NavFile extends NavEntry {
|
||||
/**
|
||||
@ -93,7 +93,7 @@ export class NavFile extends NavEntry {
|
||||
var fields = proc_output.split(/:(?=[^:]+$)/); // ensure it's the last : with lookahead
|
||||
var type = fields[1].trim();
|
||||
|
||||
if ((/^text/.test(type) || /^inode\/x-empty$/.test(type) || this.stat["size"] === 0)) {
|
||||
if (/^text/.test(type) || /^inode\/x-empty$/.test(type) || this.stat["size"] === 0 || (/^application\/octet-stream/.test(type) && this.stat["size"] === 1)) {
|
||||
this.show_edit_file_contents();
|
||||
} else {
|
||||
console.log("Unknown mimetype: " + type);
|
||||
@ -128,12 +128,9 @@ export class NavFile extends NavEntry {
|
||||
async write_to_file() {
|
||||
var new_contents = document.getElementById("nav-edit-contents-textarea").value;
|
||||
try {
|
||||
if (new_contents.length)
|
||||
await cockpit.file(this.path_str(), {superuser: "try"}).replace(new_contents);
|
||||
else
|
||||
await cockpit.script("echo -n > $1", [this.path_str()], {superuser: "try"});
|
||||
await simple_spawn(["/usr/share/cockpit/navigator/scripts/write-to-file.py3", this.path_str()], new_contents);
|
||||
} catch (e) {
|
||||
this.nav_window_ref.modal_prompt.alert(e.message);
|
||||
this.nav_window_ref.modal_prompt.alert(e);
|
||||
}
|
||||
this.nav_window_ref.refresh();
|
||||
this.hide_edit_file_contents();
|
||||
@ -229,9 +226,9 @@ export class NavFileLink extends NavFile{
|
||||
var target_path = this.get_link_target_path();
|
||||
var new_contents = document.getElementById("nav-edit-contents-textarea").value;
|
||||
try {
|
||||
await cockpit.file(target_path, {superuser: "try"}).replace(new_contents);
|
||||
await simple_spawn(["/usr/share/cockpit/navigator/scripts/write-to-file.py3", target_path], new_contents);
|
||||
} catch (e) {
|
||||
this.nav_window_ref.modal_prompt.alert(e.message);
|
||||
this.nav_window_ref.modal_prompt.alert(e);
|
||||
}
|
||||
this.nav_window_ref.refresh();
|
||||
this.hide_edit_file_contents();
|
||||
|
@ -17,13 +17,13 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {NavEntry} from "./NavEntry.js";
|
||||
import {NavDir} from "./NavDir.js";
|
||||
import {NavContextMenu} from "./NavContextMenu.js";
|
||||
import {NavDragDrop} from "./NavDragDrop.js";
|
||||
import {SortFunctions} from "./SortFunctions.js";
|
||||
import {ModalPrompt} from "./ModalPrompt.js";
|
||||
import {format_bytes, format_permissions} from "../functions.js";
|
||||
import { NavEntry } from "./NavEntry.js";
|
||||
import { NavDir } from "./NavDir.js";
|
||||
import { NavContextMenu } from "./NavContextMenu.js";
|
||||
import { NavDragDrop } from "./NavDragDrop.js";
|
||||
import { SortFunctions } from "./SortFunctions.js";
|
||||
import { ModalPrompt } from "./ModalPrompt.js";
|
||||
import { format_bytes, format_permissions } from "../functions.js";
|
||||
|
||||
export class NavWindow {
|
||||
constructor() {
|
||||
@ -256,6 +256,9 @@ export class NavWindow {
|
||||
this.select_one(this.pwd());
|
||||
this.last_selected_entry = null;
|
||||
this.update_selection_info();
|
||||
var edit_btn = document.getElementById("nav-edit-contents-btn");
|
||||
edit_btn.keep_disabled = edit_btn.disabled = true;
|
||||
edit_btn.onclick = () => {};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,6 +285,17 @@ export class NavWindow {
|
||||
this.select_one(target);
|
||||
}
|
||||
this.update_selection_info();
|
||||
|
||||
var edit_btn = document.getElementById("nav-edit-contents-btn")
|
||||
if (target.nav_type === "file") {
|
||||
edit_btn.keep_disabled = edit_btn.disabled = false;
|
||||
edit_btn.onclick = () => {
|
||||
target.open();
|
||||
};
|
||||
} else {
|
||||
edit_btn.onclick = () => {};
|
||||
edit_btn.keep_disabled = edit_btn.disabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
select_all() {
|
||||
@ -747,6 +761,7 @@ export class NavWindow {
|
||||
document.getElementById("nav-loader-container").style.display = "none";
|
||||
var buttons = document.getElementsByClassName("disable-while-loading");
|
||||
for (let button of buttons) {
|
||||
if (!button.keep_disabled)
|
||||
button.disabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -107,3 +107,25 @@ export function check_if_exists(path) {
|
||||
proc.fail((e, data) => {resolve(true)});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Spawn process and resolve/reject with output
|
||||
*
|
||||
* @param {string[]} argv argv of proc
|
||||
* @param {string | null} input optional input to stdin of proc
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
export function simple_spawn(argv, input = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
var proc = cockpit.spawn(argv, {superuser: "try"});
|
||||
proc.done(data => resolve(data));
|
||||
proc.fail((e, data) => {
|
||||
if (data)
|
||||
reject(data);
|
||||
else
|
||||
reject("Execution error: " + e);
|
||||
});
|
||||
if (input != null)
|
||||
proc.input(input);
|
||||
});
|
||||
}
|
||||
|
@ -23,13 +23,13 @@
|
||||
<base href=".">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
<link href="../base1/cockpit.css" type="text/css" rel="stylesheet">
|
||||
<link href="navigator.css" type="text/css" rel="stylesheet">
|
||||
<link href="style.css" type="text/css" rel="stylesheet">
|
||||
<link href="fontawesome/css/all.min.css" rel="stylesheet">
|
||||
<script src="fontawesome/attribution.js"></script>
|
||||
<script src="../base1/cockpit.js"></script>
|
||||
<script src="../manifests.js"></script>
|
||||
<script src="../*/po.js"></script>
|
||||
<script src="navigator.js" type="module"></script>
|
||||
<script src="main.js" type="module"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="nav-loader-container" id="nav-loader-container">
|
||||
@ -64,6 +64,8 @@
|
||||
<button class="disable-while-loading pf-c-button pf-m-primary" id="nav-touch-btn" title="New File"><i class="fas fa-file-medical"></i></button>
|
||||
<div class="horizontal-spacer"></div>
|
||||
<button class="disable-while-loading pf-c-button pf-m-primary" id="nav-ln-btn" title="New Symbolic Link"><i class="fas fa-link nav-icon-decorated"><i class="fas fa-plus nav-icon-decoration"></i></i></button>
|
||||
<div class="horizontal-spacer"></div>
|
||||
<button class="disable-while-loading pf-c-button pf-m-primary" id="nav-upload-btn" title="Upload File(s)"><i class="fas fa-upload"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="vertical-spacer"></div>
|
||||
@ -102,6 +104,8 @@
|
||||
<button class="disable-while-loading pf-c-button pf-m-danger" id="nav-delete-btn" title="Delete"><i class="fas fa-trash-alt"></i></button>
|
||||
<div class="horizontal-spacer"></div>
|
||||
<button class="disable-while-loading pf-c-button pf-m-primary" id="nav-edit-properties-btn" title="Edit Properties"><i class="fas fa-sliders-h"></i></button>
|
||||
<div class="horizontal-spacer"></div>
|
||||
<button class="disable-while-loading pf-c-button pf-m-primary" id="nav-edit-contents-btn" title="Edit Contents"><i class="fas fa-edit"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="nav-info-column-properties" id="nav-info-column-properties"></div>
|
@ -17,9 +17,9 @@
|
||||
along with Cockpit Navigator. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import {ModalPrompt} from "./components/ModalPrompt.js";
|
||||
import {NavWindow} from "./components/NavWindow.js";
|
||||
import {NAVIGATOR_VERSION} from "./version.js";
|
||||
import { ModalPrompt } from "./components/ModalPrompt.js";
|
||||
import { NavWindow } from "./components/NavWindow.js";
|
||||
import { NAVIGATOR_VERSION } from "./version.js";
|
||||
|
||||
/**
|
||||
*
|
@ -4,7 +4,7 @@
|
||||
"menu": {
|
||||
"navigator": {
|
||||
"label": "Navigator",
|
||||
"path": "navigator.html",
|
||||
"path": "index.html",
|
||||
"order": 114
|
||||
}
|
||||
}
|
||||
|
41
navigator/scripts/write-to-file.py3
Executable file
41
navigator/scripts/write-to-file.py3
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
Cockpit Navigator - A File System Browser for Cockpit.
|
||||
Copyright (C) 2021 Josh Boudreau <jboudreau@45drives.com>
|
||||
|
||||
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 <https://www.gnu.org/licenses/>.
|
||||
"""
|
||||
|
||||
"""
|
||||
Synopsis: echo <contents of file> | write-to-file.py3 <path/to/file>
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
||||
def main():
|
||||
if len(sys.argv) != 2:
|
||||
print("Invalid number of arguments.")
|
||||
sys.exit(1)
|
||||
file_path = sys.argv[1]
|
||||
try:
|
||||
with open(file_path, "w") as f:
|
||||
for line in sys.stdin:
|
||||
f.write(line)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
@ -32,6 +32,9 @@ rm -rf %{buildroot}
|
||||
/usr/share/cockpit/navigator/*
|
||||
|
||||
%changelog
|
||||
* Mon Oct 04 2021 Joshua Boudreau <jboudreau@45drives.com> 0.5.5-1
|
||||
- Fix maintaining file permissions and ownership after editing file.
|
||||
- Add file upload button to top bar.
|
||||
* Tue Jul 20 2021 Josh Boudreau <jboudreau@45drives.com> 0.5.4-1
|
||||
- Add fuzzy search.
|
||||
- Optimize folder uploads.
|
||||
|
@ -32,6 +32,9 @@ rm -rf %{buildroot}
|
||||
/usr/share/cockpit/navigator/*
|
||||
|
||||
%changelog
|
||||
* Mon Oct 04 2021 Joshua Boudreau <jboudreau@45drives.com> 0.5.5-1
|
||||
- Fix maintaining file permissions and ownership after editing file.
|
||||
- Add file upload button to top bar.
|
||||
* Tue Jul 20 2021 Josh Boudreau <jboudreau@45drives.com> 0.5.4-1
|
||||
- Add fuzzy search.
|
||||
- Optimize folder uploads.
|
||||
|
@ -1,3 +1,10 @@
|
||||
cockpit-navigator (0.5.5-1focal) focal; urgency=medium
|
||||
|
||||
* Fix maintaining file permissions and ownership after editing file.
|
||||
* Add file upload button to top bar.
|
||||
|
||||
-- Joshua Boudreau <jboudreau@45drives.com> Mon, 04 Oct 2021 11:14:20 -0300
|
||||
|
||||
cockpit-navigator (0.5.4-1focal) focal; urgency=medium
|
||||
|
||||
* Add fuzzy search.
|
||||
|
Loading…
x
Reference in New Issue
Block a user