feat(s3,web-ui): add S3 deletePrefix and getObjectUrl endpoints and add context menus in UI for S3 and Mongo views

This commit is contained in:
2026-01-25 11:24:03 +00:00
parent 31e9b29e23
commit 5d533caccb
12 changed files with 474 additions and 84 deletions

View File

@@ -4,6 +4,7 @@ import { formatSize, getFileName } from '../utilities/index.js';
import { themeStyles } from '../styles/index.js';
const { html, css, cssManager, customElement, property, state, DeesElement } = plugins;
const { DeesContextmenu } = plugins.deesCatalog;
@customElement('tsview-s3-keys')
export class TsviewS3Keys extends DeesElement {
@@ -210,6 +211,83 @@ export class TsviewS3Keys extends DeesElement {
return [...folders, ...files];
}
private handleItemContextMenu(event: MouseEvent, key: string, isFolder: boolean) {
event.preventDefault();
if (isFolder) {
DeesContextmenu.openContextMenuWithOptions(event, [
{
name: 'Open',
iconName: 'lucide:folderOpen',
action: async () => {
this.selectKey(key, true);
},
},
{
name: 'Copy Path',
iconName: 'lucide:copy',
action: async () => {
await navigator.clipboard.writeText(key);
},
},
{ divider: true },
{
name: 'Delete Folder',
iconName: 'lucide:trash2',
action: async () => {
if (confirm(`Delete folder "${getFileName(key)}" and all its contents?`)) {
const success = await apiService.deletePrefix(this.bucketName, key);
if (success) {
await this.loadObjects();
}
}
},
},
]);
} else {
DeesContextmenu.openContextMenuWithOptions(event, [
{
name: 'Preview',
iconName: 'lucide:eye',
action: async () => {
this.selectKey(key, false);
},
},
{
name: 'Download',
iconName: 'lucide:download',
action: async () => {
const url = await apiService.getObjectUrl(this.bucketName, key);
const link = document.createElement('a');
link.href = url;
link.download = getFileName(key);
link.click();
},
},
{
name: 'Copy Path',
iconName: 'lucide:copy',
action: async () => {
await navigator.clipboard.writeText(key);
},
},
{ divider: true },
{
name: 'Delete',
iconName: 'lucide:trash2',
action: async () => {
if (confirm(`Delete file "${getFileName(key)}"?`)) {
const success = await apiService.deleteObject(this.bucketName, key);
if (success) {
await this.loadObjects();
}
}
},
},
]);
}
}
render() {
return html`
<div class="keys-container">
@@ -242,6 +320,7 @@ export class TsviewS3Keys extends DeesElement {
<tr
class="${this.selectedKey === item.key ? 'selected' : ''}"
@click=${() => this.selectKey(item.key, item.isFolder)}
@contextmenu=${(e: MouseEvent) => this.handleItemContextMenu(e, item.key, item.isFolder)}
>
<td>
<div class="key-cell">