mirror of
https://github.com/45Drives/cockpit-navigator.git
synced 2025-07-30 09:05:23 +02:00
create dynamic prompts for input
This commit is contained in:
parent
35bb8241b7
commit
723941747c
@ -2,7 +2,10 @@ export class ModalPrompt {
|
||||
constructor() {
|
||||
this.ok = document.createElement("button");
|
||||
this.ok.innerText = "OK";
|
||||
this.ok.classList.add("pf-c-button", "pf-m-secondary");
|
||||
this.ok.classList.add("pf-c-button", "pf-m-primary");
|
||||
this.cancel = document.createElement("button");
|
||||
this.cancel.innerText = "Cancel";
|
||||
this.cancel.classList.add("pf-c-button", "pf-m-secondary");
|
||||
this.yes = document.createElement("button");
|
||||
this.yes.innerText = "Yes";
|
||||
this.yes.classList.add("pf-c-button", "pf-m-primary");
|
||||
@ -55,11 +58,21 @@ export class ModalPrompt {
|
||||
this.header.innerText = header;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} message
|
||||
*/
|
||||
set_body(message) {
|
||||
this.body.innerHTML = "";
|
||||
this.body.innerText = message;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} header
|
||||
* @param {string} message
|
||||
* @returns {Promise}
|
||||
*/
|
||||
alert(header, message = "") {
|
||||
this.set_header(header);
|
||||
this.set_body(message);
|
||||
@ -74,12 +87,18 @@ export class ModalPrompt {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} header
|
||||
* @param {string} message
|
||||
* @returns {Promise<boolean>}
|
||||
*/
|
||||
confirm(header, message = "") {
|
||||
this.set_header(header);
|
||||
this.set_body(message);
|
||||
this.footer.innerHTML = "";
|
||||
this.footer.appendChild(this.no);
|
||||
this.footer.appendChild(this.yes);
|
||||
this.footer.append(this.no, this.yes);
|
||||
// this.footer.appendChild(this.yes);
|
||||
this.show();
|
||||
return new Promise((resolve, reject) => {
|
||||
let resolve_true = () => {
|
||||
@ -90,9 +109,86 @@ export class ModalPrompt {
|
||||
resolve(false);
|
||||
this.hide();
|
||||
}
|
||||
this.confirm.onclick = this.yes.onclick = resolve_true;
|
||||
this.yes.onclick = resolve_true;
|
||||
this.no.onclick = resolve_false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} header
|
||||
* @param {Object.<string, {label: string, type: string, default: (string|undefined)}>} request
|
||||
* @returns {Promise<Object|string>}
|
||||
*/
|
||||
prompt(header, requests) {
|
||||
this.set_header(header);
|
||||
this.body.innerHTML = "";
|
||||
this.footer.innerHTML = "";
|
||||
this.footer.append(this.cancel, this.ok);
|
||||
let inputs = [];
|
||||
|
||||
if (typeof requests === "object") {
|
||||
let req_holder = document.createElement("div");
|
||||
req_holder.style.display = "flex";
|
||||
req_holder.style.flexFlow = "column nowrap";
|
||||
req_holder.style.alignItems = "stretch";
|
||||
this.body.appendChild(req_holder);
|
||||
for(let key of Object.keys(requests)) {
|
||||
let row = document.createElement("div");
|
||||
row.style.display = "flex";
|
||||
row.style.alignItems = "baseline";
|
||||
row.style.padding = "2px";
|
||||
let request = requests[key];
|
||||
let label = document.createElement("label");
|
||||
label.for = key;
|
||||
label.innerText = request.label;
|
||||
label.style.marginRight = "1em";
|
||||
label.style.flexBasis = "0";
|
||||
label.style.flexGrow = "1";
|
||||
let req = document.createElement("input");
|
||||
req.id = key;
|
||||
req.type = request.type;
|
||||
req.style.flexBasis = "0";
|
||||
if (request.hasOwnProperty("default")) {
|
||||
req.value = request.default;
|
||||
}
|
||||
row.append(label, req);
|
||||
req_holder.appendChild(row);
|
||||
inputs.push(req);
|
||||
switch (request.type) {
|
||||
case "text":
|
||||
req.style.flexGrow = "3";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.show();
|
||||
inputs[0].focus();
|
||||
return new Promise((resolve, reject) => {
|
||||
this.ok.onclick = () => {
|
||||
let response = {};
|
||||
for (let input of inputs) {
|
||||
switch (input.type) {
|
||||
case "checkbox":
|
||||
response[input.id] = input.checked;
|
||||
break;
|
||||
case "text":
|
||||
default:
|
||||
response[input.id] = input.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
resolve(response);
|
||||
this.hide();
|
||||
}
|
||||
this.cancel.onclick = () => {
|
||||
resolve(null);
|
||||
this.hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,9 +71,18 @@ export class NavContextMenu {
|
||||
|
||||
async rename() {
|
||||
this.hide();
|
||||
var new_name = window.prompt("New Name: ", this.target.filename());
|
||||
if (new_name === null)
|
||||
let response = await this.nav_window_ref.modal_prompt.prompt("Renaming " + this.target.filename(),
|
||||
{
|
||||
new_name: {
|
||||
label: "New Name: ",
|
||||
type: "text",
|
||||
default: this.target.filename()
|
||||
}
|
||||
}
|
||||
);
|
||||
if (response === null)
|
||||
return;
|
||||
var new_name = response.new_name;
|
||||
if (new_name.includes("/")) {
|
||||
this.nav_window_ref.modal_prompt.alert("File name can't contain `/`.");
|
||||
return;
|
||||
|
@ -392,9 +392,21 @@ export class NavWindow {
|
||||
}
|
||||
|
||||
async mkdir() {
|
||||
var new_dir_name = window.prompt("Directory Name: ");
|
||||
if (new_dir_name === null)
|
||||
let response = await this.modal_prompt.prompt("Creating Directory",
|
||||
{
|
||||
new_name: {
|
||||
label: "Name: ",
|
||||
type: "text"
|
||||
}
|
||||
}
|
||||
);
|
||||
if (response === null)
|
||||
return;
|
||||
var new_dir_name = response.new_name;
|
||||
if (new_dir_name === "") {
|
||||
this.modal_prompt.alert("Directory name can't be empty.");
|
||||
return;
|
||||
}
|
||||
if (new_dir_name.includes("/")) {
|
||||
this.modal_prompt.alert("Directory name can't contain `/`.");
|
||||
return;
|
||||
@ -420,9 +432,21 @@ export class NavWindow {
|
||||
}
|
||||
|
||||
async touch() {
|
||||
var new_file_name = window.prompt("File Name: ");
|
||||
if (new_file_name === null)
|
||||
let response = await this.modal_prompt.prompt("Creating File",
|
||||
{
|
||||
new_name: {
|
||||
label: "Name: ",
|
||||
type: "text"
|
||||
}
|
||||
}
|
||||
);
|
||||
if (response === null)
|
||||
return;
|
||||
var new_file_name = response.new_name;
|
||||
if (new_file_name === "") {
|
||||
this.modal_prompt.alert("File name can't be empty.");
|
||||
return;
|
||||
}
|
||||
if (new_file_name.includes("/")) {
|
||||
this.modal_prompt.alert("File name can't contain `/`.");
|
||||
return;
|
||||
@ -448,12 +472,31 @@ export class NavWindow {
|
||||
}
|
||||
|
||||
async ln(default_target = "") {
|
||||
var link_target = window.prompt("Link Target: ", default_target);
|
||||
if (link_target === null)
|
||||
let response = await this.modal_prompt.prompt("Creating Symbolic Link",
|
||||
{
|
||||
target: {
|
||||
label: "Target: ",
|
||||
type: "text",
|
||||
default: default_target
|
||||
},
|
||||
name: {
|
||||
label: "Name: ",
|
||||
type: "text"
|
||||
}
|
||||
}
|
||||
);
|
||||
if (response === null)
|
||||
return;
|
||||
var link_name = window.prompt("Link Name: ");
|
||||
if (link_name === null)
|
||||
var link_target = response.target;
|
||||
if (link_target === "") {
|
||||
this.modal_prompt.alert("Link target can't be empty.");
|
||||
return;
|
||||
}
|
||||
var link_name = response.name;
|
||||
if (link_name === "") {
|
||||
this.modal_prompt.alert("Link name can't be empty.");
|
||||
return;
|
||||
}
|
||||
if (link_name.includes("/")) {
|
||||
this.modal_prompt.alert("Link name can't contain `/`.");
|
||||
return;
|
||||
@ -499,7 +542,6 @@ export class NavWindow {
|
||||
}
|
||||
|
||||
async paste_clipboard() {
|
||||
this.start_load();
|
||||
var cmd = ["/usr/share/cockpit/navigator/scripts/paste.py"];
|
||||
var dest = this.pwd().path_str();
|
||||
if (this.copy_or_move === "move") {
|
||||
@ -519,8 +561,30 @@ export class NavWindow {
|
||||
proc.stream(async (data) => {
|
||||
var payload = JSON.parse(data);
|
||||
if (payload["wants-response"]) {
|
||||
var user_response = await this.modal_prompt.confirm(payload["message"]);
|
||||
proc.input(JSON.stringify(user_response) + "\n", true);
|
||||
if (payload.hasOwnProperty("conflicts")) {
|
||||
let requests = {};
|
||||
for (let conflict of payload["conflicts"]) {
|
||||
requests[conflict[0]] = {
|
||||
label: conflict[1],
|
||||
type: "checkbox",
|
||||
default: false
|
||||
}
|
||||
}
|
||||
let responses = await this.modal_prompt.prompt("Overwrite?", requests);
|
||||
if (responses === null) {
|
||||
proc.input(JSON.stringify("abort") + "\n");
|
||||
return;
|
||||
}
|
||||
let keepers = [];
|
||||
for (let response of Object.keys(responses)) {
|
||||
if (responses[response])
|
||||
keepers.push(response)
|
||||
}
|
||||
proc.input(JSON.stringify(keepers) + "\n", true);
|
||||
} else {
|
||||
var user_response = await this.modal_prompt.confirm(payload["message"]);
|
||||
proc.input(JSON.stringify(user_response) + "\n", true);
|
||||
}
|
||||
} else {
|
||||
await this.modal_prompt.alert(payload["message"]);
|
||||
}
|
||||
|
@ -28,15 +28,19 @@ from optparse import OptionParser
|
||||
import json
|
||||
import subprocess
|
||||
|
||||
def prompt_user(message, wants_response):
|
||||
def prompt_user(message, wants_response, conflicts = None):
|
||||
payload = {
|
||||
"wants-response": wants_response,
|
||||
"message": message
|
||||
}
|
||||
if conflicts != None:
|
||||
payload["conflicts"] = conflicts
|
||||
print(json.dumps(payload) + "\n")
|
||||
if wants_response:
|
||||
response = input()
|
||||
return json.loads(response)
|
||||
response = json.loads(input())
|
||||
if isinstance(response, str) and response == "abort":
|
||||
sys.exit(0)
|
||||
return response
|
||||
return
|
||||
|
||||
def split_paths_at_cwd(paths, cwd):
|
||||
@ -70,12 +74,8 @@ def filter_existing(args, cwd):
|
||||
dest = args[-1]
|
||||
(conflicts, non_conflicts) = recursive_get_conflicts(sources, cwd, dest)
|
||||
if len(conflicts):
|
||||
check_continue = prompt_user("Conflicts were found while pasting. `Cancel` to abort operation, `OK` to overwrite selectively.", True)
|
||||
if not check_continue:
|
||||
sys.exit(0)
|
||||
for conflict in conflicts:
|
||||
if prompt_user("Overwrite " + conflict[1] + "?", True):
|
||||
non_conflicts.append(conflict[0])
|
||||
conflicts = prompt_user("Overwrite?", True, conflicts)
|
||||
non_conflicts.extend(conflicts)
|
||||
if not len(non_conflicts):
|
||||
sys.exit(0) # exit if nothing to copy
|
||||
filtered_args = [*split_paths_at_cwd(non_conflicts, cwd), dest]
|
||||
|
Loading…
x
Reference in New Issue
Block a user