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:
@@ -90,6 +90,33 @@ export class TsviewMongoCollections extends DeesElement {
|
||||
font-size: 12px;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.overview-item {
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: background 0.1s;
|
||||
color: #a5d6a7;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.overview-item:hover {
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.overview-item.selected {
|
||||
background: rgba(165, 214, 167, 0.15);
|
||||
color: #a5d6a7;
|
||||
}
|
||||
|
||||
.overview-item svg {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
`,
|
||||
];
|
||||
|
||||
@@ -168,36 +195,56 @@ export class TsviewMongoCollections extends DeesElement {
|
||||
await this.loadCollections();
|
||||
}
|
||||
|
||||
private selectOverview() {
|
||||
this.dispatchEvent(
|
||||
new CustomEvent('collection-selected', {
|
||||
detail: '__overview__',
|
||||
bubbles: true,
|
||||
composed: true,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.loading) {
|
||||
return html`<div class="loading-state">Loading collections...</div>`;
|
||||
}
|
||||
|
||||
if (this.collections.length === 0) {
|
||||
return html`<div class="empty-state">No collections</div>`;
|
||||
}
|
||||
|
||||
return html`
|
||||
<div class="collections-list">
|
||||
${this.collections.map(
|
||||
(coll) => html`
|
||||
<div
|
||||
class="collection-item ${this.selectedCollection === coll.name ? 'selected' : ''}"
|
||||
@click=${() => this.selectCollection(coll.name)}
|
||||
@contextmenu=${(e: MouseEvent) => this.handleCollectionContextMenu(e, coll)}
|
||||
>
|
||||
<span class="collection-name">
|
||||
<svg class="collection-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
||||
</svg>
|
||||
${coll.name}
|
||||
</span>
|
||||
${coll.count !== undefined
|
||||
? html`<span class="collection-count">${formatCount(coll.count)}</span>`
|
||||
: ''}
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
<div
|
||||
class="overview-item ${this.selectedCollection === '__overview__' ? 'selected' : ''}"
|
||||
@click=${() => this.selectOverview()}
|
||||
>
|
||||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<rect x="3" y="3" width="7" height="7"></rect>
|
||||
<rect x="14" y="3" width="7" height="7"></rect>
|
||||
<rect x="14" y="14" width="7" height="7"></rect>
|
||||
<rect x="3" y="14" width="7" height="7"></rect>
|
||||
</svg>
|
||||
Overview
|
||||
</div>
|
||||
${this.collections.length === 0
|
||||
? html`<div class="empty-state">No collections</div>`
|
||||
: this.collections.map(
|
||||
(coll) => html`
|
||||
<div
|
||||
class="collection-item ${this.selectedCollection === coll.name ? 'selected' : ''}"
|
||||
@click=${() => this.selectCollection(coll.name)}
|
||||
@contextmenu=${(e: MouseEvent) => this.handleCollectionContextMenu(e, coll)}
|
||||
>
|
||||
<span class="collection-name">
|
||||
<svg class="collection-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
||||
<path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"></path>
|
||||
</svg>
|
||||
${coll.name}
|
||||
</span>
|
||||
${coll.count !== undefined
|
||||
? html`<span class="collection-count">${formatCount(coll.count)}</span>`
|
||||
: ''}
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user