feat(web): add database overview panel, collection overview and resizable panels; show/hide system databases; use code editor with change-tracking in document view; add getDatabaseStats API and typings; enable overwrite for S3 uploads

This commit is contained in:
2026-01-25 17:34:52 +00:00
parent 2ca5f52da3
commit a26e7a5a20
17 changed files with 718 additions and 143 deletions

View File

@@ -23,6 +23,12 @@ export class TsviewS3Browser extends DeesElement {
@state()
private accessor refreshKey: number = 0;
@state()
private accessor previewWidth: number = 350;
@state()
private accessor isResizingPreview: boolean = false;
public static styles = [
cssManager.defaultStyles,
themeStyles,
@@ -104,12 +110,24 @@ export class TsviewS3Browser extends DeesElement {
flex: 1;
display: grid;
grid-template-columns: 1fr;
gap: 16px;
gap: 0;
overflow: hidden;
}
.content.has-preview {
grid-template-columns: 1fr 350px;
grid-template-columns: 1fr 4px var(--preview-width, 350px);
}
.resize-divider {
width: 4px;
background: transparent;
cursor: col-resize;
transition: background 0.2s;
}
.resize-divider:hover,
.resize-divider.active {
background: rgba(255, 255, 255, 0.2);
}
.main-view {
@@ -122,6 +140,7 @@ export class TsviewS3Browser extends DeesElement {
background: rgba(0, 0, 0, 0.2);
border-radius: 8px;
overflow: hidden;
margin-left: 12px;
}
@media (max-width: 1024px) {
@@ -130,7 +149,8 @@ export class TsviewS3Browser extends DeesElement {
grid-template-columns: 1fr;
}
.preview-panel {
.preview-panel,
.resize-divider {
display: none;
}
}
@@ -168,6 +188,28 @@ export class TsviewS3Browser extends DeesElement {
}
}
private startPreviewResize = (e: MouseEvent) => {
e.preventDefault();
this.isResizingPreview = true;
document.addEventListener('mousemove', this.handlePreviewResize);
document.addEventListener('mouseup', this.endPreviewResize);
};
private handlePreviewResize = (e: MouseEvent) => {
if (!this.isResizingPreview) return;
const contentEl = this.shadowRoot?.querySelector('.content');
if (!contentEl) return;
const containerRect = contentEl.getBoundingClientRect();
const newWidth = Math.min(Math.max(containerRect.right - e.clientX, 250), 600);
this.previewWidth = newWidth;
};
private endPreviewResize = () => {
this.isResizingPreview = false;
document.removeEventListener('mousemove', this.handlePreviewResize);
document.removeEventListener('mouseup', this.endPreviewResize);
};
render() {
const breadcrumbParts = this.currentPrefix
? this.currentPrefix.split('/').filter(Boolean)
@@ -213,7 +255,7 @@ export class TsviewS3Browser extends DeesElement {
</div>
</div>
<div class="content ${this.selectedKey ? 'has-preview' : ''}">
<div class="content ${this.selectedKey ? 'has-preview' : ''}" style="--preview-width: ${this.previewWidth}px">
<div class="main-view">
${this.viewType === 'columns'
? html`
@@ -238,6 +280,10 @@ export class TsviewS3Browser extends DeesElement {
${this.selectedKey
? html`
<div
class="resize-divider ${this.isResizingPreview ? 'active' : ''}"
@mousedown=${this.startPreviewResize}
></div>
<div class="preview-panel">
<tsview-s3-preview
.bucketName=${this.bucketName}