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:
@@ -3,6 +3,7 @@ import { apiService } from '../services/index.js';
|
||||
import { themeStyles } from '../styles/index.js';
|
||||
|
||||
const { html, css, cssManager, customElement, state, DeesElement } = plugins;
|
||||
const { DeesContextmenu } = plugins.deesCatalog;
|
||||
|
||||
type TViewMode = 's3' | 'mongo' | 'settings';
|
||||
|
||||
@@ -359,30 +360,6 @@ export class TsviewApp extends DeesElement {
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
opacity: 0;
|
||||
padding: 4px;
|
||||
background: transparent;
|
||||
border: none;
|
||||
color: #888;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.15s;
|
||||
}
|
||||
|
||||
.sidebar-item:hover .delete-btn,
|
||||
.db-group-header:hover .delete-btn {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.delete-btn:hover {
|
||||
background: rgba(239, 68, 68, 0.2);
|
||||
color: #f87171;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -495,6 +472,66 @@ export class TsviewApp extends DeesElement {
|
||||
}
|
||||
}
|
||||
|
||||
private handleBucketContextMenu(event: MouseEvent, bucket: string) {
|
||||
event.preventDefault();
|
||||
DeesContextmenu.openContextMenuWithOptions(event, [
|
||||
{
|
||||
name: 'View Contents',
|
||||
iconName: 'lucide:folderOpen',
|
||||
action: async () => {
|
||||
this.selectBucket(bucket);
|
||||
},
|
||||
},
|
||||
{ divider: true },
|
||||
{
|
||||
name: 'Delete Bucket',
|
||||
iconName: 'lucide:trash2',
|
||||
action: async () => {
|
||||
if (confirm(`Delete bucket "${bucket}"? This will delete all objects in the bucket.`)) {
|
||||
const success = await apiService.deleteBucket(bucket);
|
||||
if (success) {
|
||||
this.buckets = this.buckets.filter(b => b !== bucket);
|
||||
if (this.selectedBucket === bucket) {
|
||||
this.selectedBucket = this.buckets[0] || '';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
private handleDatabaseContextMenu(event: MouseEvent, dbName: string) {
|
||||
event.preventDefault();
|
||||
DeesContextmenu.openContextMenuWithOptions(event, [
|
||||
{
|
||||
name: 'New Collection',
|
||||
iconName: 'lucide:folderPlus',
|
||||
action: async () => {
|
||||
this.selectedDatabase = dbName;
|
||||
this.showCreateCollectionDialog = true;
|
||||
},
|
||||
},
|
||||
{ divider: true },
|
||||
{
|
||||
name: 'Delete Database',
|
||||
iconName: 'lucide:trash2',
|
||||
action: async () => {
|
||||
if (confirm(`Delete database "${dbName}"? This will delete all collections and documents.`)) {
|
||||
const success = await apiService.dropDatabase(dbName);
|
||||
if (success) {
|
||||
this.databases = this.databases.filter(d => d.name !== dbName);
|
||||
if (this.selectedDatabase === dbName) {
|
||||
this.selectedDatabase = this.databases[0]?.name || '';
|
||||
this.selectedCollection = '';
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<div class="app-container">
|
||||
@@ -653,14 +690,9 @@ export class TsviewApp extends DeesElement {
|
||||
<div
|
||||
class="sidebar-item ${bucket === this.selectedBucket ? 'selected' : ''}"
|
||||
@click=${() => this.selectBucket(bucket)}
|
||||
@contextmenu=${(e: MouseEvent) => this.handleBucketContextMenu(e, bucket)}
|
||||
>
|
||||
<span class="sidebar-item-name">${bucket}</span>
|
||||
<button class="delete-btn" @click=${(e: Event) => this.deleteBucket(bucket, e)} title="Delete bucket">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="3 6 5 6 21 6"></polyline>
|
||||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
@@ -680,15 +712,6 @@ export class TsviewApp extends DeesElement {
|
||||
</svg>
|
||||
New Database
|
||||
</button>
|
||||
${this.selectedDatabase ? html`
|
||||
<button class="create-btn" @click=${() => this.showCreateCollectionDialog = true}>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<line x1="12" y1="5" x2="12" y2="19"></line>
|
||||
<line x1="5" y1="12" x2="19" y2="12"></line>
|
||||
</svg>
|
||||
New Collection
|
||||
</button>
|
||||
` : ''}
|
||||
<div class="sidebar-list">
|
||||
${this.databases.length === 0
|
||||
? html`<div class="sidebar-item" style="color: #666; cursor: default;">No databases found</div>`
|
||||
@@ -715,6 +738,7 @@ export class TsviewApp extends DeesElement {
|
||||
<div
|
||||
class="db-group-header ${this.selectedDatabase === db.name ? 'selected' : ''}"
|
||||
@click=${() => this.selectDatabase(db.name)}
|
||||
@contextmenu=${(e: MouseEvent) => this.handleDatabaseContextMenu(e, db.name)}
|
||||
>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<ellipse cx="12" cy="5" rx="9" ry="3"></ellipse>
|
||||
@@ -722,12 +746,6 @@ export class TsviewApp extends DeesElement {
|
||||
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path>
|
||||
</svg>
|
||||
<span style="flex: 1;">${db.name}</span>
|
||||
<button class="delete-btn" @click=${(e: Event) => this.deleteDatabase(db.name, e)} title="Delete database">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<polyline points="3 6 5 6 21 6"></polyline>
|
||||
<path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
${this.selectedDatabase === db.name ? this.renderCollectionsList(db.name) : ''}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user