Merge pull request 'feat: add visual drag-and-drop reordering indicators and improve event handling for connection items' (#4) from v1.1.2 into main
Reviewed-on: http://git.jdbnet.co.uk/jamie/goexplore/pulls/4
This commit was merged in pull request #4.
This commit is contained in:
+11
-1
@@ -91,12 +91,22 @@ async function loadConnections() {
|
|||||||
draggedConnId = null;
|
draggedConnId = null;
|
||||||
el.style.opacity = '1';
|
el.style.opacity = '1';
|
||||||
});
|
});
|
||||||
|
el.addEventListener('dragenter', (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
if (draggedConnId && draggedConnId !== c.id) {
|
||||||
|
el.style.borderTop = '2px solid var(--accent)';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
el.addEventListener('dragleave', (e) => {
|
||||||
|
el.style.borderTop = '';
|
||||||
|
});
|
||||||
el.addEventListener('dragover', (e) => {
|
el.addEventListener('dragover', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.dataTransfer.dropEffect = 'move';
|
e.dataTransfer.dropEffect = 'move';
|
||||||
});
|
});
|
||||||
el.addEventListener('drop', async (e) => {
|
el.addEventListener('drop', async (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
el.style.borderTop = '';
|
||||||
if (!draggedConnId || draggedConnId === c.id) return;
|
if (!draggedConnId || draggedConnId === c.id) return;
|
||||||
|
|
||||||
const ids = connectionsCache.map(conn => conn.id);
|
const ids = connectionsCache.map(conn => conn.id);
|
||||||
@@ -109,10 +119,10 @@ async function loadConnections() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await ReorderConnections(ids);
|
await ReorderConnections(ids);
|
||||||
await loadConnections();
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Failed to reorder connections:", err);
|
console.error("Failed to reorder connections:", err);
|
||||||
}
|
}
|
||||||
|
await loadConnections();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -57,6 +57,14 @@ body {
|
|||||||
transition: background 0.2s;
|
transition: background 0.2s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conn-item * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conn-item .edit-btn {
|
||||||
|
pointer-events: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.conn-item:hover {
|
.conn-item:hover {
|
||||||
background: var(--surface-hover);
|
background: var(--surface-hover);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func (e *SFTPExplorer) Connect() error {
|
|||||||
port = 22
|
port = 22
|
||||||
}
|
}
|
||||||
|
|
||||||
var authMethod ssh.AuthMethod
|
var authMethods []ssh.AuthMethod
|
||||||
|
|
||||||
secretStr := strings.TrimSpace(e.secret)
|
secretStr := strings.TrimSpace(e.secret)
|
||||||
// Handle case where newlines might be escaped by mistake
|
// Handle case where newlines might be escaped by mistake
|
||||||
@@ -43,16 +43,35 @@ func (e *SFTPExplorer) Connect() error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to parse private key: %w", err)
|
return fmt.Errorf("failed to parse private key: %w", err)
|
||||||
}
|
}
|
||||||
authMethod = ssh.PublicKeys(signer)
|
authMethods = append(authMethods, ssh.PublicKeys(signer))
|
||||||
} else {
|
} else {
|
||||||
authMethod = ssh.Password(e.secret)
|
authMethods = append(authMethods, ssh.Password(e.secret))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always add KeyboardInteractive to support Duo MFA and servers that require interactive auth.
|
||||||
|
authMethods = append(authMethods, ssh.KeyboardInteractive(func(user, instruction string, questions []string, echos []bool) (answers []string, err error) {
|
||||||
|
answers = make([]string, len(questions))
|
||||||
|
for i, q := range questions {
|
||||||
|
qLower := strings.ToLower(q)
|
||||||
|
if strings.Contains(secretStr, "-----BEGIN") {
|
||||||
|
// If using a private key, we don't have a password.
|
||||||
|
// If it's a Duo prompt asking for an option, "1" is typically Duo Push.
|
||||||
|
if strings.Contains(qLower, "duo push") || strings.Contains(qLower, "passcode or option") {
|
||||||
|
answers[i] = "1"
|
||||||
|
} else {
|
||||||
|
answers[i] = ""
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Otherwise, respond with the password to keyboard interactive prompts
|
||||||
|
answers[i] = e.secret
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return answers, nil
|
||||||
|
}))
|
||||||
|
|
||||||
config := &ssh.ClientConfig{
|
config := &ssh.ClientConfig{
|
||||||
User: e.cfg.Username,
|
User: e.cfg.Username,
|
||||||
Auth: []ssh.AuthMethod{
|
Auth: authMethods,
|
||||||
authMethod,
|
|
||||||
},
|
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user